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