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 17 package android.databinding.compilationTest; 18 19 20 import org.apache.commons.lang3.StringUtils; 21 import org.junit.Test; 22 23 import android.databinding.tool.processing.ErrorMessages; 24 import android.databinding.tool.processing.ScopedErrorReport; 25 import android.databinding.tool.processing.ScopedException; 26 import android.databinding.tool.store.Location; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.net.URISyntaxException; 31 import java.util.List; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertNotEquals; 35 import static org.junit.Assert.assertNotNull; 36 import static org.junit.Assert.assertTrue; 37 import static org.junit.Assert.fail; 38 39 public class SimpleCompilationTest extends BaseCompilationTest { 40 41 @Test 42 public void listTasks() throws IOException, URISyntaxException, InterruptedException { 43 prepareProject(); 44 CompilationResult result = runGradle("tasks"); 45 assertEquals(0, result.resultCode); 46 assertTrue("there should not be any errors", StringUtils.isEmpty(result.error)); 47 assertTrue("Test sanity, empty project tasks", 48 result.resultContainsText("All tasks runnable from root project")); 49 } 50 51 @Test 52 public void testEmptyCompilation() throws IOException, URISyntaxException, InterruptedException { 53 prepareProject(); 54 CompilationResult result = runGradle("assembleDebug"); 55 assertEquals(result.error, 0, result.resultCode); 56 assertTrue("there should not be any errors " + result.error, StringUtils.isEmpty(result.error)); 57 assertTrue("Test sanity, should compile fine", 58 result.resultContainsText("BUILD SUCCESSFUL")); 59 } 60 61 private ScopedException singleFileErrorTest(String resource, String targetFile, 62 String expectedExtract, String errorMessage) 63 throws IOException, URISyntaxException, InterruptedException { 64 prepareProject(); 65 copyResourceTo(resource, targetFile); 66 CompilationResult result = runGradle("assembleDebug"); 67 assertNotEquals(0, result.resultCode); 68 ScopedException scopedException = result.getBindingException(); 69 assertNotNull(result.error, scopedException); 70 ScopedErrorReport report = scopedException.getScopedErrorReport(); 71 assertNotNull(report); 72 assertEquals(1, report.getLocations().size()); 73 Location loc = report.getLocations().get(0); 74 if (expectedExtract != null) { 75 String extract = extract(targetFile, loc); 76 assertEquals(expectedExtract, extract); 77 } 78 final File errorFile = new File(report.getFilePath()); 79 assertTrue(errorFile.exists()); 80 assertEquals(new File(testFolder, targetFile).getCanonicalFile(), 81 errorFile.getCanonicalFile()); 82 if (errorMessage != null) { 83 assertEquals(errorMessage, scopedException.getBareMessage()); 84 } 85 return scopedException; 86 } 87 88 @Test 89 public void testMultipleExceptionsInDifferentFiles() 90 throws IOException, URISyntaxException, InterruptedException { 91 prepareProject(); 92 copyResourceTo("/layout/undefined_variable_binding.xml", 93 "/app/src/main/res/layout/broken.xml"); 94 copyResourceTo("/layout/invalid_setter_binding.xml", 95 "/app/src/main/res/layout/invalid_setter.xml"); 96 CompilationResult result = runGradle("assembleDebug"); 97 assertNotEquals(result.output, 0, result.resultCode); 98 List<ScopedException> bindingExceptions = result.getBindingExceptions(); 99 assertEquals(result.error, 2, bindingExceptions.size()); 100 File broken = new File(testFolder, "/app/src/main/res/layout/broken.xml"); 101 File invalidSetter = new File(testFolder, "/app/src/main/res/layout/invalid_setter.xml"); 102 for (ScopedException exception : bindingExceptions) { 103 ScopedErrorReport report = exception.getScopedErrorReport(); 104 final File errorFile = new File(report.getFilePath()); 105 String message = null; 106 String expectedErrorFile = null; 107 if (errorFile.getCanonicalPath().equals(broken.getCanonicalPath())) { 108 message = String.format(ErrorMessages.UNDEFINED_VARIABLE, "myVariable"); 109 expectedErrorFile = "/app/src/main/res/layout/broken.xml"; 110 } else if (errorFile.getCanonicalPath().equals(invalidSetter.getCanonicalPath())) { 111 message = String.format(ErrorMessages.CANNOT_FIND_SETTER_CALL, "android:textx", 112 String.class.getCanonicalName()); 113 expectedErrorFile = "/app/src/main/res/layout/invalid_setter.xml"; 114 } else { 115 fail("unexpected exception " + exception.getBareMessage()); 116 } 117 assertEquals(1, report.getLocations().size()); 118 Location loc = report.getLocations().get(0); 119 String extract = extract(expectedErrorFile, loc); 120 assertEquals("myVariable", extract); 121 assertEquals(message, exception.getBareMessage()); 122 } 123 } 124 125 @Test 126 public void testUndefinedVariable() throws IOException, URISyntaxException, 127 InterruptedException { 128 ScopedException ex = singleFileErrorTest("/layout/undefined_variable_binding.xml", 129 "/app/src/main/res/layout/broken.xml", "myVariable", 130 String.format(ErrorMessages.UNDEFINED_VARIABLE, "myVariable")); 131 } 132 133 @Test 134 public void testInvalidSetterBinding() throws IOException, URISyntaxException, 135 InterruptedException { 136 prepareProject(); 137 ScopedException ex = singleFileErrorTest("/layout/invalid_setter_binding.xml", 138 "/app/src/main/res/layout/invalid_setter.xml", "myVariable", 139 String.format(ErrorMessages.CANNOT_FIND_SETTER_CALL, "android:textx", 140 String.class.getCanonicalName())); 141 } 142 143 @Test 144 public void testInvalidVariableType() throws IOException, URISyntaxException, 145 InterruptedException { 146 prepareProject(); 147 ScopedException ex = singleFileErrorTest("/layout/invalid_variable_type.xml", 148 "/app/src/main/res/layout/invalid_variable.xml", "myVariable", 149 String.format(ErrorMessages.CANNOT_RESOLVE_TYPE, "myVariable~")); 150 } 151 152 @Test 153 public void testSingleModule() throws IOException, URISyntaxException, InterruptedException { 154 prepareApp(toMap(KEY_DEPENDENCIES, "compile project(':module1')", 155 KEY_SETTINGS_INCLUDES, "include ':app'\ninclude ':module1'")); 156 prepareModule("module1", "com.example.module1", toMap()); 157 copyResourceTo("/layout/basic_layout.xml", "/module1/src/main/res/layout/module_layout.xml"); 158 copyResourceTo("/layout/basic_layout.xml", "/app/src/main/res/layout/app_layout.xml"); 159 CompilationResult result = runGradle("assembleDebug"); 160 assertEquals(result.error, 0, result.resultCode); 161 } 162 163 @Test 164 public void testTwoLevelDependency() throws IOException, URISyntaxException, InterruptedException { 165 prepareApp(toMap(KEY_DEPENDENCIES, "compile project(':module1')", 166 KEY_SETTINGS_INCLUDES, "include ':app'\ninclude ':module1'\n" 167 + "include ':module2'")); 168 prepareModule("module1", "com.example.module1", toMap(KEY_DEPENDENCIES, 169 "compile project(':module2')")); 170 prepareModule("module2", "com.example.module2", toMap()); 171 copyResourceTo("/layout/basic_layout.xml", 172 "/module2/src/main/res/layout/module2_layout.xml"); 173 copyResourceTo("/layout/basic_layout.xml", "/module1/src/main/res/layout/module1_layout.xml"); 174 copyResourceTo("/layout/basic_layout.xml", "/app/src/main/res/layout/app_layout.xml"); 175 CompilationResult result = runGradle("assembleDebug"); 176 assertEquals(result.error, 0, result.resultCode); 177 } 178 179 @Test 180 public void testIncludeInMerge() throws Throwable { 181 prepareProject(); 182 copyResourceTo("/layout/merge_include.xml", "/app/src/main/res/layout/merge_include.xml"); 183 CompilationResult result = runGradle("assembleDebug"); 184 assertNotEquals(0, result.resultCode); 185 List<ScopedException> errors = ScopedException.extractErrors(result.error); 186 assertEquals(result.error, 1, errors.size()); 187 final ScopedException ex = errors.get(0); 188 final ScopedErrorReport report = ex.getScopedErrorReport(); 189 final File errorFile = new File(report.getFilePath()); 190 assertTrue(errorFile.exists()); 191 assertEquals( 192 new File(testFolder, "/app/src/main/res/layout/merge_include.xml") 193 .getCanonicalFile(), 194 errorFile.getCanonicalFile()); 195 assertEquals("Merge shouldn't support includes as root. Error message was '" + result.error, 196 ErrorMessages.INCLUDE_INSIDE_MERGE, ex.getBareMessage()); 197 } 198 } 199