1 // Copyright 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.google.android.downloader;
16 
17 import static com.google.common.truth.Truth.assertThat;
18 import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 import static java.util.concurrent.Executors.newSingleThreadExecutor;
21 
22 import com.google.common.io.Files;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import com.google.common.util.concurrent.ListeningExecutorService;
25 import java.io.File;
26 import java.net.HttpURLConnection;
27 import java.nio.channels.FileChannel;
28 import java.nio.file.StandardOpenOption;
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Rule;
32 import org.junit.Test;
33 import org.junit.rules.TemporaryFolder;
34 import org.junit.runner.RunWith;
35 import org.junit.runners.JUnit4;
36 
37 /** Unit tests for PlatformUrlEngine. */
38 @RunWith(JUnit4.class)
39 public class PlatformUrlEngineTest {
40   @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
41 
42   private MockWebServerUrlEngineTestHelper testHelper;
43   private PlatformUrlEngine engine;
44   private ListeningExecutorService executorService;
45 
46   @Before
setUp()47   public void setUp() {
48     executorService = listeningDecorator(newSingleThreadExecutor());
49     testHelper =
50         new MockWebServerUrlEngineTestHelper(
51             temporaryFolder, new TestingExecutorService(executorService));
52     engine =
53         new PlatformUrlEngine(
54             executorService, /* connectTimeoutMs= */ 1000, /* readTimeoutMs= */ 1000);
55   }
56 
57   @After
tearDown()58   public void tearDown() throws Exception {
59     testHelper.tearDown();
60     executorService.shutdown();
61   }
62 
63   @Test
executeRequest_normalResponse_succeeds()64   public void executeRequest_normalResponse_succeeds() throws Exception {
65     testHelper.executeRequest_normalResponse_succeeds(engine);
66   }
67 
68   @Test
executeRequest_responseThrottled_succeeds()69   public void executeRequest_responseThrottled_succeeds() throws Exception {
70     testHelper.executeRequest_responseThrottled_succeeds(engine);
71   }
72 
73   @Test
executeRequest_largeResponse_succeeds()74   public void executeRequest_largeResponse_succeeds() throws Exception {
75     testHelper.executeRequest_largeResponse_succeeds(
76         engine, PlatformUrlEngine.BUFFER_SIZE_BYTES * 3);
77   }
78 
79   @Test
executeRequest_closeBeforeWrite_failsAborted()80   public void executeRequest_closeBeforeWrite_failsAborted() throws Exception {
81     testHelper.executeRequest_closeBeforeWrite_failsAborted(engine);
82   }
83 
84   @Test
executeRequest_serverError_failsInternalError()85   public void executeRequest_serverError_failsInternalError() throws Exception {
86     testHelper.executeRequest_serverError_failsInternalError(engine);
87   }
88 
89   @Test
executeRequest_networkError_failsInternalError()90   public void executeRequest_networkError_failsInternalError() throws Exception {
91     testHelper.executeRequest_networkError_failsInternalError(engine);
92   }
93 
94   @Test
executeRequest_writeError_failsInternalError()95   public void executeRequest_writeError_failsInternalError() throws Exception {
96     testHelper.executeRequest_writeError_failsInternalError(engine);
97   }
98 
99   @Test
executeRequest_requestCanceled_requestNeverSent()100   public void executeRequest_requestCanceled_requestNeverSent() throws Exception {
101     testHelper.executeRequest_requestCanceled_requestNeverSent(engine);
102   }
103 
104   @Test
executeRequest_invalidUrl_failsInvalidArgument()105   public void executeRequest_invalidUrl_failsInvalidArgument() {
106     testHelper.executeRequest_invalidUrl_failsInvalidArgument(engine);
107   }
108 
109   @Test
executeRequest_fileUrl()110   public void executeRequest_fileUrl() throws Exception {
111     // Note: File url testing doesn't exist in MockWebServerUrlEngineTestHelper because
112     // it doesn't involve the MockWebServer and doesn't apply to all UrlEngine implementations.
113     String message = "foobar";
114     File sourceFile = temporaryFolder.newFile();
115     Files.asCharSink(sourceFile, UTF_8).write(message);
116 
117     String url = sourceFile.toURI().toURL().toString();
118     UrlRequest request = engine.createRequest(url).build();
119     ListenableFuture<? extends UrlResponse> responseFuture = request.send();
120     UrlResponse response = responseFuture.get();
121 
122     File targetFile = temporaryFolder.newFile();
123     FileChannel channel = FileChannel.open(targetFile.toPath(), StandardOpenOption.WRITE);
124     ListenableFuture<Long> writeFuture = response.readResponseBody(channel);
125     long bytesWritten = writeFuture.get();
126     response.close();
127     channel.close();
128 
129     assertThat(bytesWritten).isGreaterThan(0L);
130     assertThat(Files.asCharSource(targetFile, UTF_8).read()).isEqualTo(message);
131     assertThat(response.getResponseCode()).isEqualTo(HttpURLConnection.HTTP_OK);
132   }
133 }
134