Skip to content

Commit ae0d725

Browse files
authored
Merge pull request #36 from kentcb/multicastmessaging
feature: multicast messaging
2 parents 01d5637 + 8c4c923 commit ae0d725

File tree

13 files changed

+984
-42
lines changed

13 files changed

+984
-42
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
bin/
22
obj/
33
.vscode/
4-
4+
.vs/

FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseMessagingTest.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,76 @@ public async Task Send()
4949
Assert.True(!string.IsNullOrEmpty(id));
5050
Assert.Matches(new Regex("^projects/.*/messages/.*$"), id);
5151
}
52+
53+
[Fact]
54+
public async Task SendAll()
55+
{
56+
var message1 = new Message()
57+
{
58+
Topic = "foo-bar",
59+
Notification = new Notification()
60+
{
61+
Title = "Title",
62+
Body = "Body",
63+
},
64+
Android = new AndroidConfig()
65+
{
66+
Priority = Priority.Normal,
67+
TimeToLive = TimeSpan.FromHours(1),
68+
RestrictedPackageName = "com.google.firebase.testing",
69+
},
70+
};
71+
var message2 = new Message()
72+
{
73+
Topic = "fiz-buz",
74+
Notification = new Notification()
75+
{
76+
Title = "Title",
77+
Body = "Body",
78+
},
79+
Android = new AndroidConfig()
80+
{
81+
Priority = Priority.Normal,
82+
TimeToLive = TimeSpan.FromHours(1),
83+
RestrictedPackageName = "com.google.firebase.testing",
84+
},
85+
};
86+
var response = await FirebaseMessaging.DefaultInstance.SendAllAsync(new[] { message1, message2 }, dryRun: true);
87+
Assert.NotNull(response);
88+
Assert.Equal(2, response.SuccessCount);
89+
Assert.True(!string.IsNullOrEmpty(response.Responses[0].MessageId));
90+
Assert.Matches(new Regex("^projects/.*/messages/.*$"), response.Responses[0].MessageId);
91+
Assert.True(!string.IsNullOrEmpty(response.Responses[1].MessageId));
92+
Assert.Matches(new Regex("^projects/.*/messages/.*$"), response.Responses[1].MessageId);
93+
}
94+
95+
[Fact]
96+
public async Task SendMulticast()
97+
{
98+
var multicastMessage = new MulticastMessage
99+
{
100+
Notification = new Notification()
101+
{
102+
Title = "Title",
103+
Body = "Body",
104+
},
105+
Android = new AndroidConfig()
106+
{
107+
Priority = Priority.Normal,
108+
TimeToLive = TimeSpan.FromHours(1),
109+
RestrictedPackageName = "com.google.firebase.testing",
110+
},
111+
Tokens = new[]
112+
{
113+
"token1",
114+
"token2",
115+
},
116+
};
117+
var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(multicastMessage, dryRun: true);
118+
Assert.NotNull(response);
119+
Assert.Equal(2, response.FailureCount);
120+
Assert.NotNull(response.Responses[0].Exception);
121+
Assert.NotNull(response.Responses[1].Exception);
122+
}
52123
}
53124
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2018, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using FirebaseAdmin.Messaging;
19+
using Xunit;
20+
21+
namespace FirebaseAdmin.Tests.Messaging
22+
{
23+
public class BatchResponseTest
24+
{
25+
[Fact]
26+
public void EmptyResponses()
27+
{
28+
var responses = new List<SendResponse>();
29+
30+
var batchResponse = new BatchResponse(responses);
31+
32+
Assert.Equal(0, batchResponse.SuccessCount);
33+
Assert.Equal(0, batchResponse.FailureCount);
34+
Assert.Equal(0, batchResponse.Responses.Count);
35+
}
36+
37+
[Fact]
38+
public void SomeResponse()
39+
{
40+
var responses = new SendResponse[]
41+
{
42+
SendResponse.FromMessageId("message1"),
43+
SendResponse.FromMessageId("message2"),
44+
SendResponse.FromException(
45+
new FirebaseException(
46+
"error-message",
47+
null)),
48+
};
49+
50+
var batchResponse = new BatchResponse(responses);
51+
52+
Assert.Equal(2, batchResponse.SuccessCount);
53+
Assert.Equal(1, batchResponse.FailureCount);
54+
Assert.Equal(3, batchResponse.Responses.Count);
55+
Assert.True(responses.SequenceEqual(batchResponse.Responses));
56+
}
57+
58+
[Fact]
59+
public void ResponsesCannotBeNull()
60+
{
61+
Assert.Throws<ArgumentNullException>(() => new BatchResponse(null));
62+
}
63+
}
64+
}

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/FirebaseMessagingClientTest.cs

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// limitations under the License.
1414

1515
using System;
16+
using System.Linq;
1617
using System.Net;
17-
using System.Threading;
1818
using System.Threading.Tasks;
1919
using FirebaseAdmin.Tests;
2020
using Google.Apis.Auth.OAuth2;
@@ -60,7 +60,7 @@ public async Task SendAsync()
6060
{
6161
var handler = new MockMessageHandler()
6262
{
63-
Response = new FirebaseMessagingClient.SendResponse()
63+
Response = new FirebaseMessagingClient.SingleMessageResponse()
6464
{
6565
Name = "test-response",
6666
},
@@ -89,6 +89,162 @@ public async Task SendAsync()
8989
Assert.Equal(2, handler.Calls);
9090
}
9191

92+
[Fact]
93+
public async Task SendAllAsync()
94+
{
95+
var rawResponse = @"
96+
--batch_test-boundary
97+
Content-Type: application/http
98+
Content-ID: response-
99+
100+
HTTP/1.1 200 OK
101+
Content-Type: application/json; charset=UTF-8
102+
Vary: Origin
103+
Vary: X-Origin
104+
Vary: Referer
105+
106+
{
107+
""name"": ""projects/fir-adminintegrationtests/messages/8580920590356323124""
108+
}
109+
110+
--batch_test-boundary
111+
Content-Type: application/http
112+
Content-ID: response-
113+
114+
HTTP/1.1 200 OK
115+
Content-Type: application/json; charset=UTF-8
116+
Vary: Origin
117+
Vary: X-Origin
118+
Vary: Referer
119+
120+
{
121+
""name"": ""projects/fir-adminintegrationtests/messages/5903525881088369386""
122+
}
123+
124+
--batch_test-boundary
125+
";
126+
var handler = new MockMessageHandler()
127+
{
128+
Response = rawResponse,
129+
ApplyContentHeaders = (headers) =>
130+
{
131+
headers.Remove("Content-Type");
132+
headers.TryAddWithoutValidation("Content-Type", "multipart/mixed; boundary=batch_test-boundary");
133+
},
134+
};
135+
var factory = new MockHttpClientFactory(handler);
136+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
137+
var message1 = new Message()
138+
{
139+
Token = "test-token1",
140+
};
141+
var message2 = new Message()
142+
{
143+
Token = "test-token2",
144+
};
145+
var response = await client.SendAllAsync(new[] { message1, message2 });
146+
Assert.Equal(2, response.SuccessCount);
147+
Assert.Equal("projects/fir-adminintegrationtests/messages/8580920590356323124", response.Responses[0].MessageId);
148+
Assert.Equal("projects/fir-adminintegrationtests/messages/5903525881088369386", response.Responses[1].MessageId);
149+
}
150+
151+
[Fact]
152+
public async Task SendAllAsyncWithError()
153+
{
154+
var rawResponse = @"
155+
--batch_test-boundary
156+
Content-Type: application/http
157+
Content-ID: response-
158+
159+
HTTP/1.1 200 OK
160+
Content-Type: application/json; charset=UTF-8
161+
Vary: Origin
162+
Vary: X-Origin
163+
Vary: Referer
164+
165+
{
166+
""name"": ""projects/fir-adminintegrationtests/messages/8580920590356323124""
167+
}
168+
169+
--batch_test-boundary
170+
Content-Type: application/http
171+
Content-ID: response-
172+
173+
HTTP/1.1 400 Bad Request
174+
Content-Type: application/json; charset=UTF-8
175+
Vary: Origin
176+
Vary: X-Origin
177+
Vary: Referer
178+
179+
{
180+
""error"": {
181+
""code"": 400,
182+
""message"": ""The registration token is not a valid FCM registration token"",
183+
""errors"": [
184+
{
185+
""message"": ""The registration token is not a valid FCM registration token"",
186+
""domain"": ""global"",
187+
""reason"": ""badRequest""
188+
}
189+
],
190+
""status"": ""INVALID_ARGUMENT""
191+
}
192+
}
193+
194+
--batch_test-boundary
195+
";
196+
var handler = new MockMessageHandler()
197+
{
198+
Response = rawResponse,
199+
ApplyContentHeaders = (headers) =>
200+
{
201+
headers.Remove("Content-Type");
202+
headers.TryAddWithoutValidation("Content-Type", "multipart/mixed; boundary=batch_test-boundary");
203+
},
204+
};
205+
var factory = new MockHttpClientFactory(handler);
206+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
207+
var message1 = new Message()
208+
{
209+
Token = "test-token1",
210+
};
211+
var message2 = new Message()
212+
{
213+
Token = "test-token2",
214+
};
215+
var response = await client.SendAllAsync(new[] { message1, message2 });
216+
Assert.Equal(1, response.SuccessCount);
217+
Assert.Equal(1, response.FailureCount);
218+
Assert.Equal("projects/fir-adminintegrationtests/messages/8580920590356323124", response.Responses[0].MessageId);
219+
Assert.NotNull(response.Responses[1].Exception);
220+
}
221+
222+
[Fact]
223+
public async Task SendAllAsyncNullList()
224+
{
225+
var factory = new MockHttpClientFactory(new MockMessageHandler());
226+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
227+
228+
await Assert.ThrowsAsync<ArgumentNullException>(() => client.SendAllAsync(null));
229+
}
230+
231+
[Fact]
232+
public async Task SendAllAsyncWithNoMessages()
233+
{
234+
var factory = new MockHttpClientFactory(new MockMessageHandler());
235+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
236+
await Assert.ThrowsAsync<ArgumentException>(() => client.SendAllAsync(Enumerable.Empty<Message>()));
237+
}
238+
239+
[Fact]
240+
public async Task SendAllAsyncWithTooManyMessages()
241+
{
242+
var factory = new MockHttpClientFactory(new MockMessageHandler());
243+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
244+
var messages = Enumerable.Range(0, 101).Select(_ => new Message { Topic = "test-topic" });
245+
await Assert.ThrowsAsync<ArgumentException>(() => client.SendAllAsync(messages));
246+
}
247+
92248
[Fact]
93249
public async Task HttpErrorAsync()
94250
{
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2018, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Linq;
17+
using FirebaseAdmin.Messaging;
18+
using Xunit;
19+
20+
namespace FirebaseAdmin.Tests.Messaging
21+
{
22+
public class MulticastMessageTest
23+
{
24+
[Fact]
25+
public void GetMessageList()
26+
{
27+
var message = new MulticastMessage
28+
{
29+
Tokens = new[] { "test-token1", "test-token2" },
30+
};
31+
32+
var messages = message.GetMessageList();
33+
34+
Assert.Equal(2, messages.Count);
35+
Assert.Equal("test-token1", messages[0].Token);
36+
Assert.Equal("test-token2", messages[1].Token);
37+
}
38+
39+
[Fact]
40+
public void GetMessageListNoTokens()
41+
{
42+
var message = new MulticastMessage();
43+
44+
Assert.Throws<ArgumentException>(() => message.GetMessageList());
45+
}
46+
47+
[Fact]
48+
public void GetMessageListTooManyTokens()
49+
{
50+
var message = new MulticastMessage
51+
{
52+
Tokens = Enumerable.Range(0, 101).Select(x => x.ToString()).ToList(),
53+
};
54+
55+
Assert.Throws<ArgumentException>(() => message.GetMessageList());
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)