public async Task InitializeAsyncLoadsValuesIntoCache() { var testCache = new InMemoryBlobCache(); await testCache.InsertObject("Storage:DummyNumber", 16); await testCache.InsertObject("Storage:DummyText", "Random"); var cache = Substitute.For<IBlobCache>(); cache.Get(Arg.Any<string>()).Returns(x => testCache.Get(x.Arg<string>())); var settings = new DummySettingsStorage("Storage", cache); await settings.InitializeAsync(); int number = settings.DummyNumber; string text = settings.DummyText; Assert.Equal(16, number); Assert.Equal("Random", text); cache.ReceivedWithAnyArgs(2).Get(Arg.Any<string>()); }
public async Task RetrievesCurrentUserAsync() { var cache = new InMemoryBlobCache(); await cache.InsertObject <AccountCacheItem>("user", new AccountCacheItem(CreateOctokitUser("octocat"))); var modelService = CreateTarget(hostCache: cache); var user = await modelService.GetCurrentUser(); Assert.That("octocat", Is.EqualTo(user.Login)); }
public async Task NullSearchTermDefaultsToEmptyString() { var songs = new[] { new SoundCloudSong { IsStreamable = true, StreamUrl = new Uri("http://blabla.com"), PermaLinkUrl = new Uri("http://blabla") } }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForSoundCloudCache(string.Empty), songs); var finder = new SoundCloudSongFinder(cache); var result = await finder.GetSongsAsync(); Assert.Equal(1, result.Count); }
public async Task NullSearchTermDefaultsToEmptyString() { var songs = new[] { new YoutubeSong("http://blabla", TimeSpan.Zero) }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForYoutubeCache(string.Empty), songs); var finder = new YoutubeSongFinder(cache); var result = await finder.GetSongsAsync(); Assert.Equal(1, result.Count); }
public async Task RetrievesUserFromCache() { var apiClient = Substitute.For<IApiClient>(); var cache = new InMemoryBlobCache(); await cache.InsertObject<AccountCacheItem>("user", new AccountCacheItem(CreateOctokitUser("octocat"))); var modelService = new ModelService(apiClient, cache, Substitute.For<IAvatarProvider>()); var user = await modelService.GetUserFromCache(); Assert.Equal("octocat", user.Login); }
public async Task RetrievesUserFromCache() { var apiClient = Substitute.For <IApiClient>(); var cache = new InMemoryBlobCache(); await cache.InsertObject <AccountCacheItem>("user", new AccountCacheItem(CreateOctokitUser("octocat"))); var modelService = new ModelService(apiClient, cache, Substitute.For <IAvatarProvider>()); var user = await modelService.GetUserFromCache(); Assert.Equal("octocat", user.Login); }
public async Task UsesCachedSongsIfAvailable() { const string searchTerm = "Foo"; var songs = new[] { new YoutubeSong("http://blabla", TimeSpan.Zero) }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForYoutubeCache(searchTerm), songs); var finder = new YoutubeSongFinder(cache); var result = await finder.GetSongsAsync(searchTerm); Assert.Equal(1, result.Count); }
public async Task UsesCachedSongsIfAvailable() { const string searchTerm = "Foo"; var songs = new[] { new SoundCloudSong { IsStreamable = true, StreamUrl = new Uri("http://blabla.com"), PermaLinkUrl = new Uri("http://blabla") } }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForSoundCloudCache(searchTerm), songs); var finder = new SoundCloudSongFinder(cache); var result = await finder.GetSongsAsync(searchTerm); Assert.Equal(1, result.Count); }
public async Task InitializeAsyncLoadsValuesIntoCache() { var testCache = new InMemoryBlobCache(); await testCache.InsertObject("Storage:DummyNumber", 16); await testCache.InsertObject("Storage:DummyText", "Random"); var cache = Substitute.For <IBlobCache>(); cache.Get(Arg.Any <string>()).Returns(x => testCache.Get(x.Arg <string>())); var settings = new DummySettingsStorage("Storage", cache); await settings.InitializeAsync(); int number = settings.DummyNumber; string text = settings.DummyText; Assert.Equal(16, number); Assert.Equal("Random", text); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed cache.ReceivedWithAnyArgs(2).Get(Arg.Any <string>()); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed }
public async Task PullsSearchesFromCache() { string artist = "A"; string album = "B"; string key = BlobCacheKeys.GetKeyForOnlineArtwork(artist, album); var fetcher = Substitute.For<IArtworkFetcher>(); var blobCache = new InMemoryBlobCache(); await blobCache.InsertObject(key, "TestArtworkKey"); var fixture = new ArtworkCache(blobCache, fetcher); string returned = await fixture.FetchOnline(artist, album); Assert.Equal("TestArtworkKey", returned); fetcher.DidNotReceiveWithAnyArgs().RetrieveAsync(null, null); }
public async Task PullsSearchesFromCache() { string artist = "A"; string album = "B"; string key = BlobCacheKeys.GetKeyForOnlineArtwork(artist, album); var fetcher = Substitute.For <IArtworkFetcher>(); var blobCache = new InMemoryBlobCache(); await blobCache.InsertObject(key, "TestArtworkKey"); var fixture = new ArtworkCache(blobCache, fetcher); string returned = await fixture.FetchOnline(artist, album); Assert.Equal("TestArtworkKey", returned); fetcher.DidNotReceiveWithAnyArgs().RetrieveAsync(null, null); }
public async Task ExpiredIndexClearsItems() { var expected = 5; var username = "******"; var reponame = "repo"; var cache = new InMemoryBlobCache(); var apiClient = Substitute.For <IApiClient>(); var modelService = new ModelService(apiClient, cache, Substitute.For <IAvatarProvider>()); var user = CreateOctokitUser(username); apiClient.GetUser().Returns(Observable.Return(new UserAndScopes(user, null))); apiClient.GetOrganizations().Returns(Observable.Empty <Organization>()); var act = modelService.GetAccounts().ToEnumerable().First().First(); var repo = Substitute.For <ISimpleRepositoryModel>(); repo.Name.Returns(reponame); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); var indexKey = string.Format(CultureInfo.InvariantCulture, "{0}|{1}|pr", user.Login, repo.Name); var prcache = Enumerable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Cache " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, 0)); // seed the cache prcache .Select(item => new ModelService.PullRequestCacheItem(item)) .Select(item => item.Save <ModelService.PullRequestCacheItem>(cache, indexKey).ToEnumerable().First()) .SelectMany(item => CacheIndex.AddAndSaveToIndex(cache, indexKey, item).ToEnumerable()) .ToList(); // expire the index var indexobj = await cache.GetObject <CacheIndex>(indexKey); indexobj.UpdatedAt = DateTimeOffset.UtcNow - TimeSpan.FromMinutes(6); await cache.InsertObject(indexKey, indexobj); var prlive = Observable.Range(5, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Live " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, 0)) .DelaySubscription(TimeSpan.FromMilliseconds(10)); apiClient.GetPullRequestsForRepository(user.Login, repo.Name).Returns(prlive); await modelService.InsertUser(new AccountCacheItem(user)); var col = modelService.GetPullRequests(repo); col.ProcessingDelay = TimeSpan.Zero; var count = 0; var evt = new ManualResetEvent(false); col.Subscribe(t => { // we get all the items from the cache (items 1-5), all the items from the live (items 5-9), // and 4 deletions (items 1-4) because the cache expired the items that were not // a part of the live data if (++count == 14) { evt.Set(); } }, () => { }); evt.WaitOne(); evt.Reset(); Assert.Equal(5, col.Count); Assert.Collection(col, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(5, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(6, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(7, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(8, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(9, t.Number); } ); }
public async Task ExpiredIndexReturnsLive() { var expected = 5; var username = "******"; var reponame = "repo"; var cache = new InMemoryBlobCache(); var apiClient = Substitute.For <IApiClient>(); var modelService = new ModelService(apiClient, cache, Substitute.For <IAvatarProvider>()); var user = CreateOctokitUser(username); apiClient.GetUser().Returns(Observable.Return(new UserAndScopes(user, null))); apiClient.GetOrganizations().Returns(Observable.Empty <Organization>()); var act = modelService.GetAccounts().ToEnumerable().First().First(); var repo = Substitute.For <ILocalRepositoryModel>(); repo.Name.Returns(reponame); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); var indexKey = string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, user.Login, repo.Name); var prcache = Enumerable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Cache " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)); // seed the cache prcache .Select(item => new ModelService.PullRequestCacheItem(item)) .Select(item => item.Save <ModelService.PullRequestCacheItem>(cache, indexKey).ToEnumerable().First()) .SelectMany(item => CacheIndex.AddAndSaveToIndex(cache, indexKey, item).ToEnumerable()) .ToList(); // expire the index var indexobj = await cache.GetObject <CacheIndex>(indexKey); indexobj.UpdatedAt = DateTimeOffset.UtcNow - TimeSpan.FromMinutes(6); await cache.InsertObject(indexKey, indexobj); var prlive = Observable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Live " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)) .DelaySubscription(TimeSpan.FromMilliseconds(10)); apiClient.GetPullRequestsForRepository(user.Login, repo.Name).Returns(prlive); await modelService.InsertUser(new AccountCacheItem(user)); ITrackingCollection <IPullRequestModel> col = new TrackingCollection <IPullRequestModel>(); modelService.GetPullRequests(repo, col); col.ProcessingDelay = TimeSpan.Zero; var count = 0; var done = new ReplaySubject <Unit>(); done.OnNext(Unit.Default); done.Subscribe(); col.Subscribe(t => { if (++count == expected * 2) { done.OnCompleted(); } }, () => { }); await done; Assert.Collection(col, col.Select(x => new Action <IPullRequestModel>(t => Assert.True(x.Title.StartsWith("Live")))).ToArray()); }
public async Task ExpiredIndexClearsItemsAsync() { var expected = 5; var username = "******"; var reponame = "repo"; var cache = new InMemoryBlobCache(); var apiClient = Substitute.For <IApiClient>(); var modelService = CreateTarget(apiClient: apiClient, hostCache: cache); var user = CreateOctokitUser(username); apiClient.GetUser().Returns(Observable.Return(user)); apiClient.GetOrganizations().Returns(Observable.Empty <Organization>()); var act = modelService.GetAccounts().ToEnumerable().First().First(); var repo = Substitute.For <LocalRepositoryModel>(); repo.Name.Returns(reponame); repo.Owner.Returns(user.Login); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); var indexKey = string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, user.Login, repo.Name); var prcache = Enumerable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Cache " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)); // seed the cache prcache .Select(item => new ModelService.PullRequestCacheItem(item)) .Select(item => item.Save <ModelService.PullRequestCacheItem>(cache, indexKey).ToEnumerable().First()) .SelectMany(item => CacheIndex.AddAndSaveToIndex(cache, indexKey, item).ToEnumerable()) .ToList(); // expire the index var indexobj = await cache.GetObject <CacheIndex>(indexKey); indexobj.UpdatedAt = DateTimeOffset.UtcNow - TimeSpan.FromMinutes(6); await cache.InsertObject(indexKey, indexobj); var prlive = Observable.Range(5, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Live " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, 0)) .DelaySubscription(TimeSpan.FromMilliseconds(10)); apiClient.GetPullRequestsForRepository(user.Login, repo.Name).Returns(prlive); await modelService.InsertUser(new AccountCacheItem(user)); ITrackingCollection <IPullRequestModel> col = new TrackingCollection <IPullRequestModel>(); modelService.GetPullRequests(repo, col); col.ProcessingDelay = TimeSpan.Zero; var count = 0; var done = new ReplaySubject <Unit>(); done.OnNext(Unit.Default); done.Subscribe(); col.Subscribe(t => { // we get all the items from the cache (items 1-5), all the items from the live (items 5-9), // and 4 deletions (items 1-4) because the cache expired the items that were not // a part of the live data if (++count == 14) { done.OnCompleted(); } }, () => { }); await done; Assert.That(5, Is.EqualTo(col.Count)); /**Assert.Collection(col, * t => { Assert.StartsWith("Live", t.Title); Assert.Equal(5, t.Number); }, * t => { Assert.StartsWith("Live", t.Title); Assert.Equal(6, t.Number); }, * t => { Assert.StartsWith("Live", t.Title); Assert.Equal(7, t.Number); }, * t => { Assert.StartsWith("Live", t.Title); Assert.Equal(8, t.Number); }, * t => { Assert.StartsWith("Live", t.Title); Assert.Equal(9, t.Number); } * );*/ }
public async Task ExpiredIndexClearsItems() { var expected = 5; var username = "******"; var reponame = "repo"; var cache = new InMemoryBlobCache(); var apiClient = Substitute.For<IApiClient>(); var modelService = new ModelService(apiClient, cache, Substitute.For<IAvatarProvider>()); var user = CreateOctokitUser(username); apiClient.GetUser().Returns(Observable.Return(user)); apiClient.GetOrganizations().Returns(Observable.Empty<Organization>()); var act = modelService.GetAccounts().ToEnumerable().First().First(); var repo = Substitute.For<ISimpleRepositoryModel>(); repo.Name.Returns(reponame); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); var indexKey = string.Format(CultureInfo.InvariantCulture, "{0}|{1}|pr", user.Login, repo.Name); var prcache = Enumerable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Cache " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, 0)); // seed the cache prcache .Select(item => new ModelService.PullRequestCacheItem(item)) .Select(item => item.Save<ModelService.PullRequestCacheItem>(cache, indexKey).ToEnumerable().First()) .SelectMany(item => CacheIndex.AddAndSaveToIndex(cache, indexKey, item).ToEnumerable()) .ToList(); // expire the index var indexobj = await cache.GetObject<CacheIndex>(indexKey); indexobj.UpdatedAt = DateTimeOffset.UtcNow - TimeSpan.FromMinutes(6); await cache.InsertObject(indexKey, indexobj); var prlive = Observable.Range(5, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Live " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, 0)) .DelaySubscription(TimeSpan.FromMilliseconds(10)); apiClient.GetPullRequestsForRepository(user.Login, repo.Name).Returns(prlive); await modelService.InsertUser(new AccountCacheItem(user)); var col = modelService.GetPullRequests(repo); col.ProcessingDelay = TimeSpan.Zero; var count = 0; var evt = new ManualResetEvent(false); col.Subscribe(t => { // we get all the items from the cache (items 1-5), all the items from the live (items 5-9), // and 4 deletions (items 1-4) because the cache expired the items that were not // a part of the live data if (++count == 14) evt.Set(); }, () => { }); evt.WaitOne(); evt.Reset(); Assert.Equal(5, col.Count); Assert.Collection(col, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(5, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(6, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(7, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(8, t.Number); }, t => { Assert.True(t.Title.StartsWith("Live")); Assert.Equal(9, t.Number); } ); }
public async Task ExpiredIndexReturnsLive() { var expected = 5; var username = "******"; var reponame = "repo"; var cache = new InMemoryBlobCache(); var apiClient = Substitute.For<IApiClient>(); var modelService = new ModelService(apiClient, cache, Substitute.For<IAvatarProvider>()); var user = CreateOctokitUser(username); apiClient.GetUser().Returns(Observable.Return(new UserAndScopes(user, null))); apiClient.GetOrganizations().Returns(Observable.Empty<Organization>()); var act = modelService.GetAccounts().ToEnumerable().First().First(); var repo = Substitute.For<ILocalRepositoryModel>(); repo.Name.Returns(reponame); repo.CloneUrl.Returns(new UriString("https://github.com/" + username + "/" + reponame)); var indexKey = string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, user.Login, repo.Name); var prcache = Enumerable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Cache " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)); // seed the cache prcache .Select(item => new ModelService.PullRequestCacheItem(item)) .Select(item => item.Save<ModelService.PullRequestCacheItem>(cache, indexKey).ToEnumerable().First()) .SelectMany(item => CacheIndex.AddAndSaveToIndex(cache, indexKey, item).ToEnumerable()) .ToList(); // expire the index var indexobj = await cache.GetObject<CacheIndex>(indexKey); indexobj.UpdatedAt = DateTimeOffset.UtcNow - TimeSpan.FromMinutes(6); await cache.InsertObject(indexKey, indexobj); var prlive = Observable.Range(1, expected) .Select(id => CreatePullRequest(user, id, ItemState.Open, "Live " + id, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)) .DelaySubscription(TimeSpan.FromMilliseconds(10)); apiClient.GetPullRequestsForRepository(user.Login, repo.Name).Returns(prlive); await modelService.InsertUser(new AccountCacheItem(user)); ITrackingCollection<IPullRequestModel> col = new TrackingCollection<IPullRequestModel>(); modelService.GetPullRequests(repo, col); col.ProcessingDelay = TimeSpan.Zero; var count = 0; var done = new ReplaySubject<Unit>(); done.OnNext(Unit.Default); done.Subscribe(); col.Subscribe(t => { if (++count == expected * 2) { done.OnCompleted(); } }, () => { }); await done; Assert.Collection(col, col.Select(x => new Action<IPullRequestModel>(t => Assert.True(x.Title.StartsWith("Live")))).ToArray()); }