Skip to content

Commit 43e12e7

Browse files
committed
CSHARP-1274: added support for tracking election id.
1 parent 1a72bf8 commit 43e12e7

File tree

61 files changed

+1680
-88
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1680
-88
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* Copyright 2013-2014 MongoDB Inc.
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+
16+
using FluentAssertions;
17+
using MongoDB.Bson;
18+
using NUnit.Framework;
19+
20+
21+
namespace MongoDB.Driver.Core.Clusters
22+
{
23+
[TestFixture]
24+
public class ElectionIdTests
25+
{
26+
[Test]
27+
[TestCase("555925bfb69aa7d5be29126b", "555925bfb69aa7d5be29126b", 0)]
28+
[TestCase("555925bfb69aa7d5be29126b", "555925bfb69aa7d5be29126c", -1)]
29+
[TestCase("000000000000000000000000", "555925bfb69aa7d5be29126b", -1)]
30+
[TestCase("555925bfb69aa7d5be29126c", "555925bfb69aa7d5be29126b", 1)]
31+
[TestCase("555925bfb69aa7d5be29126b", "000000000000000000000000", 1)]
32+
[TestCase("555925bfb69aa7d5be29126b", null, 1)]
33+
public void CompareTo_should_return_the_correct_value(string oidA, string oidB, int result)
34+
{
35+
var subject1 = new ElectionId(ObjectId.Parse(oidA));
36+
ElectionId subject2 = oidB == null ? (ElectionId)null : new ElectionId(ObjectId.Parse(oidB));
37+
38+
subject1.CompareTo(subject2).Should().Be(result);
39+
}
40+
41+
[Test]
42+
public void Equals_should_return_false_if_any_field_is_not_equal()
43+
{
44+
var subject1 = new ElectionId(ObjectId.Empty);
45+
var subject2 = new ElectionId(ObjectId.GenerateNewId());
46+
subject1.Equals(subject2).Should().BeFalse();
47+
subject1.Equals((object)subject2).Should().BeFalse();
48+
subject1.GetHashCode().Should().NotBe(subject2.GetHashCode());
49+
}
50+
51+
[Test]
52+
public void Equals_should_return_true_if_all_fiels_are_equal()
53+
{
54+
var subject1 = new ElectionId(ObjectId.Empty);
55+
var subject2 = new ElectionId(ObjectId.Empty);
56+
subject1.Equals(subject2).Should().BeTrue();
57+
subject1.Equals((object)subject2).Should().BeTrue();
58+
subject1.GetHashCode().Should().Be(subject2.GetHashCode());
59+
}
60+
61+
[Test]
62+
public void ToString_should_return_string_representation()
63+
{
64+
var subject = new ElectionId(ObjectId.Empty);
65+
subject.ToString().Should().Be(ObjectId.Empty.ToString());
66+
}
67+
}
68+
}

src/MongoDB.Driver.Core.Tests/Core/Clusters/MultiServerClusterTests.cs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
using MongoDB.Driver.Core.Helpers;
2828
using NSubstitute;
2929
using NUnit.Framework;
30+
using MongoDB.Bson;
3031

3132
namespace MongoDB.Driver.Core.Clusters
3233
{
@@ -73,7 +74,7 @@ public void Constructor_should_throw_if_cluster_connection_mode_is_not_supported
7374
[Test]
7475
public void Description_should_be_correct_after_initialization()
7576
{
76-
_settings = _settings.With(endPoints: new [] { _firstEndPoint });
77+
_settings = _settings.With(endPoints: new[] { _firstEndPoint });
7778

7879
var subject = CreateSubject();
7980
subject.Initialize();
@@ -87,7 +88,7 @@ public void Description_should_be_correct_after_initialization()
8788
[Test]
8889
public void Initialize_should_throw_when_already_disposed()
8990
{
90-
_settings = _settings.With(endPoints: new [] { _firstEndPoint });
91+
_settings = _settings.With(endPoints: new[] { _firstEndPoint });
9192
var subject = CreateSubject();
9293
subject.Dispose();
9394

@@ -137,7 +138,7 @@ public void Should_remove_a_server_that_is_no_longer_in_the_primary_host_list()
137138
subject.Initialize();
138139

139140
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary,
140-
hosts: new [] { _firstEndPoint, _secondEndPoint });
141+
hosts: new[] { _firstEndPoint, _secondEndPoint });
141142

142143
var description = subject.Description;
143144
description.State.Should().Be(ClusterState.Connected);
@@ -249,7 +250,7 @@ public void Should_ignore_changes_from_a_ReplicaSetGhost()
249250
subject.Initialize();
250251

251252
PublishDescription(_firstEndPoint, ServerType.ReplicaSetGhost,
252-
hosts: new [] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
253+
hosts: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
253254

254255
var description = subject.Description;
255256
description.Servers.Should().BeEquivalentTo(GetDescriptions(_firstEndPoint));
@@ -289,7 +290,7 @@ public void Should_remove_server_from_the_seed_list_that_is_not_in_the_hosts_lis
289290
}
290291

291292
[Test]
292-
public void Should_invalidate_existing_primary_when_a_new_primary_shows_up()
293+
public void Should_invalidate_existing_primary_when_a_new_primary_shows_up_and_current_election_id_is_null()
293294
{
294295
_settings = _settings.With(endPoints: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
295296

@@ -305,6 +306,57 @@ public void Should_invalidate_existing_primary_when_a_new_primary_shows_up()
305306
.Concat(GetDescriptions(_secondEndPoint, _thirdEndPoint)));
306307
}
307308

309+
[Test]
310+
public void Should_invalidate_existing_primary_when_a_new_primary_shows_up_with_an_election_id_and_current_id_is_null()
311+
{
312+
_settings = _settings.With(endPoints: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
313+
314+
var subject = CreateSubject();
315+
subject.Initialize();
316+
317+
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary);
318+
PublishDescription(_secondEndPoint, ServerType.ReplicaSetPrimary, electionId: new ElectionId(ObjectId.GenerateNewId()));
319+
320+
var description = subject.Description;
321+
description.Servers.Should().BeEquivalentTo(
322+
new[] { GetDisconnectedDescription(_firstEndPoint) }
323+
.Concat(GetDescriptions(_secondEndPoint, _thirdEndPoint)));
324+
}
325+
326+
[Test]
327+
public void Should_invalidate_existing_primary_when_a_new_primary_shows_up_with_a_higher_election_id()
328+
{
329+
_settings = _settings.With(endPoints: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
330+
331+
var subject = CreateSubject();
332+
subject.Initialize();
333+
334+
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary, electionId: new ElectionId(ObjectId.Empty));
335+
PublishDescription(_secondEndPoint, ServerType.ReplicaSetPrimary, electionId: new ElectionId(ObjectId.GenerateNewId()));
336+
337+
var description = subject.Description;
338+
description.Servers.Should().BeEquivalentTo(
339+
new[] { GetDisconnectedDescription(_firstEndPoint) }
340+
.Concat(GetDescriptions(_secondEndPoint, _thirdEndPoint)));
341+
}
342+
343+
[Test]
344+
public void Should_invalidate_new_primary_when_it_shows_up_with_a_lesser_election_id()
345+
{
346+
_settings = _settings.With(endPoints: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
347+
348+
var subject = CreateSubject();
349+
subject.Initialize();
350+
351+
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary, electionId: new ElectionId(ObjectId.GenerateNewId()));
352+
PublishDescription(_secondEndPoint, ServerType.ReplicaSetPrimary, electionId: new ElectionId(ObjectId.Empty));
353+
354+
var description = subject.Description;
355+
description.Servers.Should().BeEquivalentTo(
356+
new[] { GetDisconnectedDescription(_secondEndPoint) }
357+
.Concat(GetDescriptions(_firstEndPoint, _thirdEndPoint)));
358+
}
359+
308360
[Test]
309361
public void Should_ignore_a_notification_from_a_server_which_has_been_removed()
310362
{
@@ -314,7 +366,7 @@ public void Should_ignore_a_notification_from_a_server_which_has_been_removed()
314366
subject.Initialize();
315367

316368
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary,
317-
hosts: new [] { _firstEndPoint, _secondEndPoint });
369+
hosts: new[] { _firstEndPoint, _secondEndPoint });
318370

319371
PublishDescription(_thirdEndPoint, ServerType.ReplicaSetPrimary);
320372

@@ -335,7 +387,7 @@ public void Should_call_initialize_on_all_servers()
335387
PublishDescription(_firstEndPoint, ServerType.ReplicaSetPrimary,
336388
hosts: new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint });
337389

338-
foreach(var endPoint in new [] { _firstEndPoint, _secondEndPoint, _thirdEndPoint })
390+
foreach (var endPoint in new[] { _firstEndPoint, _secondEndPoint, _thirdEndPoint })
339391
{
340392
var server = _serverFactory.GetServer(endPoint);
341393
server.Received().Initialize();
@@ -397,7 +449,7 @@ private void PublishDisconnectedDescription(EndPoint endPoint)
397449
_serverFactory.PublishDescription(description);
398450
}
399451

400-
private void PublishDescription(EndPoint endPoint, ServerType serverType, IEnumerable<EndPoint> hosts = null, string setName = null, EndPoint primary = null)
452+
private void PublishDescription(EndPoint endPoint, ServerType serverType, IEnumerable<EndPoint> hosts = null, string setName = null, EndPoint primary = null, ElectionId electionId = null)
401453
{
402454
var current = _serverFactory.GetServerDescription(endPoint);
403455

@@ -410,6 +462,7 @@ private void PublishDescription(EndPoint endPoint, ServerType serverType, IEnume
410462
var description = current.With(
411463
averageRoundTripTime: TimeSpan.FromMilliseconds(10),
412464
replicaSetConfig: serverType.IsReplicaSetMember() ? config : null,
465+
electionId: electionId,
413466
state: ServerState.Connected,
414467
tags: null,
415468
type: serverType,

src/MongoDB.Driver.Core.Tests/Core/Connections/IsMasterResultTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ public void Equals_should_be_false_when_both_have_different_results()
6363
subject1.Equals(subject2).Should().BeFalse();
6464
}
6565

66+
[Test]
67+
[TestCase("{ }", null)]
68+
[TestCase("{ electionId: ObjectId('555925bfb69aa7d5be29126b') }", "555925bfb69aa7d5be29126b")]
69+
public void ElectionId_should_parse_document_correctly(string json, string expectedObjectId)
70+
{
71+
var subject = new IsMasterResult(BsonDocument.Parse(json));
72+
var expected = expectedObjectId == null ? (ElectionId)null : new ElectionId(ObjectId.Parse(expectedObjectId));
73+
74+
subject.ElectionId.Should().Be(expected);
75+
}
76+
6677
[Test]
6778
[TestCase("{ maxWriteBatchSize: 100 }", 100)]
6879
[TestCase("{ maxWriteBatchSize: 0 }", 0)]

src/MongoDB.Driver.Core.Tests/Core/Servers/ServerDescriptionTests.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void Constructor_with_serverId_and_endPoint_only_should_return_disconnect
4848
{
4949
var subject = new ServerDescription(__serverId, __endPoint);
5050
subject.AverageRoundTripTime.Should().Be(TimeSpan.Zero);
51+
subject.ElectionId.Should().BeNull();
5152
subject.EndPoint.Should().Be(__endPoint);
5253
subject.ReplicaSetConfig.Should().BeNull();
5354
subject.ServerId.Should().Be(__serverId);
@@ -62,13 +63,14 @@ public void Constructor_with_serverId_and_endPoint_only_should_return_disconnect
6263
public void Constructor_with_multiple_parameters_should_return_properly_initialized_instance()
6364
{
6465
var averageRoundTripTime = TimeSpan.FromSeconds(1);
66+
var electionId = new ElectionId(ObjectId.GenerateNewId());
6567
var replicaSetConfig = new ReplicaSetConfig(
66-
new [] { new DnsEndPoint("localhost", 27017), new DnsEndPoint("localhost", 27018) },
68+
new[] { new DnsEndPoint("localhost", 27017), new DnsEndPoint("localhost", 27018) },
6769
"name",
6870
new DnsEndPoint("localhost", 27017),
6971
1);
7072
var state = ServerState.Connected;
71-
var tags = new TagSet(new [] { new Tag("x", "a") });
73+
var tags = new TagSet(new[] { new Tag("x", "a") });
7274
var type = ServerType.ReplicaSetPrimary;
7375
var version = new SemanticVersion(2, 6, 3);
7476
var wireVersionRange = new Range<int>(2, 3);
@@ -79,12 +81,14 @@ public void Constructor_with_multiple_parameters_should_return_properly_initiali
7981
state: state,
8082
type: type,
8183
averageRoundTripTime: averageRoundTripTime,
84+
electionId: electionId,
8285
replicaSetConfig: replicaSetConfig,
8386
tags: tags,
8487
version: version,
8588
wireVersionRange: wireVersionRange);
8689

8790
subject.AverageRoundTripTime.Should().Be(TimeSpan.FromSeconds(1));
91+
subject.ElectionId.Should().Be(electionId);
8892
subject.EndPoint.Should().Be(__endPoint);
8993
subject.ReplicaSetConfig.Should().Be(replicaSetConfig);
9094
subject.ServerId.Should().Be(__serverId);
@@ -93,8 +97,8 @@ public void Constructor_with_multiple_parameters_should_return_properly_initiali
9397
subject.Type.Should().Be(type);
9498
}
9599

96-
97100
[TestCase("AverageRoundTripTime")]
101+
[TestCase("ElectionId")]
98102
[TestCase("EndPoint")]
99103
[TestCase("ReplicaSetConfig")]
100104
[TestCase("ServerId")]
@@ -106,6 +110,7 @@ public void Constructor_with_multiple_parameters_should_return_properly_initiali
106110
public void Equals_should_return_false_when_any_field_is_not_equal(string notEqualField)
107111
{
108112
var averageRoundTripTime = TimeSpan.FromSeconds(1);
113+
var electionId = new ElectionId(ObjectId.GenerateNewId());
109114
var endPoint = new DnsEndPoint("localhost", 27017);
110115
var replicaSetConfig = new ReplicaSetConfig(
111116
new[] { new DnsEndPoint("localhost", 27017), new DnsEndPoint("localhost", 27018) },
@@ -133,6 +138,7 @@ public void Equals_should_return_false_when_any_field_is_not_equal(string notEqu
133138
switch (notEqualField)
134139
{
135140
case "AverageRoundTripTime": averageRoundTripTime = averageRoundTripTime.Add(TimeSpan.FromSeconds(1)); break;
141+
case "ElectionId": electionId = new ElectionId(ObjectId.Empty); break;
136142
case "EndPoint": endPoint = new DnsEndPoint(endPoint.Host, endPoint.Port + 1); serverId = new ServerId(__clusterId, endPoint); break;
137143
case "ReplicaSetConfig": replicaSetConfig = new ReplicaSetConfig(replicaSetConfig.Members, "newname", replicaSetConfig.Primary, replicaSetConfig.Version); break;
138144
case "State": state = ServerState.Disconnected; break;
@@ -149,6 +155,7 @@ public void Equals_should_return_false_when_any_field_is_not_equal(string notEqu
149155
state: state,
150156
type: type,
151157
averageRoundTripTime: averageRoundTripTime,
158+
electionId: electionId,
152159
replicaSetConfig: replicaSetConfig,
153160
tags: tags,
154161
version: version,
@@ -170,6 +177,7 @@ public void Equals_should_return_true_when_all_fields_are_equal()
170177
}
171178

172179
[TestCase("AverageRoundTripTime")]
180+
[TestCase("ElectionId")]
173181
[TestCase("ReplicaSetConfig")]
174182
[TestCase("Tags")]
175183
[TestCase("Type")]
@@ -178,6 +186,7 @@ public void Equals_should_return_true_when_all_fields_are_equal()
178186
public void WithHeartbeat_should_return_new_instance_when_a_field_is_not_equal(string notEqualField)
179187
{
180188
var averageRoundTripTime = TimeSpan.FromSeconds(1);
189+
var electionId = new ElectionId(ObjectId.GenerateNewId());
181190
var replicaSetConfig = new ReplicaSetConfig(
182191
new[] { new DnsEndPoint("localhost", 27017), new DnsEndPoint("localhost", 27018) },
183192
"name",
@@ -195,6 +204,7 @@ public void WithHeartbeat_should_return_new_instance_when_a_field_is_not_equal(s
195204
state: state,
196205
type: type,
197206
averageRoundTripTime: averageRoundTripTime,
207+
electionId: electionId,
198208
replicaSetConfig: replicaSetConfig,
199209
tags: tags,
200210
version: version,
@@ -203,6 +213,7 @@ public void WithHeartbeat_should_return_new_instance_when_a_field_is_not_equal(s
203213
switch (notEqualField)
204214
{
205215
case "AverageRoundTripTime": averageRoundTripTime = averageRoundTripTime.Add(TimeSpan.FromSeconds(1)); break;
216+
case "ElectionId": electionId = new ElectionId(ObjectId.Empty); break;
206217
case "ReplicaSetConfig": replicaSetConfig = new ReplicaSetConfig(replicaSetConfig.Members, "newname", replicaSetConfig.Primary, replicaSetConfig.Version); break;
207218
case "Tags": tags = new TagSet(new[] { new Tag("x", "b") }); break;
208219
case "Type": type = ServerType.ReplicaSetSecondary; break;
@@ -214,6 +225,7 @@ public void WithHeartbeat_should_return_new_instance_when_a_field_is_not_equal(s
214225
averageRoundTripTime: averageRoundTripTime,
215226
replicaSetConfig: replicaSetConfig,
216227
state: ServerState.Connected,
228+
electionId: electionId,
217229
tags: tags,
218230
type: type,
219231
version: version,

0 commit comments

Comments
 (0)