PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/MongoDB.Driver.Core.Tests/Specifications/server-discovery-and-monitoring/TestRunner.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 221 lines | 186 code | 21 blank | 14 comment | 7 complexity | 10f54f9bcf816feea3bf5a7209e6ea4d MD5 | raw file
Possible License(s): Apache-2.0
  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. using System.Collections.Generic;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Net;
  19. using System.Reflection;
  20. using FluentAssertions;
  21. using MongoDB.Bson;
  22. using MongoDB.Driver.Core.Clusters;
  23. using MongoDB.Driver.Core.Configuration;
  24. using MongoDB.Driver.Core.Connections;
  25. using MongoDB.Driver.Core.Events;
  26. using MongoDB.Driver.Core.Helpers;
  27. using MongoDB.Driver.Core.Misc;
  28. using MongoDB.Driver.Core.Servers;
  29. using NSubstitute;
  30. using NUnit.Framework;
  31. namespace MongoDB.Driver.Specifications.server_discovery_and_monitoring
  32. {
  33. [TestFixture]
  34. public class TestRunner
  35. {
  36. private ICluster _cluster;
  37. private IClusterListener _clusterListener;
  38. private MockClusterableServerFactory _serverFactory;
  39. [TestCaseSource(typeof(TestCaseFactory), "GetTestCases")]
  40. public void RunTestDefinition(BsonDocument definition)
  41. {
  42. _cluster = BuildCluster(definition);
  43. _cluster.Initialize();
  44. var phases = definition["phases"].AsBsonArray;
  45. foreach (var phase in phases)
  46. {
  47. ApplyPhase(phase);
  48. }
  49. }
  50. private void ApplyPhase(BsonValue phase)
  51. {
  52. var responses = phase["responses"].AsBsonArray;
  53. foreach (var response in responses)
  54. {
  55. ApplyResponse(response);
  56. }
  57. var outcome = (BsonDocument)phase["outcome"];
  58. var topologyType = (string)outcome["topologyType"];
  59. VerifyTopology(topologyType);
  60. VerifyOutcome(outcome);
  61. }
  62. private void ApplyResponse(BsonValue response)
  63. {
  64. var server = (string)response[0];
  65. var endPoint = EndPointHelper.Parse(server);
  66. var isMasterResult = new IsMasterResult((BsonDocument)response[1]);
  67. var currentDescription = _serverFactory.GetServerDescription(endPoint);
  68. var description = currentDescription.With(
  69. state: isMasterResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected,
  70. type: isMasterResult.ServerType,
  71. replicaSetConfig: isMasterResult.GetReplicaSetConfig());
  72. _serverFactory.PublishDescription(description);
  73. }
  74. private void VerifyTopology(string topologyType)
  75. {
  76. switch (topologyType)
  77. {
  78. case "Single":
  79. _cluster.Should().BeOfType<SingleServerCluster>();
  80. break;
  81. case "ReplicaSetWithPrimary":
  82. _cluster.Should().BeOfType<MultiServerCluster>();
  83. _cluster.Description.Type.Should().Be(ClusterType.ReplicaSet);
  84. _cluster.Description.Servers.Should().ContainSingle(x => x.Type == ServerType.ReplicaSetPrimary);
  85. break;
  86. case "ReplicaSetNoPrimary":
  87. _cluster.Should().BeOfType<MultiServerCluster>();
  88. _cluster.Description.Type.Should().Be(ClusterType.ReplicaSet);
  89. _cluster.Description.Servers.Should().NotContain(x => x.Type == ServerType.ReplicaSetPrimary);
  90. break;
  91. case "Sharded":
  92. _cluster.Should().BeOfType<MultiServerCluster>();
  93. _cluster.Description.Type.Should().Be(ClusterType.Sharded);
  94. break;
  95. case "Unknown":
  96. _cluster.Description.Type.Should().Be(ClusterType.Unknown);
  97. break;
  98. default:
  99. Assert.Fail("Unexpected topology type {0}.", topologyType);
  100. break;
  101. }
  102. }
  103. private void VerifyOutcome(BsonDocument outcome)
  104. {
  105. var description = _cluster.Description;
  106. var expectedServers = outcome["servers"].AsBsonDocument.Elements.Select(x => new
  107. {
  108. EndPoint = EndPointHelper.Parse(x.Name),
  109. Description = (BsonDocument)x.Value
  110. });
  111. var actualServers = description.Servers.Select(x => x.EndPoint);
  112. actualServers.Should().BeEquivalentTo(expectedServers.Select(x => x.EndPoint));
  113. foreach (var actualServer in description.Servers)
  114. {
  115. var expectedServer = expectedServers.Single(x => x.EndPoint.Equals(actualServer.EndPoint));
  116. VerifyServer(actualServer, expectedServer.Description);
  117. }
  118. }
  119. private void VerifyServer(ServerDescription actualServer, BsonDocument expectedServer)
  120. {
  121. var type = (string)expectedServer["type"];
  122. switch (type)
  123. {
  124. case "RSPrimary":
  125. actualServer.Type.Should().Be(ServerType.ReplicaSetPrimary);
  126. break;
  127. case "RSSecondary":
  128. actualServer.Type.Should().Be(ServerType.ReplicaSetSecondary);
  129. break;
  130. case "RSArbiter":
  131. actualServer.Type.Should().Be(ServerType.ReplicaSetArbiter);
  132. break;
  133. case "RSGhost":
  134. actualServer.Type.Should().Be(ServerType.ReplicaSetGhost);
  135. break;
  136. case "RSOther":
  137. actualServer.Type.Should().Be(ServerType.ReplicaSetOther);
  138. break;
  139. case "Mongos":
  140. actualServer.Type.Should().Be(ServerType.ShardRouter);
  141. break;
  142. case "Standalone":
  143. actualServer.Type.Should().Be(ServerType.Standalone);
  144. break;
  145. default:
  146. actualServer.Type.Should().Be(ServerType.Unknown);
  147. break;
  148. }
  149. BsonValue setName;
  150. if (expectedServer.TryGetValue("setName", out setName) && !setName.IsBsonNull)
  151. {
  152. actualServer.ReplicaSetConfig.Should().NotBeNull();
  153. actualServer.ReplicaSetConfig.Name.Should().Be(setName.ToString());
  154. }
  155. }
  156. private ICluster BuildCluster(BsonDocument definition)
  157. {
  158. var connectionString = new ConnectionString((string)definition["uri"]);
  159. var settings = new ClusterSettings(
  160. endPoints: Optional.Enumerable(connectionString.Hosts),
  161. connectionMode: connectionString.Connect,
  162. replicaSetName: connectionString.ReplicaSet);
  163. _serverFactory = new MockClusterableServerFactory();
  164. _clusterListener = Substitute.For<IClusterListener>();
  165. return new ClusterFactory(settings, _serverFactory, _clusterListener)
  166. .CreateCluster();
  167. }
  168. private static class TestCaseFactory
  169. {
  170. public static IEnumerable<ITestCaseData> GetTestCases()
  171. {
  172. const string prefix = "MongoDB.Driver.Specifications.server_discovery_and_monitoring.tests.";
  173. return Assembly
  174. .GetExecutingAssembly()
  175. .GetManifestResourceNames()
  176. .Where(path => path.StartsWith(prefix) && path.EndsWith(".json"))
  177. .Select(path =>
  178. {
  179. var definition = ReadDefinition(path);
  180. var fullName = path.Remove(0, prefix.Length);
  181. var data = new TestCaseData(definition);
  182. data.Categories.Add("Specifications");
  183. data.Categories.Add("server-discovery-and-monitoring");
  184. return data
  185. .SetName(fullName.Remove(fullName.Length - 5).Replace(".", "_"))
  186. .SetDescription(definition["description"].ToString());
  187. });
  188. }
  189. private static BsonDocument ReadDefinition(string path)
  190. {
  191. using (var definitionStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path))
  192. using (var definitionStringReader = new StreamReader(definitionStream))
  193. {
  194. var definitionString = definitionStringReader.ReadToEnd();
  195. return BsonDocument.Parse(definitionString);
  196. }
  197. }
  198. }
  199. }
  200. }