1f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye/*
2f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * Copyright (C) 2012 The Android Open Source Project
3f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye *
4f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * you may not use this file except in compliance with the License.
6f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * You may obtain a copy of the License at
7f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye *
8f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye *      http://www.eclipse.org/org/documents/epl-v10.php
9f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye *
10f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * Unless required by applicable law or agreed to in writing, software
11f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * distributed under the License is distributed on an "AS IS" BASIS,
12f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * See the License for the specific language governing permissions and
14f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * limitations under the License.
15f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye */
16f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyepackage com.android.ide.common.resources.platform;
17f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
18f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.ANDROID_URI;
19f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.DOT_XML;
20f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
210072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohetimport com.android.SdkConstants;
22f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.annotations.NonNull;
23f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.ide.common.api.IAttributeInfo.Format;
24f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.ide.common.resources.ResourceItem;
25f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.ide.common.resources.ResourceRepository;
26f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
270072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohetimport com.android.ide.eclipse.mock.Mocks;
280072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohetimport com.android.io.IAbstractFolder;
290072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohetimport com.android.io.IAbstractResource;
30f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.resources.ResourceType;
31f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.utils.StdLogger;
32f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.base.Charsets;
33f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.collect.ArrayListMultimap;
34f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.collect.Multimap;
35f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.collect.Sets;
36f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.io.Files;
37f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
385a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbyeimport junit.framework.TestCase;
395a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye
40f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport org.w3c.dom.Attr;
41f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport org.w3c.dom.Document;
42f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport org.w3c.dom.Element;
43f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport org.w3c.dom.NamedNodeMap;
44f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
45f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.io.File;
46f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.io.IOException;
47f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.util.Collection;
48f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.util.EnumSet;
49f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.util.Map;
50f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.util.Set;
51f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
52f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye@SuppressWarnings("javadoc")
53f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyepublic class AttributeInfoTest extends TestCase {
54f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testSimple() throws Exception {
55f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.noneOf(Format.class));
56f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("", null, null));
57f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("a b c", null, null));
58f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@android foo bar", null, null));
59f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
60f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
61f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidString() throws Exception {
62f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.STRING_SET);
63f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("", null, null));
64f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("a b c", null, null));
65f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@android foo bar", null, null));
66f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
67f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
68f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidBoolean() throws Exception {
69f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.BOOLEAN_SET);
70f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("true", null, null));
71f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("false", null, null));
72f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
735a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("TRUE", null, null));
745a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("True", null, null));
755a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("FALSE", null, null));
765a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("False", null, null));
77f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
78f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
79f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidInteger() throws Exception {
80f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.INTEGER_SET);
81f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("0", null, null));
82f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("1", null, null));
83f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("10", null, null));
84f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-10", null, null));
85f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid(Integer.toString(Integer.MAX_VALUE), null, null));
86f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
87f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
88f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("a", null, null));
89f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("a1", null, null));
90f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("1a", null, null));
91f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("1.0", null, null));
92f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
93f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
94f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidFloat() throws Exception {
95f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.FLOAT_SET);
96f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("0", null, null));
97f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("1", null, null));
98f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("10", null, null));
99f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-10", null, null));
100f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-10.1234", null, null));
101f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid(".1", null, null));
102f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-.1", null, null));
103f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("1.5e22", null, null));
104f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid(Integer.toString(Integer.MAX_VALUE), null, null));
105f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
106f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
107f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid(".", null, null));
108f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("-.", null, null));
109f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("a", null, null));
110f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("a1", null, null));
111f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("1a", null, null));
112f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
113f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
114f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidDimension() throws Exception {
115f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.DIMENSION_SET);
116f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("0dp", null, null));
117f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("1dp", null, null));
118f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("10dip", null, null));
119f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-10px", null, null));
120f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("-10.1234mm", null, null));
121f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("14sp", null, null));
122f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("72pt", null, null));
123f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
124f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
125f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("5", null, null));
126f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("50ps", null, null));
127f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // Since we allow resources even when not specified in format, don't assert
128f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // this:
129f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        //assertFalse(info.isValid("@dimen/foo"));
130f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
131f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
132f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidColor() throws Exception {
133f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.COLOR_SET);
134f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("#fff", null, null));
135f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("#ffffff", null, null));
136f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("#12345678", null, null));
137f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("#abcdef00", null, null));
138f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
139f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
140f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("#fffffffff", null, null));
141f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("red", null, null));
142f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("rgb(1,2,3)", null, null));
143f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
144f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
145f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidFraction() throws Exception {
146f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.<Format>of(Format.FRACTION));
147f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("5%", null, null));
148f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("25%p", null, null));
149f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
150f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // We don't validate fractions accurately yet
151f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        //assertFalse(info.isValid(""));
152f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        //assertFalse(info.isValid("50%%"));
153f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        //assertFalse(info.isValid("50"));
154f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        //assertFalse(info.isValid("-2%"));
155f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
156f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
157f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidReference() throws Exception {
158f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.REFERENCE_SET);
159f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@android:string/foo", null, null));
160f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@string/foo", null, null));
161f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@dimen/foo", null, null));
162f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@color/foo", null, null));
163f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@animator/foo", null, null));
164f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@anim/foo", null, null));
165f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("?android:attr/textAppearanceMedium", null, null));
1665a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("?textAppearanceMedium", null, null));
167f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
168f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
169f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("foo", null, null));
170f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("3.4", null, null));
171f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
172f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
173f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidEnum() throws Exception {
174f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.ENUM_SET);
175f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        info.setEnumValues(new String[] { "wrap_content", "match_parent" });
176f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("wrap_content", null, null));
177f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("match_parent", null, null));
178f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("", null, null));
179f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("other", null, null));
180f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("50", null, null));
181f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
182f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
183f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValidFlag() throws Exception {
184f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.FLAG_SET);
185f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        info.setFlagValues(new String[] { "left", "top", "right", "bottom" });
186f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("left", null, null));
187f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("top", null, null));
188f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("left|top", null, null));
1895a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye        assertTrue(info.isValid("", null, null));
190f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
191f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("other", null, null));
192f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("50", null, null));
193f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
194f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
195f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testCombined1() throws Exception {
196f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.<Format>of(Format.INTEGER,
197f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                Format.REFERENCE));
198f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("1", null, null));
199f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@dimen/foo", null, null));
200f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("foo", null, null));
201f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
202f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
203f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testCombined2() throws Exception {
204f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.<Format>of(Format.COLOR,
205f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                Format.REFERENCE));
206f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("#ff00ff00", null, null));
207f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@color/foo", null, null));
208f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("foo", null, null));
209f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
210f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
211f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testCombined3() throws Exception {
212f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.<Format>of(Format.STRING,
213f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                Format.REFERENCE));
214f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("test", null, null));
215f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@color/foo", null, null));
216f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
217f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
218f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testCombined4() throws Exception {
219f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", EnumSet.<Format>of(Format.ENUM,
220f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                Format.DIMENSION));
221f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        info.setEnumValues(new String[] { "wrap_content", "match_parent" });
222f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("wrap_content", null, null));
223f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("match_parent", null, null));
224f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("50dp", null, null));
225f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("50", null, null));
226f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("test", null, null));
227f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
228f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
229f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testResourcesExist() throws Exception {
2300072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet        IAbstractFolder folder = Mocks.createAbstractFolder(
2310072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet                SdkConstants.FD_RESOURCES, new IAbstractResource[0]);
2320072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet
233f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttributeInfo info = new AttributeInfo("test", Format.REFERENCE_SET);
2340072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet        TestResourceRepository projectResources = new TestResourceRepository(folder,false);
235f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        projectResources.addResource(ResourceType.STRING, "mystring");
236f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        projectResources.addResource(ResourceType.DIMEN, "mydimen");
2370072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet        TestResourceRepository frameworkResources = new TestResourceRepository(folder, true);
238f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        frameworkResources.addResource(ResourceType.LAYOUT, "mylayout");
239f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
240f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@string/mystring", null, null));
241f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@dimen/mydimen", null, null));
242f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@android:layout/mylayout", null, null));
243f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("?android:attr/listPreferredItemHeigh", null, null));
244f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
245f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@string/mystring", projectResources, frameworkResources));
246f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@dimen/mydimen", projectResources, frameworkResources));
247f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(info.isValid("@android:layout/mylayout", projectResources, frameworkResources));
248f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
249f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@android:string/mystring", projectResources,
250f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                frameworkResources));
251f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@android:dimen/mydimen", projectResources, frameworkResources));
252f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@layout/mylayout", projectResources, frameworkResources));
253f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@layout/foo", projectResources, frameworkResources));
254f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@anim/foo", projectResources, frameworkResources));
255f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertFalse(info.isValid("@android:anim/foo", projectResources, frameworkResources));
256f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
257f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
258f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    private class TestResourceRepository extends ResourceRepository {
259f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        private Multimap<ResourceType, String> mResources = ArrayListMultimap.create();
260f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
2610072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet        protected TestResourceRepository(IAbstractFolder resFolder, boolean isFrameworkRepository) {
2620072bac9da2f60fec9c7f48b17aafd1705094505Xavier Ducrohet            super(resFolder, isFrameworkRepository);
263f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
264f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
265f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        void addResource(ResourceType type, String name) {
266f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            mResources.put(type, name);
267f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
268f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
269f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        @Override
270f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        @NonNull
271f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        protected ResourceItem createResourceItem(@NonNull String name) {
272f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            fail("Not used in test");
273f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            return null;
274f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
275f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
276f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        @Override
277f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        public boolean hasResourceItem(@NonNull ResourceType type, @NonNull String name) {
278f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Collection<String> names = mResources.get(type);
279f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            if (names != null) {
280f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                return names.contains(name);
281f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            }
282f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
283f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            return false;
284f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
285f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    };
286f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
287f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
288f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    public void testIsValid() throws Exception {
289f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // This test loads the full attrs.xml file and then processes a bunch of platform
290f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // resource file and makes sure that they're all considered valid. This helps
291f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        // make sure that isValid() closely matches what aapt accepts.
292f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        String sdkPath = System.getenv("ADT_SDK_SOURCE_PATH");
293f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertNotNull("This test requires ADT_SDK_SOURCE_PATH to be set to point to the" +
294f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                "SDK git repository", sdkPath);
295f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        File sdk = new File(sdkPath);
296f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertNotNull("$ADT_SDK_SOURCE_PATH (" + sdk.getPath() + ") is not a directory",
297f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                sdk.isDirectory());
298f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        File git = sdk.getParentFile();
299f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        File attrsPath = new File(git, "frameworks" + File.separator + "base"
300f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                + File.separator + "core" + File.separator + "res" + File.separator + "res"
301f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                + File.separator + "values" + File.separator + "attrs.xml");
302f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(attrsPath.getPath(), attrsPath.exists());
303f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        AttrsXmlParser parser = new AttrsXmlParser(attrsPath.getPath(),
304f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                new StdLogger(StdLogger.Level.VERBOSE), 1100);
305f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        parser.preload();
306f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        Map<String, AttributeInfo> attributeMap = parser.getAttributeMap();
307f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertNotNull(attributeMap);
308f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertNotNull(attributeMap.get("layout_width"));
309f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        Set<String> seen = Sets.newHashSet();
310f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
311f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        checkDir(new File(git, "packages" + File.separator + "apps"), false, attributeMap, seen);
312f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
313f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
314f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    private void checkDir(File dir, boolean isResourceDir,
315f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Map<String, AttributeInfo> map, Set<String> seen) throws IOException {
316f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        assertTrue(dir.isDirectory());
317f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        File[] list = dir.listFiles();
318f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        if (list != null) {
319f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            for (File file : list) {
320f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                if (isResourceDir && file.isFile() && file.getPath().endsWith(DOT_XML)) {
321f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    checkXmlFile(file, map, seen);
322f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                } else if (file.isDirectory()) {
323f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    checkDir(file, isResourceDir || file.getName().equals("res"), map, seen);
324f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                }
325f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            }
326f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
327f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
328f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
329f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    private void checkXmlFile(File file, Map<String, AttributeInfo> map,
330f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Set<String> seen) throws IOException {
331f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        String xml = Files.toString(file, Charsets.UTF_8);
332f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        if (xml != null) {
333f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            //Document doc = DomUtilities.parseStructuredDocument(xml);
334f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Document doc = DomUtilities.parseDocument(xml, false);
335f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            if (doc != null && doc.getDocumentElement() != null) {
336f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                checkElement(file, doc.getDocumentElement(), map, seen);
337f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            }
338f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
339f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
340f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
341f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    private void checkElement(File file, Element element, Map<String, AttributeInfo> map,
342f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Set<String> seen) {
343f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        NamedNodeMap attributes = element.getAttributes();
344f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        for (int i = 0, n = attributes.getLength(); i < n; i++) {
345f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            Attr attribute = (Attr) attributes.item(i);
346f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
347f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            String uri = attribute.getNamespaceURI();
348f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            String name = attribute.getLocalName();
349f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            String value = attribute.getValue();
350f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            if (ANDROID_URI.equals(uri)) {
351f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                AttributeInfo info = map.get(name);
352f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                if (info == null) {
353f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    System.out.println("Warning: Unknown attribute '" + name + "' in " + file);
354f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                            return;
355f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                }
356f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                if (!info.isValid(value, null, null)) {
357f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    if (name.equals("duration") || name.equals("exitFadeDuration")) {
358f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                        // Already known
359f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                        return;
360f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    }
361f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    String message = "In file " +
362f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                            file.getPath() + ":\nCould not validate value \"" + value
363f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                            + "\" for attribute '"
364f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                            + name + "' where the attribute info has formats " + info.getFormats()
365f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                            + "\n";
366f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    System.out.println("\n" + message);
367f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    fail(message);
368f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                }
369f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                if ((value.startsWith("@") || value.startsWith("?")) &&
370f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                        !info.getFormats().contains(Format.REFERENCE)) {
371f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    // Print out errors in attrs.xml
372f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye
373f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    if (!seen.contains(name)) {
374f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                        seen.add(name);
375f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                        System.out.println("\"" + name + "\" with formats " + info.getFormats()
376f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                                + " was passed a reference (" + value + ") in file " + file);
377f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                    }
378f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye                }
379f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye            }
380f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye        }
381f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye    }
382f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye}
383