/// <summary> /// Tests that handler does not have to remove an item from the collection /// and that the handled item is the item on which the handler completed. /// </summary> private async Task HandleableCollectionHandleNoRemovalTestCore(bool useAsync) { using var collection = new HandleableCollection <int>(); Assert.Empty(collection); var shim = new HandleableCollectionApiShim <int>(collection, useAsync); AddRangeAndVerifyItems(collection, endInclusive: 4); const int expectedItem = 2; HandleableCollection <int> .Handler handler = (int item, out bool removeItem) => { // Do not remove any item (the purpose of this test is to handle an // item without removing it). removeItem = false; // Terminate handler on some item in the middle of the collection return(expectedItem == item); }; // Wait for handled item to be returned int handledItem = await shim.Handle(handler, DefaultPositiveVerificationTimeout); Assert.Equal(expectedItem, handledItem); Assert.Equal(new int[] { 0, 1, 2, 3, 4 }, collection); }
/// <summary> /// Tests that a non-default handler can remove items independently from /// handling an item and that the handled item is the item on which /// the handler completed. /// </summary> private async Task HandleableCollectionComplexHandlerTestCore(bool useAsync) { using var collection = new HandleableCollection <int>(); Assert.Empty(collection); var shim = new HandleableCollectionApiShim <int>(collection, useAsync); const int expectedItem = 7; AddRangeAndVerifyItems(collection, endInclusive: expectedItem); HandleableCollection <int> .Handler handler = (int item, out bool removeItem) => { removeItem = false; // Remove every third item if (item % 3 == 0) { removeItem = true; } // Terminate handler on last item return(expectedItem == item); }; int handledItem = await shim.Handle(handler, DefaultPositiveVerificationTimeout); Assert.Equal(expectedItem, handledItem); Assert.Equal(new int[] { 1, 2, 4, 5, 7 }, collection); }
/// <summary> /// Tests that the default handler handles one item at a time and /// removes each item after each successful handling. /// </summary> private async Task HandleableCollectionDefaultHandlerTestCore(bool useAsync) { using var collection = new HandleableCollection <int>(); Assert.Empty(collection); var shim = new HandleableCollectionApiShim <int>(collection, useAsync); AddRangeAndVerifyItems(collection, endInclusive: 14); int expectedCollectionCount = collection.Count(); for (int item = 0; item < 15; item++) { int handledItem = await shim.Handle(DefaultPositiveVerificationTimeout); expectedCollectionCount--; Assert.Equal(item, handledItem); Assert.Equal(expectedCollectionCount, collection.Count()); } Assert.Empty(collection); await shim.Handle(DefaultNegativeVerificationTimeout, expectTimeout : true); }
/// <summary> /// Tests that handler can be added before an item is provided to the collection. /// </summary> private async Task HandleableCollectionHandleBeforeAddTestCore(bool useAsync) { using var collection = new TestHandleableCollection <int>(); Assert.Empty(collection); var shim = new HandleableCollectionApiShim <int>(collection, useAsync); // Register to be notified when handler is beginning to be processed Task handlerBeginTask = collection.WaitForHandlerBeginAsync(DefaultPositiveVerificationTimeout); const int expectedItem = 3; HandleableCollection <int> .Handler handler = (int item, out bool removeItem) => { // Terminate handler on some item in the middle of the collection if (expectedItem == item) { removeItem = true; return(true); } removeItem = false; return(false); }; // Create task that will start handling BEFORE an item is added Task <int> handleItemTask = Task.Run(() => shim.Handle(handler, DefaultPositiveVerificationTimeout)); // Wait for handler to begin processing Task delayTask = Task.Delay(5 * DefaultPositiveVerificationTimeout); Task completedTask = await Task.WhenAny(delayTask, handlerBeginTask); Assert.Equal(handlerBeginTask, completedTask); IList <(int, int)> itemsAndCounts = new List <(int, int)>() { (0, 1), (1, 2), (2, 3), (3, 3), // Item is consumed immediately, thus collection count does not change (4, 4), (5, 5) }; AddAndVerifyItems(collection, itemsAndCounts); // Wait for handled item to be returned int handledItem = await handleItemTask; Assert.Equal(expectedItem, handledItem); Assert.Equal(new int[] { 0, 1, 2, 4, 5 }, collection); }
/// <summary> /// Tests that handler does not have to remove an item from the collection /// and that the handled item is the item on which the handler completed. /// </summary> private async Task HandleableCollectionHandlerThrowsTestCore(bool useAsync) { using var collection = new HandleableCollection <int>(); Assert.Empty(collection); var shim = new HandleableCollectionApiShim <int>(collection, useAsync); AddRangeAndVerifyItems(collection, endInclusive: 4); HandleableCollection <int> .Handler handler = (int item, out bool removeItem) => { if (6 == item) { throw new InvalidOperationException(); } removeItem = false; return(false); }; Task <int> handleTask = Task.Run(() => shim.Handle(handler, DefaultPositiveVerificationTimeout)); // Task.Delay intentionally shorter than default timeout to check that Handle* // calls did not complete quickly. Task delayTask = Task.Delay(TimeSpan.FromSeconds(1)); Task completedTask = await Task.WhenAny(delayTask, handleTask); // Check that the handle task didn't complete Assert.Equal(delayTask, completedTask); IList <(int, int)> itemsAndCounts = new List <(int, int)>(); itemsAndCounts.Add((5, 6)); itemsAndCounts.Add((6, 7)); // Handler should fault on this task itemsAndCounts.Add((7, 8)); AddAndVerifyItems(collection, itemsAndCounts); // Task.Delay intentionally longer than default timeout to check that Handle* // does complete by handling a value. The delay Task is used in case the handler doesn't // handle a value and doesn't respect cancellation so as to not stall the test indefinitely. delayTask = Task.Delay(2 * DefaultPositiveVerificationTimeout); completedTask = await Task.WhenAny(delayTask, handleTask); // Check that the handle task faulted and the collection did not change Assert.Equal(handleTask, completedTask); await Assert.ThrowsAsync <InvalidOperationException>(() => handleTask); Assert.Equal(new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }, collection); }