Пример #1
0
        public async Task ProcessOnceAsync()
        {
            var mockLogProcessor = new Mock <ILogProcessor>();
            var web3Mock         = new Web3Mock();
            var logs             = new[] { new FilterLog() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var builder = new LogsProcessorBuilder(web3Mock.Mock.Object.Eth)
                          .Set(p => p.BlocksPerBatch     = 1)
                          .Set(p => p.MinimumBlockNumber = 0)
                          .Add(mockLogProcessor.Object);

            var processor = builder.Build();

            var result = await processor.ProcessOnceAsync(new CancellationToken());

            Assert.Equal(0, result.Value.From.Value);
            Assert.Equal(0, result.Value.To.Value);

            result = await processor.ProcessOnceAsync(new CancellationToken());

            Assert.Equal(1, result.Value.From.Value);
            Assert.Equal(1, result.Value.To.Value);

            Assert.Equal((ulong)1, await builder.BlockProgressRepository.GetLastBlockNumberProcessedAsync());
        }
Пример #2
0
 public LogOrchestratorTests()
 {
     _web3Mock        = new Web3Mock();
     _logsHandled     = new List <FilterLog>();
     _logHandler      = new ProcessorHandler <FilterLog>((filterLog) => { _logsHandled.Add(filterLog); return(Task.CompletedTask); });
     _logOrchestrator = new LogOrchestrator(_web3Mock.EthApiContractServiceMock.Object, new [] { _logHandler }, null, 100, 1);
 }
Пример #3
0
        public void Construction_FromWeb3_CreatesEthApiContractService()
        {
            var mockWeb3  = new Web3Mock();
            var processor = new LogsProcessorBuilder(mockWeb3.Web3);

            Assert.NotNull(processor.Eth);
        }
        public ContractQueryBaseTest(ContractQueryConfiguration queryConfig)
        {
            this.queryConfig = queryConfig;

            decodedEvent = DecodedEvent.Empty();

            Web3Mock web3Mock = new Web3Mock();

            var fakeResults = new List <ParameterOutput>();

            fakeResults.Add(new ParameterOutput {
                Result = FAKE_QUERY_RESULT
            });

            subscriptionState     = new EventSubscriptionStateDto();
            MockEventSubscription = new Mock <IEventSubscription>();
            MockEventSubscription.Setup(s => s.State).Returns(subscriptionState);

            contractQueryEventHandler = new ContractQueryEventHandler(MockEventSubscription.Object, 1, web3Mock.Eth, queryConfig);
            contractQueryEventHandler.QueryInterceptor = (abi, address, sig, inputs) =>
            {
                actualQueryArgs                     = new QueryArgs {
                };
                actualQueryArgs.Abi                 = abi;
                actualQueryArgs.ContractAddress     = address;
                actualQueryArgs.FunctionSignature   = sig;
                actualQueryArgs.FunctionInputValues = inputs;

                return(Task.FromResult(fakeResults));
            };
        }
Пример #5
0
        public async Task When_Cancellation_Is_Requested_Does_Not_Call_Processor()
        {
            var web3Mock          = new Web3Mock();
            var catchAllProcessor = new Mock <ILogProcessor>();

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, new[] { catchAllProcessor.Object });

            catchAllProcessor
            .Setup(p => p.IsLogForEvent(It.IsAny <FilterLog>()))
            .Returns(true);

            var logs = new[] { new FilterLog() };

            var cancellationToken = new CancellationTokenSource();

            //fake cancellation being raised after logs are retrieved but before processing
            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .Callback <NewFilterInput, object>((f, o) => cancellationToken.Cancel())
            .ReturnsAsync(logs);

            await logProcessor.ProcessAsync(new BlockRange(0, 10), cancellationToken.Token);

            catchAllProcessor
            .Verify(p => p.IsLogForEvent(It.IsAny <FilterLog>()), Times.Never);
        }
Пример #6
0
        public void Construction_BlockchainProxyCanBePassed()
        {
            var mockProxy = new Web3Mock();
            var processor = new LogsProcessorBuilder(mockProxy.Eth);

            Assert.Same(mockProxy.Eth, processor.Eth);
        }
Пример #7
0
        public async Task WillRequestLogsForEachFilter()
        {
            var mockLogProcessor = new Mock <ILogProcessor>();
            var web3Mock         = new Web3Mock();
            var logs             = new[] { new FilterLog() };
            var filtersExecuted  = new List <NewFilterInput>();

            var filters = new[] { new NewFilterInput(), new NewFilterInput() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .Callback <NewFilterInput, object>((f, o) => filtersExecuted.Add(f))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var processor = new LogsProcessorBuilder(web3Mock.Eth)
                            .Set(p => p.BlocksPerBatch = 1)
                            .Filter(filters[0])
                            .Filter(filters[1])
                            .Add(mockLogProcessor.Object)
                            .Build();

            var result = await processor.ProcessOnceAsync(new CancellationToken());

            Assert.Equal(filters, filtersExecuted);
        }
Пример #8
0
        public async Task Dedupes_Logs_Matching_Multiple_Filters()
        {
            var web3Mock          = new Web3Mock();
            var catchAllProcessor = new Mock <ILogProcessor>();

            var filter1 = new NewFilterInput();
            var filter2 = new NewFilterInput();
            var filters = new[] { filter1, filter2 };

            var mockProcessors = new[] { catchAllProcessor };

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, mockProcessors.Select(p => p.Object), filters);

            var log1 = new FilterLog()
            {
                TransactionHash = "x", LogIndex = new HexBigInteger(0)
            };
            var duplicateLog = new FilterLog()
            {
                TransactionHash = "x", LogIndex = new HexBigInteger(0)
            };
            var log2 = new FilterLog()
            {
                TransactionHash = "y", LogIndex = new HexBigInteger(0)
            };

            var logsFromFilter1 = new[] { log1, duplicateLog };
            var logsFromFilter2 = new[] { log2, duplicateLog };

            catchAllProcessor
            .Setup(p => p.IsLogForEvent(It.IsAny <FilterLog>()))
            .Returns(true);

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(filter1, null))
            .ReturnsAsync(logsFromFilter1);

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(filter2, null))
            .ReturnsAsync(logsFromFilter2);

            var processedLogs = new List <FilterLog>();

            catchAllProcessor.Setup(p => p.ProcessLogsAsync(It.IsAny <FilterLog[]>()))
            .Callback <FilterLog[]>(l => processedLogs.AddRange(l))
            .Returns(Task.CompletedTask);

            await logProcessor.ProcessAsync(new BlockRange(0, 0));

            Assert.Equal(2, processedLogs.Count);
            Assert.Contains(log1, processedLogs);
            Assert.Contains(log2, processedLogs);
            Assert.DoesNotContain(duplicateLog, processedLogs);
        }
Пример #9
0
 public BlockProcessorTestBase()
 {
     Web3Mock                 = new Web3Mock();
     MockBlockHandler         = new Mock <IBlockHandler>();
     MockTransactionProcessor = new Mock <ITransactionProcessor>();
     BlockFilters             = new List <IBlockFilter>();
     BlockProcessor           = new BlockProcessor(
         Web3Mock.Web3,
         MockBlockHandler.Object,
         MockTransactionProcessor.Object,
         BlockFilters);
 }
        public BlockProcessingRpcMock(Web3Mock web3Mock) : base(web3Mock)
        {
            web3Mock.GetBlockWithTransactionsByNumberMock.Setup(s => s.SendRequestAsync(It.IsAny <HexBigInteger>(), null))
            .Returns <HexBigInteger, object>((n, id) =>
            {
                BlockRequestCount++;
                return(Task.FromResult(Blocks.FirstOrDefault(b => b.Number.Value == n.Value)));
            });

            web3Mock.GetTransactionReceiptMock.Setup(s => s.SendRequestAsync(It.IsAny <string>(), null))
            .Returns <string, object>((hash, id) =>
            {
                ReceiptRequestCount++;
                return(Task.FromResult(Receipts.FirstOrDefault(b => b.TransactionHash == hash)));
            });
        }
Пример #11
0
        public async Task Allocates_Matching_Logs_To_Processors()
        {
            var web3Mock          = new Web3Mock();
            var log1Processor     = new Mock <ILogProcessor>();
            var log2Processor     = new Mock <ILogProcessor>();
            var catchAllProcessor = new Mock <ILogProcessor>();

            var mockProcessors = new[] { log1Processor, log2Processor, catchAllProcessor };

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, mockProcessors.Select(p => p.Object));

            var log1 = new FilterLog();
            var log2 = new FilterLog();
            var log3 = new FilterLog();

            var logs = new[] { log1, log2, log3 };

            log1Processor.Setup(p => p.IsLogForEvent(log1)).Returns(true);
            log2Processor.Setup(p => p.IsLogForEvent(log2)).Returns(true);

            catchAllProcessor
            .Setup(p => p.IsLogForEvent(It.IsAny <FilterLog>()))
            .Returns(true);

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            var processedLogs = new Dictionary <Mock <ILogProcessor>, List <FilterLog> >();

            foreach (var processor in mockProcessors)
            {
                processedLogs.Add(processor, new List <FilterLog>());

                processor.Setup(p => p.ProcessLogsAsync(It.IsAny <FilterLog[]>()))
                .Callback <FilterLog[]>(l => processedLogs[processor].AddRange(l))
                .Returns(Task.CompletedTask);
            }

            await logProcessor.ProcessAsync(new BlockRange(0, 0));

            Assert.Single(processedLogs[log1Processor], log1);
            Assert.Single(processedLogs[log2Processor], log2);
            Assert.True(logs.SequenceEqual(processedLogs[catchAllProcessor]));
        }
Пример #12
0
        public async Task RunInBackgroundAsync_Using_OnBatchProcessed()
        {
            LogBatchProcessedArgs lastBatchProcessedArgs = null;

            var mockLogProcessor = new Mock <ILogProcessor>();
            var web3Mock         = new Web3Mock();
            var logs             = new[] { new FilterLog() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));

            var builder = new LogsProcessorBuilder(web3Mock.Eth)
                          .Set(p => p.BlocksPerBatch     = 1)
                          .Set(p => p.MinimumBlockNumber = 0)
                          // escape hatch
                          .OnBatchProcessed((args) =>
            {
                lastBatchProcessedArgs = args;
                cancellationTokenSource.Cancel();
            })
                          .Add(mockLogProcessor.Object);

            var processor = builder.Build();

            var backgroundProcessingTask = processor.ProcessContinuallyInBackgroundAsync(cancellationTokenSource.Token);

            //simulate doing some work until cancellation is requested
            while (!backgroundProcessingTask.IsCompleted)
            {
                await Task.Delay(10);
            }

            Assert.Equal((uint)1, lastBatchProcessedArgs.BatchesProcessedSoFar);
            Assert.Equal(0, lastBatchProcessedArgs.LastRangeProcessed.From.Value);
            Assert.Equal(0, lastBatchProcessedArgs.LastRangeProcessed.To.Value);

            Assert.Equal(0, await builder.BlockProgressRepository.GetLastBlockNumberProcessedAsync());
        }
Пример #13
0
        public async Task Catches_Too_Many_Records_RpcException_And_Throws_Specific_Too_Many_Records_Exception()
        {
            var tooManyRecordsRpcEx = RpcResponseExceptionExtensions.CreateFakeTooManyRecordsRpcException();
            var web3Mock            = new Web3Mock();
            var catchAllProcessor   = new Mock <ILogProcessor>();

            var filter1 = new NewFilterInput();

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, new[] { catchAllProcessor.Object }, new[] { filter1 });

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(filter1, null))
            .Throws(tooManyRecordsRpcEx);

            var actualException = await Assert.ThrowsAsync <TooManyRecordsException>(async() => await logProcessor.ProcessAsync(new BlockRange(0, 0)));

            Assert.Same(tooManyRecordsRpcEx, actualException.InnerException);
        }
Пример #14
0
        public async Task RunInBackgroundAsync_Using_OnFatalError()
        {
            Exception fakeException = new Exception();
            Exception fatalError    = null;

            //set up processor to throw
            var mockLogProcessor = new Mock <ILogProcessor>();

            mockLogProcessor
            .Setup(s => s.ProcessLogsAsync(It.IsAny <FilterLog[]>()))
            .ThrowsAsync(fakeException);


            var web3Mock = new Web3Mock();
            var logs     = new[] { new FilterLog() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));

            var processor = new LogsProcessorBuilder(web3Mock.Eth)
                            .Set(p => p.BlocksPerBatch     = 1)
                            .Set(p => p.MinimumBlockNumber = 0)
                            .OnFatalError(e => fatalError  = e)
                            .Add(mockLogProcessor.Object)
                            .Build();

            var backgroundTask = processor.ProcessContinuallyInBackgroundAsync(cancellationTokenSource.Token);

            //simulate doing some work until cancellation is requested
            while (!backgroundTask.IsCompleted)
            {
                await Task.Delay(100);
            }

            Assert.Same(fakeException, fatalError);
        }
Пример #15
0
        public LogProcessingRpcMock(Web3Mock web3Mock) : base(web3Mock)
        {
            web3Mock.GetLogsMock.Setup(s => s.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .Returns <NewFilterInput, object>((filter, id) => {
                GetLogsFiltersInvoked.Add(filter);
                GetLogRequestCount++;

                if (GetLogsException != null)
                {
                    throw GetLogsException;
                }

                var logs = Logs.Where(l =>
                                      l.BlockNumber.Value >=
                                      filter.FromBlock.BlockNumber.Value &&
                                      l.BlockNumber.Value <=
                                      filter.ToBlock.BlockNumber.Value).ToArray();

                return(Task.FromResult(logs));
            });
        }
Пример #16
0
        public async Task ProcessContinuallyAsync_Using_OnBatchProcessed()
        {
            LogBatchProcessedArgs lastBatchProcessedArgs = null;

            var mockLogProcessor = new Mock <ILogProcessor>();
            var web3Mock         = new Web3Mock();
            var logs             = new[] { new FilterLog() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));

            var builder = new LogsProcessorBuilder(web3Mock.ContractServiceMock.Object)
                          .Set(p => p.BlocksPerBatch     = 1)
                          .Set(p => p.MinimumBlockNumber = 0)
                          // escape hatch
                          .OnBatchProcessed((args) =>
            {
                lastBatchProcessedArgs = args;
                cancellationTokenSource.Cancel();
            })
                          .Add(mockLogProcessor.Object);

            var processor = builder.Build();

            var rangesProcessed = await processor.ProcessContinuallyAsync(cancellationTokenSource.Token);

            Assert.Equal(1, rangesProcessed);
            Assert.Equal((uint)1, lastBatchProcessedArgs.BatchesProcessedSoFar);
            Assert.Equal(0, lastBatchProcessedArgs.LastRangeProcessed.From.Value);
            Assert.Equal(0, lastBatchProcessedArgs.LastRangeProcessed.To.Value);

            Assert.Equal(0, await builder.BlockProgressRepository.GetLastBlockNumberProcessedAsync());
        }
Пример #17
0
        public async Task Checks_For_Cancellation_Before_Each_Processing_Batch()
        {
            var web3Mock           = new Web3Mock();
            var catchAllProcessor1 = new Mock <ILogProcessor>();
            var catchAllProcessor2 = new Mock <ILogProcessor>();

            catchAllProcessor1
            .Setup(p => p.IsLogForEvent(It.IsAny <FilterLog>()))
            .Returns(true);

            catchAllProcessor2
            .Setup(p => p.IsLogForEvent(It.IsAny <FilterLog>()))
            .Returns(true);

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, new[] { catchAllProcessor1.Object, catchAllProcessor2.Object });

            var logs = new[] { new FilterLog() };

            var cancellationToken = new CancellationTokenSource();

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            //cancel after processor 1 finishes
            catchAllProcessor1
            .Setup(p => p.ProcessLogsAsync(It.IsAny <FilterLog[]>()))
            .Callback <FilterLog[]>(l => cancellationToken.Cancel())
            .Returns(Task.CompletedTask);

            await logProcessor.ProcessAsync(new BlockRange(0, 10), cancellationToken.Token);

            catchAllProcessor1
            .Verify(p => p.ProcessLogsAsync(It.IsAny <FilterLog[]>()), Times.Once);

            catchAllProcessor2
            .Verify(p => p.ProcessLogsAsync(It.IsAny <FilterLog[]>()), Times.Never);
        }
Пример #18
0
        public async Task Passes_Correct_Block_Range_To_Proxy()
        {
            var web3Mock = new Web3Mock();

            var logProcessor = new BlockRangeLogsProcessor(
                web3Mock.Web3, Array.Empty <ILogProcessor>());

            var logs = Array.Empty <FilterLog>();

            NewFilterInput actualFilter = null;

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .Callback <NewFilterInput, object>((f, o) => actualFilter = f)
            .ReturnsAsync(logs);

            await logProcessor.ProcessAsync(new BlockRange(0, 10));

            Assert.NotNull(actualFilter);
            Assert.Equal(0, actualFilter.FromBlock.BlockNumber.Value);
            Assert.Equal(10, actualFilter.ToBlock.BlockNumber.Value);
        }
Пример #19
0
        public async Task IfMinimumBlockNumberIsNull_AndThereIsNoPreviousProgress_StartsAtCurrentBlockOnChain()
        {
            var mockLogProcessor = new Mock <ILogProcessor>();
            var web3Mock         = new Web3Mock();
            var logs             = new[] { new FilterLog() };

            web3Mock.GetLogsMock
            .Setup(p => p.SendRequestAsync(It.IsAny <NewFilterInput>(), null))
            .ReturnsAsync(logs);

            web3Mock.BlockNumberMock
            .Setup(p => p.SendRequestAsync(null))
            .ReturnsAsync(100.ToHexBigInteger());

            var processor = new LogsProcessorBuilder(web3Mock.Eth)
                            .Set(p => p.BlocksPerBatch = 1)
                            .Add(mockLogProcessor.Object)
                            .Build();

            var result = await processor.ProcessOnceAsync(new CancellationToken());

            Assert.Equal(100.ToHexBigInteger(), result.Value.From);
            Assert.Equal(100.ToHexBigInteger(), result.Value.To);
        }