예제 #1
0
        public void GetEncoder_should_return_encoder()
        {
            var subject = new QueryMessage(_requestId, _collectionNamespace, _query, _fields, _queryValidator, _skip, _batchSize, false, false, false, false, false, false);
            var mockEncoderFactory = new Mock<IMessageEncoderFactory>();
            var encoder = new Mock<IMessageEncoder>().Object;
            mockEncoderFactory.Setup(f => f.GetQueryMessageEncoder()).Returns(encoder);

            var result = subject.GetEncoder(mockEncoderFactory.Object);

            result.Should().BeSameAs(encoder);
        }
        public void GetEncoder_should_return_encoder()
        {
            var subject = new QueryMessage(_requestId, _collectionNamespace, _query, _fields, _queryValidator, _skip, _batchSize, false, false, false, false, false);
            var stubEncoderFactory = Substitute.For<IMessageEncoderFactory>();
            var stubEncoder = Substitute.For<IMessageEncoder>();
            stubEncoderFactory.GetQueryMessageEncoder().Returns(stubEncoder);

            var result = subject.GetEncoder(stubEncoderFactory);

            result.Should().BeSameAs(stubEncoder);
        }
 public void Constructor_should_initialize_instance(bool awaitData, bool noCursorTimeout, bool partialOk, bool slaveOk, bool tailableCursor)
 {
     var subject = new QueryMessage(_requestId, _collectionNamespace, _query, _fields, _queryValidator, _skip, _batchSize, slaveOk, partialOk, noCursorTimeout, tailableCursor, awaitData);
     subject.AwaitData.Should().Be(awaitData);
     subject.BatchSize.Should().Be(_batchSize);
     subject.CollectionNamespace.Should().Be(_collectionNamespace);
     subject.Fields.Should().Be(_fields);
     subject.NoCursorTimeout.Should().Be(noCursorTimeout);
     subject.PartialOk.Should().Be(partialOk);
     subject.Query.Should().Be(_query);
     subject.RequestId.Should().Be(_requestId);
     subject.SlaveOk.Should().Be(slaveOk);
     subject.TailableCursor.Should().Be(tailableCursor);
 }
        // static constructor
        static QueryMessageBinaryEncoderTests()
        {
            __testMessage = new QueryMessage(__requestId, __collectionNamespace, __query, __fields, __queryValidator, __skip, __batchSize, __slaveOk, __partialOk, __noCursorTimeout, __oplogReplay, __tailableCursor, __awaitData);

            __testMessageBytes = new byte[]
            {
                0, 0, 0, 0, // messageLength
                1, 0, 0, 0, // requestId
                0, 0, 0, 0, // responseTo
                212, 7, 0, 0, // opcode = 2004
                190, 0, 0, 0, // flags
                (byte)'d', (byte)'.', (byte)'c', 0, // fullCollectionName
                2, 0, 0, 0, // numberToSkip
                3, 0, 0, 0, // numberToReturn
                12, 0, 0, 0, 0x10, (byte)'x', 0, 1, 0, 0, 0, 0, // query
                12, 0, 0, 0, 0x10, (byte)'f', 0, 1, 0, 0, 0, 0 // fields
            };
            __testMessageBytes[0] = (byte)__testMessageBytes.Length;
            __flagsOffset = 16;
        }
        // static constructor
        static QueryMessageJsonEncoderTests()
        {
            __testMessage = new QueryMessage(__requestId, __collectionNamespace, __query, __fields, __queryValidator, __skip, __batchSize, __slaveOk, __partialOk, __noCursorTimeout, __tailableCursor, __awaitData);

            __testMessageJson =
                "{ " +
                    "\"opcode\" : \"query\", " +
                    "\"requestId\" : 1, " +
                    "\"database\" : \"d\", " +
                    "\"collection\" : \"c\", " +
                    "\"fields\" : { \"f\" : 1 }, " +
                    "\"skip\" : 2, " +
                    "\"batchSize\" : 3, " +
                    "\"slaveOk\" : true, " +
                    "\"partialOk\" : true, " +
                    "\"noCursorTimeout\" : true, " +
                    "\"tailableCursor\" : true, " +
                    "\"awaitData\" : true, " +
                    "\"query\" : { \"x\" : 1 }" +
                " }";
        }
        public void WriteMessage_should_encode_flags_correctly(int flags, bool tailableCursor, bool slaveOk, bool noCursorTimeout, bool oplogReplay, bool awaitData, bool partialOk)
        {
            var message = new QueryMessage(__requestId, __collectionNamespace, __query, __fields, __queryValidator, __skip, __batchSize, slaveOk, partialOk, noCursorTimeout, oplogReplay, tailableCursor, awaitData);

            using (var stream = new MemoryStream())
            {
                var subject = new QueryMessageBinaryEncoder(stream, __messageEncoderSettings);
                subject.WriteMessage(message);
                var bytes = stream.ToArray();
                bytes[__flagsOffset].Should().Be((byte)flags);
            }
        }
        private BsonDocument BuildFindCommandFromQuery(QueryMessage message)
        {
            var batchSize = EventContext.FindOperationBatchSize ?? 0;
            var limit = EventContext.FindOperationLimit ?? 0;
            var command = new BsonDocument
            {
                { "find", message.CollectionNamespace.CollectionName },
                { "projection", message.Fields, message.Fields != null },
                { "skip", message.Skip, message.Skip > 0 },
                { "batchSize", batchSize, batchSize > 0 },
                { "limit", limit, limit != 0 },
                { "awaitData", message.AwaitData, message.AwaitData },
                { "noCursorTimeout", message.NoCursorTimeout, message.NoCursorTimeout },
                { "allowPartialResults", message.PartialOk, message.PartialOk },
                { "tailable", message.TailableCursor, message.TailableCursor },
                { "oplogReplay", message.OplogReplay, message.OplogReplay }
            };

            var query = message.Query;
            if (query.ElementCount == 1 && !query.Contains("$query"))
            {
                command["filter"] = query;
            }
            else
            {
                foreach (var element in query)
                {
                    switch (element.Name)
                    {
                        case "$query":
                            command["filter"] = element.Value;
                            break;
                        case "$orderby":
                            command["sort"] = element.Value;
                            break;
                        case "$showDiskLoc":
                            command["showRecordId"] = element.Value;
                            break;
                        case "$explain":
                            // explain is special and gets handled elsewhere
                            break;
                        default:
                            if (element.Name.StartsWith("$"))
                            {
                                command[element.Name.Substring(1)] = element.Value;
                            }
                            else
                            {
                                // theoretically, this should never happen and is illegal.
                                // however, we'll push this up anyways and a command-failure
                                // event will likely get thrown.
                                command[element.Name] = element.Value;
                            }
                            break;
                    }
                }
            }

            return command;
        }
        private void ProcessQueryMessage(QueryMessage originalMessage, ConnectionId connectionId, QueryMessageBinaryEncoder encoder, Stopwatch stopwatch)
        {
            var requestId = originalMessage.RequestId;
            var operationId = EventContext.OperationId;

            var decodedMessage = encoder.ReadMessage(RawBsonDocumentSerializer.Instance);
            try
            {
                var isCommand = IsCommand(decodedMessage.CollectionNamespace);
                string commandName;
                BsonDocument command;
                if (isCommand)
                {
                    command = decodedMessage.Query;
                    var firstElement = command.GetElement(0);
                    commandName = firstElement.Name;
                    if (__securitySensitiveCommands.Contains(commandName))
                    {
                        command = new BsonDocument();
                    }
                }
                else
                {
                    commandName = "find";
                    command = BuildFindCommandFromQuery(decodedMessage);
                    if (decodedMessage.Query.GetValue("$explain", false).ToBoolean())
                    {
                        commandName = "explain";
                        command = new BsonDocument("explain", command);
                    }
                }

                if (_startedEvent != null)
                {
                    var @event = new CommandStartedEvent(
                        commandName,
                        command,
                        decodedMessage.CollectionNamespace.DatabaseNamespace,
                        operationId,
                        requestId,
                        connectionId);

                    _startedEvent(@event);
                }

                if (_shouldTrackState)
                {
                    _state.TryAdd(requestId, new CommandState
                    {
                        CommandName = commandName,
                        OperationId = operationId,
                        Stopwatch = stopwatch,
                        QueryNamespace = decodedMessage.CollectionNamespace,
                        ExpectedResponseType = isCommand ? ExpectedResponseType.Command : ExpectedResponseType.Query
                    });
                }
            }
            finally
            {
                var disposable = decodedMessage.Query as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
                disposable = decodedMessage.Fields as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
        }
        public void GetEncoder_should_return_encoder()
        {
            var mockEncoder = Substitute.For<IMessageEncoder<QueryMessage>>();
            var mockEncoderFactory = Substitute.For<IMessageEncoderFactory>();
            mockEncoderFactory.GetQueryMessageEncoder().Returns(mockEncoder);

            var subject = new QueryMessage(_requestId, _databaseName, _collectionName, _query, _fields, _skip, _batchSize, false, false, false, false, false);
            var encoder = subject.GetEncoder(mockEncoderFactory);
            encoder.Should().BeSameAs(mockEncoder);
        }