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