• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.csuite.core;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.junit.Assert.assertThrows;
21 import static org.mockito.Mockito.when;
22 
23 import android.service.dropbox.DropBoxManagerServiceDumpProto;
24 
25 import com.android.csuite.core.DeviceUtils.DeviceTimestamp;
26 import com.android.csuite.core.DeviceUtils.DeviceUtilsException;
27 import com.android.csuite.core.DeviceUtils.DropboxEntry;
28 import com.android.tradefed.device.DeviceRuntimeException;
29 import com.android.tradefed.device.ITestDevice;
30 import com.android.tradefed.util.CommandResult;
31 import com.android.tradefed.util.CommandStatus;
32 import com.android.tradefed.util.IRunUtil;
33 
34 import com.google.common.jimfs.Jimfs;
35 import com.google.protobuf.ByteString;
36 
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.junit.runners.JUnit4;
40 import org.mockito.ArgumentMatcher;
41 import org.mockito.Mockito;
42 
43 import java.io.IOException;
44 import java.nio.file.FileSystem;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.util.Arrays;
48 import java.util.List;
49 import java.util.Set;
50 import java.util.concurrent.atomic.AtomicBoolean;
51 
52 @RunWith(JUnit4.class)
53 public final class DeviceUtilsTest {
54     private ITestDevice mDevice = Mockito.mock(ITestDevice.class);
55     private IRunUtil mRunUtil = Mockito.mock(IRunUtil.class);
56     private final FileSystem mFileSystem =
57             Jimfs.newFileSystem(com.google.common.jimfs.Configuration.unix());
58 
59     @Test
launchPackage_packageDoesNotExist_returnsFalse()60     public void launchPackage_packageDoesNotExist_returnsFalse() throws Exception {
61         when(mDevice.executeShellV2Command(Mockito.startsWith("monkey -p")))
62                 .thenReturn(createFailedCommandResult());
63         DeviceUtils sut = createSubjectUnderTest();
64 
65         assertThrows(DeviceUtilsException.class, () -> sut.launchPackage("package.name"));
66     }
67 
68     @Test
launchPackage_successfullyLaunchedThePackage_returnsTrue()69     public void launchPackage_successfullyLaunchedThePackage_returnsTrue() throws Exception {
70         when(mDevice.executeShellV2Command(Mockito.startsWith("monkey -p")))
71                 .thenReturn(createSuccessfulCommandResultWithStdout(""));
72         DeviceUtils sut = createSubjectUnderTest();
73 
74         sut.launchPackage("package.name");
75     }
76 
77     @Test
currentTimeMillis_deviceCommandFailed_throwsException()78     public void currentTimeMillis_deviceCommandFailed_throwsException() throws Exception {
79         DeviceUtils sut = createSubjectUnderTest();
80         when(mDevice.executeShellV2Command(Mockito.startsWith("echo")))
81                 .thenReturn(createFailedCommandResult());
82 
83         assertThrows(DeviceRuntimeException.class, () -> sut.currentTimeMillis());
84     }
85 
86     @Test
currentTimeMillis_unexpectedFormat_throwsException()87     public void currentTimeMillis_unexpectedFormat_throwsException() throws Exception {
88         DeviceUtils sut = createSubjectUnderTest();
89         when(mDevice.executeShellV2Command(Mockito.startsWith("echo")))
90                 .thenReturn(createSuccessfulCommandResultWithStdout(""));
91 
92         assertThrows(DeviceRuntimeException.class, () -> sut.currentTimeMillis());
93     }
94 
95     @Test
currentTimeMillis_successful_returnsTime()96     public void currentTimeMillis_successful_returnsTime() throws Exception {
97         DeviceUtils sut = createSubjectUnderTest();
98         when(mDevice.executeShellV2Command(Mockito.startsWith("echo")))
99                 .thenReturn(createSuccessfulCommandResultWithStdout("123"));
100 
101         DeviceTimestamp result = sut.currentTimeMillis();
102 
103         assertThat(result.get()).isEqualTo(Long.parseLong("123"));
104     }
105 
106     @Test
runWithScreenRecording_recordingDidNotStart_jobIsExecuted()107     public void runWithScreenRecording_recordingDidNotStart_jobIsExecuted() throws Exception {
108         DeviceUtils sut = createSubjectUnderTest();
109         when(mRunUtil.runCmdInBackground(Mockito.argThat(contains("shell", "screenrecord"))))
110                 .thenReturn(Mockito.mock(Process.class));
111         when(mDevice.executeShellV2Command(Mockito.startsWith("ls")))
112                 .thenReturn(createFailedCommandResult());
113         AtomicBoolean executed = new AtomicBoolean(false);
114         DeviceUtils.RunnableThrowingDeviceNotAvailable job = () -> executed.set(true);
115 
116         sut.runWithScreenRecording(job, video -> {});
117 
118         assertThat(executed.get()).isTrue();
119     }
120 
121     @Test
runWithScreenRecording_recordCommandThrowsException_jobIsExecuted()122     public void runWithScreenRecording_recordCommandThrowsException_jobIsExecuted()
123             throws Exception {
124         when(mRunUtil.runCmdInBackground(Mockito.argThat(contains("shell", "screenrecord"))))
125                 .thenThrow(new IOException());
126         DeviceUtils sut = createSubjectUnderTest();
127         AtomicBoolean executed = new AtomicBoolean(false);
128         DeviceUtils.RunnableThrowingDeviceNotAvailable job = () -> executed.set(true);
129 
130         sut.runWithScreenRecording(job, video -> {});
131 
132         assertThat(executed.get()).isTrue();
133     }
134 
135     @Test
runWithScreenRecording_jobThrowsException_videoFileIsHandled()136     public void runWithScreenRecording_jobThrowsException_videoFileIsHandled() throws Exception {
137         when(mRunUtil.runCmdInBackground(Mockito.argThat(contains("shell", "screenrecord"))))
138                 .thenReturn(Mockito.mock(Process.class));
139         when(mDevice.executeShellV2Command(Mockito.startsWith("ls")))
140                 .thenReturn(createSuccessfulCommandResultWithStdout(""));
141         DeviceUtils sut = createSubjectUnderTest();
142         DeviceUtils.RunnableThrowingDeviceNotAvailable job =
143                 () -> {
144                     throw new RuntimeException();
145                 };
146         AtomicBoolean handled = new AtomicBoolean(false);
147 
148         assertThrows(
149                 RuntimeException.class,
150                 () -> sut.runWithScreenRecording(job, video -> handled.set(true)));
151 
152         assertThat(handled.get()).isTrue();
153     }
154 
155     @Test
getPackageVersionName_deviceCommandFailed_returnsUnknown()156     public void getPackageVersionName_deviceCommandFailed_returnsUnknown() throws Exception {
157         DeviceUtils sut = createSubjectUnderTest();
158         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionName")))
159                 .thenReturn(createFailedCommandResult());
160 
161         String result = sut.getPackageVersionName("any");
162 
163         assertThat(result).isEqualTo(DeviceUtils.UNKNOWN);
164     }
165 
166     @Test
getPackageVersionName_deviceCommandReturnsUnexpected_returnsUnknown()167     public void getPackageVersionName_deviceCommandReturnsUnexpected_returnsUnknown()
168             throws Exception {
169         DeviceUtils sut = createSubjectUnderTest();
170         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionName")))
171                 .thenReturn(
172                         createSuccessfulCommandResultWithStdout(
173                                 "unexpected " + DeviceUtils.VERSION_NAME_PREFIX));
174 
175         String result = sut.getPackageVersionName("any");
176 
177         assertThat(result).isEqualTo(DeviceUtils.UNKNOWN);
178     }
179 
180     @Test
getPackageVersionName_deviceCommandSucceed_returnsVersionName()181     public void getPackageVersionName_deviceCommandSucceed_returnsVersionName() throws Exception {
182         DeviceUtils sut = createSubjectUnderTest();
183         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionName")))
184                 .thenReturn(
185                         createSuccessfulCommandResultWithStdout(
186                                 " " + DeviceUtils.VERSION_NAME_PREFIX + "123"));
187 
188         String result = sut.getPackageVersionName("any");
189 
190         assertThat(result).isEqualTo("123");
191     }
192 
193     @Test
getPackageVersionCode_deviceCommandFailed_returnsUnknown()194     public void getPackageVersionCode_deviceCommandFailed_returnsUnknown() throws Exception {
195         DeviceUtils sut = createSubjectUnderTest();
196         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionCode")))
197                 .thenReturn(createFailedCommandResult());
198 
199         String result = sut.getPackageVersionCode("any");
200 
201         assertThat(result).isEqualTo(DeviceUtils.UNKNOWN);
202     }
203 
204     @Test
getPackageVersionCode_deviceCommandReturnsUnexpected_returnsUnknown()205     public void getPackageVersionCode_deviceCommandReturnsUnexpected_returnsUnknown()
206             throws Exception {
207         DeviceUtils sut = createSubjectUnderTest();
208         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionCode")))
209                 .thenReturn(
210                         createSuccessfulCommandResultWithStdout(
211                                 "unexpected " + DeviceUtils.VERSION_CODE_PREFIX));
212 
213         String result = sut.getPackageVersionCode("any");
214 
215         assertThat(result).isEqualTo(DeviceUtils.UNKNOWN);
216     }
217 
218     @Test
getPackageVersionCode_deviceCommandSucceed_returnVersionCode()219     public void getPackageVersionCode_deviceCommandSucceed_returnVersionCode() throws Exception {
220         DeviceUtils sut = createSubjectUnderTest();
221         when(mDevice.executeShellV2Command(Mockito.endsWith("grep versionCode")))
222                 .thenReturn(
223                         createSuccessfulCommandResultWithStdout(
224                                 " " + DeviceUtils.VERSION_CODE_PREFIX + "123"));
225 
226         String result = sut.getPackageVersionCode("any");
227 
228         assertThat(result).isEqualTo("123");
229     }
230 
231     @Test
getDropboxEntries_noEntries_returnsEmptyList()232     public void getDropboxEntries_noEntries_returnsEmptyList() throws Exception {
233         DeviceUtils sut = createSubjectUnderTest();
234         when(mRunUtil.runTimedCmd(
235                         Mockito.anyLong(),
236                         Mockito.eq("sh"),
237                         Mockito.eq("-c"),
238                         Mockito.contains("dumpsys dropbox")))
239                 .thenReturn(createSuccessfulCommandResultWithStdout(""));
240 
241         List<DropboxEntry> result = sut.getDropboxEntries(Set.of(""));
242 
243         assertThat(result).isEmpty();
244     }
245 
246     @Test
getDropboxEntries_entryExists_returnsEntry()247     public void getDropboxEntries_entryExists_returnsEntry() throws Exception {
248         Path dumpFile = Files.createTempFile(mFileSystem.getPath("/"), "test", ".tmp");
249         long time = 123;
250         String data = "abc";
251         String tag = "tag";
252         DropBoxManagerServiceDumpProto proto =
253                 DropBoxManagerServiceDumpProto.newBuilder()
254                         .addEntries(
255                                 DropBoxManagerServiceDumpProto.Entry.newBuilder()
256                                         .setTimeMs(time)
257                                         .setData(ByteString.copyFromUtf8(data)))
258                         .build();
259         Files.write(dumpFile, proto.toByteArray());
260         DeviceUtils sut = createSubjectUnderTestWithTempFile(dumpFile);
261         when(mRunUtil.runTimedCmd(
262                         Mockito.anyLong(), Mockito.eq("sh"), Mockito.eq("-c"), Mockito.anyString()))
263                 .thenReturn(createSuccessfulCommandResultWithStdout(""));
264 
265         List<DropboxEntry> result = sut.getDropboxEntries(Set.of(tag));
266 
267         assertThat(result.get(0).getTime()).isEqualTo(time);
268         assertThat(result.get(0).getData()).isEqualTo(data);
269         assertThat(result.get(0).getTag()).isEqualTo(tag);
270     }
271 
createSubjectUnderTestWithTempFile(Path tempFile)272     private DeviceUtils createSubjectUnderTestWithTempFile(Path tempFile) {
273         when(mDevice.getSerialNumber()).thenReturn("SERIAL");
274         FakeClock fakeClock = new FakeClock();
275         return new DeviceUtils(
276                 mDevice, fakeClock.getSleeper(), fakeClock, () -> mRunUtil, () -> tempFile);
277     }
278 
createSubjectUnderTest()279     private DeviceUtils createSubjectUnderTest() {
280         when(mDevice.getSerialNumber()).thenReturn("SERIAL");
281         FakeClock fakeClock = new FakeClock();
282         return new DeviceUtils(
283                 mDevice,
284                 fakeClock.getSleeper(),
285                 fakeClock,
286                 () -> mRunUtil,
287                 () -> Files.createTempFile(mFileSystem.getPath("/"), "test", ".tmp"));
288     }
289 
290     private static class FakeClock implements DeviceUtils.Clock {
291         private long mCurrentTime = System.currentTimeMillis();
292         private DeviceUtils.Sleeper mSleeper = duration -> mCurrentTime += duration;
293 
getSleeper()294         private DeviceUtils.Sleeper getSleeper() {
295             return mSleeper;
296         }
297 
298         @Override
currentTimeMillis()299         public long currentTimeMillis() {
300             return mCurrentTime += 1;
301         }
302     }
303 
contains(String... args)304     private static ArgumentMatcher<String[]> contains(String... args) {
305         return array -> Arrays.asList(array).containsAll(Arrays.asList(args));
306     }
307 
createSuccessfulCommandResultWithStdout(String stdout)308     private static CommandResult createSuccessfulCommandResultWithStdout(String stdout) {
309         CommandResult commandResult = new CommandResult(CommandStatus.SUCCESS);
310         commandResult.setExitCode(0);
311         commandResult.setStdout(stdout);
312         commandResult.setStderr("");
313         return commandResult;
314     }
315 
createFailedCommandResult()316     private static CommandResult createFailedCommandResult() {
317         CommandResult commandResult = new CommandResult(CommandStatus.FAILED);
318         commandResult.setExitCode(1);
319         commandResult.setStdout("");
320         commandResult.setStderr("error");
321         return commandResult;
322     }
323 }
324