public void MultipleOrdersShouldBeProcessedConsecutively() { LoggerStub logger = new LoggerStub(); // Assume that publisher execution takes some time (random number of seconds) QuotePublisherStub publisher = new QuotePublisherStub(async(Quote q) => { int duration = new Random().Next(1, 3); await Task.Delay(TimeSpan.FromSeconds(duration)); }); QuoteFeedController controller = new QuoteFeedController(publisher, logger); // Produce multiple orders and wait for publishing List <Task> tasks = new List <Task>(TASKS_COUNT); for (int i = 0; i < TASKS_COUNT; i++) { var task = controller.ProcessOrderbook(CreateOrder("btc", true, Utils.ParseUtc("2017-01-01 10:10:12Z"), new[] { new VolumePrice() { Volume = 1, Price = i } })); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); // There should be the same number of events as the number of incoming orders. // If orders were processed in different order, there would be less events // as the price is constantly increasing. Assert.Equal(TASKS_COUNT, publisher.Published.Count); }
static void Main(string[] args) { var logger = new LoggerStub(); Helpers.LogCurrentMemoryUsage(logger); var serviceClientFactory = new ServiceClientFactory(logger); using (var testServiceClient = serviceClientFactory.CreateServiceClient <ITestService>( "localhost")) { Console.WriteLine("Test service client created."); // Warm up const int warmUpCallsCount = 5000; Enumerable .Range(0, warmUpCallsCount) .ParallelForEach(_ => SendRequestAndLogResult(testServiceClient.ServiceInstance, logger)); Console.WriteLine("Warmup done"); GC.Collect(2, GCCollectionMode.Forced); // Thread.Sleep(TimeSpan.FromSeconds(5)); const int callsCount = 10000; RunTests(() => TestAsyncOperations(testServiceClient.ServiceInstance, logger, callsCount), logger); Console.WriteLine("All requests send."); Console.ReadLine(); } }
public void InvalidDateIsIgnored() { LoggerStub logger = new LoggerStub(); QuotePublisherStub publisher = new QuotePublisherStub(); QuoteFeedController controller = new QuoteFeedController(publisher, logger); DateTime unspecified = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Unspecified); DateTime local = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Local); controller.ProcessOrderbook(CreateOrder("btc", true, unspecified, new VolumePrice[] { new VolumePrice() { Volume = 1, Price = 100 } })).Wait(); controller.ProcessOrderbook(CreateOrder("btc", true, local, new VolumePrice[] { new VolumePrice() { Volume = 1, Price = 100 } })).Wait(); controller.ProcessOrderbook(CreateOrder("btc", true, DateTime.MinValue, new VolumePrice[] { new VolumePrice() { Volume = 1, Price = 100 } })).Wait(); controller.ProcessOrderbook(CreateOrder("btc", true, DateTime.MaxValue, new VolumePrice[] { new VolumePrice() { Volume = 1, Price = 100 } })).Wait(); Assert.Equal(0, publisher.Published.Count); }
public void InvalidDateIsIgnored() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryStub(); var controller = new CandleGenerationController(repo, logger, "test component", env); DateTime unspecified = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Unspecified); DateTime local = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Local); controller.HandleQuote(new Quote() { AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = unspecified }).Wait(); controller.HandleQuote(new Quote() { AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = local }).Wait(); controller.HandleQuote(new Quote() { AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = DateTime.MinValue }).Wait(); controller.HandleQuote(new Quote() { AssetPair = "btcrub", IsBuy = true, Price = 1, Timestamp = DateTime.MaxValue }).Wait(); Assert.Equal(0, repo.Stored.Count); }
public static void Main(string[] args) { var logger = new LoggerStub(); // using (var logger = new ConsoleLoggerWrapper(new LoggerStub())) // { Helpers.LogCurrentMemoryUsage(logger); // Console.ReadLine(); var messagePackSerializerFactory = new MessagePackSerializerFactory(); var rpcTcpServicePublisher = new RpcTcpServicePublisher(messagePackSerializerFactory, logger); var defaultServiceTimeout = TimeSpan.FromMinutes(1); var testService = new TestService(logger); using (new DisposableCollectionHolder( rpcTcpServicePublisher.PublishUnsecured <ITestService>( testService, defaultServiceTimeout))) { using (ServiceHostContainerFactory.Create <TestService, ITestService>()) { Console.WriteLine("Services started. Press Enter to stop."); Console.ReadLine(); Helpers.LogCurrentMemoryUsage(logger); } } // } Console.WriteLine("Services stopped."); }
static void Main(string[] args) { var logger = new LoggerStub(); // using (var logger = new ConsoleLoggerWrapper(new LoggerStub())) // { Helpers.LogCurrentMemoryUsage(logger); // Console.ReadLine(); var messagePackSerializerFactory = new MessagePackSerializerFactory(); using (var testServiceClient = ServiceClientFactory.CreateServiceClient <ITestService>( "localhost", logger, messagePackSerializerFactory)) { using (var wcfTestServiceClient = CommonWcfComponents.ServiceClient <ITestService> .Create()) { Console.WriteLine("Test service client created."); RunTest(wcfTestServiceClient.Service, logger); Helpers.LogCurrentMemoryUsage(logger); Console.WriteLine("All requests send."); Console.ReadLine(); } } // } }
public PaymentMethodServiceTests() { _repoMock = new MockContext <IPaymentMethodRepo>(); var repoMock = new PaymentMethodRepoMock(_repoMock); var loggerStub = new LoggerStub <PaymentMethodService>(); _subject = new PaymentMethodService(repoMock, loggerStub); }
public PaymentMethodsControllerTests() { _serviceMock = new MockContext <IPaymentMethodService>(); var repositoryMock = new PaymentMethodServiceMock(_serviceMock); var loggerStub = new LoggerStub <PaymentMethodsController>(); _subject = new PaymentMethodsController(repositoryMock, loggerStub); }
public ICustomStringLocalizer BuildCustomStringLocalizer() { ILogger loggerStub = new LoggerStub(); IStringLocalizer stringLocalizer = new JsonStringLocalizer( "Resources", "TaskForModule5", loggerStub); return(new CustomStringLocalizer(stringLocalizer)); }
public void NullIsIgnored() { LoggerStub logger = new LoggerStub(); QuotePublisherStub publisher = new QuotePublisherStub(); QuoteFeedController controller = new QuoteFeedController(publisher, logger); controller.ProcessOrderbook(null).Wait(); Assert.Equal(0, publisher.Published.Count); }
public void NullIsIgnored() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryStub(); var controller = new CandleGenerationController(repo, logger, "test component", env); controller.HandleQuote(null).Wait(); Assert.Equal(0, repo.Stored.Count); }
public void QuoteIsUpdatedWhenDateIsEqualAndBestPrice() { LoggerStub logger = new LoggerStub(); QuotePublisherStub publisher = new QuotePublisherStub(); QuoteFeedController controller = new QuoteFeedController(publisher, logger); // BTCUSD / BUY, 1st order controller.ProcessOrderbook(CreateOrder("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), new[] { new VolumePrice() { Volume = 1, Price = 999 }, new VolumePrice() { Volume = 1, Price = 1000 } })).Wait(); Assert.Equal(1, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), 1000.0)); // BTCUSD / BUY, 2nd order controller.ProcessOrderbook(CreateOrder("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), new[] { new VolumePrice() { Volume = 1, Price = 1001 } })).Wait(); Assert.Equal(2, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), 1001.0)); // BTCRUB / SELL, 1st order controller.ProcessOrderbook(CreateOrder("btcrub", false, Utils.ParseUtc("2017-01-02 10:10:10Z"), new[] { new VolumePrice() { Volume = 1, Price = 50 }, new VolumePrice() { Volume = 1, Price = 60 } })).Wait(); Assert.Equal(3, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcrub", false, Utils.ParseUtc("2017-01-02 10:10:10Z"), 50)); // BTCRUB / SELL, 2nd order controller.ProcessOrderbook(CreateOrder("btcrub", false, Utils.ParseUtc("2017-01-02 10:10:10Z"), new[] { new VolumePrice() { Volume = 1, Price = 40 } })).Wait(); Assert.Equal(4, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcrub", false, Utils.ParseUtc("2017-01-02 10:10:10Z"), 40)); }
public void EmptyPricesIsIgnored() { LoggerStub logger = new LoggerStub(); QuotePublisherStub publisher = new QuotePublisherStub(); QuoteFeedController controller = new QuoteFeedController(publisher, logger); controller.ProcessOrderbook(CreateOrder("btc", true, Utils.ParseUtc("2017-01-01 10:10:12Z"), null)).Wait(); controller.ProcessOrderbook(CreateOrder("btc", true, Utils.ParseUtc("2017-01-01 10:10:12Z"), new VolumePrice[] { })).Wait(); Assert.Equal(0, publisher.Published.Count); }
public void ItShouldSkipFindFirstMigrationIfVersionHigher() { var database = new DatabaseStub(3); var logger = new LoggerStub(); var schema = new Schema(database, logger); var migrator = new Migrator(schema, typeof(FirstMigration).Assembly, logger); migrator.MigrateToLatest(); Assert.That(logger.Logs.Any(x => x.Contains(@"No Migrations Found"))); }
public void ItShouldApplyMigrationsSinceLastVersionAndUpdateSchemaTable() { var database = new DatabaseStub(); var logger = new LoggerStub(); var schema = new Schema(database, logger); var migrator = new Migrator(schema, typeof(FirstMigration).Assembly, logger); migrator.MigrateToLatest(); Assert.That(database.Statements.Any(x => x.Contains("FirstMigration"))); }
public void ItShouldNotApplyMigrationsSinceLastVersionWhenVersionBiggerThanMigration() { var database = new DatabaseStub(3); var logger = new LoggerStub(); var schema = new Schema(database, logger); var migrator = new Migrator(schema, typeof(FirstMigration).Assembly, logger); migrator.MigrateToLatest(); Assert.That(database.Statements.Any(x => x.Contains("FirstMigration")), Is.False); }
public void ItShouldInformIfNoMigrationsFoundInAssembly() { var database = new DatabaseStub(); var logger = new LoggerStub(); var schema = new Schema(database, logger); var migrator = new Migrator(schema, typeof(Schema).Assembly, logger); migrator.MigrateToLatest(); Assert.That(logger.Logs.Any(x => x.Contains(@"No Migrations Found"))); }
public void NoExceptionExpectedOnMultithread() { var logger = new LoggerStub(); var candlesRepo = new CandleHistoryRepositoryStub(); var env = new EnvironmentStub(new List <AssetPair>() { new AssetPair() { Id = "btcusd", Accuracy = 5 } }); var controller = new CandleGenerationController(candlesRepo, logger, "test component", env); // Cancel after 1 sec CancellationTokenSource tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); CancellationToken token = tokenSource.Token; int consumeCalledTimes = 0; int tickCalledTimes = 0; // Call Consume and Tick methods at the same time repeatedly and check that there was no exception. Task producing = Task.Run(async() => { while (!token.IsCancellationRequested) { await controller.HandleQuote(new Quote() { AssetPair = "btcusd", IsBuy = true, Price = 100, Timestamp = DateTime.UtcNow }); await Task.Delay(50); Interlocked.Increment(ref consumeCalledTimes); } }, token); Task timer = Task.Run(() => { while (!token.IsCancellationRequested) { controller.Tick(); Interlocked.Increment(ref tickCalledTimes); } }, token); Task.WaitAll(producing, timer); Assert.True(consumeCalledTimes > 0); Assert.True(tickCalledTimes > 0); Assert.True(candlesRepo.Stored.Count > 0); }
public void CheckMinutesGeneration() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryResolver((string asset, string tableName) => { return(CreateStorage <CandleTableEntity>(asset, tableName, logger)); }); DateTime dt = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc); const string asset1 = "btcusd"; // 1. Prepare incoming quotes // IEnumerable <Quote> quotes = new Quote[] { // Asset 1 new Quote() { AssetPair = asset1, IsBuy = true, Price = 1, Timestamp = dt }, // Second 1 // Day 1 new Quote() { AssetPair = asset1, IsBuy = true, Price = 2, Timestamp = dt.AddMinutes(1) }, new Quote() { AssetPair = asset1, IsBuy = true, Price = 3, Timestamp = dt.AddMinutes(2) }, // Second 2 new Quote() { AssetPair = asset1, IsBuy = true, Price = 4, Timestamp = dt.AddMinutes(3) }, // Second 2 new Quote() { AssetPair = asset1, IsBuy = true, Price = 5, Timestamp = dt.AddMinutes(4) }, // Second 3 }; // 2. Process incoming quotes // ProcessAllQuotes(quotes, repo, logger); // ... check for errors Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count()); // 3. Read candles with repository and check count of generated candles // CheckCountGenerated(repo, dt.AddDays(-1), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Sec, PriceType = PriceType.Bid, CountExpected = 5 }, new { Asset = asset1, Interval = TimeInterval.Minute, PriceType = PriceType.Bid, CountExpected = 5 } }); }
public void ItShouldNotUpdateSchemaVersionTo1IfMigrationNotApplicable() { var database = new DatabaseStub(3); var logger = new LoggerStub(); var schema = new Schema(database, logger); var migrator = new Migrator(schema, typeof(FirstMigration).Assembly, logger); migrator.MigrateToLatest(); Assert.That(database.Statements.Any(x => x.Contains(@"INSERT INTO [dbo].[SchemaInfo] ([Version]) VALUES (1)")), Is.False); }
public TestServiceClient(string hostName, int port, ISerializerFactory serializerFactory) { var logger = new LoggerStub(); _serviceDescriptor = ServiceDescriptor.Of <ITestService>(); _serializerFactory = serializerFactory; _tcpClient = new UnprotectedRpcTcpClient( hostName, port, new StalePooledObjectsCleaner(logger), new DateTimeProvider(), _serializerFactory, logger, null); }
public void EmptyAssetIsIgnored() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryStub(); var controller = new CandleGenerationController(repo, logger, "test component", env); controller.HandleQuote(new Quote() { AssetPair = null, IsBuy = true, Price = 1, Timestamp = Utils.ParseUtc("2017-01-01 10:10:10Z") }).Wait(); controller.HandleQuote(new Quote() { AssetPair = "", IsBuy = true, Price = 1, Timestamp = Utils.ParseUtc("2017-01-01 10:10:10Z") }).Wait(); Assert.Equal(0, repo.Stored.Count); }
public void GeneratedQuotesHaveUtcKind() { LoggerStub logger = new LoggerStub(); QuotePublisherStub publisher = new QuotePublisherStub(); QuoteFeedController controller = new QuoteFeedController(publisher, logger); // BTCUSD / BUY, 1st order controller.ProcessOrderbook(CreateOrder("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), new[] { new VolumePrice() { Volume = 1, Price = 999 }, new VolumePrice() { Volume = 1, Price = 1000 } })).Wait(); Assert.Equal(1, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:10Z"), 1000.0)); // BTCUSD / BUY, 2nd order controller.ProcessOrderbook(CreateOrder("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:11Z"), new[] { new VolumePrice() { Volume = 1, Price = 1001 }, new VolumePrice() { Volume = 1, Price = 999 } })).Wait(); Assert.Equal(2, publisher.Published.Count); publisher.Published.Last().Equals(CreateQuote("btcusd", true, Utils.ParseUtc("2017-01-01 10:10:11Z"), 1001.0)); /// Check Kind foreach (var quote in publisher.Published) { Assert.Equal(0, quote.Timestamp.Kind.CompareTo(DateTimeKind.Utc)); } }
public void ControllerHandlesRepositoryExceptions() { const string asset1 = "btcusd"; DateTime dt = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc); var logger = new LoggerStub(); ClearTable(asset1, new string[] { "sec", "minute", "min30", "hour", "day", "week", "month" }); var repo = new CandleHistoryRepositoryResolver((string asset, string tableName) => { return(CreateStorage <CandleTableEntity>(asset, tableName, logger, 2, clear: false)); }); // 2. Process incoming quotes // var env = new EnvironmentStub(new List <AssetPair>() { new AssetPair() { Id = asset1, Accuracy = 3 } }); var controller = new CandleGenerationController(repo, logger, "test component", env); for (int i = 0; i < 5; i++) { var tasks = new List <Task>(); // pass a quote and signal controller to process quotes var q = new Quote() { AssetPair = asset1, IsBuy = true, Price = i + 1, Timestamp = dt.AddMinutes(i) }; var task = controller.HandleQuote(q); tasks.Add(task); Task.WaitAll(tasks.ToArray()); // ... signal controller to process quotes controller.Tick(); int counter = 0; while (counter < 60) { Task.Delay(1000).Wait(); // Wait while produce task is finished. if (controller.QueueLength == 0) { break; } counter++; } } Assert.Equal(0, controller.QueueLength); controller.Stop(); // ... check for errors //Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count()); var logs = logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info); // 3. Read candles with repository and check count of generated candles // IEnumerable <IFeedCandle> candles = repo.GetCandlesAsync(asset1, TimeInterval.Minute, PriceType.Bid, dt.AddDays(-1), dt.AddDays(1)).Result; Assert.Equal(5, candles.Count()); candles = repo.GetCandlesAsync(asset1, TimeInterval.Sec, PriceType.Bid, dt.AddDays(-1), dt.AddDays(1)).Result; Assert.Equal(5, candles.Count()); }
public void Setup() { this.MockLogger = LoggerStub.GetLogger(); this.CallService = new SafeCallService(this.MockLogger.Object); }
public void QuotesSortedByAssetAndBuy() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryResolver((string asset, string tableName) => { return(CreateStorage <CandleTableEntity>(asset, tableName, logger)); }); DateTime dt = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc); const string asset1 = "btcusd"; const string asset2 = "btcrub"; // 1. Prepare incoming quotes // IEnumerable <Quote> quotes = new Quote[] { // Asset 1 new Quote() { AssetPair = asset1, IsBuy = true, Price = 101, Timestamp = dt }, // Second 1 // Day 1 new Quote() { AssetPair = asset1, IsBuy = true, Price = 101, Timestamp = dt.AddMilliseconds(1) }, new Quote() { AssetPair = asset1, IsBuy = true, Price = 100, Timestamp = dt.AddSeconds(2) }, // Second 2 new Quote() { AssetPair = asset1, IsBuy = false, Price = 100, Timestamp = dt.AddSeconds(10) }, // Second 3 // Asset 2 new Quote() { AssetPair = asset2, IsBuy = true, Price = 101, Timestamp = dt.AddDays(1) }, // Second 1 // Day 2 new Quote() { AssetPair = asset2, IsBuy = true, Price = 101, Timestamp = dt.AddDays(1).AddMilliseconds(1) }, new Quote() { AssetPair = asset2, IsBuy = true, Price = 100, Timestamp = dt.AddDays(1).AddSeconds(2) }, // Second 2 new Quote() { AssetPair = asset2, IsBuy = false, Price = 100, Timestamp = dt.AddDays(1).AddSeconds(10) }, // Second 3 }; // 2. Process incoming quotes // ProcessAllQuotes(quotes, repo, logger); // ... check for errors Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count()); // 3. Read candles with repository and check count of generated candles // #region "Validation" CheckCountGenerated(repo, dt.AddDays(-1), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Sec, PriceType = PriceType.Bid, CountExpected = 2 }, new { Asset = asset1, Interval = TimeInterval.Minute, PriceType = PriceType.Bid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Min30, PriceType = PriceType.Bid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Hour, PriceType = PriceType.Bid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Day, PriceType = PriceType.Bid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Month, PriceType = PriceType.Bid, CountExpected = 1 } }); CheckCountGenerated(repo, new DateTime(2016, 12, 26), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Week, PriceType = PriceType.Bid, CountExpected = 1 } }); CheckCountGenerated(repo, dt.AddDays(-1), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Sec, PriceType = PriceType.Ask, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Minute, PriceType = PriceType.Ask, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Min30, PriceType = PriceType.Ask, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Hour, PriceType = PriceType.Ask, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Day, PriceType = PriceType.Ask, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Month, PriceType = PriceType.Ask, CountExpected = 1 } }); CheckCountGenerated(repo, new DateTime(2016, 12, 26), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Week, PriceType = PriceType.Ask, CountExpected = 1 } }); CheckCountGenerated(repo, dt.AddDays(-1), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Sec, PriceType = PriceType.Mid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Minute, PriceType = PriceType.Mid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Min30, PriceType = PriceType.Mid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Hour, PriceType = PriceType.Mid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Day, PriceType = PriceType.Mid, CountExpected = 1 }, new { Asset = asset1, Interval = TimeInterval.Month, PriceType = PriceType.Mid, CountExpected = 1 } }); CheckCountGenerated(repo, new DateTime(2016, 12, 26), dt.AddDays(1), new[] { new { Asset = asset1, Interval = TimeInterval.Week, PriceType = PriceType.Mid, CountExpected = 1 } }); #endregion }
public void CandlesAreInsertedAndMerged() { var logger = new LoggerStub(); var repo = new CandleHistoryRepositoryResolver((string ast, string tableName) => { return(CreateStorage <CandleTableEntity>(ast, tableName, logger)); }); DateTime dt = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc); const string asset = "btcusd"; // 1. Prepare incoming quotes // IEnumerable <Quote> quotes = new Quote[] { new Quote() { AssetPair = asset, IsBuy = true, Price = 101, Timestamp = dt }, // Second 1 }; // 2. Process incoming quotes // ProcessAllQuotes(quotes, repo, logger); // ... check for no errors Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count()); // 3. Read candles with repository and check count of generated candles // CheckCountGenerated(repo, dt.AddDays(-1), dt.AddDays(1), new[] { new { Asset = asset, Interval = TimeInterval.Sec, PriceType = PriceType.Bid, CountExpected = 1 } }); // 4. Send more quotes that should generate two candles. One candle should be merged and one candle should be added. // IEnumerable <Quote> quotes2 = new Quote[] { new Quote() { AssetPair = asset, IsBuy = true, Price = 102, Timestamp = dt }, // Second 1 (updated) new Quote() { AssetPair = asset, IsBuy = true, Price = 103, Timestamp = dt.AddSeconds(1) }, // Second 2 }; ProcessAllQuotes(quotes2, repo, logger); // ... check for no errors Assert.Equal(0, logger.Log.Where(rec => rec.Severity != LoggerStub.Severity.Info).Count()); // 5. Validate merging // var candles = repo.GetCandlesAsync(asset, TimeInterval.Sec, PriceType.Bid, dt.AddDays(-1), dt.AddDays(1)).Result.ToArray(); Assert.Equal(2, candles.Length); // ! Low value is from the first quote Assert.True(candles[0].IsEqual(new FeedCandle() { Open = 102, Close = 102, High = 102, Low = 101, IsBuy = true, DateTime = dt })); Assert.True(candles[1].IsEqual(new FeedCandle() { Open = 103, Close = 103, High = 103, Low = 103, IsBuy = true, DateTime = dt.AddSeconds(1) })); }
private static void ProcessAllQuotes(IEnumerable <Quote> quotes, ICandleHistoryRepository repo, LoggerStub logger) { var env = new EnvironmentStub(new List <AssetPair>() { new AssetPair() { Id = "btcusd", Accuracy = 3 }, //new AssetPair() { Id = "btcrub", Accuracy = 3 } }); var controller = new CandleGenerationController(repo, logger, "test component", env); var tasks = new List <Task>(); foreach (var quote in quotes) { var task = controller.HandleQuote(quote); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); // ... signal controller to process quotes controller.Tick(); int counter = 0; while (counter < 5) { Task.Delay(1000).Wait(); // Wait while produce task is finished. if (controller.QueueLength == 0) { break; } counter++; } Assert.Equal(0, controller.QueueLength); }