1/*
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @summary Unit test for java.net.CookieManager
27 * @bug 6244040 7150552 7051862
28 * @modules jdk.httpserver
29 * @run main/othervm -ea CookieManagerTest
30 * @author Edward Wang
31 */
32
33import com.sun.net.httpserver.*;
34import java.io.IOException;
35import java.net.*;
36import static java.net.Proxy.NO_PROXY;
37
38public class CookieManagerTest {
39
40    static CookieTransactionHandler httpTrans;
41    static HttpServer server;
42
43    static final String hostAddress = getAddr();
44
45    /** Returns an IP literal suitable for use by the test. */
46    static String getAddr() {
47        try {
48            InetAddress lh = InetAddress.getLocalHost();
49            System.out.println("Trying: " + lh);
50            if (lh.isReachable(5_000)) {
51                System.out.println("Using: " + lh);
52                return lh.getHostAddress();
53            }
54        } catch (IOException x) {
55            System.out.println("Debug: caught:" + x);
56        }
57        System.out.println("Using: \"127.0.0.1\"");
58        return "127.0.0.1";
59    }
60
61    public static void main(String[] args) throws Exception {
62        startHttpServer();
63        makeHttpCall();
64
65        if (httpTrans.badRequest) {
66            throw new RuntimeException("Test failed : bad cookie header");
67        }
68        checkCookiePolicy();
69    }
70
71   public static void startHttpServer() throws IOException {
72        httpTrans = new CookieTransactionHandler();
73        server = HttpServer.create(new InetSocketAddress(0), 0);
74        server.createContext("/", httpTrans);
75        server.start();
76    }
77
78    /*
79     * Checks if CookiePolicy.ACCEPT_ORIGINAL_SERVER#shouldAccept()
80     * returns false for null arguments
81     */
82    private static void checkCookiePolicy() throws Exception {
83        CookiePolicy cp = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
84        boolean retVal;
85        retVal = cp.shouldAccept(null, null);
86        checkValue(retVal);
87        retVal = cp.shouldAccept(null, new HttpCookie("CookieName", "CookieVal"));
88        checkValue(retVal);
89        retVal = cp.shouldAccept((new URL("http", "localhost", 2345, "/")).toURI(),
90                                  null);
91        checkValue(retVal);
92    }
93
94    private static void checkValue(boolean val) {
95        if (val)
96            throw new RuntimeException("Return value is not false!");
97    }
98
99    public static void makeHttpCall() throws IOException {
100        try {
101            int port = server.getAddress().getPort();
102            System.out.println("http server listenining on: " + port);
103
104            // install CookieManager to use
105            CookieHandler.setDefault(new CookieManager());
106
107            for (int i = 0; i < CookieTransactionHandler.testCount; i++) {
108                System.out.println("====== CookieManager test " + (i+1)
109                                    + " ======");
110                ((CookieManager)CookieHandler.getDefault())
111                    .setCookiePolicy(CookieTransactionHandler.testPolicies[i]);
112                ((CookieManager)CookieHandler.getDefault())
113                    .getCookieStore().removeAll();
114                URL url = new URL("http" ,
115                                  hostAddress,
116                                  server.getAddress().getPort(),
117                                  CookieTransactionHandler.testCases[i][0]
118                                                          .serverPath);
119                System.out.println("Requesting " + url);
120                HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY);
121                uc.getResponseCode();
122                uc.disconnect();
123            }
124        } finally {
125            server.stop(0);
126        }
127    }
128}
129
130class CookieTransactionHandler implements HttpHandler {
131
132    private int testcaseDone = 0;
133    private int testDone = 0;
134
135    public static boolean badRequest = false;
136    // the main test control logic will also loop exactly this number
137    // to send http request
138    public static final int testCount = 6;
139
140    @Override
141    public void handle(HttpExchange exchange) throws IOException {
142        if (testDone < testCases[testcaseDone].length) {
143            // still have other tests to run,
144            // check the Cookie header and then redirect it
145            if (testDone > 0) checkRequest(exchange.getRequestHeaders());
146            exchange.getResponseHeaders().add("Location",
147                    testCases[testcaseDone][testDone].serverPath);
148            exchange.getResponseHeaders()
149                    .add(testCases[testcaseDone][testDone].headerToken,
150                         testCases[testcaseDone][testDone].cookieToSend);
151            exchange.sendResponseHeaders(302, -1);
152            testDone++;
153        } else {
154            // the last test of this test case
155            if (testDone > 0) checkRequest(exchange.getRequestHeaders());
156            testcaseDone++;
157            testDone = 0;
158            exchange.sendResponseHeaders(200, -1);
159        }
160        exchange.close();
161    }
162
163    private void checkRequest(Headers hdrs) {
164
165        assert testDone > 0;
166        String cookieHeader = hdrs.getFirst("Cookie");
167        if (cookieHeader != null &&
168            cookieHeader
169                .equalsIgnoreCase(testCases[testcaseDone][testDone-1]
170                                  .cookieToRecv))
171        {
172            System.out.printf("%15s %s\n", "PASSED:", cookieHeader);
173        } else {
174            System.out.printf("%15s %s\n", "FAILED:", cookieHeader);
175            System.out.printf("%15s %s\n\n", "should be:",
176                    testCases[testcaseDone][testDone-1].cookieToRecv);
177            badRequest = true;
178        }
179    }
180
181    // test cases
182    public static class CookieTestCase {
183        public String headerToken;
184        public String cookieToSend;
185        public String cookieToRecv;
186        public String serverPath;
187
188        public CookieTestCase(String h, String cts, String ctr, String sp) {
189            headerToken = h;
190            cookieToSend = cts;
191            cookieToRecv = ctr;
192            serverPath = sp;
193        }
194    };
195
196    /*
197     * these two must match each other,
198     * i.e. testCases.length == testPolicies.length
199     */
200
201    // the test cases to run; each test case may contain multiple roundtrips
202    public static CookieTestCase[][] testCases = null;
203    // indicates what CookiePolicy to use with each test cases
204    public static CookiePolicy[] testPolicies = null;
205
206    CookieTransactionHandler() {
207        testCases = new CookieTestCase[testCount][];
208        testPolicies = new CookiePolicy[testCount];
209
210        String localHostAddr = CookieManagerTest.hostAddress;
211
212        int count = 0;
213
214        // an http session with Netscape cookies exchanged
215        testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
216        testCases[count++] = new CookieTestCase[]{
217                new CookieTestCase("Set-Cookie",
218                "CUSTOMER=WILE:BOB; " +
219                "path=/; expires=Sat, 09-Nov-2030 23:12:40 GMT;" + "domain=." +
220                localHostAddr,
221                "CUSTOMER=WILE:BOB",
222                "/"
223                ),
224                new CookieTestCase("Set-Cookie",
225                "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/;" + "domain=." + localHostAddr,
226                "CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001",
227                "/"
228                ),
229                new CookieTestCase("Set-Cookie",
230                "SHIPPING=FEDEX; path=/foo;" + "domain=." + localHostAddr,
231                "CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001",
232                "/"
233                ),
234                new CookieTestCase("Set-Cookie",
235                "SHIPPING=FEDEX; path=/foo;" + "domain=." + localHostAddr,
236                "CUSTOMER=WILE:BOB; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX",
237                "/foo"
238                )
239                };
240
241        // check whether or not path rule is applied
242        testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
243        testCases[count++] = new CookieTestCase[]{
244                new CookieTestCase("Set-Cookie",
245                "PART_NUMBER=ROCKET_LAUNCHER_0001; path=/;" + "domain=." + localHostAddr,
246                "PART_NUMBER=ROCKET_LAUNCHER_0001",
247                "/"
248                ),
249                new CookieTestCase("Set-Cookie",
250                "PART_NUMBER=RIDING_ROCKET_0023; path=/ammo;" + "domain=." + localHostAddr,
251                "PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001",
252                "/ammo"
253                )
254                };
255
256        // an http session with rfc2965 cookies exchanged
257        testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
258        testCases[count++] = new CookieTestCase[]{
259                new CookieTestCase("Set-Cookie2",
260                "Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
261                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
262                "/acme/login"
263                ),
264                new CookieTestCase("Set-Cookie2",
265                "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\";" + "domain=." + localHostAddr,
266                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." +
267                    localHostAddr  + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";"
268                    + "$Domain=\"." + localHostAddr +  "\"",
269                "/acme/pickitem"
270                ),
271                new CookieTestCase("Set-Cookie2",
272                "Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
273                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr  +
274                    "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"."
275                    + localHostAddr  + "\"" + "; Shipping=\"FedEx\";$Path=\"/acme\";" +
276                    "$Domain=\"." + localHostAddr + "\"",
277                "/acme/shipping"
278                )
279                };
280
281        // check whether or not the path rule is applied
282        testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
283        testCases[count++] = new CookieTestCase[]{
284                new CookieTestCase("Set-Cookie2",
285                "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
286                "$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
287                "/acme/ammo"
288                ),
289                new CookieTestCase("Set-Cookie2",
290                "Part_Number=\"Riding_Rocket_0023\"; Version=\"1\"; Path=\"/acme/ammo\";" + "domain=."
291                    + localHostAddr,
292                "$Version=\"1\"; Part_Number=\"Riding_Rocket_0023\";$Path=\"/acme/ammo\";$Domain=\"."
293                    + localHostAddr  + "\"" + "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";"
294                    + "$Domain=\"." + localHostAddr + "\"",
295                "/acme/ammo"
296                ),
297                new CookieTestCase("",
298                "",
299                "$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";" + "$Domain=\"." + localHostAddr + "\"",
300                "/acme/parts"
301                )
302                };
303
304        // new cookie should overwrite old cookie
305        testPolicies[count] = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
306        testCases[count++] = new CookieTestCase[]{
307                new CookieTestCase("Set-Cookie2",
308                "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
309                "$Version=\"1\"; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
310                "/acme"
311                ),
312                new CookieTestCase("Set-Cookie2",
313                "Part_Number=\"Rocket_Launcher_2000\"; Version=\"1\"; Path=\"/acme\";" + "domain=." + localHostAddr,
314                "$Version=\"1\"; Part_Number=\"Rocket_Launcher_2000\";$Path=\"/acme\";$Domain=\"." + localHostAddr + "\"",
315                "/acme"
316                )
317                };
318
319        // cookies without domain attributes
320        // RFC 2965 states that domain should default to host
321        testPolicies[count] = CookiePolicy.ACCEPT_ALL;
322        testCases[count++] = new CookieTestCase[]{
323                new CookieTestCase("Set-Cookie2",
324                "Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\"",
325                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
326                "/acme/login"
327                ),
328                new CookieTestCase("Set-Cookie2",
329                "Part_Number=\"Rocket_Launcher_0001\"; Version=\"1\";Path=\"/acme\"",
330                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
331                    "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
332                "/acme/pickitem"
333                ),
334                new CookieTestCase("Set-Cookie2",
335                "Shipping=\"FedEx\"; Version=\"1\"; Path=\"/acme\"",
336                "$Version=\"1\"; Customer=\"WILE_E_COYOTE\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
337                    "; Part_Number=\"Rocket_Launcher_0001\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"" +
338                    "; Shipping=\"FedEx\";$Path=\"/acme\";$Domain=\""+localHostAddr+"\"",
339                "/acme/shipping"
340                )
341                };
342
343        assert count == testCount;
344    }
345}
346