• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.url;
6 
7 import static org.mockito.ArgumentMatchers.any;
8 import static org.mockito.Mockito.doThrow;
9 
10 import androidx.test.filters.SmallTest;
11 
12 import org.junit.Assert;
13 import org.junit.Before;
14 import org.junit.Test;
15 import org.junit.runner.RunWith;
16 import org.mockito.Mock;
17 import org.mockito.MockitoAnnotations;
18 
19 import org.chromium.base.test.BaseJUnit4ClassRunner;
20 import org.chromium.base.test.util.Batch;
21 import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
22 
23 import java.net.URISyntaxException;
24 
25 /**
26  * Tests for {@link GURL}. GURL relies heavily on the native implementation, and the lion's share of
27  * the logic is tested there. This test is primarily to make sure everything is plumbed through
28  * correctly.
29  */
30 @RunWith(BaseJUnit4ClassRunner.class)
31 @Batch(Batch.UNIT_TESTS)
32 public class GURLJavaTest {
33     @Mock GURL.Natives mGURLMocks;
34 
35     @Before
setUp()36     public void setUp() {
37         MockitoAnnotations.initMocks(this);
38 
39         NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
40         GURLJavaTestHelper.nativeInitializeICU();
41     }
42 
deepAssertEquals(GURL expected, GURL actual)43     /* package */ static void deepAssertEquals(GURL expected, GURL actual) {
44         Assert.assertEquals(expected, actual);
45         Assert.assertEquals(expected.getScheme(), actual.getScheme());
46         Assert.assertEquals(expected.getUsername(), actual.getUsername());
47         Assert.assertEquals(expected.getPassword(), actual.getPassword());
48         Assert.assertEquals(expected.getHost(), actual.getHost());
49         Assert.assertEquals(expected.getPort(), actual.getPort());
50         Assert.assertEquals(expected.getPath(), actual.getPath());
51         Assert.assertEquals(expected.getQuery(), actual.getQuery());
52         Assert.assertEquals(expected.getRef(), actual.getRef());
53     }
54 
prependLengthToSerialization(String serialization)55     private String prependLengthToSerialization(String serialization) {
56         return Integer.toString(serialization.length()) + GURL.SERIALIZER_DELIMITER + serialization;
57     }
58 
59     @SmallTest
60     @Test
testGURLEquivalence()61     public void testGURLEquivalence() {
62         GURLJavaTestHelper.nativeTestGURLEquivalence();
63     }
64 
65     // Equivalent of GURLTest.Components
66     @SmallTest
67     @Test
68     @SuppressWarnings(value = "AuthLeak")
testComponents()69     public void testComponents() {
70         GURL empty = new GURL("");
71         Assert.assertTrue(empty.isEmpty());
72         Assert.assertFalse(empty.isValid());
73 
74         GURL url = new GURL("http://user:pass@google.com:99/foo;bar?q=a#ref");
75         Assert.assertFalse(url.isEmpty());
76         Assert.assertTrue(url.isValid());
77         Assert.assertTrue(url.getScheme().equals("http"));
78 
79         Assert.assertEquals("http://user:pass@google.com:99/foo;bar?q=a#ref", url.getSpec());
80 
81         Assert.assertEquals("http", url.getScheme());
82         Assert.assertEquals("user", url.getUsername());
83         Assert.assertEquals("pass", url.getPassword());
84         Assert.assertEquals("google.com", url.getHost());
85         Assert.assertEquals("99", url.getPort());
86         Assert.assertEquals("/foo;bar", url.getPath());
87         Assert.assertEquals("q=a", url.getQuery());
88         Assert.assertEquals("ref", url.getRef());
89 
90         // Test parsing userinfo with special characters.
91         GURL urlSpecialPass = new GURL("http://user:%40!$&'()*+,;=:@google.com:12345");
92         Assert.assertTrue(urlSpecialPass.isValid());
93         // GURL canonicalizes some delimiters.
94         Assert.assertEquals("%40!$&%27()*+,%3B%3D%3A", urlSpecialPass.getPassword());
95         Assert.assertEquals("google.com", urlSpecialPass.getHost());
96         Assert.assertEquals("12345", urlSpecialPass.getPort());
97     }
98 
99     // Equivalent of GURLTest.Empty
100     @SmallTest
101     @Test
testEmpty()102     public void testEmpty() {
103         GURLJni.TEST_HOOKS.setInstanceForTesting(mGURLMocks);
104         doThrow(new RuntimeException("Should not need to parse empty URL"))
105                 .when(mGURLMocks)
106                 .init(any(), any());
107         GURL url = new GURL("");
108         Assert.assertFalse(url.isValid());
109         Assert.assertEquals("", url.getSpec());
110 
111         Assert.assertEquals("", url.getScheme());
112         Assert.assertEquals("", url.getUsername());
113         Assert.assertEquals("", url.getPassword());
114         Assert.assertEquals("", url.getHost());
115         Assert.assertEquals("", url.getPort());
116         Assert.assertEquals("", url.getPath());
117         Assert.assertEquals("", url.getQuery());
118         Assert.assertEquals("", url.getRef());
119         GURLJni.TEST_HOOKS.setInstanceForTesting(null);
120     }
121 
122     // Test that GURL and URI return the correct Origin.
123     @SmallTest
124     @Test
125     @SuppressWarnings(value = "AuthLeak")
testOrigin()126     public void testOrigin() throws URISyntaxException {
127         final String kExpectedOrigin1 = "http://google.com:21/";
128         final String kExpectedOrigin2 = "";
129         GURL url1 = new GURL("filesystem:http://user:pass@google.com:21/blah#baz");
130         GURL url2 = new GURL("javascript:window.alert(\"hello,world\");");
131         URI uri = new URI("filesystem:http://user:pass@google.com:21/blah#baz");
132 
133         Assert.assertEquals(kExpectedOrigin1, url1.getOrigin().getSpec());
134         Assert.assertEquals(kExpectedOrigin2, url2.getOrigin().getSpec());
135         URI origin = uri.getOrigin();
136         Assert.assertEquals(kExpectedOrigin1, origin.getSpec());
137     }
138 
139     @SmallTest
140     @Test
testWideInput()141     public void testWideInput() throws URISyntaxException {
142         final String kExpectedSpec = "http://xn--1xa.com/";
143 
144         GURL url = new GURL("http://\u03C0.com");
145         Assert.assertEquals(kExpectedSpec, url.getSpec());
146         Assert.assertEquals("http", url.getScheme());
147         Assert.assertEquals("", url.getUsername());
148         Assert.assertEquals("", url.getPassword());
149         Assert.assertEquals("xn--1xa.com", url.getHost());
150         Assert.assertEquals("", url.getPort());
151         Assert.assertEquals("/", url.getPath());
152         Assert.assertEquals("", url.getQuery());
153         Assert.assertEquals("", url.getRef());
154     }
155 
156     @SmallTest
157     @Test
158     @SuppressWarnings(value = "AuthLeak")
testSerialization()159     public void testSerialization() {
160         GURL cases[] = {
161             // Common Standard URLs.
162             new GURL("https://www.google.com"),
163             new GURL("https://www.google.com/"),
164             new GURL("https://www.google.com/maps.htm"),
165             new GURL("https://www.google.com/maps/"),
166             new GURL("https://www.google.com/index.html"),
167             new GURL("https://www.google.com/index.html?q=maps"),
168             new GURL("https://www.google.com/index.html#maps/"),
169             new GURL("https://foo:bar@www.google.com/maps.htm"),
170             new GURL("https://www.google.com/maps/au/index.html"),
171             new GURL("https://www.google.com/maps/au/north"),
172             new GURL("https://www.google.com/maps/au/north/"),
173             new GURL("https://www.google.com/maps/au/index.html?q=maps#fragment/"),
174             new GURL("http://www.google.com:8000/maps/au/index.html?q=maps#fragment/"),
175             new GURL("https://www.google.com/maps/au/north/?q=maps#fragment"),
176             new GURL("https://www.google.com/maps/au/north?q=maps#fragment"),
177             // Less common standard URLs.
178             new GURL("filesystem:http://www.google.com/temporary/bar.html?baz=22"),
179             new GURL("file:///temporary/bar.html?baz=22"),
180             new GURL("ftp://foo/test/index.html"),
181             new GURL("gopher://foo/test/index.html"),
182             new GURL("ws://foo/test/index.html"),
183             // Non-standard,
184             new GURL("chrome://foo/bar.html"),
185             new GURL("httpa://foo/test/index.html"),
186             new GURL("blob:https://foo.bar/test/index.html"),
187             new GURL("about:blank"),
188             new GURL("data:foobar"),
189             new GURL("scheme:opaque_data"),
190             // Invalid URLs.
191             new GURL("foobar"),
192             // URLs containing the delimiter
193             new GURL("https://www.google.ca/" + GURL.SERIALIZER_DELIMITER + ",foo"),
194             new GURL("https://www.foo" + GURL.SERIALIZER_DELIMITER + "bar.com"),
195         };
196 
197         GURLJni.TEST_HOOKS.setInstanceForTesting(mGURLMocks);
198         doThrow(
199                         new RuntimeException(
200                                 "Should not re-initialize for deserialization when the "
201                                         + "version hasn't changed."))
202                 .when(mGURLMocks)
203                 .init(any(), any());
204         for (GURL url : cases) {
205             GURL out = GURL.deserialize(url.serialize());
206             deepAssertEquals(url, out);
207         }
208         GURLJni.TEST_HOOKS.setInstanceForTesting(null);
209     }
210 
211     /**
212      * Tests that we re-parse the URL from the spec, which must always be the last token in the
213      * serialization, if the serialization version differs.
214      */
215     @SmallTest
216     @Test
testSerializationWithVersionSkew()217     public void testSerializationWithVersionSkew() {
218         GURL url = new GURL("https://www.google.com");
219         String serialization =
220                 (GURL.SERIALIZER_VERSION + 1)
221                         + ",0,0,0,0,foo,https://url.bad,blah,0,"
222                                 .replace(',', GURL.SERIALIZER_DELIMITER)
223                         + url.getSpec();
224         serialization = prependLengthToSerialization(serialization);
225         GURL out = GURL.deserialize(serialization);
226         deepAssertEquals(url, out);
227     }
228 
229     /** Tests that fields that aren't visible to java code are correctly serialized. */
230     @SmallTest
231     @Test
testSerializationOfPrivateFields()232     public void testSerializationOfPrivateFields() {
233         String serialization =
234                 GURL.SERIALIZER_VERSION
235                         + ",true,"
236                         // Outer Parsed.
237                         + "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,false,true,"
238                         // Inner Parsed.
239                         + "17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,true,false,"
240                         + "chrome://foo/bar.html";
241         serialization = serialization.replace(',', GURL.SERIALIZER_DELIMITER);
242         serialization = prependLengthToSerialization(serialization);
243         GURL url = GURL.deserialize(serialization);
244         Assert.assertEquals(url.serialize(), serialization);
245     }
246 
247     /** Tests serialized GURL truncated by storage. */
248     @SmallTest
249     @Test
testTruncatedDeserialization()250     public void testTruncatedDeserialization() {
251         String serialization = "123,1,true,1,2,3,4,5,6,7,8,9,10";
252         serialization = serialization.replace(',', GURL.SERIALIZER_DELIMITER);
253         GURL url = GURL.deserialize(serialization);
254         Assert.assertEquals(url, GURL.emptyGURL());
255     }
256 
257     /** Tests serialized GURL truncated by storage. */
258     @SmallTest
259     @Test
testCorruptedSerializations()260     public void testCorruptedSerializations() {
261         String serialization = new GURL("https://www.google.ca").serialize();
262         // Replace the scheme length (5) with an extra delimiter.
263         String corruptedParsed = serialization.replace('5', GURL.SERIALIZER_DELIMITER);
264         GURL url = GURL.deserialize(corruptedParsed);
265         Assert.assertEquals(GURL.emptyGURL(), url);
266 
267         String corruptedVersion =
268                 serialization.replaceFirst(Integer.toString(GURL.SERIALIZER_VERSION), "x");
269         url = GURL.deserialize(corruptedVersion);
270         Assert.assertEquals(GURL.emptyGURL(), url);
271     }
272 
273     // Test that domainIs is hooked up correctly.
274     @SmallTest
275     @Test
testDomainIs()276     public void testDomainIs() {
277         GURL url1 = new GURL("https://www.google.com");
278         GURL url2 = new GURL("https://www.notgoogle.com");
279 
280         Assert.assertTrue(url1.domainIs("com"));
281         Assert.assertTrue(url2.domainIs("com"));
282         Assert.assertTrue(url1.domainIs("google.com"));
283         Assert.assertFalse(url2.domainIs("google.com"));
284 
285         Assert.assertTrue(url1.domainIs("www.google.com"));
286         Assert.assertFalse(url1.domainIs("images.google.com"));
287     }
288 
289     // Test that replaceComponents is hooked up correctly.
290     @SmallTest
291     @Test
292     @SuppressWarnings(value = "AuthLeak")
testReplaceComponents()293     public void testReplaceComponents() {
294         GURL url = new GURL("http://user:pass@google.com:99/foo;bar?q=a#ref");
295 
296         GURL unchanged = url.replaceComponents(null, false, null, false);
297         Assert.assertEquals("user", unchanged.getUsername());
298         Assert.assertEquals("pass", unchanged.getPassword());
299 
300         GURL cleared = url.replaceComponents(null, true, null, true);
301         Assert.assertTrue(cleared.getUsername().isEmpty());
302         Assert.assertTrue(cleared.getPassword().isEmpty());
303 
304         GURL changed = url.replaceComponents("newusername", false, "newpassword", false);
305         Assert.assertEquals("newusername", changed.getUsername());
306         Assert.assertEquals("newpassword", changed.getPassword());
307     }
308 
309     // Tests Mojom conversion.
310     @SmallTest
311     @Test
testMojomConvertion()312     public void testMojomConvertion() {
313         // Valid:
314         Assert.assertEquals(
315                 "https://www.google.com/", new GURL("https://www.google.com/").toMojom().url);
316 
317         // Null:
318         Assert.assertEquals("", new GURL(null).toMojom().url);
319 
320         // Empty:
321         Assert.assertEquals("", new GURL("").toMojom().url);
322 
323         // Invalid:
324         Assert.assertEquals("", new GURL(new String(new byte[] {1, 1, 1})).toMojom().url);
325 
326         // Too long.
327         Assert.assertEquals(
328                 "",
329                 new GURL("https://www.google.com/".concat("a".repeat(2 * 1024 * 1024)))
330                         .toMojom()
331                         .url);
332     }
333 }
334