BaseCompilationTest.java revision 3e3bf43a2e11fb433b43558e2e05255edfa5b6a8
1/*
2 * Copyright (C) 2015 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
17package android.databinding.compilationTest;
18
19import org.apache.commons.io.FileUtils;
20import org.apache.commons.io.IOUtils;
21import org.junit.Before;
22
23import java.io.File;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.net.URISyntaxException;
28import java.net.URL;
29import java.nio.file.Files;
30import java.nio.file.Paths;
31import java.nio.file.attribute.PosixFilePermission;
32import java.util.HashMap;
33import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
36import java.util.regex.Matcher;
37import java.util.regex.Pattern;
38
39import static org.junit.Assert.assertEquals;
40import static org.junit.Assert.assertNotNull;
41import static org.junit.Assert.assertTrue;
42
43
44public class BaseCompilationTest {
45    static Pattern VARIABLES = Pattern.compile("!@\\{([A-Za-z0-9_-]*)}");
46
47    public static final String KEY_MANIFEST_PACKAGE = "PACKAGE";
48    public static final String KEY_DEPENDENCIES = "DEPENDENCIES";
49    public static final String KEY_SETTINGS_INCLUDES = "SETTINGS_INCLUDES";
50    public static final String DEFAULT_APP_PACKAGE = "com.android.databinding.compilationTest.test";
51
52    File testFolder = new File("./build/build-test");
53
54    protected void copyResourceTo(String name, String path) throws IOException {
55        copyResourceTo(name, new File(testFolder, path));
56    }
57
58    protected void copyResourceDirectory(String name, String targetPath)
59            throws URISyntaxException, IOException {
60        URL dir = getClass().getResource(name);
61        assertNotNull(dir);
62        assertEquals("file", dir.getProtocol());
63        File folder = new File(dir.toURI());
64        assertTrue(folder.isDirectory());
65        File target = new File(testFolder, targetPath);
66        int len = folder.getAbsolutePath().length() + 1;
67        for (File item : FileUtils.listFiles(folder, null, true)) {
68            if (item.getAbsolutePath().equals(folder.getAbsolutePath())) {
69                continue;
70            }
71            String resourcePath = item.getAbsolutePath().substring(len);
72
73            copyResourceTo(name + "/" + resourcePath, new File(target, resourcePath));
74        }
75    }
76
77    @Before
78    public void clear() throws IOException {
79        if (testFolder.exists()) {
80            FileUtils.forceDelete(testFolder);
81        }
82    }
83
84    protected void copyResourceTo(String name, File targetFile) throws IOException {
85        File directory = targetFile.getParentFile();
86        FileUtils.forceMkdir(directory);
87        InputStream contents = getClass().getResourceAsStream(name);
88        FileOutputStream fos = new FileOutputStream(targetFile);
89        IOUtils.copy(contents, fos);
90        IOUtils.closeQuietly(fos);
91        IOUtils.closeQuietly(contents);
92    }
93
94    protected static Map<String, String> toMap(String... keysAndValues) {
95        assertEquals(0, keysAndValues.length % 2);
96        Map<String, String> map = new HashMap<>();
97        for (int i = 0; i < keysAndValues.length; i+=2) {
98            map.put(keysAndValues[i], keysAndValues[i + 1]);
99        }
100        return map;
101    }
102
103    protected void copyResourceTo(String name, File targetFile, Map<String, String> replacements)
104            throws IOException {
105        if (replacements.isEmpty()) {
106            copyResourceTo(name, targetFile);
107        }
108        InputStream inputStream = getClass().getResourceAsStream(name);
109        final String contents = IOUtils.toString(inputStream);
110        IOUtils.closeQuietly(inputStream);
111
112        StringBuilder out = new StringBuilder(contents.length());
113        final Matcher matcher = VARIABLES.matcher(contents);
114        int location = 0;
115        while (matcher.find()) {
116            int start = matcher.start();
117            if (start > location) {
118                out.append(contents, location, start);
119            }
120            final String key = matcher.group(1);
121            final String replacement = replacements.get(key);
122            if (replacement != null) {
123                out.append(replacement);
124            }
125            location = matcher.end();
126        }
127        if (location < contents.length()) {
128            out.append(contents, location, contents.length());
129        }
130
131        FileUtils.writeStringToFile(targetFile, out.toString());
132    }
133
134    protected void prepareProject() throws IOException, URISyntaxException {
135        prepareApp(null);
136    }
137
138    private Map<String, String> addDefaults(Map<String, String> map) {
139        if (map == null) {
140            map = new HashMap<>();
141        }
142        if (!map.containsKey(KEY_MANIFEST_PACKAGE)) {
143            map.put(KEY_MANIFEST_PACKAGE, DEFAULT_APP_PACKAGE);
144        }
145        if (!map.containsKey(KEY_SETTINGS_INCLUDES)) {
146            map.put(KEY_SETTINGS_INCLUDES, "include ':app'");
147        }
148        return map;
149    }
150
151    protected void prepareApp(Map<String, String> replacements) throws IOException,
152            URISyntaxException {
153        replacements = addDefaults(replacements);
154        // how to get build folder, pass from gradle somehow ?
155        FileUtils.forceMkdir(testFolder);
156        copyResourceTo("/AndroidManifest.xml", new File(testFolder, "app/src/main/AndroidManifest.xml"), replacements);
157        copyResourceTo("/project_build.gradle", new File(testFolder, "build.gradle"), replacements);
158        copyResourceTo("/app_build.gradle", new File(testFolder, "app/build.gradle"), replacements);
159        copyResourceTo("/settings.gradle", new File(testFolder, "settings.gradle"), replacements);
160        File localProperties = new File("../local.properties");
161        if (localProperties.exists()) {
162            FileUtils.copyFile(localProperties, new File(testFolder, "local.properties"));
163        }
164        FileUtils.copyFile(new File("../gradlew"), new File(testFolder, "gradlew"));
165        FileUtils.copyDirectory(new File("../gradle"), new File(testFolder, "gradle"));
166    }
167
168    protected void prepareModule(String moduleName, String packageName,
169            Map<String, String> replacements) throws IOException, URISyntaxException {
170        replacements = addDefaults(replacements);
171        replacements.put(KEY_MANIFEST_PACKAGE, packageName);
172        File moduleFolder = new File(testFolder, moduleName);
173        if (moduleFolder.exists()) {
174            FileUtils.forceDelete(moduleFolder);
175        }
176        FileUtils.forceMkdir(moduleFolder);
177        copyResourceTo("/AndroidManifest.xml",
178                new File(moduleFolder, "src/main/AndroidManifest.xml"), replacements);
179        copyResourceTo("/module_build.gradle", new File(moduleFolder, "build.gradle"), replacements);
180    }
181
182    protected CompilationResult runGradle(String params) throws IOException, InterruptedException {
183        setExecutable();
184        File pathToExecutable = new File(testFolder, "gradlew");
185        ProcessBuilder builder = new ProcessBuilder(pathToExecutable.getAbsolutePath(), params);
186        builder.environment().putAll(System.getenv());
187        builder.directory(testFolder);
188        //builder.redirectErrorStream(true); // merges error and input streams
189        Process process =  builder.start();
190        String output = IOUtils.toString(process.getInputStream());
191        String error = IOUtils.toString(process.getErrorStream());
192        int result = process.waitFor();
193        return new CompilationResult(result, output, error);
194    }
195
196    private void setExecutable() throws IOException {
197        Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
198        //add owners permission
199        perms.add(PosixFilePermission.OWNER_READ);
200        perms.add(PosixFilePermission.OWNER_WRITE);
201        perms.add(PosixFilePermission.OWNER_EXECUTE);
202        //add group permissions
203        perms.add(PosixFilePermission.GROUP_READ);
204        //add others permissions
205        perms.add(PosixFilePermission.OTHERS_READ);
206        Files.setPosixFilePermissions(Paths.get(new File(testFolder, "gradlew").getAbsolutePath()), perms);
207    }
208
209
210}
211