/** * Scenario: Download failed with network I/O error. * * <p>Verify that: * Error is not counted as failure */ @Test public void testNetworkErrorIsNotCountedAsFailure() throws Exception { DownloadContent content = createFont(); DownloadContentCatalog catalog = mockCatalogWithScheduledDownloads(content); DownloadAction action = spy(new DownloadAction(null)); doReturn(true).when(action).isConnectedToNetwork(RuntimeEnvironment.application); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); doReturn(mockNotExistingFile()) .when(action) .createTemporaryFile(RuntimeEnvironment.application, content); doReturn(mockNotExistingFile()) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); doReturn(true).when(action).hasEnoughDiskSpace(eq(content), any(File.class), any(File.class)); HttpClient client = mock(HttpClient.class); doThrow(IOException.class).when(client).execute(any(HttpUriRequest.class)); doReturn(client).when(action).buildHttpClient(); action.perform(RuntimeEnvironment.application, catalog); verify(catalog, never()).rememberFailure(eq(content), anyInt()); verify(catalog, never()).markAsDownloaded(content); }
/** * Scenario: Download is completed but verification (checksum) failed. * * <p>Verify that: * Downloaded file is deleted * File will not be extracted * Content is not * marked as downloaded in the catalog */ @Test public void testTemporaryFileWillBeDeletedIfVerificationFails() throws Exception { DownloadContent content = new DownloadContent.Builder() .setKind(DownloadContent.KIND_FONT) .setType(DownloadContent.TYPE_ASSET_ARCHIVE) .setSize(1337L) .build(); DownloadContentCatalog catalog = mock(DownloadContentCatalog.class); doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads(); DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); doNothing().when(action).download(any(HttpClient.class), anyString(), any(File.class)); doReturn(false).when(action).verify(any(File.class), anyString()); File temporaryFile = mockNotExistingFile(); doReturn(temporaryFile) .when(action) .createTemporaryFile(RuntimeEnvironment.application, content); File destinationFile = mockNotExistingFile(); doReturn(destinationFile) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); action.perform(RuntimeEnvironment.application, catalog); verify(temporaryFile).delete(); verify(action, never()).extract(any(File.class), any(File.class), anyString()); verify(catalog, never()).markAsDownloaded(content); }
/** * Scenario: Enough storage space for temporary and destination file available. * * <p>Verify that: * hasEnoughDiskSpace() returns true */ @Test public void testWithEnoughSpaceForEverything() throws Exception { DownloadContent content = createFontWithSize(2048); File destinationFile = mockNotExistingFileWithUsableSpace(4096); File temporaryFile = mockNotExistingFileWithUsableSpace(4096); DownloadAction action = new DownloadAction(null); Assert.assertTrue(action.hasEnoughDiskSpace(content, destinationFile, temporaryFile)); }
/** * Scenario: The current network is metered. * * <p>Verify that: * No download is performed on a metered network */ @Test public void testNothingIsDoneOnMeteredNetwork() throws Exception { DownloadAction action = spy(new DownloadAction(null)); doReturn(true).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); action.perform(RuntimeEnvironment.application, null); verify(action, never()).buildHttpClient(); verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class)); }
/** * Scenario: No (connected) network is available. * * <p>Verify that: * No download is performed */ @Test public void testNothingIsDoneIfNoNetworkIsAvailable() throws Exception { DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isConnectedToNetwork(RuntimeEnvironment.application); action.perform(RuntimeEnvironment.application, null); verify(action, never()).isActiveNetworkMetered(any(Context.class)); verify(action, never()).buildHttpClient(); verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class)); }
/** * Scenario: Server returns a client error (HTTP 404). * * <p>Verify that: * Situation is treated as unrecoverable (UnrecoverableDownloadContentException) */ @Test(expected = BaseAction.UnrecoverableDownloadContentException.class) public void testClientErrorsAreUnrecoverable() throws Exception { HttpClient client = mockHttpClient(404, ""); File temporaryFile = mock(File.class); doReturn(false).when(temporaryFile).exists(); DownloadAction action = spy(new DownloadAction(null)); action.download(client, TEST_URL, temporaryFile); verify(client).execute(any(HttpUriRequest.class)); }
/** * Scenario: Pretend a partially downloaded file already exists. * * <p>Verify that: * Range header is set in request * Content will be appended to existing file * * Content will be marked as downloaded in catalog */ @Test public void testResumingDownloadFromExistingFile() throws Exception { DownloadContent content = new DownloadContent.Builder() .setKind(DownloadContent.KIND_FONT) .setType(DownloadContent.TYPE_ASSET_ARCHIVE) .setSize(4223) .build(); DownloadContentCatalog catalog = mock(DownloadContentCatalog.class); doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads(); DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); File temporaryFile = mockFileWithSize(1337L); doReturn(temporaryFile) .when(action) .createTemporaryFile(RuntimeEnvironment.application, content); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); doReturn(outputStream).when(action).openFile(eq(temporaryFile), anyBoolean()); HttpClient client = mockHttpClient(HttpStatus.SC_PARTIAL_CONTENT, "HelloWorld"); doReturn(client).when(action).buildHttpClient(); File destinationFile = mockNotExistingFile(); doReturn(destinationFile) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); doReturn(true).when(action).verify(eq(temporaryFile), anyString()); doNothing().when(action).extract(eq(temporaryFile), eq(destinationFile), anyString()); action.perform(RuntimeEnvironment.application, catalog); ArgumentCaptor<HttpGet> argument = ArgumentCaptor.forClass(HttpGet.class); verify(client).execute(argument.capture()); HttpGet request = argument.getValue(); Assert.assertTrue(request.containsHeader("Range")); Assert.assertEquals("bytes=1337-", request.getFirstHeader("Range").getValue()); Assert.assertEquals("HelloWorld", new String(outputStream.toByteArray(), "UTF-8")); verify(action).openFile(eq(temporaryFile), eq(true)); verify(catalog).markAsDownloaded(content); verify(temporaryFile).delete(); }
/** * Scenario: Disk IO Error when extracting file. * * <p>Verify that: * Error is counted as failure * After multiple errors the content is marked as * permanently failed */ @Test public void testDiskIOErrorIsCountedAsFailure() throws Exception { DownloadContent content = createFont(); DownloadContentCatalog catalog = mockCatalogWithScheduledDownloads(content); doCallRealMethod().when(catalog).rememberFailure(eq(content), anyInt()); doCallRealMethod().when(catalog).markAsPermanentlyFailed(content); Assert.assertEquals(DownloadContent.STATE_NONE, content.getState()); DownloadAction action = spy(new DownloadAction(null)); doReturn(true).when(action).isConnectedToNetwork(RuntimeEnvironment.application); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); doReturn(mockNotExistingFile()) .when(action) .createTemporaryFile(RuntimeEnvironment.application, content); doReturn(mockNotExistingFile()) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); doReturn(true).when(action).hasEnoughDiskSpace(eq(content), any(File.class), any(File.class)); doNothing().when(action).download(any(HttpClient.class), anyString(), any(File.class)); doReturn(true).when(action).verify(any(File.class), anyString()); File destinationFile = mock(File.class); doReturn(false).when(destinationFile).exists(); File parentFile = mock(File.class); doReturn(false).when(parentFile).mkdirs(); doReturn(false).when(parentFile).exists(); doReturn(parentFile).when(destinationFile).getParentFile(); doReturn(destinationFile) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); for (int i = 0; i < 10; i++) { action.perform(RuntimeEnvironment.application, catalog); Assert.assertEquals(DownloadContent.STATE_NONE, content.getState()); } action.perform(RuntimeEnvironment.application, catalog); Assert.assertEquals(DownloadContent.STATE_FAILED, content.getState()); verify(catalog, times(11)).rememberFailure(eq(content), anyInt()); }
/** * Scenario: Content is scheduled for download but already exists locally (with correct checksum). * * <p>Verify that: * No download is performed for existing file * Content is marked as downloaded * in the catalog */ @Test public void testExistingAndVerifiedFilesAreNotDownloadedAgain() throws Exception { DownloadContent content = new DownloadContent.Builder().build(); DownloadContentCatalog catalog = mock(DownloadContentCatalog.class); doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads(); DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); File file = mock(File.class); doReturn(true).when(file).exists(); doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content); doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content); doReturn(true).when(action).verify(eq(file), anyString()); action.perform(RuntimeEnvironment.application, catalog); verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class)); verify(catalog).markAsDownloaded(content); }
/** * Scenario: Download fails with IOException. * * <p>Verify that: * Partially downloaded file will not be deleted * Content will not be marked as * downloaded in catalog */ @Test public void testTemporaryFileIsNotDeletedAfterDownloadAborted() throws Exception { DownloadContent content = new DownloadContent.Builder() .setKind(DownloadContent.KIND_FONT) .setType(DownloadContent.TYPE_ASSET_ARCHIVE) .setSize(4223) .build(); DownloadContentCatalog catalog = mock(DownloadContentCatalog.class); doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads(); DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); File temporaryFile = mockFileWithSize(1337L); doReturn(temporaryFile) .when(action) .createTemporaryFile(RuntimeEnvironment.application, content); ByteArrayOutputStream outputStream = spy(new ByteArrayOutputStream()); doReturn(outputStream).when(action).openFile(eq(temporaryFile), anyBoolean()); doThrow(IOException.class).when(outputStream).write(any(byte[].class), anyInt(), anyInt()); HttpClient client = mockHttpClient(HttpStatus.SC_PARTIAL_CONTENT, "HelloWorld"); doReturn(client).when(action).buildHttpClient(); doReturn(mockNotExistingFile()) .when(action) .getDestinationFile(RuntimeEnvironment.application, content); action.perform(RuntimeEnvironment.application, catalog); verify(catalog, never()).markAsDownloaded(content); verify(action, never()).verify(any(File.class), anyString()); verify(temporaryFile, never()).delete(); }