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;
16  
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Set;
22  
23  import org.htmlunit.html.HtmlPage;
24  import org.htmlunit.junit.BrowserRunner;
25  import org.htmlunit.junit.annotation.Alerts;
26  import org.htmlunit.util.Cookie;
27  import org.junit.Test;
28  import org.junit.runner.RunWith;
29  
30  /**
31   * Unit tests for {@link CookieManager}.
32   *
33   * @author Daniel Gredler
34   * @author Ahmed Ashour
35   * @author Marc Guillemot
36   * @author Ronald Brill
37   */
38  @RunWith(BrowserRunner.class)
39  public class CookieManager2Test extends SimpleWebTestCase {
40  
41      /**
42       * @throws Exception if the test fails
43       */
44      @Test
45      public void resettingCookie() throws Exception {
46          final String html = DOCTYPE_HTML
47              + "<html><head>\n"
48              + "<script>\n"
49              + "  function createCookie(name, value, days, path) {\n"
50              + "    if (days) {\n"
51              + "      var date = new Date();\n"
52              + "      date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));\n"
53              + "      var expires = '; expires=' + date.toGMTString();\n"
54              + "    }\n"
55              + "    else\n"
56              + "      var expires = '';\n"
57              + "    document.cookie = name + '=' + value + expires + '; path=' + path;\n"
58              + "  }\n"
59              + "\n"
60              + "  function readCookie(name) {\n"
61              + "    var nameEQ = name + '=';\n"
62              + "    var ca = document.cookie.split(';');\n"
63              + "    for(var i = 0; i < ca.length; i++) {\n"
64              + "      var c = ca[i];\n"
65              + "      while (c.charAt(0) == ' ')\n"
66              + "        c = c.substring(1, c.length);\n"
67              + "      if (c.indexOf(nameEQ) == 0)\n"
68              + "        return c.substring(nameEQ.length, c.length);\n"
69              + "    }\n"
70              + "    return null;\n"
71              + "  }\n"
72              + "</script></head><body>\n"
73              + "  <input id='button1' type='button' "
74              + "onclick=\"createCookie('button','button1',1,'/'); alert('cookie:' + readCookie('button'));\" "
75              + "value='Button 1'>\n"
76              + "  <input id='button2' type='button' "
77              + "onclick=\"createCookie('button','button2',1,'/'); alert('cookie:' + readCookie('button'));\" "
78              + "value='Button 2'>\n"
79              + "</form></body></html>";
80  
81          final String[] expectedAlerts = {"cookie:button1", "cookie:button2"};
82          final List<String> collectedAlerts = new ArrayList<>();
83          final HtmlPage page = loadPage(html, collectedAlerts);
84          page.getHtmlElementById("button1").click();
85          page.getHtmlElementById("button2").click();
86          assertEquals(expectedAlerts, collectedAlerts);
87      }
88  
89      /**
90       * @throws Exception if the test fails
91       */
92      @Test
93      @Alerts("my_key=§")
94      public void cookie_nullValue() throws Exception {
95          final WebClient webClient = getWebClient();
96          final MockWebConnection webConnection = new MockWebConnection();
97  
98          final URL url = URL_FIRST;
99          webConnection.setResponse(url, CookieManagerTest.HTML_ALERT_COOKIE);
100         webClient.setWebConnection(webConnection);
101 
102         final CookieManager mgr = webClient.getCookieManager();
103         mgr.addCookie(new Cookie(URL_FIRST.getHost(), "my_key", null, "/", null, false));
104 
105         final List<String> collectedAlerts = new ArrayList<>();
106         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
107 
108         final HtmlPage page = webClient.getPage(URL_FIRST);
109         assertEquals(getExpectedAlerts()[0], page.getTitleText());
110     }
111 
112     /**
113      * @throws Exception if the test fails
114      */
115     @Test
116     @Alerts("my_name=my_data§")
117     public void cookie_maxAgeMinusOne() throws Exception {
118         final WebClient webClient = getWebClient();
119         final MockWebConnection webConnection = new MockWebConnection();
120 
121         final URL url = URL_FIRST;
122         webConnection.setResponse(url, CookieManagerTest.HTML_ALERT_COOKIE);
123         webClient.setWebConnection(webConnection);
124 
125         final CookieManager mgr = webClient.getCookieManager();
126         mgr.addCookie(new Cookie(URL_FIRST.getHost(), "my_name", "my_data", "/", -1, false));
127 
128         final HtmlPage page = webClient.getPage(URL_FIRST);
129         assertEquals(getExpectedAlerts()[0], page.getTitleText());
130     }
131 
132     /**
133      * Regression test for bug 3053526: HtmlUnit was throwing an Exception when asking for cookies
134      * of "about:blank".
135      * @throws Exception if the test fails
136      */
137     @Test
138     public void cookiesForAboutBlank() throws Exception {
139         final WebClient webClient = getWebClient();
140         final HtmlPage htmlPage = webClient.getPage("about:blank");
141 
142         final Set<Cookie> cookies = webClient.getCookies(htmlPage.getUrl());
143         assertTrue(cookies.toString(), cookies.isEmpty());
144     }
145 
146     /**
147      * This was causing a ConcurrentModificationException.
148      * In "real life" the problem was arising due to changes to the cookies made from
149      * the JS processing thread.
150      * @throws Exception if the test fails
151      */
152     @Test
153     public void getCookiesShouldReturnACopyOfCurentState() throws Exception {
154         final String html = DOCTYPE_HTML
155                 + "<html><body>\n"
156                 + "<button id='it' onclick=\"document.cookie = 'foo=bla'\">click me</button>\n"
157                 + "<script>\n"
158                 + "document.cookie = 'cookie1=value1';\n"
159                 + "</script></body></html>";
160 
161         final WebClient webClient = getWebClient();
162 
163         final HtmlPage page = loadPage(html);
164         final Set<Cookie> initialCookies = webClient.getCookieManager().getCookies();
165         assertEquals(1, initialCookies.size());
166         final Iterator<Cookie> iterator = initialCookies.iterator();
167 
168         page.getHtmlElementById("it").click();
169         iterator.next(); // ConcurrentModificationException was here
170         assertEquals(1, initialCookies.size());
171         assertEquals(2, webClient.getCookieManager().getCookies().size());
172     }
173 }