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