BaseCompilationTest.java revision 9784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3
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.util.ArrayList; 35import java.util.Collections; 36import java.util.HashMap; 37import java.util.HashSet; 38import java.util.List; 39import java.util.Map; 40import java.util.Set; 41import java.util.regex.Matcher; 42import java.util.regex.Pattern; 43 44import static org.junit.Assert.assertEquals; 45import static org.junit.Assert.assertNotNull; 46import static org.junit.Assert.assertTrue; 47 48 49public class BaseCompilationTest { 50 51 private static final String PRINT_ENCODED_ERRORS_PROPERTY 52 = "android.injected.invoked.from.ide"; 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 * 107 * @param pathInApp The path, relative to the root of the application under test 108 * @param location The location to extract 109 * @return The string that is contained in the given location 110 * @throws IOException If file is invalid. 111 */ 112 protected String extract(String pathInApp, Location location) throws IOException { 113 File file = new File(testFolder, pathInApp); 114 assertTrue(file.exists()); 115 StringBuilder result = new StringBuilder(); 116 List<String> lines = FileUtils.readLines(file); 117 for (int i = location.startLine; i <= location.endLine; i++) { 118 if (i > location.startLine) { 119 result.append("\n"); 120 } 121 String line = lines.get(i); 122 int start = 0; 123 if (i == location.startLine) { 124 start = location.startOffset; 125 } 126 int end = line.length() - 1; // inclusive 127 if (i == location.endLine) { 128 end = location.endOffset; 129 } 130 result.append(line.substring(start, end + 1)); 131 } 132 return result.toString(); 133 } 134 135 protected void copyResourceTo(String name, File targetFile) throws IOException { 136 File directory = targetFile.getParentFile(); 137 FileUtils.forceMkdir(directory); 138 InputStream contents = getClass().getResourceAsStream(name); 139 FileOutputStream fos = new FileOutputStream(targetFile); 140 IOUtils.copy(contents, fos); 141 IOUtils.closeQuietly(fos); 142 IOUtils.closeQuietly(contents); 143 } 144 145 protected static Map<String, String> toMap(String... keysAndValues) { 146 assertEquals(0, keysAndValues.length % 2); 147 Map<String, String> map = new HashMap<String, String>(); 148 for (int i = 0; i < keysAndValues.length; i += 2) { 149 map.put(keysAndValues[i], keysAndValues[i + 1]); 150 } 151 return map; 152 } 153 154 protected void copyResourceTo(String name, File targetFile, Map<String, String> replacements) 155 throws IOException { 156 if (replacements.isEmpty()) { 157 copyResourceTo(name, targetFile); 158 } 159 InputStream inputStream = getClass().getResourceAsStream(name); 160 final String contents = IOUtils.toString(inputStream); 161 IOUtils.closeQuietly(inputStream); 162 163 StringBuilder out = new StringBuilder(contents.length()); 164 final Matcher matcher = VARIABLES.matcher(contents); 165 int location = 0; 166 while (matcher.find()) { 167 int start = matcher.start(); 168 if (start > location) { 169 out.append(contents, location, start); 170 } 171 final String key = matcher.group(1); 172 final String replacement = replacements.get(key); 173 if (replacement != null) { 174 out.append(replacement); 175 } 176 location = matcher.end(); 177 } 178 if (location < contents.length()) { 179 out.append(contents, location, contents.length()); 180 } 181 182 FileUtils.writeStringToFile(targetFile, out.toString()); 183 } 184 185 protected void prepareProject() throws IOException, URISyntaxException { 186 prepareApp(null); 187 } 188 189 private Map<String, String> addDefaults(Map<String, String> map) { 190 if (map == null) { 191 map = new HashMap<String, String>(); 192 } 193 if (!map.containsKey(KEY_MANIFEST_PACKAGE)) { 194 map.put(KEY_MANIFEST_PACKAGE, DEFAULT_APP_PACKAGE); 195 } 196 if (!map.containsKey(KEY_SETTINGS_INCLUDES)) { 197 map.put(KEY_SETTINGS_INCLUDES, "include ':app'"); 198 } 199 return map; 200 } 201 202 protected void prepareApp(Map<String, String> replacements) throws IOException, 203 URISyntaxException { 204 replacements = addDefaults(replacements); 205 // how to get build folder, pass from gradle somehow ? 206 FileUtils.forceMkdir(testFolder); 207 copyResourceTo("/AndroidManifest.xml", 208 new File(testFolder, "app/src/main/AndroidManifest.xml"), replacements); 209 copyResourceTo("/project_build.gradle", new File(testFolder, "build.gradle"), replacements); 210 copyResourceTo("/app_build.gradle", new File(testFolder, "app/build.gradle"), replacements); 211 copyResourceTo("/settings.gradle", new File(testFolder, "settings.gradle"), replacements); 212 File localProperties = new File("../local.properties"); 213 if (localProperties.exists()) { 214 FileUtils.copyFile(localProperties, new File(testFolder, "local.properties")); 215 } 216 FileUtils.copyFile(new File("../propLoader.gradle"), 217 new File(testFolder, "propLoaderClone.gradle")); 218 FileUtils.copyFile(new File("../gradlew"), new File(testFolder, "gradlew")); 219 FileUtils.copyDirectory(new File("../gradle"), new File(testFolder, "gradle")); 220 } 221 222 protected void prepareModule(String moduleName, String packageName, 223 Map<String, String> replacements) throws IOException, URISyntaxException { 224 replacements = addDefaults(replacements); 225 replacements.put(KEY_MANIFEST_PACKAGE, packageName); 226 File moduleFolder = new File(testFolder, moduleName); 227 if (moduleFolder.exists()) { 228 FileUtils.forceDelete(moduleFolder); 229 } 230 FileUtils.forceMkdir(moduleFolder); 231 copyResourceTo("/AndroidManifest.xml", 232 new File(moduleFolder, "src/main/AndroidManifest.xml"), replacements); 233 copyResourceTo("/module_build.gradle", new File(moduleFolder, "build.gradle"), 234 replacements); 235 } 236 237 protected CompilationResult runGradle(String... params) 238 throws IOException, InterruptedException { 239 setExecutable(); 240 File pathToExecutable = new File(testFolder, "gradlew"); 241 List<String> args = new ArrayList<String>(); 242 args.add(pathToExecutable.getAbsolutePath()); 243 args.add("-P" + PRINT_ENCODED_ERRORS_PROPERTY + "=true"); 244 if ("true".equals(System.getProperties().getProperty("useReleaseVersion", "false"))) { 245 args.add("-PuseReleaseVersion=true"); 246 } 247 if ("true".equals(System.getProperties().getProperty("addRemoteRepos", "false"))) { 248 args.add("-PaddRemoteRepos=true"); 249 } 250 args.add("--project-cache-dir"); 251 args.add(new File("../.caches/", name.getMethodName()).getAbsolutePath()); 252 Collections.addAll(args, params); 253 ProcessBuilder builder = new ProcessBuilder(args); 254 builder.environment().putAll(System.getenv()); 255 String javaHome = System.getProperty("java.home"); 256 if (StringUtils.isNotBlank(javaHome)) { 257 builder.environment().put("JAVA_HOME", javaHome); 258 } 259 builder.directory(testFolder); 260 Process process = builder.start(); 261 String output = IOUtils.toString(process.getInputStream()); 262 String error = IOUtils.toString(process.getErrorStream()); 263 int result = process.waitFor(); 264 return new CompilationResult(result, output, error); 265 } 266 267 private void setExecutable() throws IOException { 268 File gw = new File(testFolder, "gradlew"); 269 gw.setExecutable(true); 270 } 271 272 273} 274