• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
17 package com.android.cts.netpolicy;
18 
19 import static com.android.cts.netpolicy.arguments.InstrumentationArguments.ARG_CONNECTION_CHECK_CUSTOM_URL;
20 
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.fail;
24 
25 import android.platform.test.flag.junit.CheckFlagsRule;
26 import android.platform.test.flag.junit.host.HostFlagsValueProvider;
27 
28 import com.android.ddmlib.Log;
29 import com.android.tradefed.config.Option;
30 import com.android.tradefed.device.DeviceNotAvailableException;
31 import com.android.tradefed.invoker.TestInformation;
32 import com.android.tradefed.targetprep.BuildError;
33 import com.android.tradefed.targetprep.TargetSetupError;
34 import com.android.tradefed.targetprep.suite.SuiteApkInstaller;
35 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
36 import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
37 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
38 import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
39 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
40 import com.android.tradefed.util.RunUtil;
41 
42 import org.junit.Rule;
43 import org.junit.runner.RunWith;
44 
45 import java.util.Map;
46 
47 @RunWith(DeviceJUnit4ClassRunner.class)
48 abstract class HostsideNetworkPolicyTestCase extends BaseHostJUnit4Test {
49     protected static final boolean DEBUG = false;
50     protected static final String TAG = "HostsideNetworkPolicyTests";
51     protected static final String TEST_PKG = "com.android.cts.netpolicy.hostside";
52     protected static final String TEST_APK = "CtsHostsideNetworkPolicyTestsApp.apk";
53     protected static final String TEST_APP2_PKG = "com.android.cts.netpolicy.hostside.app2";
54     protected static final String TEST_APP2_APK = "CtsHostsideNetworkPolicyTestsApp2.apk";
55 
56     @Option(name = "custom-url", importance = Option.Importance.IF_UNSET,
57             description = "A custom url to use for testing network connections")
58     protected String mCustomUrl;
59 
60     @Rule
61     public final CheckFlagsRule mCheckFlagsRule =
62             HostFlagsValueProvider.createCheckFlagsRule(this::getDevice);
63 
64     @BeforeClassWithInfo
setUpOnceBase(TestInformation testInfo)65     public static void setUpOnceBase(TestInformation testInfo) throws Exception {
66         uninstallPackage(testInfo, TEST_PKG, false);
67         installPackage(testInfo, TEST_APK);
68     }
69 
70     @AfterClassWithInfo
tearDownOnceBase(TestInformation testInfo)71     public static void tearDownOnceBase(TestInformation testInfo)
72             throws DeviceNotAvailableException {
73         uninstallPackage(testInfo, TEST_PKG, true);
74     }
75 
76     // Custom static method to install the specified package, this is used to bypass auto-cleanup
77     // per test in BaseHostJUnit4.
installPackage(TestInformation testInfo, String apk)78     protected static void installPackage(TestInformation testInfo, String apk)
79             throws DeviceNotAvailableException, TargetSetupError {
80         assertNotNull(testInfo);
81         final int userId = testInfo.getDevice().getCurrentUser();
82         final SuiteApkInstaller installer = new SuiteApkInstaller();
83         // Force the apk clean up
84         installer.setCleanApk(true);
85         installer.addTestFileName(apk);
86         installer.setUserId(userId);
87         installer.setShouldGrantPermission(true);
88         installer.addInstallArg("-t");
89         try {
90             installer.setUp(testInfo);
91         } catch (BuildError e) {
92             throw new TargetSetupError(
93                     e.getMessage(), e, testInfo.getDevice().getDeviceDescriptor(), e.getErrorId());
94         }
95     }
96 
installPackage(String apk)97     protected void installPackage(String apk) throws DeviceNotAvailableException, TargetSetupError {
98         installPackage(getTestInformation(), apk);
99     }
100 
uninstallPackage(TestInformation testInfo, String packageName, boolean shouldSucceed)101     protected static void uninstallPackage(TestInformation testInfo, String packageName,
102             boolean shouldSucceed)
103             throws DeviceNotAvailableException {
104         assertNotNull(testInfo);
105         final String result = testInfo.getDevice().uninstallPackage(packageName);
106         if (shouldSucceed) {
107             assertNull("uninstallPackage(" + packageName + ") failed: " + result, result);
108         }
109     }
110 
uninstallPackage(String packageName, boolean shouldSucceed)111     protected void uninstallPackage(String packageName,
112             boolean shouldSucceed)
113             throws DeviceNotAvailableException {
114         uninstallPackage(getTestInformation(), packageName, shouldSucceed);
115     }
116 
assertPackageUninstalled(String packageName)117     protected void assertPackageUninstalled(String packageName) throws DeviceNotAvailableException {
118         final String command = "cmd package list packages " + packageName;
119         final int max_tries = 5;
120         for (int i = 1; i <= max_tries; i++) {
121             final String result = runCommand(command);
122             if (result.trim().isEmpty()) {
123                 return;
124             }
125             // 'list packages' filters by substring, so we need to iterate with the results
126             // and check one by one, otherwise 'com.android.cts.netpolicy.hostside' could return
127             // 'com.android.cts.netpolicy.hostside.app2'
128             boolean found = false;
129             for (String line : result.split("[\\r\\n]+")) {
130                 if (line.endsWith(packageName)) {
131                     found = true;
132                     break;
133                 }
134             }
135             if (!found) {
136                 return;
137             }
138             Log.v(TAG, "Package " + packageName + " not uninstalled yet (" + result
139                     + "); sleeping 1s before polling again");
140             RunUtil.getDefault().sleep(1000);
141         }
142         fail("Package '" + packageName + "' not uinstalled after " + max_tries + " seconds");
143     }
144 
getUid(String packageName)145     protected int getUid(String packageName) throws DeviceNotAvailableException {
146         final int currentUser = getDevice().getCurrentUser();
147         final String uidLines = runCommand(
148                 "cmd package list packages -U --user " + currentUser + " " + packageName);
149         for (String uidLine : uidLines.split("\n")) {
150             if (uidLine.startsWith("package:" + packageName + " uid:")) {
151                 final String[] uidLineParts = uidLine.split(":");
152                 // 3rd entry is package uid
153                 return Integer.parseInt(uidLineParts[2].trim());
154             }
155         }
156         throw new IllegalStateException("Failed to find the test app on the device; pkg="
157                 + packageName + ", u=" + currentUser);
158     }
159 
runDeviceTestsWithCustomOptions(String packageName, String className)160     protected boolean runDeviceTestsWithCustomOptions(String packageName, String className)
161             throws DeviceNotAvailableException {
162         return runDeviceTestsWithCustomOptions(packageName, className, null);
163     }
164 
runDeviceTestsWithCustomOptions(String packageName, String className, String methodName)165     protected boolean runDeviceTestsWithCustomOptions(String packageName, String className,
166             String methodName) throws DeviceNotAvailableException {
167         return runDeviceTestsWithCustomOptions(packageName, className, methodName, null);
168     }
169 
runDeviceTestsWithCustomOptions(String packageName, String className, String methodName, Map<String, String> testArgs)170     protected boolean runDeviceTestsWithCustomOptions(String packageName, String className,
171             String methodName, Map<String, String> testArgs) throws DeviceNotAvailableException {
172         final DeviceTestRunOptions deviceTestRunOptions = new DeviceTestRunOptions(packageName)
173                 .setTestClassName(className)
174                 .setTestMethodName(methodName);
175 
176         // Currently there is only one custom option that the test exposes.
177         if (mCustomUrl != null) {
178             deviceTestRunOptions.addInstrumentationArg(ARG_CONNECTION_CHECK_CUSTOM_URL, mCustomUrl);
179         }
180         // Pass over any test specific arguments.
181         if (testArgs != null) {
182             for (Map.Entry<String, String> arg : testArgs.entrySet()) {
183                 deviceTestRunOptions.addInstrumentationArg(arg.getKey(), arg.getValue());
184             }
185         }
186         return runDeviceTests(deviceTestRunOptions);
187     }
188 
runCommand(String command)189     protected String runCommand(String command) throws DeviceNotAvailableException {
190         Log.d(TAG, "Command: '" + command + "'");
191         final String output = getDevice().executeShellCommand(command);
192         if (DEBUG) Log.v(TAG, "Output: " + output.trim());
193         return output;
194     }
195 }
196