public void Should_publish_pasta_price_as_soon_as_all_needed_RawMaterialMarketData_are_received() { // spaghetti(eggs-flour) // Prepares the marketdata mocks var eggsMarketDataMock = Substitute.For<IRawMaterialMarketData>(); eggsMarketDataMock.RawMaterialName.Returns("eggs"); var flourMarketDataMock = Substitute.For<IRawMaterialMarketData>(); flourMarketDataMock.RawMaterialName.Returns("flour"); // setup the pricing agent var sequencer = new Sequencer(new DirectDispatcher()); var pricingAgent = new PastaPricingAgent(sequencer, "spaghetti"); pricingAgent.SubscribeToMarketData(new List<IRawMaterialMarketData>() { eggsMarketDataMock, flourMarketDataMock }); var pastaPriceHasChanged = false; pricingAgent.PastaPriceChanged += (o, args) => { pastaPriceHasChanged = true; }; Check.That(pastaPriceHasChanged).IsFalse(); // Raises event for "eggs" eggsMarketDataMock.PriceChanged += Raise.EventWith(new object(), new RawMaterialPriceChangedEventArgs("eggs", 0)); Check.That(pastaPriceHasChanged).IsFalse(); // Raises event for "flour" => all needed market data has been received, the price must have been published now flourMarketDataMock.PriceChanged += Raise.EventWith(new object(), new RawMaterialPriceChangedEventArgs("flour", 0)); Check.That(pastaPriceHasChanged).IsTrue(); }
public void DoesNotLoseAnyTaskWithTwoWriterThreadsOnTheSameSequencer() { var rootDispatcher = new DotNetThreadPoolUnitOfExecution(); var sequencer = new Sequencer(rootDispatcher); const int NumberOfWritesPerThread = 10000; var tasksOutput = new List<int>(); using (var unleashThreadsEvent = new AutoResetEvent(false)) using (var firstWriterFinishedEvent = new AutoResetEvent(false)) using (var secondWriterFinishedEvent = new AutoResetEvent(false)) { var firstWriter = new Thread(() => this.WriterRoutine(sequencer, unleashThreadsEvent, 0, NumberOfWritesPerThread, tasksOutput, firstWriterFinishedEvent)); firstWriter.Start(); var secondWriter = new Thread(() => this.WriterRoutine(sequencer, unleashThreadsEvent, 0, NumberOfWritesPerThread, tasksOutput, secondWriterFinishedEvent)); secondWriter.Start(); // ready, set, mark unleashThreadsEvent.Set(); // Waits until the two writers have finished their writes Check.That(firstWriterFinishedEvent.WaitOne(2 * ThreeSecondsMax) && secondWriterFinishedEvent.WaitOne(2 * ThreeSecondsMax)).IsTrue(); // Checks that no write has been missing Check.That(tasksOutput).HasSize(2 * NumberOfWritesPerThread); } }
public void SequencerExecutesTasksInTheOrderOfTheirDispatch() { var rootDispatcher = new DotNetThreadPoolUnitOfExecution(); var sequencer = new Sequencer(rootDispatcher); const int TasksNumber = 100000; var tasksOutput = new List<int>(); using (var dispatchingFinishedEvent = new AutoResetEvent(false)) { // Dispatches tasks to the sequencer for (int i = 0; i < TasksNumber; i++) { int antiClosureSideEffectNumber = i; sequencer.Dispatch(() => tasksOutput.Add(antiClosureSideEffectNumber)); } // Indicates the end of the sequence with a final task sequencer.Dispatch(() => dispatchingFinishedEvent.Set()); // Waits for sequence completion Check.That(dispatchingFinishedEvent.WaitOne(ThreeSecondsMax)).IsTrue(); // Checks that everything was properly processed in sequence for (int k = 0; k < TasksNumber; k++) { Check.That(tasksOutput[k]).IsEqualTo(k); } } }
public void Should_Compute_expected_price_from_known_market_data_inputs() { // Check.That(pastaCalculator.Compute(flourPrice: 1.3m, eggsPrice: 2.4m, flavorPrice: 1.2m)).IsEqualTo(2.52m); // spaghetti(eggs-flour) // Prepares the marketdata mocks var eggsMarketDataMock = Substitute.For<IRawMaterialMarketData>(); eggsMarketDataMock.RawMaterialName.Returns("eggs"); var flourMarketDataMock = Substitute.For<IRawMaterialMarketData>(); flourMarketDataMock.RawMaterialName.Returns("flour"); var tomatoMarketDataMock = Substitute.For<IRawMaterialMarketData>(); tomatoMarketDataMock.RawMaterialName.Returns("tomato"); // setup the pricing agent var sequencer = new Sequencer(new DirectDispatcher()); var pricingAgent = new PastaPricingAgent(sequencer, "tomato spaghetti"); pricingAgent.SubscribeToMarketData(new List<IRawMaterialMarketData>() { eggsMarketDataMock, flourMarketDataMock, tomatoMarketDataMock }); var publishedPastaPrice = 0m; pricingAgent.PastaPriceChanged += (o, args) => { publishedPastaPrice = args.Price; }; Check.That(publishedPastaPrice).IsEqualTo(0); // Raises event for "eggs" eggsMarketDataMock.PriceChanged += Raise.EventWith(new object(), new RawMaterialPriceChangedEventArgs("eggs", 2.4m)); Check.That(publishedPastaPrice).IsEqualTo(0); // Raises event for "tomato" tomatoMarketDataMock.PriceChanged += Raise.EventWith(new object(), new RawMaterialPriceChangedEventArgs("tomato", 1.2m)); Check.That(publishedPastaPrice).IsEqualTo(0); // Raises event for "flour" => all needed market data has been received, the price must have been published now flourMarketDataMock.PriceChanged += Raise.EventWith(new object(), new RawMaterialPriceChangedEventArgs("flour", 1.3m)); const decimal ExpectedPastaPrice = 2.52m; Check.That(publishedPastaPrice).IsEqualTo(ExpectedPastaPrice); }
private void WriterRoutine(Sequencer sequencer, AutoResetEvent readySetMarkEvent, int firstIndex, int lastIndex, List<int> tasksOutput, AutoResetEvent lastTaskEvent) { readySetMarkEvent.WaitOne(ThreeSecondsMax); for (int i = firstIndex; i < lastIndex; i++) { int antiClosureSideEffectNumber = i; sequencer.Dispatch(() => tasksOutput.Add(antiClosureSideEffectNumber)); } // Indicates the end of the sequence with a final task sequencer.Dispatch(() => lastTaskEvent.Set()); }