BaseCompilationTest.java revision aafbe5a2394ff9826201cca97d3298a9f355e311
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.apache.commons.lang3.StringUtils; 22import org.junit.Before; 23import org.junit.Rule; 24import org.junit.rules.TestName; 25 26import android.databinding.tool.store.Location; 27 28import java.io.File; 29import java.io.FileOutputStream; 30import java.io.IOException; 31import java.io.InputStream; 32import java.net.URISyntaxException; 33import java.net.URL; 34import java.nio.file.Files; 35import java.nio.file.Paths; 36import java.nio.file.attribute.PosixFilePermission; 37import java.util.ArrayList; 38import java.util.Collections; 39import java.util.HashMap; 40import java.util.HashSet; 41import java.util.List; 42import java.util.Map; 43import java.util.Set; 44import java.util.regex.Matcher; 45import java.util.regex.Pattern; 46 47import static org.junit.Assert.assertEquals; 48import static org.junit.Assert.assertNotNull; 49import static org.junit.Assert.assertTrue; 50 51 52public class BaseCompilationTest { 53 @Rule 54 public TestName name = new TestName(); 55 static Pattern VARIABLES = Pattern.compile("!@\\{([A-Za-z0-9_-]*)}"); 56 57 public static final String KEY_MANIFEST_PACKAGE = "PACKAGE"; 58 public static final String KEY_DEPENDENCIES = "DEPENDENCIES"; 59 public static final String KEY_SETTINGS_INCLUDES = "SETTINGS_INCLUDES"; 60 public static final String DEFAULT_APP_PACKAGE = "com.android.databinding.compilationTest.test"; 61 public static final String KEY_CLASS_NAME = "CLASSNAME"; 62 public static final String KEY_CLASS_TYPE = "CLASSTYPE"; 63 public static final String KEY_IMPORT_TYPE = "IMPORTTYPE"; 64 public static final String KEY_INCLUDE_ID = "INCLUDEID"; 65 public static final String KEY_VIEW_ID = "VIEWID"; 66 67 protected final File testFolder = new File("./build/build-test"); 68 69 protected void copyResourceTo(String name, String path) throws IOException { 70 copyResourceTo(name, new File(testFolder, path)); 71 } 72 73 protected void copyResourceTo(String name, String path, Map<String, String> replacements) 74 throws IOException { 75 copyResourceTo(name, new File(testFolder, path), replacements); 76 } 77 78 protected void copyResourceDirectory(String name, String targetPath) 79 throws URISyntaxException, IOException { 80 URL dir = getClass().getResource(name); 81 assertNotNull(dir); 82 assertEquals("file", dir.getProtocol()); 83 File folder = new File(dir.toURI()); 84 assertTrue(folder.isDirectory()); 85 File target = new File(testFolder, targetPath); 86 int len = folder.getAbsolutePath().length() + 1; 87 for (File item : FileUtils.listFiles(folder, null, true)) { 88 if (item.getAbsolutePath().equals(folder.getAbsolutePath())) { 89 continue; 90 } 91 String resourcePath = item.getAbsolutePath().substring(len); 92 93 copyResourceTo(name + "/" + resourcePath, new File(target, resourcePath)); 94 } 95 } 96 97 @Before 98 public void clear() throws IOException { 99 if (testFolder.exists()) { 100 FileUtils.forceDelete(testFolder); 101 } 102 } 103 104 /** 105 * Extracts the text in the given location from the the at the given application path. 106 * @param pathInApp The path, relative to the root of the application under test 107 * @param location The location to extract 108 * @return The string that is contained in the given location 109 * @throws IOException If file is invalid. 110 */ 111 protected String extract(String pathInApp, Location location) throws IOException { 112 File file = new File(testFolder, pathInApp); 113 assertTrue(file.exists()); 114 StringBuilder result = new StringBuilder(); 115 List<String> lines = FileUtils.readLines(file); 116 for (int i = location.startLine; i <= location.endLine; i ++) { 117 if (i > location.startLine) { 118 result.append("\n"); 119 } 120 String line = lines.get(i); 121 int start = 0; 122 if (i == location.startLine) { 123 start = location.startOffset; 124 } 125 int end = line.length() - 1; // inclusive 126 if (i == location.endLine) { 127 end = location.endOffset; 128 } 129 result.append(line.substring(start, end + 1)); 130 } 131 return result.toString(); 132 } 133 134 protected void copyResourceTo(String name, File targetFile) throws IOException { 135 File directory = targetFile.getParentFile(); 136 FileUtils.forceMkdir(directory); 137 InputStream contents = getClass().getResourceAsStream(name); 138 FileOutputStream fos = new FileOutputStream(targetFile); 139 IOUtils.copy(contents, fos); 140 IOUtils.closeQuietly(fos); 141 IOUtils.closeQuietly(contents); 142 } 143 144 protected static Map<String, String> toMap(String... keysAndValues) { 145 assertEquals(0, keysAndValues.length % 2); 146 Map<String, String> map = new HashMap<>(); 147 for (int i = 0; i < keysAndValues.length; i+=2) { 148 map.put(keysAndValues[i], keysAndValues[i + 1]); 149 } 150 return map; 151 } 152 153 protected void copyResourceTo(String name, File targetFile, Map<String, String> replacements) 154 throws IOException { 155 if (replacements.isEmpty()) { 156 copyResourceTo(name, targetFile); 157 } 158 InputStream inputStream = getClass().getResourceAsStream(name); 159 final String contents = IOUtils.toString(inputStream); 160 IOUtils.closeQuietly(inputStream); 161 162 StringBuilder out = new StringBuilder(contents.length()); 163 final Matcher matcher = VARIABLES.matcher(contents); 164 int location = 0; 165 while (matcher.find()) { 166 int start = matcher.start(); 167 if (start > location) { 168 out.append(contents, location, start); 169 } 170 final String key = matcher.group(1); 171 final String replacement = replacements.get(key); 172 if (replacement != null) { 173 out.append(replacement); 174 } 175 location = matcher.end(); 176 } 177 if (location < contents.length()) { 178 out.append(contents, location, contents.length()); 179 } 180 181 FileUtils.writeStringToFile(targetFile, out.toString()); 182 } 183 184 protected void prepareProject() throws IOException, URISyntaxException { 185 prepareApp(null); 186 } 187 188 private Map<String, String> addDefaults(Map<String, String> map) { 189 if (map == null) { 190 map = new HashMap<>(); 191 } 192 if (!map.containsKey(KEY_MANIFEST_PACKAGE)) { 193 map.put(KEY_MANIFEST_PACKAGE, DEFAULT_APP_PACKAGE); 194 } 195 if (!map.containsKey(KEY_SETTINGS_INCLUDES)) { 196 map.put(KEY_SETTINGS_INCLUDES, "include ':app'"); 197 } 198 return map; 199 } 200 201 protected void prepareApp(Map<String, String> replacements) throws IOException, 202 URISyntaxException { 203 replacements = addDefaults(replacements); 204 // how to get build folder, pass from gradle somehow ? 205 FileUtils.forceMkdir(testFolder); 206 copyResourceTo("/AndroidManifest.xml", new File(testFolder, "app/src/main/AndroidManifest.xml"), replacements); 207 copyResourceTo("/project_build.gradle", new File(testFolder, "build.gradle"), replacements); 208 copyResourceTo("/app_build.gradle", new File(testFolder, "app/build.gradle"), replacements); 209 copyResourceTo("/settings.gradle", new File(testFolder, "settings.gradle"), replacements); 210 File localProperties = new File("../local.properties"); 211 if (localProperties.exists()) { 212 FileUtils.copyFile(localProperties, new File(testFolder, "local.properties")); 213 } 214 FileUtils.copyFile(new File("../gradlew"), new File(testFolder, "gradlew")); 215 FileUtils.copyDirectory(new File("../gradle"), new File(testFolder, "gradle")); 216 } 217 218 protected void prepareModule(String moduleName, String packageName, 219 Map<String, String> replacements) throws IOException, URISyntaxException { 220 replacements = addDefaults(replacements); 221 replacements.put(KEY_MANIFEST_PACKAGE, packageName); 222 File moduleFolder = new File(testFolder, moduleName); 223 if (moduleFolder.exists()) { 224 FileUtils.forceDelete(moduleFolder); 225 } 226 FileUtils.forceMkdir(moduleFolder); 227 copyResourceTo("/AndroidManifest.xml", 228 new File(moduleFolder, "src/main/AndroidManifest.xml"), replacements); 229 copyResourceTo("/module_build.gradle", new File(moduleFolder, "build.gradle"), replacements); 230 } 231 232 protected CompilationResult runGradle(String... params) throws IOException, InterruptedException { 233 setExecutable(); 234 File pathToExecutable = new File(testFolder, "gradlew"); 235 List<String> args = new ArrayList<>(); 236 args.add(pathToExecutable.getAbsolutePath()); 237 args.add("--project-cache-dir"); 238 args.add(new File("../.caches/", name.getMethodName()).getAbsolutePath()); 239 Collections.addAll(args, params); 240 ProcessBuilder builder = new ProcessBuilder(args); 241 builder.environment().putAll(System.getenv()); 242 String javaHome = System.getProperty("java.home"); 243 if (StringUtils.isNotBlank(javaHome)) { 244 builder.environment().put("JAVA_HOME", javaHome); 245 } 246 builder.directory(testFolder); 247 Process process = builder.start(); 248 String output = IOUtils.toString(process.getInputStream()); 249 String error = IOUtils.toString(process.getErrorStream()); 250 int result = process.waitFor(); 251 return new CompilationResult(result, output, error); 252 } 253 254 private void setExecutable() throws IOException { 255 Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>(); 256 //add owners permission 257 perms.add(PosixFilePermission.OWNER_READ); 258 perms.add(PosixFilePermission.OWNER_WRITE); 259 perms.add(PosixFilePermission.OWNER_EXECUTE); 260 //add group permissions 261 perms.add(PosixFilePermission.GROUP_READ); 262 //add others permissions 263 perms.add(PosixFilePermission.OTHERS_READ); 264 Files.setPosixFilePermissions(Paths.get(new File(testFolder, "gradlew").getAbsolutePath()), perms); 265 } 266 267 268} 269