View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
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    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.proxyautoconfig;
16  
17  import java.net.MalformedURLException;
18  import java.net.URL;
19  import java.text.DateFormat;
20  import java.text.SimpleDateFormat;
21  import java.util.Calendar;
22  import java.util.Locale;
23  import java.util.TimeZone;
24  
25  import org.htmlunit.BrowserVersion;
26  import org.htmlunit.SimpleWebTestCase;
27  import org.htmlunit.corejs.javascript.Undefined;
28  import org.htmlunit.javascript.JavaScriptEngine;
29  import org.junit.jupiter.api.Test;
30  
31  /**
32   * Tests for the {@link ProxyAutoConfig}.
33   *
34   * @author Ahmed Ashour
35   * @author Ronald Brill
36   */
37  public class ProxyAutoConfigTest extends SimpleWebTestCase {
38  
39      /**
40       * Test case.
41       */
42      @Test
43      public void shExpMatch() {
44          assertTrue(ProxyAutoConfig.shExpMatch("http://home.netscape.com/people/ari/index.html", "*/ari/*"));
45          assertFalse(ProxyAutoConfig.shExpMatch("http://home.netscape.com/people/montulli/index.html", "*/ari/*"));
46      }
47  
48      /**
49       * Test case.
50       */
51      @Test
52      public void dnsLevelDomains() {
53          assertEquals(0, ProxyAutoConfig.dnsDomainLevels("localhost"));
54          assertEquals(1, ProxyAutoConfig.dnsDomainLevels("example.com"));
55          assertEquals(2, ProxyAutoConfig.dnsDomainLevels("www.example.com"));
56          assertEquals(3, ProxyAutoConfig.dnsDomainLevels("api.sub.example.com"));
57          assertEquals(4, ProxyAutoConfig.dnsDomainLevels("deep.api.sub.example.com"));
58  
59          assertEquals(2, ProxyAutoConfig.dnsDomainLevels(".example.com"));
60          assertEquals(2, ProxyAutoConfig.dnsDomainLevels("example.com."));
61          assertEquals(2, ProxyAutoConfig.dnsDomainLevels("example..com"));
62          assertEquals(3, ProxyAutoConfig.dnsDomainLevels("example...com"));
63  
64          assertEquals(0, ProxyAutoConfig.dnsDomainLevels(""));
65          assertEquals(1, ProxyAutoConfig.dnsDomainLevels("."));
66          assertEquals(3, ProxyAutoConfig.dnsDomainLevels("..."));
67  
68          assertEquals(3, ProxyAutoConfig.dnsDomainLevels("192.168.1.1"));
69      }
70  
71      /**
72       * Test case.
73       */
74      @Test
75      public void weekdayRange() {
76          final Object undefined = Undefined.instance;
77  
78          final TimeZone timeZone = TimeZone.getDefault();
79          try {
80              TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
81  
82              Calendar calendar = Calendar.getInstance(Locale.ROOT);
83              DateFormat dateFormat = new SimpleDateFormat("EEE", Locale.ROOT);
84              String today = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
85              calendar.add(Calendar.DAY_OF_MONTH, 1);
86              String tomorrow = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
87              calendar.add(Calendar.DAY_OF_MONTH, -2);
88              String yesterday = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
89  
90              assertTrue(ProxyAutoConfig.weekdayRange(today, undefined, undefined));
91              assertTrue(ProxyAutoConfig.weekdayRange(today, tomorrow, undefined));
92              assertTrue(ProxyAutoConfig.weekdayRange(yesterday, today, undefined));
93              assertTrue(ProxyAutoConfig.weekdayRange(yesterday, tomorrow, undefined));
94              assertFalse(ProxyAutoConfig.weekdayRange(tomorrow, yesterday, undefined));
95  
96              assertTrue(ProxyAutoConfig.weekdayRange(today, undefined, "GMT"));
97              assertTrue(ProxyAutoConfig.weekdayRange(today, tomorrow, "GMT"));
98              assertTrue(ProxyAutoConfig.weekdayRange(yesterday, today, "GMT"));
99              assertTrue(ProxyAutoConfig.weekdayRange(yesterday, tomorrow, "GMT"));
100             assertFalse(ProxyAutoConfig.weekdayRange(tomorrow, yesterday, "GMT"));
101 
102             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
103 
104             calendar = Calendar.getInstance(Locale.ROOT);
105             dateFormat = new SimpleDateFormat("EEE", Locale.ROOT);
106             today = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
107             calendar.add(Calendar.DAY_OF_MONTH, 1);
108             tomorrow = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
109             calendar.add(Calendar.DAY_OF_MONTH, -2);
110             yesterday = dateFormat.format(calendar.getTime()).toUpperCase(Locale.ROOT);
111 
112             assertTrue(ProxyAutoConfig.weekdayRange(today, undefined, undefined));
113             assertTrue(ProxyAutoConfig.weekdayRange(today, tomorrow, undefined));
114             assertTrue(ProxyAutoConfig.weekdayRange(yesterday, today, undefined));
115             assertTrue(ProxyAutoConfig.weekdayRange(yesterday, tomorrow, undefined));
116             assertFalse(ProxyAutoConfig.weekdayRange(tomorrow, yesterday, undefined));
117 
118             assertTrue(ProxyAutoConfig.weekdayRange(today, undefined, "GMT"));
119             assertTrue(ProxyAutoConfig.weekdayRange(today, tomorrow, "GMT"));
120             assertTrue(ProxyAutoConfig.weekdayRange(yesterday, today, "GMT"));
121             assertTrue(ProxyAutoConfig.weekdayRange(yesterday, tomorrow, "GMT"));
122             assertFalse(ProxyAutoConfig.weekdayRange(tomorrow, yesterday, "GMT"));
123         }
124         finally {
125             TimeZone.setDefault(timeZone);
126         }
127     }
128 
129     /**
130      * Test case.
131      */
132     @Test
133     public void dateRange() {
134         final Object undefined = Undefined.instance;
135 
136         final TimeZone timeZone = TimeZone.getDefault();
137         try {
138             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
139 
140             Calendar calendar = Calendar.getInstance(Locale.ROOT);
141             int today = calendar.get(Calendar.DAY_OF_MONTH);
142             calendar.add(Calendar.DAY_OF_MONTH, 1);
143             int tomorrow = calendar.get(Calendar.DAY_OF_MONTH);
144             calendar.add(Calendar.DAY_OF_MONTH, -2);
145             int yesterday = calendar.get(Calendar.DAY_OF_MONTH);
146 
147             assertTrue(ProxyAutoConfig.dateRange(String.valueOf(today),
148                     undefined, undefined, undefined, undefined, undefined, undefined));
149             assertFalse(ProxyAutoConfig.dateRange(String.valueOf(yesterday),
150                     undefined, undefined, undefined, undefined, undefined, undefined));
151             assertFalse(ProxyAutoConfig.dateRange(String.valueOf(tomorrow),
152                     undefined, undefined, undefined, undefined, undefined, undefined));
153 
154             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
155 
156             calendar = Calendar.getInstance(Locale.ROOT);
157             today = calendar.get(Calendar.DAY_OF_MONTH);
158             calendar.add(Calendar.DAY_OF_MONTH, 1);
159             tomorrow = calendar.get(Calendar.DAY_OF_MONTH);
160             calendar.add(Calendar.DAY_OF_MONTH, -2);
161             yesterday = calendar.get(Calendar.DAY_OF_MONTH);
162 
163             assertTrue(ProxyAutoConfig.dateRange(String.valueOf(today),
164                     undefined, undefined, undefined, undefined, undefined, undefined));
165             assertFalse(ProxyAutoConfig.dateRange(String.valueOf(yesterday),
166                     undefined, undefined, undefined, undefined, undefined, undefined));
167             assertFalse(ProxyAutoConfig.dateRange(String.valueOf(tomorrow),
168                     undefined, undefined, undefined, undefined, undefined, undefined));
169         }
170         finally {
171             TimeZone.setDefault(timeZone);
172         }
173     }
174 
175     /**
176      * Test case.
177      */
178     @Test
179     public void timeRange() {
180         final Object undefined = Undefined.instance;
181 
182         final TimeZone timeZone = TimeZone.getDefault();
183         try {
184             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
185 
186             Calendar calendar = Calendar.getInstance(Locale.ROOT);
187             int now = calendar.get(Calendar.HOUR_OF_DAY);
188             calendar.add(Calendar.HOUR_OF_DAY, 2);
189             int after = calendar.get(Calendar.HOUR_OF_DAY);
190             calendar.add(Calendar.HOUR_OF_DAY, -4);
191             int before = calendar.get(Calendar.HOUR_OF_DAY);
192 
193             assertTrue(ProxyAutoConfig.timeRange(String.valueOf(now),
194                     undefined, undefined, undefined, undefined, undefined, undefined));
195             assertFalse(ProxyAutoConfig.timeRange(String.valueOf(before),
196                     undefined, undefined, undefined, undefined, undefined, undefined));
197             assertFalse(ProxyAutoConfig.timeRange(String.valueOf(after),
198                     undefined, undefined, undefined, undefined, undefined, undefined));
199 
200             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
201 
202             calendar = Calendar.getInstance(Locale.ROOT);
203             now = calendar.get(Calendar.HOUR_OF_DAY);
204             calendar.add(Calendar.HOUR_OF_DAY, 2);
205             after = calendar.get(Calendar.HOUR_OF_DAY);
206             calendar.add(Calendar.HOUR_OF_DAY, -4);
207             before = calendar.get(Calendar.HOUR_OF_DAY);
208 
209             assertTrue(ProxyAutoConfig.timeRange(String.valueOf(now),
210                     undefined, undefined, undefined, undefined, undefined, undefined));
211             assertFalse(ProxyAutoConfig.timeRange(String.valueOf(before),
212                     undefined, undefined, undefined, undefined, undefined, undefined));
213             assertFalse(ProxyAutoConfig.timeRange(String.valueOf(after),
214                     undefined, undefined, undefined, undefined, undefined, undefined));
215         }
216         finally {
217             TimeZone.setDefault(timeZone);
218         }
219     }
220 
221     /**
222      * Test case.
223      */
224     @Test
225     public void simple() {
226         final String content = "function FindProxyForURL(url, host) { "
227                 + "return \"PROXY proxy.example.com:8080; DIRECT\"; }";
228         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME, content, URL_FIRST);
229         assertEquals("PROXY proxy.example.com:8080; DIRECT", value);
230     }
231 
232     /**
233      * Test case.
234      */
235     @Test
236     public void someConditions() throws MalformedURLException {
237         final String content = "function FindProxyForURL(url, host) {\n"
238                 + "  if (shExpMatch(host,\"*.example.com\")) {\n"
239                 + "    return \"DIRECT\";\n"
240                 + "  }\n"
241 
242                 + "  return \"PROXY proxy.example.com:8000; DIRECT\";\n"
243                 + "}";
244 
245         String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
246                                             content, new URL("ftp://www.example.com"));
247         assertEquals("DIRECT", value);
248 
249         value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME, content, new URL("ftp://example.com"));
250         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
251     }
252 
253     /**
254      * Test case.
255      */
256     @Test
257     public void bindings() {
258         final String content = "ProxyConfig.bindings.com = 'my_com';\n"
259             + "ProxyConfig.bindings.org = 'my_org';\n"
260             + "ProxyConfig.bindings.net = 'my_net';\n"
261             + "ProxyConfig.bindings.edu = 'my_edu';\n"
262             + "ProxyConfig.bindings.gov = 'my_gov';\n"
263             + "function FindProxyForURL(url, host) {\n"
264             + "  var returnValue = '';\n"
265             + "  for (var x in ProxyConfig.bindings) {\n"
266             + "    returnValue += x + ' ';\n"
267             + "  }\n"
268             + "  return returnValue;\n"
269             + "}\n";
270         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME, content, URL_FIRST);
271         assertEquals("com org net edu gov ", value);
272     }
273 
274     /**
275      * Test case for #1649.
276      */
277     @Test
278     public void isInNet() {
279         final boolean isInNet = ProxyAutoConfig.isInNet("www.1234abcd.abc", "172.16.0.0", "255.240.0.0");
280         assertFalse(isInNet);
281     }
282 
283     /**
284      * Test case for #1911.
285      */
286     @Test
287     public void isInNetRange() {
288         final boolean isInNet = ProxyAutoConfig.isInNet("172.22.0.7", "172.16.0.0", "255.240.0.0");
289         assertTrue(isInNet);
290     }
291 
292     /**
293      * Test case.
294      */
295     @Test
296     public void isPlainHostNameFalse() throws MalformedURLException {
297         final String content = "function FindProxyForURL(url, host) {\n"
298                 + "  if (isPlainHostName('www.mozilla.org')) {\n"
299                 + "    return 'DIRECT';\n"
300                 + "  }\n"
301 
302                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
303                 + "}";
304 
305         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
306                                             content, new URL("https://www.mozilla.org"));
307         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
308     }
309 
310     /**
311      * Test case.
312      */
313     @Test
314     public void isPlainHostNameTrue() throws MalformedURLException {
315         final String content = "function FindProxyForURL(url, host) {\n"
316                 + "  if (isPlainHostName('www')) {\n"
317                 + "    return 'DIRECT';\n"
318                 + "  }\n"
319 
320                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
321                 + "}";
322 
323         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
324                                             content, new URL("https://www.mozilla.org"));
325         assertEquals("DIRECT", value);
326     }
327 
328     /**
329      * Test case.
330      */
331     @Test
332     public void dnsDomainIsFalse() throws MalformedURLException {
333         final String content = "function FindProxyForURL(url, host) {\n"
334                 + "  if (dnsDomainIs('www', '.mozilla.org')) {\n"
335                 + "    return 'DIRECT';\n"
336                 + "  }\n"
337 
338                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
339                 + "}";
340 
341         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
342                                             content, new URL("https://www.mozilla.org"));
343         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
344     }
345 
346     /**
347      * Test case.
348      */
349     @Test
350     public void dnsDomainIsTrue() throws MalformedURLException {
351         final String content = "function FindProxyForURL(url, host) {\n"
352                 + "  if (dnsDomainIs('www.mozilla.org', '.mozilla.org')) {\n"
353                 + "    return 'DIRECT';\n"
354                 + "  }\n"
355 
356                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
357                 + "}";
358 
359         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
360                                             content, new URL("https://www.mozilla.org"));
361         assertEquals("DIRECT", value);
362     }
363 
364     /**
365      * Test case.
366      */
367     @Test
368     public void localHostOrDomainIsFalseDomain() throws MalformedURLException {
369         final String content = "function FindProxyForURL(url, host) {\n"
370                 + "  if (localHostOrDomainIs('www.google.com', 'www.mozilla.org')) {\n"
371                 + "    return 'DIRECT';\n"
372                 + "  }\n"
373 
374                 + "   return 'PROXY proxy.example.com:8000; DIRECT';\n"
375                 + "}";
376 
377         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
378                                             content, new URL("https://www.mozilla.org"));
379         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
380     }
381 
382     /**
383      * Test case.
384      */
385     @Test
386     public void localHostOrDomainIsFalseHostname() throws MalformedURLException {
387         final String content = "function FindProxyForURL(url, host) {\n"
388                 + "  if (localHostOrDomainIs('home.mozilla.org', 'www.mozilla.org')) {\n"
389                 + "    return 'DIRECT';\n"
390                 + "  }\n"
391 
392                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
393                 + "}";
394 
395         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
396                                             content, new URL("https://www.mozilla.org"));
397         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
398     }
399 
400     /**
401      * Test case.
402      */
403     @Test
404     public void localHostOrDomainIsTrue() throws MalformedURLException {
405         final String content = "function FindProxyForURL(url, host) {\n"
406                 + "  if (localHostOrDomainIs('www.mozilla.org', 'www.mozilla.org')) {\n"
407                 + "    return 'DIRECT';\n"
408                 + "  }\n"
409 
410                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
411                 + "}";
412 
413         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
414                                             content, new URL("https://www.mozilla.org"));
415         assertEquals("DIRECT", value);
416     }
417 
418     /**
419      * Test case.
420      */
421     @Test
422     public void localHostOrDomainIsTrueNoDomain() throws MalformedURLException {
423         final String content = "function FindProxyForURL(url, host) {\n"
424                 + "  if (localHostOrDomainIs('www', 'www.mozilla.org')) {\n"
425                 + "    return 'DIRECT';\n"
426                 + "  }\n"
427 
428                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
429                 + "}";
430 
431         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
432                                             content, new URL("https://www.mozilla.org"));
433         assertEquals("DIRECT", value);
434     }
435 
436     /**
437      * Test case.
438      */
439     @Test
440     public void isResolvableFalse() throws MalformedURLException {
441         final String content = "function FindProxyForURL(url, host) {\n"
442                 + "  if (isResolvable('A17.2547876535.817')) {\n"
443                 + "    return 'DIRECT';\n"
444                 + "  }\n"
445 
446                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
447                 + "}";
448 
449         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
450                                             content, new URL("https://www.mozilla.org"));
451         assertEquals("PROXY proxy.example.com:8000; DIRECT", value);
452     }
453 
454     /**
455      * Test case.
456      */
457     @Test
458     public void isResolvableTrue() throws MalformedURLException {
459         final String content = "function FindProxyForURL(url, host) {\n"
460                 + "  if (isResolvable('www.mozilla.org')) {\n"
461                 + "    return 'DIRECT';\n"
462                 + "  }\n"
463 
464                 + "  return 'PROXY proxy.example.com:8000; DIRECT';\n"
465                 + "}";
466 
467         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
468                                             content, new URL("https://www.mozilla.org"));
469         assertEquals("DIRECT", value);
470     }
471 
472     /**
473      * Test case.
474      */
475     @Test
476     public void dnsResolve() throws MalformedURLException {
477         final String content = "function FindProxyForURL(url, host) {\n"
478                 + "  return dnsResolve('www.wetator.org');\n"
479                 + "}";
480 
481         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
482                                             content, new URL("https://www.mozilla.org"));
483         assertTrue(value, value.contains("."));
484     }
485 
486     /**
487      * Test case.
488      */
489     @Test
490     public void convertAddr() throws MalformedURLException {
491         final String content = "function FindProxyForURL(url, host) {\n"
492                 + "  return convert_addr('192.0.2.172');\n"
493                 + "}";
494 
495         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
496                                             content, new URL("https://www.mozilla.org"));
497         assertEquals("-1073741140", value);
498     }
499 
500     /**
501      * Test case.
502      */
503     @Test
504     public void myIpAddress() throws MalformedURLException {
505         final String content = "function FindProxyForURL(url, host) {\n"
506                 + "  return myIpAddress();\n"
507                 + "}";
508 
509         final String value = JavaScriptEngine.evaluateProxyAutoConfig(BrowserVersion.CHROME,
510                                             content, new URL("https://www.mozilla.org"));
511         assertTrue(value, value.contains("."));
512     }
513 }