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.junit.Test;
20
21import android.databinding.tool.processing.ErrorMessages;
22import android.databinding.tool.processing.ScopedErrorReport;
23import android.databinding.tool.processing.ScopedException;
24import android.databinding.tool.store.Location;
25
26import java.io.File;
27import java.io.IOException;
28import java.net.URISyntaxException;
29import java.util.List;
30
31import static org.junit.Assert.assertEquals;
32import static org.junit.Assert.assertNotEquals;
33import static org.junit.Assert.assertNotNull;
34import static org.junit.Assert.assertTrue;
35import static org.junit.Assert.fail;
36
37public class MultiLayoutVerificationTest extends BaseCompilationTest {
38    @Test
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
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
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
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