| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.databinding.compilationTest; |
| |
| import org.apache.commons.io.FileUtils; |
| import org.apache.commons.io.IOUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.rules.TestName; |
| |
| import android.databinding.tool.store.Location; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.nio.file.Files; |
| import java.nio.file.Paths; |
| import java.nio.file.attribute.PosixFilePermission; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| |
| public class BaseCompilationTest { |
| |
| private static final String PRINT_ENCODED_ERRORS_PROPERTY |
| = "android.databinding.injected.print.encoded.errors"; |
| @Rule |
| public TestName name = new TestName(); |
| static Pattern VARIABLES = Pattern.compile("!@\\{([A-Za-z0-9_-]*)}"); |
| |
| public static final String KEY_MANIFEST_PACKAGE = "PACKAGE"; |
| public static final String KEY_DEPENDENCIES = "DEPENDENCIES"; |
| public static final String KEY_SETTINGS_INCLUDES = "SETTINGS_INCLUDES"; |
| public static final String DEFAULT_APP_PACKAGE = "com.android.databinding.compilationTest.test"; |
| public static final String KEY_CLASS_NAME = "CLASSNAME"; |
| public static final String KEY_CLASS_TYPE = "CLASSTYPE"; |
| public static final String KEY_IMPORT_TYPE = "IMPORTTYPE"; |
| public static final String KEY_INCLUDE_ID = "INCLUDEID"; |
| public static final String KEY_VIEW_ID = "VIEWID"; |
| |
| protected final File testFolder = new File("./build/build-test"); |
| |
| protected void copyResourceTo(String name, String path) throws IOException { |
| copyResourceTo(name, new File(testFolder, path)); |
| } |
| |
| protected void copyResourceTo(String name, String path, Map<String, String> replacements) |
| throws IOException { |
| copyResourceTo(name, new File(testFolder, path), replacements); |
| } |
| |
| protected void copyResourceDirectory(String name, String targetPath) |
| throws URISyntaxException, IOException { |
| URL dir = getClass().getResource(name); |
| assertNotNull(dir); |
| assertEquals("file", dir.getProtocol()); |
| File folder = new File(dir.toURI()); |
| assertTrue(folder.isDirectory()); |
| File target = new File(testFolder, targetPath); |
| int len = folder.getAbsolutePath().length() + 1; |
| for (File item : FileUtils.listFiles(folder, null, true)) { |
| if (item.getAbsolutePath().equals(folder.getAbsolutePath())) { |
| continue; |
| } |
| String resourcePath = item.getAbsolutePath().substring(len); |
| |
| copyResourceTo(name + "/" + resourcePath, new File(target, resourcePath)); |
| } |
| } |
| |
| @Before |
| public void clear() throws IOException { |
| if (testFolder.exists()) { |
| FileUtils.forceDelete(testFolder); |
| } |
| } |
| |
| /** |
| * Extracts the text in the given location from the the at the given application path. |
| * |
| * @param pathInApp The path, relative to the root of the application under test |
| * @param location The location to extract |
| * @return The string that is contained in the given location |
| * @throws IOException If file is invalid. |
| */ |
| protected String extract(String pathInApp, Location location) throws IOException { |
| File file = new File(testFolder, pathInApp); |
| assertTrue(file.exists()); |
| StringBuilder result = new StringBuilder(); |
| List<String> lines = FileUtils.readLines(file); |
| for (int i = location.startLine; i <= location.endLine; i++) { |
| if (i > location.startLine) { |
| result.append("\n"); |
| } |
| String line = lines.get(i); |
| int start = 0; |
| if (i == location.startLine) { |
| start = location.startOffset; |
| } |
| int end = line.length() - 1; // inclusive |
| if (i == location.endLine) { |
| end = location.endOffset; |
| } |
| result.append(line.substring(start, end + 1)); |
| } |
| return result.toString(); |
| } |
| |
| protected void copyResourceTo(String name, File targetFile) throws IOException { |
| File directory = targetFile.getParentFile(); |
| FileUtils.forceMkdir(directory); |
| InputStream contents = getClass().getResourceAsStream(name); |
| FileOutputStream fos = new FileOutputStream(targetFile); |
| IOUtils.copy(contents, fos); |
| IOUtils.closeQuietly(fos); |
| IOUtils.closeQuietly(contents); |
| } |
| |
| protected static Map<String, String> toMap(String... keysAndValues) { |
| assertEquals(0, keysAndValues.length % 2); |
| Map<String, String> map = new HashMap<>(); |
| for (int i = 0; i < keysAndValues.length; i += 2) { |
| map.put(keysAndValues[i], keysAndValues[i + 1]); |
| } |
| return map; |
| } |
| |
| protected void copyResourceTo(String name, File targetFile, Map<String, String> replacements) |
| throws IOException { |
| if (replacements.isEmpty()) { |
| copyResourceTo(name, targetFile); |
| } |
| InputStream inputStream = getClass().getResourceAsStream(name); |
| final String contents = IOUtils.toString(inputStream); |
| IOUtils.closeQuietly(inputStream); |
| |
| StringBuilder out = new StringBuilder(contents.length()); |
| final Matcher matcher = VARIABLES.matcher(contents); |
| int location = 0; |
| while (matcher.find()) { |
| int start = matcher.start(); |
| if (start > location) { |
| out.append(contents, location, start); |
| } |
| final String key = matcher.group(1); |
| final String replacement = replacements.get(key); |
| if (replacement != null) { |
| out.append(replacement); |
| } |
| location = matcher.end(); |
| } |
| if (location < contents.length()) { |
| out.append(contents, location, contents.length()); |
| } |
| |
| FileUtils.writeStringToFile(targetFile, out.toString()); |
| } |
| |
| protected void prepareProject() throws IOException, URISyntaxException { |
| prepareApp(null); |
| } |
| |
| private Map<String, String> addDefaults(Map<String, String> map) { |
| if (map == null) { |
| map = new HashMap<>(); |
| } |
| if (!map.containsKey(KEY_MANIFEST_PACKAGE)) { |
| map.put(KEY_MANIFEST_PACKAGE, DEFAULT_APP_PACKAGE); |
| } |
| if (!map.containsKey(KEY_SETTINGS_INCLUDES)) { |
| map.put(KEY_SETTINGS_INCLUDES, "include ':app'"); |
| } |
| return map; |
| } |
| |
| protected void prepareApp(Map<String, String> replacements) throws IOException, |
| URISyntaxException { |
| replacements = addDefaults(replacements); |
| // how to get build folder, pass from gradle somehow ? |
| FileUtils.forceMkdir(testFolder); |
| copyResourceTo("/AndroidManifest.xml", |
| new File(testFolder, "app/src/main/AndroidManifest.xml"), replacements); |
| copyResourceTo("/project_build.gradle", new File(testFolder, "build.gradle"), replacements); |
| copyResourceTo("/app_build.gradle", new File(testFolder, "app/build.gradle"), replacements); |
| copyResourceTo("/settings.gradle", new File(testFolder, "settings.gradle"), replacements); |
| File localProperties = new File("../local.properties"); |
| if (localProperties.exists()) { |
| FileUtils.copyFile(localProperties, new File(testFolder, "local.properties")); |
| } |
| FileUtils.copyFile(new File("../propLoader.gradle"), new File(testFolder, "propLoaderClone.gradle")); |
| FileUtils.copyFile(new File("../gradlew"), new File(testFolder, "gradlew")); |
| FileUtils.copyDirectory(new File("../gradle"), new File(testFolder, "gradle")); |
| } |
| |
| protected void prepareModule(String moduleName, String packageName, |
| Map<String, String> replacements) throws IOException, URISyntaxException { |
| replacements = addDefaults(replacements); |
| replacements.put(KEY_MANIFEST_PACKAGE, packageName); |
| File moduleFolder = new File(testFolder, moduleName); |
| if (moduleFolder.exists()) { |
| FileUtils.forceDelete(moduleFolder); |
| } |
| FileUtils.forceMkdir(moduleFolder); |
| copyResourceTo("/AndroidManifest.xml", |
| new File(moduleFolder, "src/main/AndroidManifest.xml"), replacements); |
| copyResourceTo("/module_build.gradle", new File(moduleFolder, "build.gradle"), |
| replacements); |
| } |
| |
| protected CompilationResult runGradle(String... params) |
| throws IOException, InterruptedException { |
| setExecutable(); |
| File pathToExecutable = new File(testFolder, "gradlew"); |
| List<String> args = new ArrayList<>(); |
| args.add(pathToExecutable.getAbsolutePath()); |
| args.add("-P" + PRINT_ENCODED_ERRORS_PROPERTY + "=true"); |
| args.add("--project-cache-dir"); |
| args.add(new File("../.caches/", name.getMethodName()).getAbsolutePath()); |
| Collections.addAll(args, params); |
| ProcessBuilder builder = new ProcessBuilder(args); |
| builder.environment().putAll(System.getenv()); |
| String javaHome = System.getProperty("java.home"); |
| if (StringUtils.isNotBlank(javaHome)) { |
| builder.environment().put("JAVA_HOME", javaHome); |
| } |
| builder.directory(testFolder); |
| Process process = builder.start(); |
| String output = IOUtils.toString(process.getInputStream()); |
| String error = IOUtils.toString(process.getErrorStream()); |
| int result = process.waitFor(); |
| return new CompilationResult(result, output, error); |
| } |
| |
| private void setExecutable() throws IOException { |
| Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>(); |
| //add owners permission |
| perms.add(PosixFilePermission.OWNER_READ); |
| perms.add(PosixFilePermission.OWNER_WRITE); |
| perms.add(PosixFilePermission.OWNER_EXECUTE); |
| //add group permissions |
| perms.add(PosixFilePermission.GROUP_READ); |
| //add others permissions |
| perms.add(PosixFilePermission.OTHERS_READ); |
| Files.setPosixFilePermissions(Paths.get(new File(testFolder, "gradlew").getAbsolutePath()), |
| perms); |
| } |
| |
| |
| } |