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()); }
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); }
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)); }; }
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); }
public void Construction_BlockchainProxyCanBePassed() { var mockProxy = new Web3Mock(); var processor = new LogsProcessorBuilder(mockProxy.Eth); Assert.Same(mockProxy.Eth, processor.Eth); }
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); }
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); }
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))); }); }
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])); }
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()); }
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); }
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); }
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)); }); }
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()); }
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); }
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); }
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); }