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 import org.junit.Test;
20 
21 import android.databinding.tool.processing.ErrorMessages;
22 import android.databinding.tool.processing.ScopedErrorReport;
23 import android.databinding.tool.processing.ScopedException;
24 import android.databinding.tool.store.Location;
25 
26 import java.io.File;
27 import java.io.IOException;
28 import java.net.URISyntaxException;
29 import java.util.List;
30 
31 import static org.junit.Assert.assertEquals;
32 import static org.junit.Assert.assertNotEquals;
33 import static org.junit.Assert.assertNotNull;
34 import static org.junit.Assert.assertTrue;
35 import static org.junit.Assert.fail;
36 
37 public class MultiLayoutVerificationTest extends BaseCompilationTest {
38     @Test
testMultipleLayoutFilesWithNameMismatch()39     public void testMultipleLayoutFilesWithNameMismatch()
40             throws IOException, URISyntaxException, InterruptedException {
41         prepareProject();
42         copyResourceTo("/layout/layout_with_class_name.xml",
43                 "/app/src/main/res/layout/with_class_name.xml", toMap(KEY_CLASS_NAME,
44                         "AClassName"));
45         copyResourceTo("/layout/layout_with_class_name.xml",
46                 "/app/src/main/res/layout-land/with_class_name.xml", toMap(KEY_CLASS_NAME,
47                         "SomeOtherClassName"));
48         CompilationResult result = runGradle("assembleDebug");
49         assertNotEquals(result.output, 0, result.resultCode);
50         List<ScopedException> exceptions = result.getBindingExceptions();
51         assertEquals(result.error, 2, exceptions.size());
52         boolean foundNormal = false;
53         boolean foundLandscape = false;
54         for (ScopedException exception : exceptions) {
55             ScopedErrorReport report = exception.getScopedErrorReport();
56             assertNotNull(report);
57             File file = new File(report.getFilePath());
58             assertTrue(file.exists());
59             assertEquals(1, report.getLocations().size());
60             Location location = report.getLocations().get(0);
61             String name = file.getParentFile().getName();
62             if ("layout".equals(name)) {
63                 assertEquals(new File(testFolder,
64                         "/app/src/main/res/layout/with_class_name.xml")
65                         .getCanonicalFile(), file.getCanonicalFile());
66                 String extract = extract("/app/src/main/res/layout/with_class_name.xml",
67                         location);
68                 assertEquals(extract, "AClassName");
69                 assertEquals(String.format(
70                         ErrorMessages.MULTI_CONFIG_LAYOUT_CLASS_NAME_MISMATCH,
71                         DEFAULT_APP_PACKAGE + ".databinding.AClassName",
72                         "layout/with_class_name"), exception.getBareMessage());
73                 foundNormal = true;
74             } else if ("layout-land".equals(name)) {
75                     assertEquals(new File(testFolder,
76                             "/app/src/main/res/layout-land/with_class_name.xml")
77                             .getCanonicalFile(), file.getCanonicalFile());
78                     String extract = extract("/app/src/main/res/layout-land/with_class_name.xml",
79                             location);
80                     assertEquals("SomeOtherClassName", extract);
81                     assertEquals(String.format(
82                             ErrorMessages.MULTI_CONFIG_LAYOUT_CLASS_NAME_MISMATCH,
83                             DEFAULT_APP_PACKAGE + ".databinding.SomeOtherClassName",
84                             "layout-land/with_class_name"), exception.getBareMessage());
85                     foundLandscape = true;
86             } else {
87                 fail("unexpected error file");
88             }
89         }
90         assertTrue("should find default config error\n" + result.error, foundNormal);
91         assertTrue("should find landscape error\n" + result.error, foundLandscape);
92     }
93 
94     @Test
testMultipleLayoutFilesVariableMismatch()95     public void testMultipleLayoutFilesVariableMismatch()
96             throws IOException, URISyntaxException, InterruptedException {
97         prepareProject();
98         copyResourceTo("/layout/layout_with_variable_type.xml",
99                 "/app/src/main/res/layout/layout_with_variable_type.xml", toMap(KEY_CLASS_TYPE,
100                         "String"));
101         copyResourceTo("/layout/layout_with_variable_type.xml",
102                 "/app/src/main/res/layout-land/layout_with_variable_type.xml", toMap(KEY_CLASS_TYPE,
103                         "CharSequence"));
104         CompilationResult result = runGradle("assembleDebug");
105         assertNotEquals(result.output, 0, result.resultCode);
106         List<ScopedException> exceptions = result.getBindingExceptions();
107         assertEquals(result.error, 2, exceptions.size());
108         boolean foundNormal = false;
109         boolean foundLandscape = false;
110         for (ScopedException exception : exceptions) {
111             ScopedErrorReport report = exception.getScopedErrorReport();
112             assertNotNull(report);
113             File file = new File(report.getFilePath());
114             assertTrue(file.exists());
115             assertEquals(result.error, 1, report.getLocations().size());
116             Location location = report.getLocations().get(0);
117             // validated in switch
118             String name = file.getParentFile().getName();
119             String config = name;
120             String type = "???";
121             if ("layout".equals(name)) {
122                 type = "String";
123                 foundNormal = true;
124             } else if ("layout-land".equals(name)) {
125                 type = "CharSequence";
126                 foundLandscape = true;
127             } else {
128                 fail("unexpected error file");
129             }
130             assertEquals(new File(testFolder,
131                     "/app/src/main/res/" + config + "/layout_with_variable_type.xml")
132                     .getCanonicalFile(), file.getCanonicalFile());
133             String extract = extract("/app/src/main/res/" + config +
134                             "/layout_with_variable_type.xml", location);
135             assertEquals(extract, "<variable name=\"myVariable\" type=\"" + type + "\"/>");
136             assertEquals(String.format(
137                     ErrorMessages.MULTI_CONFIG_VARIABLE_TYPE_MISMATCH,
138                     "myVariable", type,
139                     config + "/layout_with_variable_type"), exception.getBareMessage());
140         }
141         assertTrue(result.error, foundNormal);
142         assertTrue(result.error, foundLandscape);
143     }
144 
145     @Test
testMultipleLayoutFilesImportMismatch()146     public void testMultipleLayoutFilesImportMismatch()
147             throws IOException, URISyntaxException, InterruptedException {
148         prepareProject();
149         String typeNormal = "java.util.List";
150         String typeLand = "java.util.Map";
151         copyResourceTo("/layout/layout_with_import_type.xml",
152                 "/app/src/main/res/layout/layout_with_import_type.xml", toMap(KEY_IMPORT_TYPE,
153                         typeNormal));
154         copyResourceTo("/layout/layout_with_import_type.xml",
155                 "/app/src/main/res/layout-land/layout_with_import_type.xml", toMap(KEY_IMPORT_TYPE,
156                         typeLand));
157         CompilationResult result = runGradle("assembleDebug");
158         assertNotEquals(result.output, 0, result.resultCode);
159         List<ScopedException> exceptions = result.getBindingExceptions();
160         assertEquals(result.error, 2, exceptions.size());
161         boolean foundNormal = false;
162         boolean foundLandscape = false;
163         for (ScopedException exception : exceptions) {
164             ScopedErrorReport report = exception.getScopedErrorReport();
165             assertNotNull(report);
166             File file = new File(report.getFilePath());
167             assertTrue(file.exists());
168             assertEquals(result.error, 1, report.getLocations().size());
169             Location location = report.getLocations().get(0);
170             // validated in switch
171             String name = file.getParentFile().getName();
172             String config = name;
173             String type = "???";
174             if ("layout".equals(name)) {
175                 type = typeNormal;
176                 foundNormal = true;
177             } else if ("layout-land".equals(name)) {
178                 type = typeLand;
179                 foundLandscape = true;
180             } else {
181                 fail("unexpected error file");
182             }
183             assertEquals(new File(testFolder,
184                     "/app/src/main/res/" + config + "/layout_with_import_type.xml")
185                     .getCanonicalFile(), file.getCanonicalFile());
186             String extract = extract("/app/src/main/res/" + config + "/layout_with_import_type.xml",
187                     location);
188             assertEquals(extract, "<import alias=\"Blah\" type=\"" + type + "\"/>");
189             assertEquals(String.format(
190                     ErrorMessages.MULTI_CONFIG_IMPORT_TYPE_MISMATCH,
191                     "Blah", type,
192                     config + "/layout_with_import_type"), exception.getBareMessage());
193         }
194         assertTrue(result.error, foundNormal);
195         assertTrue(result.error, foundLandscape);
196     }
197 
198     @Test
testSameIdInIncludeAndView()199     public void testSameIdInIncludeAndView()
200             throws IOException, URISyntaxException, InterruptedException {
201         prepareProject();
202         copyResourceTo("/layout/basic_layout.xml",
203                 "/app/src/main/res/layout/basic_layout.xml");
204         copyResourceTo("/layout/layout_with_include.xml",
205                 "/app/src/main/res/layout/foo.xml", toMap(KEY_INCLUDE_ID, "sharedId"));
206         copyResourceTo("/layout/layout_with_view_id.xml",
207                 "/app/src/main/res/layout-land/foo.xml", toMap(KEY_VIEW_ID, "sharedId"));
208         CompilationResult result = runGradle("assembleDebug");
209         assertNotEquals(result.output, 0, result.resultCode);
210         List<ScopedException> exceptions = result.getBindingExceptions();
211 
212         boolean foundNormal = false;
213         boolean foundLandscape = false;
214         for (ScopedException exception : exceptions) {
215             ScopedErrorReport report = exception.getScopedErrorReport();
216             assertNotNull(report);
217             if (exception.getMessage().startsWith("Cannot find the setter")) {
218                 continue;
219             }
220             File file = new File(report.getFilePath());
221             assertTrue(file.exists());
222             assertEquals(result.error, 1, report.getLocations().size());
223             Location location = report.getLocations().get(0);
224             // validated in switch
225             String config = file.getParentFile().getName();
226             if ("layout".equals(config)) {
227                 String extract = extract("/app/src/main/res/" + config + "/foo.xml", location);
228                 assertEquals(extract, "<include layout=\"@layout/basic_layout\" "
229                         + "android:id=\"@+id/sharedId\" bind:myVariable=\"@{myVariable}\"/>");
230                 foundNormal = true;
231             } else if ("layout-land".equals(config)) {
232                 String extract = extract("/app/src/main/res/" + config + "/foo.xml", location);
233                 assertEquals(extract, "<TextView android:layout_width=\"wrap_content\" "
234                         + "android:layout_height=\"wrap_content\" android:id=\"@+id/sharedId\" "
235                         + "android:text=\"@{myVariable}\"/>");
236                 foundLandscape = true;
237             } else {
238                 fail("unexpected error file");
239             }
240             assertEquals(new File(testFolder,
241                     "/app/src/main/res/" + config + "/foo.xml").getCanonicalFile(),
242                     file.getCanonicalFile());
243             assertEquals(String.format(
244                     ErrorMessages.MULTI_CONFIG_ID_USED_AS_IMPORT, "@+id/sharedId"),
245                     exception.getBareMessage());
246         }
247         assertTrue(result.error, foundNormal);
248         assertTrue(result.error, foundLandscape);
249     }
250 
251 
252 }
253