Skip to content

Commit 81a4a5e

Browse files
committed
Add multicast/send-all support
1 parent 9719659 commit 81a4a5e

File tree

13 files changed

+533
-30
lines changed

13 files changed

+533
-30
lines changed

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
}

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/SendResponseTest.cs renamed to FirebaseAdmin/FirebaseAdmin.Tests/Messaging/BatchItemResponseTest.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
namespace FirebaseAdmin.Tests.Messaging
66
{
7-
public class SendResponseTest
7+
public class BatchItemResponseTest
88
{
99
[Fact]
1010
public void SuccessfulResponse()
1111
{
12-
var response = SendResponse.FromMessageId("message-id");
12+
var response = BatchItemResponse.FromMessageId("message-id");
1313

1414
Assert.Equal("message-id", response.MessageId);
1515
Assert.True(response.IsSuccessful);
@@ -20,10 +20,10 @@ public void SuccessfulResponse()
2020
public void FailureResponse()
2121
{
2222
FirebaseMessagingException exception = new FirebaseMessagingException(
23-
"error-code",
23+
400,
2424
"error-message",
2525
null);
26-
SendResponse response = SendResponse.FromException(exception);
26+
var response = BatchItemResponse.FromException(exception);
2727

2828
Assert.Null(response.MessageId);
2929
Assert.False(response.IsSuccessful);
@@ -33,19 +33,19 @@ public void FailureResponse()
3333
[Fact]
3434
public void MessageIdCannotBeNull()
3535
{
36-
Assert.Throws<ArgumentNullException>(() => SendResponse.FromMessageId(null));
36+
Assert.Throws<ArgumentNullException>(() => BatchItemResponse.FromMessageId(null));
3737
}
3838

3939
[Fact]
4040
public void MessageIdCannotBeEmpty()
4141
{
42-
Assert.Throws<ArgumentException>(() => SendResponse.FromMessageId(string.Empty));
42+
Assert.Throws<ArgumentException>(() => BatchItemResponse.FromMessageId(string.Empty));
4343
}
4444

4545
[Fact]
4646
public void ExceptionCannotBeNull()
4747
{
48-
Assert.Throws<ArgumentNullException>(() => SendResponse.FromException(null));
48+
Assert.Throws<ArgumentNullException>(() => BatchItemResponse.FromException(null));
4949
}
5050
}
5151
}

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/BatchResponseTest.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class BatchResponseTest
1111
[Fact]
1212
public void EmptyResponses()
1313
{
14-
var responses = new List<SendResponse>();
14+
var responses = new List<BatchItemResponse>();
1515

1616
var batchResponse = new BatchResponse(responses);
1717

@@ -23,13 +23,13 @@ public void EmptyResponses()
2323
[Fact]
2424
public void SomeResponse()
2525
{
26-
var responses = new SendResponse[]
26+
var responses = new BatchItemResponse[]
2727
{
28-
SendResponse.FromMessageId("message1"),
29-
SendResponse.FromMessageId("message2"),
30-
SendResponse.FromException(
28+
BatchItemResponse.FromMessageId("message1"),
29+
BatchItemResponse.FromMessageId("message2"),
30+
BatchItemResponse.FromException(
3131
new FirebaseMessagingException(
32-
"error-code",
32+
400,
3333
"error-message",
3434
null)),
3535
};

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/FirebaseMessagingClientTest.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
using System;
1616
using System.Net;
17-
using System.Threading;
1817
using System.Threading.Tasks;
1918
using FirebaseAdmin.Tests;
2019
using Google.Apis.Auth.OAuth2;
@@ -89,6 +88,65 @@ public async Task SendAsync()
8988
Assert.Equal(2, handler.Calls);
9089
}
9190

91+
[Fact]
92+
public async Task SendAllAsync()
93+
{
94+
var rawResponse = @"
95+
--batch_test-boundary
96+
Content-Type: application/http
97+
Content-ID: response-
98+
99+
HTTP/1.1 200 OK
100+
Content-Type: application/json; charset=UTF-8
101+
Vary: Origin
102+
Vary: X-Origin
103+
Vary: Referer
104+
105+
{
106+
""name"": ""projects/fir-adminintegrationtests/messages/8580920590356323124""
107+
}
108+
109+
--batch_test-boundary
110+
Content-Type: application/http
111+
Content-ID: response-
112+
113+
HTTP/1.1 200 OK
114+
Content-Type: application/json; charset=UTF-8
115+
Vary: Origin
116+
Vary: X-Origin
117+
Vary: Referer
118+
119+
{
120+
""name"": ""projects/fir-adminintegrationtests/messages/5903525881088369386""
121+
}
122+
123+
--batch_test-boundary
124+
";
125+
var handler = new MockMessageHandler()
126+
{
127+
Response = rawResponse,
128+
ApplyContentHeaders = (headers) =>
129+
{
130+
headers.Remove("Content-Type");
131+
headers.TryAddWithoutValidation("Content-Type", "multipart/mixed; boundary=batch_test-boundary");
132+
},
133+
};
134+
var factory = new MockHttpClientFactory(handler);
135+
var client = new FirebaseMessagingClient(factory, MockCredential, "test-project");
136+
var message1 = new Message()
137+
{
138+
Token = "test-token1",
139+
};
140+
var message2 = new Message()
141+
{
142+
Token = "test-token2",
143+
};
144+
var response = await client.SendAllAsync(new[] { message1, message2 });
145+
Assert.Equal(2, response.SuccessCount);
146+
Assert.Equal("projects/fir-adminintegrationtests/messages/8580920590356323124", response.Responses[0].MessageId);
147+
Assert.Equal("projects/fir-adminintegrationtests/messages/5903525881088369386", response.Responses[1].MessageId);
148+
}
149+
92150
[Fact]
93151
public async Task HttpErrorAsync()
94152
{

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/MulticastMessageTest.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
64
using FirebaseAdmin.Messaging;
75
using Google.Apis.Json;
86
using Newtonsoft.Json.Linq;
@@ -23,6 +21,21 @@ public void EmptyMulticastMessage()
2321
this.AssertJsonEquals(new JObject() { { "tokens", new JArray("test-token") } }, message);
2422
}
2523

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+
2639
[Fact]
2740
public void Data()
2841
{
@@ -143,6 +156,12 @@ public void MessageWithNoTokens()
143156
Assert.Throws<ArgumentException>(() => new MulticastMessage { Tokens = new string[] { } }.CopyAndValidate());
144157
}
145158

159+
[Fact]
160+
public void MessageWithTooManyTokens()
161+
{
162+
Assert.Throws<ArgumentException>(() => new MulticastMessage { Tokens = Enumerable.Range(0, 101).Select(x => x.ToString()).ToList() }.CopyAndValidate());
163+
}
164+
146165
[Fact]
147166
public void AndroidConfig()
148167
{

FirebaseAdmin/FirebaseAdmin.Tests/MockMessageHandler.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public MockMessageHandler()
3939

4040
public delegate void SetHeaders(HttpResponseHeaders header);
4141

42+
public delegate void SetContentHeaders(HttpContentHeaders header);
43+
4244
public string Request { get; private set; }
4345

4446
public HttpStatusCode StatusCode { get; set; }
@@ -47,6 +49,8 @@ public MockMessageHandler()
4749

4850
public SetHeaders ApplyHeaders { get; set; }
4951

52+
public SetContentHeaders ApplyContentHeaders { get; set; }
53+
5054
protected override async Task<HttpResponseMessage> SendAsyncCore(
5155
HttpRequestMessage request, CancellationToken cancellationToken)
5256
{
@@ -80,7 +84,15 @@ protected override async Task<HttpResponseMessage> SendAsyncCore(
8084
this.ApplyHeaders(resp.Headers);
8185
}
8286

83-
resp.Content = new StringContent(json, Encoding.UTF8, "application/json");
87+
var responseContent = new StringContent(json, Encoding.UTF8, "application/json");
88+
89+
if (this.ApplyContentHeaders != null)
90+
{
91+
this.ApplyContentHeaders(responseContent.Headers);
92+
}
93+
94+
resp.Content = responseContent;
95+
8496
var tcs = new TaskCompletionSource<HttpResponseMessage>();
8597
tcs.SetResult(resp);
8698
return await tcs.Task;

FirebaseAdmin/FirebaseAdmin/FirebaseException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace FirebaseAdmin
1919
/// <summary>
2020
/// Common error type for all exceptions raised by Firebase APIs.
2121
/// </summary>
22-
public sealed class FirebaseException : Exception
22+
public class FirebaseException : Exception
2323
{
2424
internal FirebaseException(string message)
2525
: base(message) { }

FirebaseAdmin/FirebaseAdmin/Messaging/SendResponse.cs renamed to FirebaseAdmin/FirebaseAdmin/Messaging/BatchItemResponse.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ namespace FirebaseAdmin.Messaging
2020
/// The result of an individual send operation that was executed as part of a batch. See
2121
/// <see cref="BatchResponse"/> for more details.
2222
/// </summary>
23-
public sealed class SendResponse
23+
public sealed class BatchItemResponse
2424
{
25-
private SendResponse(string messageId)
25+
private BatchItemResponse(string messageId)
2626
{
2727
this.MessageId = messageId;
2828
}
2929

30-
private SendResponse(FirebaseMessagingException exception)
30+
private BatchItemResponse(FirebaseException exception)
3131
{
3232
this.Exception = exception;
3333
}
@@ -40,7 +40,7 @@ private SendResponse(FirebaseMessagingException exception)
4040
/// <summary>
4141
/// Gets an exception if the send operation failed. Otherwise returns null.
4242
/// </summary>
43-
public FirebaseMessagingException Exception { get; }
43+
public FirebaseException Exception { get; }
4444

4545
/// <summary>
4646
/// Gets a value indicating whether the send operation was successful or not. When this property
@@ -50,7 +50,7 @@ private SendResponse(FirebaseMessagingException exception)
5050
/// </summary>
5151
public bool IsSuccessful => !string.IsNullOrEmpty(this.MessageId);
5252

53-
internal static SendResponse FromMessageId(string messageId)
53+
internal static BatchItemResponse FromMessageId(string messageId)
5454
{
5555
if (messageId == null)
5656
{
@@ -62,17 +62,17 @@ internal static SendResponse FromMessageId(string messageId)
6262
throw new ArgumentException("Cannot be empty.", nameof(messageId));
6363
}
6464

65-
return new SendResponse(messageId);
65+
return new BatchItemResponse(messageId);
6666
}
6767

68-
internal static SendResponse FromException(FirebaseMessagingException exception)
68+
internal static BatchItemResponse FromException(FirebaseException exception)
6969
{
7070
if (exception == null)
7171
{
7272
throw new ArgumentNullException(nameof(exception));
7373
}
7474

75-
return new SendResponse(exception);
75+
return new BatchItemResponse(exception);
7676
}
7777
}
7878
}

FirebaseAdmin/FirebaseAdmin/Messaging/BatchResponse.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public sealed class BatchResponse
2727
/// Initializes a new instance of the <see cref="BatchResponse"/> class.
2828
/// </summary>
2929
/// <param name="responses">The responses.</param>
30-
public BatchResponse(IEnumerable<SendResponse> responses)
30+
public BatchResponse(IEnumerable<BatchItemResponse> responses)
3131
{
3232
if (responses == null)
3333
{
@@ -52,7 +52,7 @@ public BatchResponse(IEnumerable<SendResponse> responses)
5252
/// <summary>
5353
/// Gets information about all responses for the batch.
5454
/// </summary>
55-
public IReadOnlyList<SendResponse> Responses { get; }
55+
public IReadOnlyList<BatchItemResponse> Responses { get; }
5656

5757
/// <summary>
5858
/// Gets a count of how many of the responses in <see cref="Responses"/> were

0 commit comments

Comments
 (0)