public async Task Return_from_local_cache()
            {
                // Arrange
                var expectedFile = new AppFile("acme.vanilla", "path", new byte[0]);
                var connector = new TestableAppsContextConnector("foo", new string[0]);
                connector.CachedFiles["acme.vanilla:some/file.txt"] = expectedFile;

                // Act
                var file = await connector.GetFileAsync("acme.vanilla", "some/file.txt", None);

                // Assert
                file.ShouldBeSameAs(expectedFile);
            }
            public async Task Return_from_app_or_sandbox()
            {
                // Arrange
                var connector = new TestableAppsContextConnector("foo", new string[0])
                    .WithApp(new App("acme", "vanilla", "1.2.3"))
                    .WithFileInAppOrSandbox("acme.vanilla", "1.2.3", "some/file.txt", new byte[] { 1, 2, 3 });

                // Act
                var file = await connector.GetFileAsync("acme.vanilla", "some/file.txt", None);

                // Assert
                file.App.ShouldBe("acme.vanilla");
                file.Path.ShouldBe("some/file.txt");
                file.Content.ShouldBe(new byte[] {1, 2, 3});
                connector.CachedFiles["acme.vanilla:some/file.txt"].ShouldBeSameAs(file);
            }
            public async Task Return_from_archive()
            {
                // Arrange
                var archive = new FileList(new Dictionary<string, FileListItem>
                {
                    ["some/file.txt"] = new FileListItem(AnyHash, AnySize, "abc 123", ContentEncoding.Utf8)
                });
                var connector = new TestableAppsContextConnector("some", new string[0])
                    .WithApp(new App("acme", "vanilla", "1.2.3"))
                    .WithArchive("acme.vanilla", "1.2.3", archive);

                // Act
                var file = await connector.GetFileAsync("acme.vanilla", "some/file.txt", None);

                // Assert
                file.App.ShouldBe("acme.vanilla");
                file.Path.ShouldBe("some/file.txt");
                file.Content.ShouldBe(Encoding.UTF8.GetBytes("abc 123"));
                connector.CachedFiles["acme.vanilla:some/file.txt"].ShouldBeSameAs(file);
            }
            public void Throw_error_when_file_does_not_exist_in_archive()
            {
                // Arrange
                var archive = new FileList(new Dictionary<string, FileListItem>());
                var connector = new TestableAppsContextConnector("some", new string[0])
                    .WithApp(new App("acme", "vanilla", "1.2.3"))
                    .WithArchive("acme.vanilla", "1.2.3", archive);

                // Act & Assert
                Should.Throw<AppFileNotFoundException>(() =>
                    connector.GetFileAsync("acme.vanilla", "some/file.txt", None));
            }
            public async Task Return_from_cache()
            {
                // Arrange
                var expectedArchive = new FileList(new Dictionary<string, FileListItem>());

                var appsClient = Mock.Of<IAppsClient>();
                var sandboxesClient = Mock.Of<ISandboxesClient>();

                var connector = new TestableAppsContextConnector(appsClient, sandboxesClient,
                    null, "a", new[] { "b" });
                connector.CachedArchives["acme.vanilla"] = expectedArchive;

                // Act
                var archive = await connector.GetArchiveAsync("acme.vanilla", "1.2.3");

                // Assert
                archive.ShouldBeSameAs(expectedArchive);
            }
            public void Resource_not_found_should_throw_error()
            {
                // Arrange
                var appsClient = Mock.Of<IAppsClient>();
                appsClient.Setup(x => x.ListFilesAsync("acme.vanilla", "1.2.3", It.IsAny<FileListingOptions>(), None))
                    .ThrowsAsync(new ResourceNotFoundException("bla"));
                var sandboxesClient = Mock.Of<ISandboxesClient>();

                var connector = new TestableAppsContextConnector(appsClient, sandboxesClient, null);

                // Act & Assert
                Should.Throw<ResourceNotFoundException>(() =>
                    connector.ListFilesAsync("acme.vanilla", "1.2.3"));
            }
            public async Task Return_from_cache()
            {
                // Arrange
                var appsClient = Mock.Of<IAppsClient>();
                var sandboxesClient = Mock.Of<ISandboxesClient>();
                var descriptors = new[]
                {
                    new AppFileDescriptor("acme.vanilla", "a", "A", 1),
                    new AppFileDescriptor("acme.vanilla", "b", "B", 2),
                    new AppFileDescriptor("acme.vanilla", "c", "C", 3),
                };

                var connector = new TestableAppsContextConnector(appsClient, sandboxesClient, null);
                connector.CachedFileLists["acme.vanilla"] = descriptors;

                // Act
                var files = await connector.ListFilesAsync("acme.vanilla", "1.2.3");

                // Assert
                files.ShouldBeSameAs(descriptors);
            }
            public async Task Return_from_sandbox()
            {
                // Arrange
                var archive = new FileList(new Dictionary<string, FileListItem>
                {
                    ["a"] = new FileListItem("A", 1, AnyContent, AnyEncoding),
                    ["b"] = new FileListItem("B", 2, AnyContent, AnyEncoding),
                    ["c"] = new FileListItem("C", 3, AnyContent, AnyEncoding)
                });
                var appsClient = Substitute.For<IAppsClient>();
                var sandboxesClient = Substitute.For<ISandboxesClient>();
                sandboxesClient.ListFilesAsync("acme", "cool", "vanilla", Arg.Any<FileListingOptions>(), None)
                    .Returns(Task.FromResult(archive));
                
                var sandboxes = new SandboxCollection(new[] {new Sandbox("acme", "cool", new[] {"vanilla"})});
                var connector = new TestableAppsContextConnector(appsClient, sandboxesClient, sandboxes);

                // Act
                var files = await connector.ListFilesAsync("acme.vanilla", "1.2.3");

                // Assert
                files.ShouldBe(new[]
                {
                    new AppFileDescriptor("acme.vanilla", "a", "A", 1),
                    new AppFileDescriptor("acme.vanilla", "b", "B", 2),
                    new AppFileDescriptor("acme.vanilla", "c", "C", 3),
                });
                connector.CachedFileLists["acme.vanilla"].ShouldBe(files);
            }
            public void Throw_error_when_file_from_app_or_sandbox_cannot_be_found()
            {
                // Arrange
                var connector = new TestableAppsContextConnector("foo", new string[0]);

                // Act & Assert
                Should.Throw<ResourceNotFoundException>(() =>
                    connector.GetFileAsync("acme.vanilla", "some/file.txt", None));
            }