public void Should_GenerateNewSessionId_When_SessionIsCreated()
        {
            var sessionNames       = new ConcurrentQueue <string>();
            var sessionFactoryMock = Mock.Of <ISessionFactory>();

            Mock.Get(sessionFactoryMock).Setup(s =>
                                               s.CreateSessionAsync(It.IsAny <IInternalCluster>(), It.IsAny <string>(), It.IsAny <ISerializerManager>(), It.IsAny <string>()))
            .ReturnsAsync(Mock.Of <IInternalSession>())
            .Callback <IInternalCluster, string, ISerializerManager, string>((c, ks, serializer, name) => { sessionNames.Enqueue(name); });

            var config = new TestConfigurationBuilder
            {
                Policies = new Cassandra.Policies(
                    new RoundRobinPolicy(),
                    new ConstantReconnectionPolicy(100),
                    new DefaultRetryPolicy()),
                SessionFactory           = sessionFactoryMock,
                ControlConnectionFactory = new FakeControlConnectionFactory(),
                ConnectionFactory        = new FakeConnectionFactory()
            }.Build();

            var initializer = Mock.Of <IInitializer>();

            Mock.Get(initializer).Setup(i => i.ContactPoints).Returns(new IPEndPoint[0]);
            Mock.Get(initializer).Setup(i => i.GetConfiguration()).Returns(config);
            using (var cluster = Cluster.BuildFrom(initializer, new[] { "127.0.0.1" }, config))
            {
                var target = cluster.Connect();
                Assert.IsTrue(sessionNames.TryDequeue(out var sessionId));
                var newTarget = cluster.Connect();
                Assert.IsTrue(sessionNames.TryDequeue(out var newSessionId));
                Assert.AreEqual(0, sessionNames.Count);
                Assert.AreNotEqual(Guid.Empty, sessionId);
                Assert.AreNotEqual(sessionId, newSessionId);
            }
        }
        public void Should_NotThrowException_When_AValidHostIsObtained(bool currentHostRetry)
        {
            var mockSession           = Mock.Of <IInternalSession>();
            var requestHandlerFactory = Mock.Of <IRequestHandlerFactory>();

            Mock.Get(requestHandlerFactory)
            .Setup(r => r.Create(
                       It.IsAny <IInternalSession>(),
                       It.IsAny <Serializer>(),
                       It.IsAny <IRequest>(),
                       It.IsAny <IStatement>(),
                       It.IsAny <IRequestOptions>()))
            .Returns(Mock.Of <IRequestHandler>());
            var config = new TestConfigurationBuilder
            {
                RequestHandlerFactory = requestHandlerFactory
            }.Build();

            Mock.Get(mockSession).SetupGet(m => m.Cluster.Configuration).Returns(config);
            var mockRequest          = Mock.Of <IRequest>();
            var mockRequestExecution = Mock.Of <IRequestHandler>();
            var host = new Host(
                new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9047),
                new ConstantReconnectionPolicy(1));
            var validHost = ValidHost.New(
                host,
                HostDistance.Local);

            Mock.Get(mockRequestExecution)
            .SetupSequence(m => m.GetNextValidHost(It.IsAny <Dictionary <IPEndPoint, Exception> >()))
            .Returns(validHost)
            .Throws(new NoHostAvailableException(new Dictionary <IPEndPoint, Exception>()));
            var sut = new RequestExecution(mockRequestExecution, mockSession, mockRequest);

            sut.Start(currentHostRetry);
        }
        public void Should_RetryRequestToSameHost_When_ConnectionFailsAndRetryDecisionIsRetrySameHost()
        {
            var mockSession           = Mock.Of <IInternalSession>();
            var requestHandlerFactory = Mock.Of <IRequestHandlerFactory>();

            Mock.Get(requestHandlerFactory)
            .Setup(r => r.Create(
                       It.IsAny <IInternalSession>(),
                       It.IsAny <Serializer>(),
                       It.IsAny <IRequest>(),
                       It.IsAny <IStatement>()))
            .Returns(Mock.Of <IRequestHandler>());
            var config = new TestConfigurationBuilder
            {
                RequestHandlerFactory = requestHandlerFactory
            }.Build();

            Mock.Get(mockSession).SetupGet(m => m.Cluster.Configuration).Returns(config);
            Mock.Get(mockSession).SetupGet(m => m.Configuration).Returns(config);
            var mockRequest = Mock.Of <IRequest>();
            var mockParent  = Mock.Of <IRequestHandler>();
            var connection  = Mock.Of <IConnection>();

            // Setup hosts
            var host = new Host(
                new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9047),
                new ConstantReconnectionPolicy(1));
            var validHost = ValidHost.New(
                host,
                HostDistance.Local);
            var secondHost = new Host(
                new IPEndPoint(IPAddress.Parse("127.0.0.2"), 9047),
                new ConstantReconnectionPolicy(1)); // second host should never be used if test passes
            var secondValidHost = ValidHost.New(
                secondHost,
                HostDistance.Local);

            // Setup query plan
            Mock.Get(mockParent)
            .SetupSequence(m => m.GetNextValidHost(It.IsAny <Dictionary <IPEndPoint, Exception> >()))
            .Returns(validHost)
            .Returns(secondValidHost);

            // Setup retry policy
            var exception = new OverloadedException(string.Empty);

            Mock.Get(mockParent)
            .SetupGet(m => m.RetryPolicy)
            .Returns(() =>
                     Mock.Of <IExtendedRetryPolicy>(a =>
                                                    a.OnRequestError(
                                                        It.IsAny <IStatement>(), config, exception, 0)
                                                    == RetryDecision.Retry(null, true)));

            // Setup connection failure
            Mock.Get(mockParent)
            .Setup(m => m.GetConnectionToValidHostAsync(validHost, It.IsAny <Dictionary <IPEndPoint, Exception> >()))
            .ThrowsAsync(exception);

            // Setup successful second connection on the same host retry (different method call - ValidateHostAndGetConnectionAsync)
            Mock.Get(mockParent)
            .Setup(m => m.ValidateHostAndGetConnectionAsync(validHost.Host, It.IsAny <Dictionary <IPEndPoint, Exception> >()))
            .ReturnsAsync(connection);

            var sut = new RequestExecution(mockParent, mockSession, mockRequest);

            sut.Start(false);

            // Validate request is sent
            TestHelper.RetryAssert(
                () =>
            {
                Mock.Get(connection).Verify(
                    c => c.Send(mockRequest, It.IsAny <Action <Exception, Response> >(), It.IsAny <int>()),
                    Times.Once);
            });

            // Validate that there were 2 connection attempts (1 with each method)
            Mock.Get(mockParent).Verify(
                m => m.GetConnectionToValidHostAsync(validHost, It.IsAny <Dictionary <IPEndPoint, Exception> >()),
                Times.Once);
            Mock.Get(mockParent).Verify(
                m => m.ValidateHostAndGetConnectionAsync(validHost.Host, It.IsAny <Dictionary <IPEndPoint, Exception> >()),
                Times.Once);
        }
Beispiel #4
0
        public void Should_UpdateKeyspacesAndTokenMapCorrectly_When_MultipleThreadsCallingRefreshKeyspace()
        {
            var keyspaces = new ConcurrentDictionary <string, KeyspaceMetadata>();

            // unique configurations
            keyspaces.AddOrUpdate("ks1", FakeSchemaParserFactory.CreateSimpleKeyspace("ks1", 2), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks2", FakeSchemaParserFactory.CreateSimpleKeyspace("ks2", 10), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks3", FakeSchemaParserFactory.CreateSimpleKeyspace("ks3", 5), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks4", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks4", new Dictionary <string, int> {
                { "dc1", 2 }, { "dc2", 2 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks5", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks5", new Dictionary <string, int> {
                { "dc1", 1 }, { "dc2", 2 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks6", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks6", new Dictionary <string, int> {
                { "dc1", 1 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);

            // duplicate configurations
            keyspaces.AddOrUpdate("ks7", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks7", new Dictionary <string, int> {
                { "dc1", 2 }, { "dc2", 2 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks8", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks8", new Dictionary <string, int> {
                { "dc1", 1 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks9", FakeSchemaParserFactory.CreateNetworkTopologyKeyspace("ks9", new Dictionary <string, int> {
                { "dc1", 1 }, { "dc2", 2 }
            }), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks10", FakeSchemaParserFactory.CreateSimpleKeyspace("ks10", 10), (s, keyspaceMetadata) => keyspaceMetadata);
            keyspaces.AddOrUpdate("ks11", FakeSchemaParserFactory.CreateSimpleKeyspace("ks11", 2), (s, keyspaceMetadata) => keyspaceMetadata);

            var schemaParser = new FakeSchemaParser(keyspaces);
            var config       = new TestConfigurationBuilder
            {
                ConnectionFactory = new FakeConnectionFactory()
            }.Build();
            var metadata = new Metadata(config, schemaParser)
            {
                Partitioner = "Murmur3Partitioner"
            };

            metadata.ControlConnection = new ControlConnection(
                Mock.Of <IInternalCluster>(),
                new ProtocolEventDebouncer(new TaskBasedTimerFactory(), TimeSpan.FromMilliseconds(20), TimeSpan.FromSeconds(100)),
                ProtocolVersion.V3,
                config,
                metadata,
                new List <IContactPoint>
            {
                new IpLiteralContactPoint(IPAddress.Parse("127.0.0.1"), config.ProtocolOptions, config.ServerNameResolver)
            });
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.1"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.2"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.3"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.4"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.5"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.6"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.7"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.8"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.9"), 9042));
            metadata.Hosts.Add(new IPEndPoint(IPAddress.Parse("192.168.0.10"), 9042));
            var initialToken = 1;

            foreach (var h in metadata.Hosts)
            {
                h.SetInfo(new TestHelper.DictionaryBasedRow(new Dictionary <string, object>
                {
                    { "data_center", initialToken % 2 == 0 ? "dc1" : "dc2" },
                    { "rack", "rack1" },
                    { "tokens", GenerateTokens(initialToken, 256) },
                    { "release_version", "3.11.1" }
                }));
                initialToken++;
            }
            metadata.RebuildTokenMapAsync(false, true).GetAwaiter().GetResult();
            var expectedTokenMap = metadata.TokenToReplicasMap;

            Assert.NotNull(expectedTokenMap);
            var bag   = new ConcurrentBag <string>();
            var tasks = new List <Task>();

            for (var i = 0; i < 100; i++)
            {
                var index = i;
                tasks.Add(Task.Factory.StartNew(
                              () =>
                {
                    for (var j = 0; j < 35; j++)
                    {
                        if (j % 10 == 0 && index % 2 == 0)
                        {
                            metadata.RefreshSchemaAsync().GetAwaiter().GetResult();
                        }
                        else if (j % 16 == 0)
                        {
                            if (bag.TryTake(out var ksName))
                            {
                                if (keyspaces.TryRemove(ksName, out var ks))
                                {
                                    metadata.RefreshSchemaAsync(ksName).GetAwaiter().GetResult();
                                    ks = metadata.GetKeyspace(ksName);
                                    if (ks != null)
                                    {
                                        throw new Exception($"refresh for {ks.Name} returned non null after refresh single.");
                                    }
                                }
                            }
                        }
                        else
                        if (j % 2 == 0)
                        {
                            if (bag.TryTake(out var ksName))
                            {
                                if (keyspaces.TryRemove(ksName, out var ks))
                                {
                                    metadata.ControlConnection.HandleKeyspaceRefreshLaterAsync(ks.Name).GetAwaiter().GetResult();
                                    ks = metadata.GetKeyspace(ksName);
                                    if (ks != null)
                                    {
                                        throw new Exception($"refresh for {ks.Name} returned non null after remove.");
                                    }
                                }
                            }
                        }
                        else
                        {
                            var keyspaceName = $"ks_____{index}_____{j}";
                            var ks           = FakeSchemaParserFactory.CreateSimpleKeyspace(keyspaceName, (index * j) % 10);
                            keyspaces.AddOrUpdate(
                                keyspaceName,
                                ks,
                                (s, keyspaceMetadata) => ks);
                            metadata.ControlConnection.HandleKeyspaceRefreshLaterAsync(ks.Name).GetAwaiter().GetResult();
                            ks = metadata.GetKeyspace(ks.Name);
                            if (ks == null)
                            {
                                throw new Exception($"refresh for {keyspaceName} returned null after add.");
                            }
                            bag.Add(keyspaceName);
                        }
                    }
                },
                              TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach));
            }
            Task.WaitAll(tasks.ToArray());
            AssertSameReplicas(keyspaces.Values, expectedTokenMap, metadata.TokenToReplicasMap);
        }