1 /*
2  * Copyright (C) 2019 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 android.server.wm.intent;
18 
19 import static androidx.test.InstrumentationRegistry.getInstrumentation;
20 
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.res.AssetManager;
24 import android.os.Environment;
25 import android.platform.test.annotations.Presubmit;
26 import android.server.wm.intent.Persistence.IntentFlag;
27 import android.server.wm.intent.Persistence.TestCase;
28 
29 import androidx.test.filters.FlakyTest;
30 import androidx.test.filters.LargeTest;
31 
32 import com.google.common.collect.Lists;
33 
34 import org.json.JSONException;
35 import org.json.JSONObject;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.Parameterized;
39 
40 import java.io.BufferedInputStream;
41 import java.io.BufferedReader;
42 import java.io.File;
43 import java.io.IOException;
44 import java.io.InputStreamReader;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.util.Collection;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.stream.Collectors;
51 
52 /**
53  * This test will verify every intent_test json file in a separately run test, through JUnits
54  * Parameterized runner.
55  *
56  * Running a single test using this class is not supported.
57  * For this use case look at {@link IntentGenerationTests#verifySingle()}
58  *
59  * Note: atest CtsWindowManagerDeviceTestCases:IntentTests#verify does not work because the
60  * Parameterized runner won't expose the test that way to atest.
61  *
62  * Build/Install/Run:
63  * atest CtsWindowManagerDeviceTestCases:IntentTests
64  */
65 @FlakyTest(detail = "Promote once confirmed non-flaky")
66 @Presubmit
67 @LargeTest
68 @RunWith(Parameterized.class)
69 public class IntentTests extends IntentTestBase {
70     private static final Cases CASES = new Cases();
71 
72     /**
73      * The flag parsing table used to parse the json files.
74      */
75     private static final Map<String, IntentFlag> TABLE = CASES.createFlagParsingTable();
76     private static Context TARGET_CONTEXT = getInstrumentation().getTargetContext();
77 
78     private static final int JSON_INDENTATION_LEVEL = 4;
79 
80     /**
81      * The runner used to verify the recorded test cases.
82      */
83     private LaunchRunner mLaunchRunner;
84 
85     /**
86      * The Test case we are currently verifying.
87      */
88     private TestCase mTestCase;
89 
IntentTests(TestCase testCase, String name)90     public IntentTests(TestCase testCase, String name) {
91         mTestCase = testCase;
92     }
93 
94     /**
95      * Read all the tests in the assets of the application and create a separate test to run for
96      * each of them using the {@link org.junit.runners.Parameterized}
97      */
98     @Parameterized.Parameters(name = "{1}")
data()99     public static Collection<Object[]> data() throws IOException, JSONException {
100         return readAllFromAssets().stream().map(
101                 test -> new Object[]{test, test.getName()}).collect(
102                 Collectors.toList());
103     }
104 
105     @Test
verify()106     public void verify() {
107         mLaunchRunner.verify(TARGET_CONTEXT, mTestCase);
108     }
109 
110 
111     @Override
setUp()112     public void setUp() throws Exception {
113         super.setUp();
114         mLaunchRunner = new LaunchRunner(this);
115     }
116 
117     @Override
activitiesUsedInTest()118     List<ComponentName> activitiesUsedInTest() {
119         return mTestCase.getSetup().componentsInCase();
120     }
121 
readAllFromAssets()122     public static List<TestCase> readAllFromAssets() throws IOException, JSONException {
123         List<TestCase> testCases = Lists.newArrayList();
124         AssetManager assets = TARGET_CONTEXT.getAssets();
125 
126         List<String> testFiles = Lists.newArrayList();
127         for (String dir : assets.list("")) {
128             for (String file : assets.list(dir)) {
129                 if (file.endsWith(".json")) {
130                     testFiles.add(dir + "/" + file);
131                 }
132             }
133         }
134 
135         for (String testFile : testFiles) {
136             try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
137                     new BufferedInputStream(assets.open(testFile))))) {
138                 String jsonData = bufferedReader.lines().collect(
139                         Collectors.joining("\n"));
140 
141                 TestCase testCase = TestCase.fromJson(
142                         new JSONObject(jsonData), TABLE, testFile);
143 
144                 testCases.add(testCase);
145             }
146         }
147 
148         return testCases;
149     }
150 
writeToDocumentsStorage(TestCase testCase, int number, String dirName)151     static void writeToDocumentsStorage(TestCase testCase, int number, String dirName)
152             throws JSONException, IOException {
153         File documentsDirectory = Environment.getExternalStoragePublicDirectory(
154                 Environment.DIRECTORY_DOCUMENTS);
155         Path testsFilePath = documentsDirectory.toPath().resolve(dirName);
156 
157         if (!Files.exists(testsFilePath)) {
158             Files.createDirectories(testsFilePath);
159         }
160         Files.write(testsFilePath.resolve("test-" + number + ".json"),
161                 Lists.newArrayList(testCase.toJson().toString(JSON_INDENTATION_LEVEL)));
162     }
163 }
164 
165