public void WriteMoreThanPageSizeEventsAddsNextPageWithPreviousLink( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var events = eventGenerator.Take(sut.PageSize + 1).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); var previousLink = nextPage.Links.SingleOrDefault(l => l.IsPreviousLink); Assert.NotNull(previousLink); Assert.Equal( firstPage.Links.Single(l => l.IsSelfLink).Href, previousLink.Href); }
public void WritePageSizeEventsStoresAllEntriesInFirstPage( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var actual = FindFirstPage(writtenFeeds, sut.Id); var expectedFeed = new AtomFeedLikeness( before, actual.Id, events.AsEnumerable().Reverse().ToArray()); Assert.True( expectedFeed.Equals(actual), "Expected feed must match actual feed."); }
public void WriteMoreThanTwicePageSizeCorrectlyStoresOverflowingEvent( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize * 2 + 1).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); nextPage = FindNextPage(nextPage, writtenFeeds); var expectedPage = new AtomFeedLikeness( before, nextPage.Id, events.AsEnumerable().Reverse().First()); Assert.True( expectedPage.Equals(nextPage), "Expected feed must match actual feed."); }
public void WriteMoreThanPageSizeEventsCorrectlyUpdatesLastLink( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize + 1).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var index = FindIndex(writtenFeeds, sut.Id); var lastLink = index.Links.SingleOrDefault(l => l.IsLastLink); Assert.NotNull(lastLink); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); var expected = nextPage.Links.SingleOrDefault(l => l.IsSelfLink); Assert.NotNull(expected); Assert.Equal(expected.Href, lastLink.Href); }
public void WriteMoreThanPageSizeEventsWritesInCorrectOrder( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] SpyAtomEventStore spyStore, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var events = eventGenerator.Take(sut.PageSize + 1).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenFeeds = spyStore.Feeds.Select(ParseAtomFeed); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); var expected = new[] { nextPage.Id, firstPage.Id, sut.Id }; var actual = spyStore .ObservedArguments .OfType <AtomFeed>() .Select(f => f.Id) .Reverse() .Take(3) .Reverse(); Assert.Equal(expected, actual); }
public void WriteFirstEventFailsIfWritingIndexFails( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen] Mock <IAtomEventStorage> storeStub, AtomEventsInMemory innerStorage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, XmlAttributedTestEventX @event) { storeStub .Setup(s => s.CreateFeedReaderFor(It.IsAny <Uri>())) .Returns((Uri u) => innerStorage.CreateFeedReaderFor(u)); storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id != sut.Id))) .Returns((AtomFeed f) => innerStorage.CreateFeedWriterFor(f)); var expected = new Exception("On-purpose write failure."); storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id == sut.Id))) .Throws(expected); var ae = Assert.Throws <AggregateException>(() => writerFactory.Create(usage).WriteTo(sut, @event)); Assert.True( ae.InnerExceptions.Any(expected.Equals), "Expected exception not thrown."); }
public void WriteWritesEventToCorrectPageEvenIfLastLinkIsNotUpToDate( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { // Fixture setup var writer = writerFactory.Create(usage); var events = eventGenerator.Take(sut.PageSize * 2 + 1).ToList(); events.ForEach(e => writer.WriteTo(sut, e)); /* Point the 'last' link to the second page, instead of to the last * page. This simulates that when the true last page was created, * the index wasn't correctly updated. This could for example * happen due to a network failure. */ var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var index = FindIndex(writtenFeeds, sut.Id); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); var incorrectLastLink = nextPage.Links.Single(l => l.IsSelfLink).ToLastLink(); index = index.WithLinks(index.Links .Where(l => !l.IsLastLink) .Concat(new[] { incorrectLastLink })); using (var w = storage.CreateFeedWriterFor(index)) index.WriteTo(w, sut.Serializer); var expected = eventGenerator.First(); // Exercise system writer.WriteTo(sut, expected); // Verify outcome writtenFeeds = storage.Feeds.Select(ParseAtomFeed); index = FindIndex(writtenFeeds, sut.Id); firstPage = FindFirstPage(writtenFeeds, sut.Id); nextPage = FindNextPage(firstPage, writtenFeeds); nextPage = FindNextPage(nextPage, writtenFeeds); Assert.Equal(expected, nextPage.Entries.First().Content.Item); Assert.Equal( nextPage.Links.Single(l => l.IsSelfLink).Href, index.Links.Single(l => l.IsLastLink).Href); // Teardown }
public void WriteFirstEventWritesPageBeforeIndex( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] SpyAtomEventStore spyStore, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, XmlAttributedTestEventX @event) { writerFactory.Create(usage).WriteTo(sut, @event); var feed = Assert.IsAssignableFrom <AtomFeed>( spyStore.ObservedArguments.Last()); Assert.Equal(sut.Id, feed.Id); }
public void WriteTwoEventsOnlyWritesIndexOnce( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] SpyAtomEventStore spyStore, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var events = eventGenerator.Take(2).ToList(); var writer = writerFactory.Create(usage); events.ForEach(e => writer.WriteTo(sut, e)); var writtenIds = spyStore.ObservedArguments .OfType <AtomFeed>() .Select(f => f.Id); Assert.Equal(1, writtenIds.Count(id => sut.Id == id)); }
public void WriteCorrectlyStoresFeed( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, XmlAttributedTestEventX expectedEvent) { var before = DateTimeOffset.Now; writerFactory.Create(usage).WriteTo(sut, expectedEvent); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var actual = FindFirstPage(writtenFeeds, sut.Id); var expectedFeed = new AtomFeedLikeness(before, actual.Id, expectedEvent); Assert.True( expectedFeed.Equals(actual), "Expected feed must match actual feed."); }
public void WriteCorrectlyStoresLastLinkOnIndex( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, XmlAttributedTestEventX expectedEvent) { var before = DateTimeOffset.Now; writerFactory.Create(usage).WriteTo(sut, expectedEvent); var writtenFeeds = storage.Feeds.Select(ParseAtomFeed); var index = FindIndex(writtenFeeds, sut.Id); var firstLink = index.Links.SingleOrDefault(l => l.IsFirstLink); Assert.NotNull(firstLink); var lastLink = index.Links.SingleOrDefault(l => l.IsLastLink); Assert.NotNull(lastLink); Assert.Equal(firstLink.Href, lastLink.Href); }
public void AttemptToCorrecLastLinkDoesNotThrowOnFailure( AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen] Mock <IAtomEventStorage> storeStub, AtomEventsInMemory innerStorage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { // Fixture setup storeStub .Setup(s => s.CreateFeedReaderFor(It.IsAny <Uri>())) .Returns((Uri u) => innerStorage.CreateFeedReaderFor(u)); storeStub .Setup(s => s.CreateFeedWriterFor(It.IsAny <AtomFeed>())) .Returns((AtomFeed f) => innerStorage.CreateFeedWriterFor(f)); var writer = writerFactory.Create(usage); var events = eventGenerator.Take(sut.PageSize * 2 + 1).ToList(); events.ForEach(e => writer.WriteTo(sut, e)); /* Point the 'last' link to the second page, instead of to the last * page. This simulates that when the true last page was created, * the index wasn't correctly updated. This could for example * happen due to a network failure. */ var writtenFeeds = innerStorage.Feeds.Select(ParseAtomFeed); var index = FindIndex(writtenFeeds, sut.Id); var firstPage = FindFirstPage(writtenFeeds, sut.Id); var nextPage = FindNextPage(firstPage, writtenFeeds); var incorrectLastLink = nextPage.Links.Single(l => l.IsSelfLink).ToLastLink(); index = index.WithLinks(index.Links .Where(l => !l.IsLastLink) .Concat(new[] { incorrectLastLink })); using (var w = innerStorage.CreateFeedWriterFor(index)) index.WriteTo(w, sut.Serializer); /* Configure storage to fail when writing the index, but not for * other documents. */ storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id != index.Id))) .Returns((AtomFeed f) => innerStorage.CreateFeedWriterFor(f)); storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id == index.Id))) .Throws(new Exception("On-purpose write failure.")); var expected = eventGenerator.First(); // Exercise system writer.WriteTo(sut, expected); // Verify outcome writtenFeeds = innerStorage.Feeds.Select(ParseAtomFeed); var lastPage = FindLastPage(writtenFeeds, sut.Id); Assert.True( lastPage.Entries.Select(e => e.Content.Item).Any(expected.Equals), "Last written event should be present."); // Teardown }
public void WriteMoreThanPageSizeDoesNotThrowWhenIndexWriteFails( int initialPageCount, int secondaryPageCount, AtomEventWriteUsage usage, [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen] Mock <IAtomEventStorage> storeStub, AtomEventsInMemory innerStorage, AtomEventWriterFactory <XmlAttributedTestEventX> writerFactory, AtomEventObserver <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { // Fixture setup storeStub .Setup(s => s.CreateFeedReaderFor(It.IsAny <Uri>())) .Returns((Uri u) => innerStorage.CreateFeedReaderFor(u)); storeStub .Setup(s => s.CreateFeedWriterFor(It.IsAny <AtomFeed>())) .Returns((AtomFeed f) => innerStorage.CreateFeedWriterFor(f)); var writer = writerFactory.Create(usage); /* Write some pages full. */ var events = eventGenerator.Take(sut.PageSize * initialPageCount).ToList(); events.ForEach(e => writer.WriteTo(sut, e)); /* Find the index. */ var writtenFeeds = innerStorage.Feeds.Select(ParseAtomFeed); var index = FindIndex(writtenFeeds, sut.Id); /* Configure storage to fail when writing the index, but not for * other documents. */ storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id != index.Id))) .Returns((AtomFeed f) => innerStorage.CreateFeedWriterFor(f)); storeStub .Setup(s => s.CreateFeedWriterFor( It.Is <AtomFeed>(f => f.Id == index.Id))) .Throws(new Exception("On-purpose write failure.")); /* Write some more pages, this time with the index update * consistently failing. */ eventGenerator .Take(sut.PageSize * secondaryPageCount) .ToList() .ForEach(e => writer.WriteTo(sut, e)); // Exercise system var expected = eventGenerator.Take(sut.PageSize).ToList(); expected.ForEach(e => writer.WriteTo(sut, e)); // Verify outcome writtenFeeds = innerStorage.Feeds.Select(ParseAtomFeed); var lastPage = FindLastPage(writtenFeeds, sut.Id); Assert.True( lastPage.Entries .Select(e => e.Content.Item) .Reverse() .SequenceEqual(expected), "Last written events should be present." ); // Teardown }