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 AppendAsyncTwicePageSizeEventDoesNotAddPreviousLinkToPreviousPage( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomFeedParser <XmlContentSerializer> parser, AtomEventStream <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize * 2).ToList(); events.ForEach(e => sut.AppendAsync(e).Wait()); var writtenIndex = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == sut.Id); UuidIri previousPageId = Guid.Parse( writtenIndex.Links .Single(AtomEventStream.IsPreviousFeedLink) .Href.ToString()); var previousPage = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == previousPageId); Assert.Equal( 0, previousPage.Links.Count(AtomEventStream.IsPreviousFeedLink)); }
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 AppendAsyncMoreThanPageSizeEventsStoresPreviousPage( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomFeedParser <XmlContentSerializer> parser, AtomEventStream <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize + 1).ToList(); events.ForEach(e => sut.AppendAsync(e).Wait()); var writtenIndex = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == sut.Id); UuidIri previousPageId = Guid.Parse( writtenIndex.Links .Single(AtomEventStream.IsPreviousFeedLink) .Href.ToString()); Assert.True( storage.Feeds .Select(parser.Parse) .Any(f => f.Id == previousPageId), "The previous feed should have been stored."); }
public void ReadNonPersistedFeedReturnsCorrectFeed( AtomEventsInMemory sut, UuidIri id, IContentSerializer dummySerializer) { var expectedSelfLink = AtomLink.CreateSelfLink( new Uri( ((Guid)id).ToString(), UriKind.Relative)); var before = DateTimeOffset.Now; using (var r = sut.CreateFeedReaderFor(expectedSelfLink.Href)) { var actual = AtomFeed.ReadFrom(r, dummySerializer); Assert.Equal(id, actual.Id); Assert.Equal("Index of event stream " + (Guid)id, actual.Title); Assert.True(before <= actual.Updated, "Updated should be very recent."); Assert.True(actual.Updated <= DateTimeOffset.Now, "Updated should not be in the future."); Assert.Empty(actual.Entries); Assert.Contains( expectedSelfLink, actual.Links); } }
public void SutIsInitiallyEmpty( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, AtomEventStream <DataContractTestEventX> sut) { Assert.False(sut.Any(), "Intial event stream should be empty."); Assert.Empty(sut); }
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 async Task WriteASingleEventAsynchronously() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver<object>( eventStreamId, // a Guid pageSize, // an Int32 storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; await obs.AppendAsync(userCreated); Assert.NotEmpty(storage); } }
public void AppendAsyncMoreThanPageSizeEventsStoresOldestEventsInPreviousPage( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomFeedParser <XmlContentSerializer> parser, AtomEventStream <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize + 1).ToList(); events.ForEach(e => sut.AppendAsync(e).Wait()); var writtenIndex = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == sut.Id); UuidIri previousPageId = Guid.Parse( writtenIndex.Links .Single(AtomEventStream.IsPreviousFeedLink) .Href.ToString()); var actualPreviousPage = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == previousPageId); var expectedPreviousPage = new AtomFeedLikeness( before, previousPageId, events.AsEnumerable().Reverse().Skip(1).ToArray()); Assert.True( expectedPreviousPage.Equals(actualPreviousPage), "Expected feed must match actual feed."); }
public void ReadASingleEvent() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver <object>( eventStreamId, pageSize, storage, serializer); var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; obs.OnNext(userCreated); IEnumerable <object> events = new FifoEvents <object>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var firstEvent = events.First(); var uc = Assert.IsAssignableFrom <UserCreated>(firstEvent); Assert.Equal(userCreated, uc, new SemanticComparer <UserCreated>()); } }
public void ReadASingleEvent() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver<object>( eventStreamId, pageSize, storage, serializer); var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; obs.OnNext(userCreated); IEnumerable<object> events = new FifoEvents<object>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var firstEvent = events.First(); var uc = Assert.IsAssignableFrom<UserCreated>(firstEvent); Assert.Equal(userCreated, uc, new SemanticComparer<UserCreated>()); } }
public async Task WriteASingleEventAsynchronously() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver <IUserEvent>( eventStreamId, // a Guid pageSize, // an Int32 storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; await obs.AppendAsync(userCreated); Assert.NotEmpty(storage); } }
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 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 ReadMultipleEvents() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = new DataContractContentSerializer( new TypeResolutionTable( new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "user-created", typeof(UserCreated)), new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "email-verified", typeof(EmailVerified)), new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "email-changed", typeof(EmailChanged)))); var obs = new AtomEventObserver <IUserEvent>( eventStreamId, pageSize, storage, serializer); obs.OnNext(new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }); obs.OnNext(new EmailVerified { UserId = eventStreamId, Email = "*****@*****.**" }); obs.OnNext(new EmailChanged { UserId = eventStreamId, NewEmail = "*****@*****.**" }); var events = new FifoEvents <IUserEvent>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var user = User.Fold(events); Assert.Equal(eventStreamId, user.Id); Assert.Equal("ploeh", user.Name); Assert.Equal("12345", user.Password); Assert.Equal("*****@*****.**", user.Email); Assert.False(user.EmailVerified); } }
public void OnNextAppendsItem( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, AtomEventStream <XmlAttributedTestEventX> sut, XmlAttributedTestEventX tex) { sut.OnNext(tex); Assert.Equal(tex, sut.SingleOrDefault()); }
public void AppendAsyncMoreThanTwicePageSizeEventsCreatesThreeFeedPages( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomEventStream <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var events = eventGenerator.Take(sut.PageSize * 2 + 1).ToList(); events.ForEach(e => sut.AppendAsync(e).Wait()); Assert.Equal(3, storage.Feeds.Count()); }
public void SutCanAppendAndYieldPolymorphicEvents( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, AtomEventStream <IXmlAttributedTestEvent> sut, XmlAttributedTestEventX tex, XmlAttributedTestEventY tey) { sut.AppendAsync(tex).Wait(); sut.AppendAsync(tey).Wait(); var expected = new IXmlAttributedTestEvent[] { tey, tex }; Assert.True(expected.SequenceEqual(sut)); }
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 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 ClientCanReadWrittenFeed( AtomEventsInMemory sut, AtomFeedBuilder <XmlAttributedTestEventY> feedBuilder, XmlContentSerializer serializer) { var expected = feedBuilder.Build(); 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 SutYieldsCorrectEvents( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, AtomEventStream <XmlAttributedTestEventX> sut, List <XmlAttributedTestEventX> events) { events.ForEach(e => sut.AppendAsync(e).Wait()); var expected = events.AsEnumerable().Reverse(); Assert.True( expected.SequenceEqual(sut), "Events should be yielded in a FILO order"); Assert.True( expected.Cast <object>().SequenceEqual(sut.OfType <object>()), "Events should be yielded in a FILO order"); }
public void ClientCanReadWrittenFeed( AtomEventsInMemory sut, AtomFeedBuilder<XmlAttributedTestEventY> feedBuilder, XmlContentSerializer serializer) { var expected = feedBuilder.Build(); 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 ReadASingleEvent() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = new DataContractContentSerializer( new TypeResolutionTable( new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "user-created", typeof(UserCreated)), new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "email-verified", typeof(EmailVerified)), new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "email-changed", typeof(EmailChanged)))); var obs = new AtomEventObserver <object>( eventStreamId, pageSize, storage, serializer); var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; obs.OnNext(userCreated); IEnumerable <object> events = new FifoEvents <object>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var firstEvent = events.First(); var uc = Assert.IsAssignableFrom <UserCreated>(firstEvent); Assert.Equal(userCreated, uc, new SemanticComparer <UserCreated>()); } }
public void SutCanAppendAndYieldPolymorphicEvents( [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, [Frozen] UuidIri dummyId, AtomEventObserver <IXmlAttributedTestEvent> writer, LifoEvents <IXmlAttributedTestEvent> sut, XmlAttributedTestEventX tex, XmlAttributedTestEventY tey) { writer.AppendAsync(tex).Wait(); writer.AppendAsync(tey).Wait(); var expected = new IXmlAttributedTestEvent[] { tey, tex }; Assert.True(expected.SequenceEqual(sut)); }
public void AppendAsyncCorrectlyStoresFeed( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomFeedParser <XmlContentSerializer> parser, AtomEventStream <XmlAttributedTestEventX> sut, XmlAttributedTestEventX expectedEvent) { var before = DateTimeOffset.Now; sut.AppendAsync(expectedEvent).Wait(); var writtenFeed = storage.Feeds.Select(parser.Parse).Single(); var expectedFeed = new AtomFeedLikeness(before, sut.Id, expectedEvent); Assert.True( expectedFeed.Equals(writtenFeed), "Expected feed must match actual feed."); }
public void ReadMultipleEvents() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver <IUserEvent>( eventStreamId, pageSize, storage, serializer); obs.OnNext(new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }); obs.OnNext(new EmailVerified { UserId = eventStreamId, Email = "*****@*****.**" }); obs.OnNext(new EmailChanged { UserId = eventStreamId, NewEmail = "*****@*****.**" }); var events = new FifoEvents <IUserEvent>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var user = User.Fold(events); Assert.Equal(eventStreamId, user.Id); Assert.Equal("ploeh", user.Name); Assert.Equal("12345", user.Password); Assert.Equal("*****@*****.**", user.Email); Assert.False(user.EmailVerified); } }
public void ReverseReturnsCorrectResult( UuidIri id, AtomEventsInMemory storage, XmlContentSerializer serializer) { var sut = new LifoEvents <XmlAttributedTestEventX>(id, storage, serializer); var expected = new FifoEvents <XmlAttributedTestEventX>(id, storage, serializer); var actual = sut.Reverse(); var fifo = Assert.IsType <FifoEvents <XmlAttributedTestEventX> >(actual); Assert.Equal(expected.Id, fifo.Id); Assert.Equal(expected.Storage, fifo.Storage); Assert.Equal(expected.Serializer, fifo.Serializer); }
public void SutYieldsCorrectEvents( [Frozen(As = typeof(ITypeResolver))] TestEventTypeResolver dummyResolver, [Frozen(As = typeof(IContentSerializer))] XmlContentSerializer dummySerializer, [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, [Frozen] UuidIri dummyId, AtomEventObserver <XmlAttributedTestEventX> writer, FifoEvents <XmlAttributedTestEventX> sut, List <XmlAttributedTestEventX> expected) { expected.ForEach(e => writer.AppendAsync(e).Wait()); Assert.True( expected.SequenceEqual(sut), "Events should be yielded in a FIFO order"); Assert.True( expected.Cast <object>().SequenceEqual(sut.OfType <object>()), "Events should be yielded in a FIFO order"); }
public void AppendAsyncMoreThanPageSizeEventsAddsLinkToPreviousPageToIndex( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory storage, AtomFeedParser <XmlContentSerializer> parser, AtomEventStream <XmlAttributedTestEventX> sut, Generator <XmlAttributedTestEventX> eventGenerator) { var before = DateTimeOffset.Now; var events = eventGenerator.Take(sut.PageSize + 1).ToList(); events.ForEach(e => sut.AppendAsync(e).Wait()); var writtenIndex = storage.Feeds .Select(parser.Parse) .Single(f => f.Id == sut.Id); Assert.Equal( 1, writtenIndex.Links.Count(AtomEventStream.IsPreviousFeedLink)); }
public void SutCanAppendAndYieldEnclosedPolymorphicEvents( [Frozen(As = typeof(IAtomEventStorage))] AtomEventsInMemory dummyInjectedIntoSut, AtomEventStream <DataContractEnvelope <IDataContractTestEvent> > sut, DataContractEnvelope <DataContractTestEventX> texEnvelope, DataContractEnvelope <DataContractTestEventY> teyEnvelope) { var texA = texEnvelope.Cast <IDataContractTestEvent>(); var teyA = teyEnvelope.Cast <IDataContractTestEvent>(); sut.AppendAsync(texA).Wait(); sut.AppendAsync(teyA).Wait(); var expected = new DataContractEnvelope <IDataContractTestEvent>[] { teyA, texA }; Assert.True(expected.SequenceEqual(sut)); }
public async Task WriteASingleEventAsynchronously() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = new DataContractContentSerializer( new TypeResolutionTable( new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "user-created", typeof(UserCreated)), new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "email-verified", typeof(EmailVerified)), new TypeResolutionEntry( "urn:grean:samples:user-sign-up", "email-changed", typeof(EmailChanged)))); var obs = new AtomEventObserver <IUserEvent>( eventStreamId, // a Guid pageSize, // an Int32 storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var userCreated = new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }; await obs.AppendAsync(userCreated); Assert.NotEmpty(storage); } }
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 FeedsAreInitiallyEmpty(AtomEventsInMemory sut) { IEnumerable<string> actual = sut.Feeds; Assert.Empty(actual); }
public void ReadMultipleEvents() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; /* This is an example of how to use the TypeResolutionEntry * class, so it should not be refactored to one of the terser * alternatives. */ var resolver = new TypeResolutionTable( new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "user-created", typeof(UserCreated)), new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "email-verified", typeof(EmailVerified)), new TypeResolutionEntry( "urn:grean:samples:user-on-boarding", "email-changed", typeof(EmailChanged))); var serializer = new DataContractContentSerializer(resolver); var obs = new AtomEventObserver<object>( eventStreamId, pageSize, storage, serializer); obs.OnNext(new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }); obs.OnNext(new EmailVerified { UserId = eventStreamId, Email = "*****@*****.**" }); obs.OnNext(new EmailChanged { UserId = eventStreamId, NewEmail = "*****@*****.**" }); var events = new FifoEvents<object>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var user = User.Fold(events); Assert.Equal(eventStreamId, user.Id); Assert.Equal("ploeh", user.Name); Assert.Equal("12345", user.Password); Assert.Equal("*****@*****.**", user.Email); Assert.False(user.EmailVerified); } }
public void ReadMultipleEvents() { var eventStreamId = new Guid("A0E50259-7345-48F9-84B4-BEEB5CEC662C"); using (var storage = new AtomEventsInMemory()) { var pageSize = 25; var serializer = DataContractContentSerializer.Scan( typeof(UserCreated).Assembly); var obs = new AtomEventObserver<IUserEvent>( eventStreamId, pageSize, storage, serializer); obs.OnNext(new UserCreated { UserId = eventStreamId, UserName = "******", Password = "******", Email = "*****@*****.**" }); obs.OnNext(new EmailVerified { UserId = eventStreamId, Email = "*****@*****.**" }); obs.OnNext(new EmailChanged { UserId = eventStreamId, NewEmail = "*****@*****.**" }); var events = new FifoEvents<IUserEvent>( eventStreamId, // a Guid storage, // an IAtomEventStorage object serializer); // an IContentSerializer object var user = User.Fold(events); Assert.Equal(eventStreamId, user.Id); Assert.Equal("ploeh", user.Name); Assert.Equal("12345", user.Password); Assert.Equal("*****@*****.**", user.Email); Assert.False(user.EmailVerified); } }
public void EmptySutIsEmpty(AtomEventsInMemory sut) { Assert.False(sut.Any(), "Empty store should be empty."); Assert.Empty(sut); }
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 SutIsEnumerableOfIds(AtomEventsInMemory sut) { Assert.IsAssignableFrom<IEnumerable<UuidIri>>(sut); }
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 SutIsAtomEventPersistence(AtomEventsInMemory sut) { Assert.IsAssignableFrom<IAtomEventStorage>(sut); }
public SpyAtomEventStore() { this.store = new AtomEventsInMemory(); this.observedArguments = new List<object>(); }