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);
        }
예제 #6
0
        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));
        }
예제 #10
0
        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.");
        }
예제 #11
0
        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);
        }
예제 #12
0
        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
        }
예제 #13
0
        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
        }