public async Task AddTransactionAsync_TimeoutAndFailToCallback_ShouldNotThrow() { using (var elapsed = new ManualResetEventSlim()) { // Arrange. await this.Initialize(CancellationToken.None); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(200); this.ruleRepository.When(r => r.UpdateStatusAsync(Arg.Any <Guid>(), Arg.Any <RuleStatus>(), Arg.Any <CancellationToken>())) .Throw(info => { elapsed.Set(); return(new Exception()); }); // Act. await builder.Call(this.subject.AddTransactionAsync); elapsed.Wait(1500); // Assert. _ = this.callbackExecuter .Received(0) .ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>() ); } }
public async Task AddTransactionAsync_AndPushNoEvent_ShouldTimeout() { using (var elapsed = new ManualResetEventSlim()) { // Arrange. await this.Initialize(CancellationToken.None); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(200); this.callbackExecuter.When(e => e.ExecuteAsync(Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>())) .Do(c => elapsed.Set()); // Act. await builder.Call(this.subject.AddTransactionAsync); elapsed.Wait(1500); // Assert. _ = this.callbackExecuter .Received(1) .ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Is <CallbackResult>(r => r.Status == CallbackResult.StatusError), Arg.Any <CancellationToken>() ); } }
public async Task AddTransactionAsync_AndWaitSomeWatchesToTimeout_ShouldCallExecute() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); // Act. builder.Timeout = TimeSpan.FromSeconds(1); await builder.Call(this.subject.AddTransactionAsync); builder.Timeout = TimeSpan.FromSeconds(2); await builder.Call(this.subject.AddTransactionAsync); builder.Timeout = TimeSpan.FromDays(1); await builder.Call(this.subject.AddTransactionAsync); Thread.Sleep(TimeSpan.FromSeconds(3)); // Assert. _ = this.callbackExecuter.Received(2).ExecuteAsync ( Arg.Any <Guid>(), this.defaultUrl, Arg.Is <CallbackResult> ( result => result == builder.TimeoutData ), Arg.Any <CancellationToken>() ); }
public async Task AddTransactionAsync_WithOnChainTransactionAndFork_ShouldBeResumeAndTimeout() { // Arrange. var transaction = Transaction.Parse(TestTransaction.Raw1, ZcoinNetworks.Instance.Regtest); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Transaction = transaction.GetHash(); this.blockStorage .GetTransactionAsync(transaction.GetHash(), Arg.Any <CancellationToken>()) .Returns(transaction); var(block, _) = GenerateBlock(); builder.Timeout = TimeSpan.FromMilliseconds(500); await builder.Call(this.subject.AddTransactionAsync); // Act. await this.blockListener.BlockRemovingAsync(block, 1, CancellationToken.None); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Assert. _ = this.callbackExecuter.Received(1).ExecuteAsync ( Arg.Any <Guid>(), this.defaultUrl, Arg.Is <CallbackResult> ( result => result == builder.TimeoutData ), Arg.Any <CancellationToken>() ); }
public async Task ConfirmationUpdateAsync_AndReachRequiredConfirmations_ShouldCallSuccess() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(2); builder.Confirmations = 10; var rule = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(rule, uint256.Zero, builder.Transaction), }; await this.handler.AddWatchesAsync(watches, CancellationToken.None); // Act. for (var confirmation = 1; confirmation <= builder.Confirmations; confirmation++) { await this.handler.ConfirmationUpdateAsync(watches[0], confirmation, ConfirmationType.Confirmed, CancellationToken.None); } Thread.Sleep(TimeSpan.FromSeconds(2)); // Assert. _ = this.callbackExecuter.Received(1).ExecuteAsync ( rule.Callback.Id, rule.Callback.Url, Arg.Is <CallbackResult> ( result => result.Status == CallbackResult.StatusSuccess ), Arg.Any <CancellationToken>() ); }
public async Task AddTransactionAsync_AndSuccessToExecuteCallback_CompletedFlagAndHistorySuccessFlagShouldBeSet() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(500); // Act. var rule = await builder.Call(this.subject.AddTransactionAsync); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Assert. _ = this.ruleRepository.Received(1).UpdateStatusAsync(rule.Id, Arg.Any <RuleStatus>(), Arg.Any <CancellationToken>()); _ = this.callbackExecuter.Received(1).ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>() ); _ = this.callbackRepository.Received(1).SetCompletedAsyc ( Arg.Any <Guid>(), Arg.Any <CancellationToken>() ); }
public async Task AddWatchesAsync_WithValidArgs_ShouldNotThrow() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); var watch1 = await builder.Call(this.subject.AddTransactionAsync); var watch2 = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(watch1, uint256.Zero, uint256.Zero), new TransactionWatch <Rule>(watch2, uint256.Zero, uint256.Zero), }; // Act. await this.handler.AddWatchesAsync(watches, CancellationToken.None); _ = this.ruleRepository.Received(1).UpdateCurrentWatchAsync ( Arg.Is <Guid>(id => id == watch1.Id), Arg.Is <Guid>(id => id == watches[0].Id), Arg.Any <CancellationToken>() ); _ = this.ruleRepository.Received(1).UpdateCurrentWatchAsync ( Arg.Is <Guid>(id => id == watch2.Id), Arg.Is <Guid>(id => id == watches[1].Id), Arg.Any <CancellationToken>() ); }
public async Task AddTransactionAsync_WithValidArgument_ShouldSuccess() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(500); // Act. var rule = await builder.Call(this.subject.AddTransactionAsync); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Assert. _ = this.callbackRepository.Received(1).AddAsync ( Arg.Is <IPAddress>(ip => ip == builder.Ip), Arg.Is <Uri>(url => url == builder.CallbackUrl), Arg.Any <CancellationToken>() ); _ = this.ruleRepository.Received(1).AddAsync ( Arg.Is <uint256>(tx => tx == builder.Transaction), Arg.Is <int>(confirmations => confirmations == builder.Confirmations), Arg.Is <TimeSpan>(t => t == builder.Timeout), Arg.Is <CallbackResult>(r => r == builder.SuccessData), Arg.Is <CallbackResult>(r => r == builder.TimeoutData), Arg.Is <Callback>(c => c == rule.Callback), Arg.Any <CancellationToken>() ); _ = this.callbackExecuter.Received(1).ExecuteAsync ( Arg.Is <Guid>(id => id == rule.Callback.Id), this.defaultUrl, Arg.Is <CallbackResult> ( result => result == builder.TimeoutData ), Arg.Any <CancellationToken>() ); _ = this.callbackRepository.Received(1).AddHistoryAsync ( Arg.Is <Guid>(id => id == rule.Callback.Id), Arg.Is <CallbackResult>(r => r == rule.TimeoutResponse), Arg.Any <CancellationToken>() ); _ = this.callbackRepository.Received(1).SetCompletedAsyc ( Arg.Is <Guid>(id => id == rule.Callback.Id), Arg.Any <CancellationToken>() ); }
public async Task RemoveUncompletedWatchesAsync_WithRemainingTimeout_ShouldNotExecuteTimeoutImmediately() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(500); builder.Confirmations = 10; var watch = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(watch, uint256.Zero, builder.Transaction), }; await this.handler.AddWatchesAsync(watches, CancellationToken.None); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Act & Assert. var updated = await this.ruleRepository.GetAsync(watch.Id, CancellationToken.None); Assert.True(await this.ruleRepository.GetRemainingWaitingTimeAsync(updated.Id, CancellationToken.None) < TimeSpan.FromSeconds(1)); await this.handler.RemoveUncompletedWatchesAsync(uint256.Zero, CancellationToken.None); _ = this.callbackExecuter.Received(0).ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>() ); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); _ = this.callbackExecuter.Received(1).ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Is <CallbackResult> ( result => result.Status == CallbackResult.StatusError ), Arg.Any <CancellationToken>() ); _ = this.ruleRepository.Received(1).UpdateCurrentWatchAsync( Arg.Is <Guid>(id => id == watch.Id), Arg.Is <Guid?>(id => id == null), Arg.Any <CancellationToken>()); }
public async Task AddTransactionAsync_WithNullArguments_ShouldThrow() { var builder = new WatchArgsBuilder(this.callbackRepository); var callback = await this.callbackRepository.AddAsync( builder.Ip, builder.CallbackUrl, CancellationToken.None); await Assert.ThrowsAsync <ArgumentOutOfRangeException>( () => this.subject.AddTransactionAsync( uint256.One, 10, TimeSpan.MinValue, callback, new CallbackResult("", ""), new CallbackResult("", ""), CancellationToken.None) ); }
public async Task AddTransactionAsync_AndPushUntilRequiredConfirmation_ShouldCallSuccess() { // Arrange. await this.Initialize(CancellationToken.None); var(block, _) = GenerateBlock(); block.AddTransaction(Transaction.Create(ZcoinNetworks.Instance.Regtest)); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Confirmations = 10; builder.Timeout = TimeSpan.FromMilliseconds(500); builder.Transaction = block.Transactions[0].GetHash(); var rule = await builder.Call(this.subject.AddTransactionAsync); // Act. await this.blockListener.BlockAddedAsync(block, 1, CancellationToken.None); for (var i = 0; i < builder.Confirmations - 1; i++) { int height; (block, height) = GenerateBlock(); await this.blockListener.BlockAddedAsync(block, height, CancellationToken.None); } // Assert. _ = this.callbackExecuter .Received(1) .ExecuteAsync ( rule.Callback.Id, rule.Callback.Url, Arg.Is <CallbackResult> ( r => r.Status == CallbackResult.StatusSuccess ), Arg.Any <CancellationToken>() ); }
public async Task AddTransactionAsync_AndPushBlockWhichContainTransaction_TimerShouldBeStopped() { // Arrange. await this.Initialize(CancellationToken.None); var(block, _) = GenerateBlock(); block.AddTransaction(Transaction.Create(ZcoinNetworks.Instance.Regtest)); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(1); builder.Transaction = block.Transactions[0].GetHash(); await builder.Call(this.subject.AddTransactionAsync); // Act. await this.blockListener.BlockAddedAsync(block, 1, CancellationToken.None); Thread.Sleep(TimeSpan.FromSeconds(1)); // Assert. _ = this.callbackExecuter.Received(0).ExecuteAsync(Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>()); }
public async Task RemoveUncompletedWatchesAsync_TimerShouldbeResume() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(500); builder.Confirmations = 10; var rule = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >(); var watch = new TransactionWatch <Rule>(rule, uint256.Zero, builder.Transaction); watches.Add(watch); await this.handler.AddWatchesAsync(watches, CancellationToken.None); // Act. await this.handler.RemoveUncompletedWatchesAsync(uint256.Zero, CancellationToken.None); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Assert. _ = this.callbackExecuter.Received(1).ExecuteAsync ( rule.Callback.Id, rule.Callback.Url, Arg.Is <CallbackResult> ( result => result.Status == CallbackResult.StatusError ), Arg.Any <CancellationToken>() ); _ = this.ruleRepository.Received(1).UpdateCurrentWatchAsync( Arg.Is <Guid>(id => id == rule.Id), Arg.Is <Guid?>(id => id == null), Arg.Any <CancellationToken>()); }
public async Task ConfirmationUpdateAsync_WithValidWatch_ShouldSuccess() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(1); var watch = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(watch, uint256.Zero, builder.Transaction), }; await this.handler.AddWatchesAsync(watches, CancellationToken.None); // Act. var result = await this.handler.ConfirmationUpdateAsync(watches[0], 1, ConfirmationType.Confirmed, CancellationToken.None); Thread.Sleep(TimeSpan.FromSeconds(2)); // Assert. Assert.False(result); _ = this.callbackExecuter.Received(0).ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Any <CallbackResult>(), Arg.Any <CancellationToken>() ); var received = await this.handler.GetCurrentWatchesAsync(CancellationToken.None); Assert.Single(received); Assert.Equal(watches[0].Id, received.First().Id); }
public async Task GetCurrentWatchesAsync_WithNonEmpty_ShouldReceivedWatches() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); var watch1 = await builder.Call(this.subject.AddTransactionAsync); var watch2 = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(watch1, uint256.Zero, watch1.TransactionHash), new TransactionWatch <Rule>(watch2, uint256.Zero, watch1.TransactionHash), }; await this.handler.AddWatchesAsync(watches, CancellationToken.None); // Act. var received = await this.handler.GetCurrentWatchesAsync(CancellationToken.None); // Assert. Assert.Equal(2, received.Count()); Assert.Contains(received, w => w.Context.Id == watch1.Id); Assert.Contains(received, w => w.Context.Id == watch2.Id); }
public async Task CreateContextsAsync_WithValidArgs_ShouldSuccess() { // Arrange. var tx = Transaction.Parse(TestTransaction.Raw1, ZcoinNetworks.Instance.Mainnet); var untrackedTx = Transaction.Parse(TestTransaction.Raw2, ZcoinNetworks.Instance.Mainnet); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(1); builder.Transaction = tx.GetHash(); await builder.Call(this.subject.AddTransactionAsync); builder.Timeout = TimeSpan.FromSeconds(2); await builder.Call(this.subject.AddTransactionAsync); // Act. var contexts = await this.handler.CreateContextsAsync(tx, CancellationToken.None); var untrackedTxContexts = await this.handler.CreateContextsAsync(untrackedTx, CancellationToken.None); // Assert. Assert.Equal(2, contexts.Count()); Assert.Empty(untrackedTxContexts); }
public async Task RemoveCompletedWatchesAsync_WithExistKey_ShouldSuccess() { // Arrange. var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(1); builder.Confirmations = 10; var watch = await builder.Call(this.subject.AddTransactionAsync); var watches = new List <TransactionWatch <Rule> >() { new TransactionWatch <Rule>(watch, uint256.Zero, builder.Transaction), }; await this.handler.AddWatchesAsync(watches, CancellationToken.None); // Act. await this.handler.RemoveCompletedWatchesAsync(watches, CancellationToken.None); // Assert. Assert.Empty(await this.handler.GetCurrentWatchesAsync(CancellationToken.None)); _ = this.ruleRepository.Received(1).UpdateCurrentWatchAsync( Arg.Is <Guid>(id => id == watch.Id), Arg.Is <Guid?>(id => id == null), Arg.Any <CancellationToken>()); }
public async Task AddTransactionAsync_AndBlocksAreRemoved_TimersShouldBeResume() { // Arrange. await this.Initialize(CancellationToken.None); var(block, _) = GenerateBlock(); block.AddTransaction(Transaction.Create(ZcoinNetworks.Instance.Regtest)); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromMilliseconds(500); builder.Transaction = block.Transactions[0].GetHash(); var rule = await builder.Call(this.subject.AddTransactionAsync); // Act. await this.blockListener.BlockAddedAsync(block, 1, CancellationToken.None); await this.blockListener.BlockRemovingAsync(block, 1, CancellationToken.None); Thread.Sleep(TimeSpan.FromMilliseconds(1000)); // Assert. _ = this.callbackExecuter .Received(1) .ExecuteAsync ( rule.Callback.Id, rule.Callback.Url, Arg.Is <CallbackResult> ( r => r.Status == CallbackResult.StatusError ), Arg.Any <CancellationToken>() ); }
public async Task Initialize_WithNonEmptyRepository_ShouldInitializeWatches() { // Arrange. var tx = Transaction.Parse(TestTransaction.Raw1, ZcoinNetworks.Instance.Mainnet); var builder = new WatchArgsBuilder(this.callbackRepository); builder.Timeout = TimeSpan.FromSeconds(1); builder.Transaction = tx.GetHash(); var callback = await this.callbackRepository.AddAsync ( builder.Ip, builder.CallbackUrl, CancellationToken.None ); _ = await this.ruleRepository.AddAsync ( builder.Transaction, builder.Confirmations, builder.Timeout, builder.SuccessData, builder.TimeoutData, callback, CancellationToken.None ); // Completed watch var completedCallback = new Callback ( Guid.NewGuid(), IPAddress.Loopback, DateTime.UtcNow, true, this.defaultUrl ); var watch = await this.ruleRepository.AddAsync ( builder.Transaction, builder.Confirmations, builder.Timeout, builder.SuccessData, builder.TimeoutData, completedCallback, CancellationToken.None ); await this.ruleRepository.UpdateStatusAsync(watch.Id, RuleStatus.Success, CancellationToken.None); // Act. ITransactionConfirmationWatcherHandler <Rule> localHandler; TransactionConfirmationWatcher localWatcher; localHandler = localWatcher = new TransactionConfirmationWatcher ( this.callbackRepository, this.ruleRepository, this.blockStorage, this.callbackExecuter, this.watchRepository, this.logger ); await localWatcher.StartAsync(CancellationToken.None); var retrievedCount = (await localHandler.CreateContextsAsync(tx, CancellationToken.None)).Count(); Thread.Sleep(TimeSpan.FromSeconds(2)); // Assert. Assert.Equal(1, retrievedCount); _ = this.callbackExecuter.Received(1).ExecuteAsync ( Arg.Any <Guid>(), Arg.Any <Uri>(), Arg.Is <CallbackResult> ( result => result.Status == CallbackResult.StatusError ), Arg.Any <CancellationToken>() ); }
public async Task AddTransactionAsync_WithNullArgs_ShouldThrow() { // Arrange. await this.Initialize(CancellationToken.None); var builder = new WatchArgsBuilder(this.callbackRepository); var callback = await this.callbackRepository.AddAsync( builder.Ip, builder.CallbackUrl, CancellationToken.None); // Assert. await Assert.ThrowsAsync <ArgumentNullException>( "transaction", () => this.subject.AddTransactionAsync( null, builder.Confirmations, builder.Timeout, callback, builder.SuccessData, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentOutOfRangeException>( "confirmation", () => this.subject.AddTransactionAsync( builder.Transaction, 0, builder.Timeout, callback, builder.SuccessData, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentOutOfRangeException>( "unconfirmedWaitingTime", () => this.subject.AddTransactionAsync( builder.Transaction, builder.Confirmations, Ztm.Threading.TimerSchedulers.ThreadPoolScheduler.MaxDuration + TimeSpan.FromSeconds(1), callback, builder.SuccessData, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentOutOfRangeException>( "unconfirmedWaitingTime", () => this.subject.AddTransactionAsync( builder.Transaction, builder.Confirmations, Ztm.Threading.TimerSchedulers.ThreadPoolScheduler.MinDuration - TimeSpan.FromSeconds(1), callback, builder.SuccessData, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentNullException>( "callback", () => this.subject.AddTransactionAsync( builder.Transaction, builder.Confirmations, builder.Timeout, null, builder.SuccessData, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentNullException>( "successResponse", () => this.subject.AddTransactionAsync( builder.Transaction, builder.Confirmations, builder.Timeout, callback, null, builder.TimeoutData, CancellationToken.None) ); await Assert.ThrowsAsync <ArgumentNullException>( "timeoutResponse", () => this.subject.AddTransactionAsync( builder.Transaction, builder.Confirmations, builder.Timeout, callback, builder.SuccessData, null, CancellationToken.None) ); }