Exemple #1
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 SutEnumeratesIndexedIndexes(
            AtomEventsInMemory sut,
            IEnumerable <AtomFeedBuilder <DataContractTestEventX> > feedBuilders,
            Mock <ITypeResolver> resolverStub)
        {
            resolverStub
            .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
            .Returns(typeof(DataContractTestEventX));
            var feeds = feedBuilders
                        .Select(b => b.Build())
                        .Select(f => f.WithLinks(f.Links.Select(MakeSelfLinkIndexed)))
                        .ToArray();

            foreach (var f in feeds)
            {
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(
                        w,
                        new DataContractContentSerializer(
                            resolverStub.Object));
            }

            var actual = sut;

            var expected = new HashSet <UuidIri>(feeds.Select(f => f.Id));

            Assert.True(
                expected.SetEquals(actual),
                "AtomEventsInMemory should yield index IDs.");
        }
        public void ClientCanReadSecondFeed(
            AtomEventsInMemory sut,
            AtomFeedBuilder<XmlAttributedTestEventX> feedBuilder1,
            AtomFeedBuilder<XmlAttributedTestEventY> feedBuilder2,
            XmlContentSerializer serializer)
        {
            var other = feedBuilder1.Build();
            var expected = feedBuilder2.Build();

            using (var w = sut.CreateFeedWriterFor(other))
                other.WriteTo(w, serializer);
            using (var w = sut.CreateFeedWriterFor(expected))
                expected.WriteTo(w, serializer);

            using (var r = sut.CreateFeedReaderFor(expected.Locate()))
            {
                var actual = AtomFeed.ReadFrom(r, serializer);

                Assert.Equal(expected, actual, new AtomFeedComparer());
            }
        }
        public void ClientCanReadSecondFeed(
            AtomEventsInMemory sut,
            AtomFeedBuilder <XmlAttributedTestEventX> feedBuilder1,
            AtomFeedBuilder <XmlAttributedTestEventY> feedBuilder2,
            XmlContentSerializer serializer)
        {
            var other    = feedBuilder1.Build();
            var expected = feedBuilder2.Build();

            using (var w = sut.CreateFeedWriterFor(other))
                other.WriteTo(w, serializer);
            using (var w = sut.CreateFeedWriterFor(expected))
                expected.WriteTo(w, serializer);

            using (var r = sut.CreateFeedReaderFor(expected.Locate()))
            {
                var actual = AtomFeed.ReadFrom(r, serializer);

                Assert.Equal(expected, actual, new AtomFeedComparer());
            }
        }
        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
        }
Exemple #6
0
        public void EnumerationStartsFromMostRecentEventEvenIfLastLinkIsStale(
            int pageCount,
            int staleCount,
            [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver,
            [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer,
            [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage,
            [Frozen] UuidIri id,
            LifoEvents <IXmlAttributedTestEvent> sut,
            AtomEventObserver <XmlAttributedTestEventX> writer,
            Generator <XmlAttributedTestEventX> eventGenerator)
        {
            // Fixture setup
            var events =
                eventGenerator.Take(writer.PageSize * pageCount + 1).ToList();

            events.ForEach(writer.OnNext);

            /* Point the 'last' link to an older 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 lastPage     = FindLastPage(writtenFeeds, id);
            var olderPage    =
                FindPreviousPage(lastPage, writtenFeeds, staleCount);
            var staleLastLink =
                olderPage.Links.Single(l => l.IsSelfLink).ToLastLink();
            var index = FindIndex(writtenFeeds, id);

            index = index.WithLinks(index.Links
                                    .Where(l => !l.IsLastLink)
                                    .Concat(new[] { staleLastLink }));
            using (var w = storage.CreateFeedWriterFor(index))
                index.WriteTo(w, sut.Serializer);

            // Exercise system

            /* (The method being exercised is actual GetEnumerator and the
             * returned implementation of IEnumerator<T>, but ToList or ToArray
             * or similar methods triggers that.) */
            var actual = sut.ToList();

            // Verify outcome
            var expected = events.AsEnumerable().Reverse();

            Assert.True(
                expected.SequenceEqual(actual),
                "All written events should be enumerated in correct order.");
        }
        public void FeedsReturnWrittenFeeds(
            AtomEventsInMemory sut,
            IEnumerable <AtomFeedBuilder <XmlAttributedTestEventY> > feedBuilders,
            XmlContentSerializer serializer)
        {
            var feeds = feedBuilders.Select(b => b.Build());

            foreach (var f in feeds)
            {
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(w, serializer);
            }

            var actual = sut.Feeds.Select(s => AtomFeed.Parse(s, serializer));

            var expected = new HashSet <AtomFeed>(feeds, new AtomFeedComparer());

            Assert.True(
                expected.SetEquals(actual),
                "Written feeds should be enumerated.");
        }
        public void SutSeemsToBeThreadSafe(
            AtomEventsInMemory sut,
            Generator <AtomFeedBuilder <DataContractTestEventX> > g,
            Mock <ITypeResolver> resolverStub)
        {
            resolverStub
            .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
            .Returns(typeof(DataContractTestEventX));
            var feeds = g.Take(500).Select(b => b.Build()).ToArray();

            var tasks = feeds
                        .AsParallel()
                        .Select(f => Task.Factory.StartNew(() =>
            {
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(
                        w,
                        new DataContractContentSerializer(
                            resolverStub.Object));
            }))
                        .ToArray();
            var readFeeds = feeds
                            .AsParallel()
                            .Select(f => f.Locate())
                            .Select(uri =>
            {
                using (var r = sut.CreateFeedReaderFor(uri))
                    return(AtomFeed.ReadFrom(
                               r,
                               new DataContractContentSerializer(
                                   resolverStub.Object)));
            })
                            .ToArray();

            Task.WaitAll(tasks);

            Assert.Equal(feeds.Length, readFeeds.Length);
        }
        public void SutOnlyEnumeratesIndexedIndexes(
            AtomEventsInMemory sut,
            Generator <AtomFeedBuilder <DataContractTestEventX> > feedBuilders,
            Mock <ITypeResolver> resolverStub)
        {
            resolverStub
            .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
            .Returns(typeof(DataContractTestEventX));
            var feeds   = feedBuilders.Select(b => b.Build()).Take(5).ToList();
            var indexes = feeds
                          .PickRandom(2)
                          .Select(f => f.WithLinks(f.Links.Select(MakeSelfLinkIndexed)))
                          .ToList();

            var feedsToWrite = feeds
                               .Where(f => !indexes.Any(i => i.Id == f.Id))
                               .Concat(indexes)
                               .ToArray()
                               .Shuffle();

            foreach (var f in feedsToWrite)
            {
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(
                        w,
                        new DataContractContentSerializer(
                            resolverStub.Object));
            }

            var actual = sut;

            var expected = new HashSet <UuidIri>(indexes.Select(f => f.Id));

            Assert.True(
                expected.SetEquals(actual),
                "AtomEventsInMemory should only yield index IDs.");
        }
        public void SutSeemsToBeThreadSafe(
            AtomEventsInMemory sut,
            Generator<AtomFeedBuilder<DataContractTestEventX>> g,
            Mock<ITypeResolver> resolverStub)
        {
            resolverStub
                .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
                .Returns(typeof(DataContractTestEventX));
            var feeds = g.Take(500).Select(b => b.Build()).ToArray();

            var tasks = feeds
                .AsParallel()
                .Select(f => Task.Factory.StartNew(() =>
                {
                    using (var w = sut.CreateFeedWriterFor(f))
                        f.WriteTo(
                            w,
                            new DataContractContentSerializer(
                                resolverStub.Object));
                }))
                .ToArray();
            var readFeeds = feeds
                .AsParallel()
                .Select(f => f.Locate())
                .Select(uri =>
                {
                    using (var r = sut.CreateFeedReaderFor(uri))
                        return AtomFeed.ReadFrom(
                            r,
                            new DataContractContentSerializer(
                                resolverStub.Object));
                })
                .ToArray();
            Task.WaitAll(tasks);

            Assert.Equal(feeds.Length, readFeeds.Length);
        }
        public void SutOnlyEnumeratesIndexedIndexes(
            AtomEventsInMemory sut,
            Generator<AtomFeedBuilder<DataContractTestEventX>> feedBuilders,
            Mock<ITypeResolver> resolverStub)
        {
            resolverStub
                .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
                .Returns(typeof(DataContractTestEventX));
            var feeds = feedBuilders.Select(b => b.Build()).Take(5).ToList();
            var indexes = feeds
                .PickRandom(2)
                .Select(f => f.WithLinks(f.Links.Select(MakeSelfLinkIndexed)))
                .ToList();

            var feedsToWrite = feeds
                .Where(f => !indexes.Any(i => i.Id == f.Id))
                .Concat(indexes)
                .ToArray()
                .Shuffle();
            foreach (var f in feedsToWrite)
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(
                        w,
                        new DataContractContentSerializer(
                            resolverStub.Object));

            var actual = sut;

            var expected = new HashSet<UuidIri>(indexes.Select(f => f.Id));
            Assert.True(
                expected.SetEquals(actual),
                "AtomEventsInMemory should only yield index IDs.");
        }
        public void SutEnumeratesIndexedIndexes(
            AtomEventsInMemory sut,
            IEnumerable<AtomFeedBuilder<DataContractTestEventX>> feedBuilders,
            Mock<ITypeResolver> resolverStub)
        {
            resolverStub
                .Setup(r => r.Resolve("test-event-x", "http://grean.rocks/dc"))
                .Returns(typeof(DataContractTestEventX));
            var feeds = feedBuilders
                .Select(b => b.Build())
                .Select(f => f.WithLinks(f.Links.Select(MakeSelfLinkIndexed)))
                .ToArray();
            foreach (var f in feeds)
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(
                        w,
                        new DataContractContentSerializer(
                            resolverStub.Object));

            var actual = sut;

            var expected = new HashSet<UuidIri>(feeds.Select(f => f.Id));
            Assert.True(
                expected.SetEquals(actual),
                "AtomEventsInMemory should yield index IDs.");
        }
        public void FeedsReturnWrittenFeeds(
            AtomEventsInMemory sut,
            IEnumerable<AtomFeedBuilder<XmlAttributedTestEventY>> feedBuilders,
            XmlContentSerializer serializer)
        {
            var feeds = feedBuilders.Select(b => b.Build());
            foreach (var f in feeds)
                using (var w = sut.CreateFeedWriterFor(f))
                    f.WriteTo(w, serializer);

            var actual = sut.Feeds.Select(s => AtomFeed.Parse(s, serializer));

            var expected = new HashSet<AtomFeed>(feeds, new AtomFeedComparer());
            Assert.True(
                expected.SetEquals(actual),
                "Written feeds should be enumerated.");
        }
Exemple #14
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
        }
Exemple #15
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
        }