1 /*
2 * Copyright 2010, Christophe Huriaux
3 * Copyright 2014-2020, Haiku, inc.
4 * Distributed under the terms of the MIT licence
5 */
6
7
8 #include "HttpTest.h"
9
10 #include <algorithm>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <fstream>
15 #include <map>
16 #include <posix/libgen.h>
17 #include <string>
18
19 #include <AutoDeleter.h>
20 #include <HttpRequest.h>
21 #include <NetworkKit.h>
22 #include <UrlProtocolListener.h>
23 #include <UrlProtocolRoster.h>
24
25 #include <tools/cppunit/ThreadedTestCaller.h>
26
27 #include "TestServer.h"
28
29
30 using namespace BPrivate::Network;
31
32
33 namespace {
34
35 typedef std::map<std::string, std::string> HttpHeaderMap;
36
37
38 class TestListener : public BUrlProtocolListener, public BDataIO {
39 public:
TestListener(const std::string & expectedResponseBody,const HttpHeaderMap & expectedResponseHeaders)40 TestListener(const std::string& expectedResponseBody,
41 const HttpHeaderMap& expectedResponseHeaders)
42 :
43 fExpectedResponseBody(expectedResponseBody),
44 fExpectedResponseHeaders(expectedResponseHeaders)
45 {
46 }
47
Write(const void * data,size_t size)48 virtual ssize_t Write(
49 const void *data,
50 size_t size)
51 {
52 std::copy_n(
53 (const char*)data,
54 size,
55 std::back_inserter(fActualResponseBody));
56 return size;
57 }
58
HeadersReceived(BUrlRequest * caller)59 virtual void HeadersReceived(
60 BUrlRequest* caller)
61 {
62 const BHttpResult& http_result
63 = dynamic_cast<const BHttpResult&>(caller->Result());
64 const BHttpHeaders& headers = http_result.Headers();
65
66 for (int32 i = 0; i < headers.CountHeaders(); ++i) {
67 const BHttpHeader& header = headers.HeaderAt(i);
68 fActualResponseHeaders[std::string(header.Name())]
69 = std::string(header.Value());
70 }
71 }
72
73
CertificateVerificationFailed(BUrlRequest * caller,BCertificate & certificate,const char * message)74 virtual bool CertificateVerificationFailed(
75 BUrlRequest* caller,
76 BCertificate& certificate,
77 const char* message)
78 {
79 // TODO: Add tests that exercize this behavior.
80 //
81 // At the moment there doesn't seem to be any public API for providing
82 // an alternate certificate authority, or for constructing a
83 // BCertificate to be sent to BUrlContext::AddCertificateException().
84 // Once we have such a public API then it will be useful to create
85 // test scenarios that exercize the validation performed by the
86 // undrelying TLS implementaiton to verify that it is configured
87 // to do so.
88 //
89 // For now we just disable TLS certificate validation entirely because
90 // we are generating a self-signed TLS certificate for these tests.
91 return true;
92 }
93
94
Verify()95 void Verify()
96 {
97 CPPUNIT_ASSERT_EQUAL(fExpectedResponseBody, fActualResponseBody);
98
99 for (HttpHeaderMap::iterator iter = fActualResponseHeaders.begin();
100 iter != fActualResponseHeaders.end();
101 ++iter)
102 {
103 CPPUNIT_ASSERT_EQUAL_MESSAGE(
104 "(header " + iter->first + ")",
105 fExpectedResponseHeaders[iter->first],
106 iter->second);
107 }
108 CPPUNIT_ASSERT_EQUAL(
109 fExpectedResponseHeaders.size(),
110 fActualResponseHeaders.size());
111 }
112
113 private:
114 std::string fExpectedResponseBody;
115 std::string fActualResponseBody;
116
117 HttpHeaderMap fExpectedResponseHeaders;
118 HttpHeaderMap fActualResponseHeaders;
119 };
120
121
SendAuthenticatedRequest(BUrlContext & context,BUrl & testUrl,const std::string & expectedResponseBody,const HttpHeaderMap & expectedResponseHeaders)122 void SendAuthenticatedRequest(
123 BUrlContext &context,
124 BUrl &testUrl,
125 const std::string& expectedResponseBody,
126 const HttpHeaderMap &expectedResponseHeaders)
127 {
128 TestListener listener(expectedResponseBody, expectedResponseHeaders);
129
130 ObjectDeleter<BUrlRequest> requestDeleter(
131 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
132 &context));
133 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
134 CPPUNIT_ASSERT(request != NULL);
135
136 request->SetUserName("walter");
137 request->SetPassword("secret");
138
139 CPPUNIT_ASSERT(request->Run());
140
141 while (request->IsRunning())
142 snooze(1000);
143
144 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
145
146 const BHttpResult &result =
147 dynamic_cast<const BHttpResult &>(request->Result());
148 CPPUNIT_ASSERT_EQUAL(200, result.StatusCode());
149 CPPUNIT_ASSERT_EQUAL(BString("OK"), result.StatusText());
150
151 listener.Verify();
152 }
153
154
155 // Return the path of a file path relative to this source file.
TestFilePath(const std::string & relativePath)156 std::string TestFilePath(const std::string& relativePath)
157 {
158 char *testFileSource = strdup(__FILE__);
159 MemoryDeleter _(testFileSource);
160
161 std::string testSrcDir(::dirname(testFileSource));
162
163 return testSrcDir + "/" + relativePath;
164 }
165
166
167 template <typename T>
AddCommonTests(BThreadedTestCaller<T> & testCaller)168 void AddCommonTests(BThreadedTestCaller<T>& testCaller)
169 {
170 testCaller.addThread("GetTest", &T::GetTest);
171 testCaller.addThread("HeadTest", &T::HeadTest);
172 testCaller.addThread("NoContentTest", &T::NoContentTest);
173 testCaller.addThread("UploadTest", &T::UploadTest);
174 testCaller.addThread("BasicAuthTest", &T::AuthBasicTest);
175 testCaller.addThread("DigestAuthTest", &T::AuthDigestTest);
176 testCaller.addThread("AutoRedirectTest", &T::AutoRedirectTest);
177 }
178
179 }
180
181
HttpTest(TestServerMode mode)182 HttpTest::HttpTest(TestServerMode mode)
183 :
184 fTestServer(mode)
185 {
186 }
187
188
~HttpTest()189 HttpTest::~HttpTest()
190 {
191 }
192
193
194 void
setUp()195 HttpTest::setUp()
196 {
197 CPPUNIT_ASSERT_EQUAL_MESSAGE(
198 "Starting up test server",
199 B_OK,
200 fTestServer.Start());
201 }
202
203
204 void
GetTest()205 HttpTest::GetTest()
206 {
207 _GetTest("/");
208 }
209
210
211 void
HeadTest()212 HttpTest::HeadTest()
213 {
214 BUrl testUrl(fTestServer.BaseUrl(), "/");
215 BUrlContext* context = new BUrlContext();
216 context->AcquireReference();
217
218 std::string expectedResponseBody("");
219 HttpHeaderMap expectedResponseHeaders;
220 expectedResponseHeaders["Content-Encoding"] = "gzip";
221 expectedResponseHeaders["Content-Length"] = "144";
222 expectedResponseHeaders["Content-Type"] = "text/plain";
223 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
224 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
225
226 TestListener listener(expectedResponseBody, expectedResponseHeaders);
227
228 ObjectDeleter<BUrlRequest> requestDeleter(
229 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
230 context));
231 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
232 CPPUNIT_ASSERT(request != NULL);
233
234 request->SetAutoReferrer(false);
235 request->SetMethod("HEAD");
236
237 CPPUNIT_ASSERT(request->Run());
238 while (request->IsRunning())
239 snooze(1000);
240
241 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
242
243 const BHttpResult& result
244 = dynamic_cast<const BHttpResult&>(request->Result());
245 CPPUNIT_ASSERT_EQUAL(200, result.StatusCode());
246 CPPUNIT_ASSERT_EQUAL(BString("OK"), result.StatusText());
247
248 CPPUNIT_ASSERT_EQUAL(144, result.Length());
249
250 listener.Verify();
251
252 CPPUNIT_ASSERT(!context->GetCookieJar().GetIterator().HasNext());
253 // This page should not set cookies
254
255 context->ReleaseReference();
256 }
257
258
259 void
NoContentTest()260 HttpTest::NoContentTest()
261 {
262 BUrl testUrl(fTestServer.BaseUrl(), "/204");
263 BUrlContext* context = new BUrlContext();
264 context->AcquireReference();
265
266 std::string expectedResponseBody("");
267 HttpHeaderMap expectedResponseHeaders;
268 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
269 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
270
271 TestListener listener(expectedResponseBody, expectedResponseHeaders);
272
273 ObjectDeleter<BUrlRequest> requestDeleter(
274 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
275 context));
276 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
277 CPPUNIT_ASSERT(request != NULL);
278
279 request->SetAutoReferrer(false);
280
281 CPPUNIT_ASSERT(request->Run());
282 while (request->IsRunning())
283 snooze(1000);
284
285 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
286
287 const BHttpResult& result
288 = dynamic_cast<const BHttpResult&>(request->Result());
289 CPPUNIT_ASSERT_EQUAL(204, result.StatusCode());
290 CPPUNIT_ASSERT_EQUAL(BString("No Content"), result.StatusText());
291
292 listener.Verify();
293
294 CPPUNIT_ASSERT(!context->GetCookieJar().GetIterator().HasNext());
295 // This page should not set cookies
296
297 context->ReleaseReference();
298 }
299
300
301 void
ProxyTest()302 HttpTest::ProxyTest()
303 {
304 BUrl testUrl(fTestServer.BaseUrl(), "/");
305
306 TestProxyServer proxy;
307 CPPUNIT_ASSERT_EQUAL_MESSAGE(
308 "Test proxy server startup",
309 B_OK,
310 proxy.Start());
311
312 BUrlContext* context = new BUrlContext();
313 context->AcquireReference();
314 context->SetProxy("127.0.0.1", proxy.Port());
315
316 std::string expectedResponseBody(
317 "Path: /\r\n"
318 "\r\n"
319 "Headers:\r\n"
320 "--------\r\n"
321 "Host: 127.0.0.1:PORT\r\n"
322 "Content-Length: 0\r\n"
323 "Accept: */*\r\n"
324 "Accept-Encoding: gzip\r\n"
325 "Connection: close\r\n"
326 "User-Agent: Services Kit (Haiku)\r\n"
327 "X-Forwarded-For: 127.0.0.1:PORT\r\n");
328 HttpHeaderMap expectedResponseHeaders;
329 expectedResponseHeaders["Content-Encoding"] = "gzip";
330 expectedResponseHeaders["Content-Length"] = "169";
331 expectedResponseHeaders["Content-Type"] = "text/plain";
332 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
333 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
334
335 TestListener listener(expectedResponseBody, expectedResponseHeaders);
336
337 ObjectDeleter<BUrlRequest> requestDeleter(
338 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
339 context));
340 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
341 CPPUNIT_ASSERT(request != NULL);
342
343 CPPUNIT_ASSERT(request->Run());
344
345 while (request->IsRunning())
346 snooze(1000);
347
348 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
349
350 const BHttpResult& response
351 = dynamic_cast<const BHttpResult&>(request->Result());
352 CPPUNIT_ASSERT_EQUAL(200, response.StatusCode());
353 CPPUNIT_ASSERT_EQUAL(BString("OK"), response.StatusText());
354 CPPUNIT_ASSERT_EQUAL(169, response.Length());
355 // Fixed size as we know the response format.
356 CPPUNIT_ASSERT(!context->GetCookieJar().GetIterator().HasNext());
357 // This page should not set cookies
358
359 listener.Verify();
360
361 context->ReleaseReference();
362 }
363
364
365 void
UploadTest()366 HttpTest::UploadTest()
367 {
368 std::string testFilePath = TestFilePath("testfile.txt");
369
370 // The test server will echo the POST body back to us in the HTTP response,
371 // so here we load it into memory so that we can compare to make sure that
372 // the server received it.
373 std::string fileContents;
374 {
375 std::ifstream inputStream(
376 testFilePath.c_str(),
377 std::ios::in | std::ios::binary);
378 CPPUNIT_ASSERT(inputStream);
379
380 inputStream.seekg(0, std::ios::end);
381 fileContents.resize(inputStream.tellg());
382
383 inputStream.seekg(0, std::ios::beg);
384 inputStream.read(&fileContents[0], fileContents.size());
385 inputStream.close();
386
387 CPPUNIT_ASSERT(!fileContents.empty());
388 }
389
390 std::string expectedResponseBody(
391 "Path: /post\r\n"
392 "\r\n"
393 "Headers:\r\n"
394 "--------\r\n"
395 "Host: 127.0.0.1:PORT\r\n"
396 "Accept: */*\r\n"
397 "Accept-Encoding: gzip\r\n"
398 "Connection: close\r\n"
399 "User-Agent: Services Kit (Haiku)\r\n"
400 "Content-Type: multipart/form-data; boundary=<<BOUNDARY-ID>>\r\n"
401 "Content-Length: 1404\r\n"
402 "\r\n"
403 "Request body:\r\n"
404 "-------------\r\n"
405 "--<<BOUNDARY-ID>>\r\n"
406 "Content-Disposition: form-data; name=\"_uploadfile\";"
407 " filename=\"testfile.txt\"\r\n"
408 "Content-Type: application/octet-stream\r\n"
409 "\r\n"
410 + fileContents
411 + "\r\n"
412 "--<<BOUNDARY-ID>>\r\n"
413 "Content-Disposition: form-data; name=\"hello\"\r\n"
414 "\r\n"
415 "world\r\n"
416 "--<<BOUNDARY-ID>>--\r\n"
417 "\r\n");
418 HttpHeaderMap expectedResponseHeaders;
419 expectedResponseHeaders["Content-Encoding"] = "gzip";
420 expectedResponseHeaders["Content-Length"] = "913";
421 expectedResponseHeaders["Content-Type"] = "text/plain";
422 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
423 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
424 TestListener listener(expectedResponseBody, expectedResponseHeaders);
425
426 BUrl testUrl(fTestServer.BaseUrl(), "/post");
427
428 BUrlContext context;
429
430 ObjectDeleter<BUrlRequest> requestDeleter(
431 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
432 &context));
433 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
434 CPPUNIT_ASSERT(request != NULL);
435
436 BHttpForm form;
437 form.AddString("hello", "world");
438 CPPUNIT_ASSERT_EQUAL(
439 B_OK,
440 form.AddFile("_uploadfile", BPath(testFilePath.c_str())));
441
442 request->SetPostFields(form);
443
444 CPPUNIT_ASSERT(request->Run());
445
446 while (request->IsRunning())
447 snooze(1000);
448
449 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
450
451 const BHttpResult &result =
452 dynamic_cast<const BHttpResult &>(request->Result());
453 CPPUNIT_ASSERT_EQUAL(200, result.StatusCode());
454 CPPUNIT_ASSERT_EQUAL(BString("OK"), result.StatusText());
455 CPPUNIT_ASSERT_EQUAL(913, result.Length());
456
457 listener.Verify();
458 }
459
460
461 void
AuthBasicTest()462 HttpTest::AuthBasicTest()
463 {
464 BUrlContext context;
465
466 BUrl testUrl(fTestServer.BaseUrl(), "/auth/basic/walter/secret");
467
468 std::string expectedResponseBody(
469 "Path: /auth/basic/walter/secret\r\n"
470 "\r\n"
471 "Headers:\r\n"
472 "--------\r\n"
473 "Host: 127.0.0.1:PORT\r\n"
474 "Accept: */*\r\n"
475 "Accept-Encoding: gzip\r\n"
476 "Connection: close\r\n"
477 "User-Agent: Services Kit (Haiku)\r\n"
478 "Referer: SCHEME://127.0.0.1:PORT/auth/basic/walter/secret\r\n"
479 "Authorization: Basic d2FsdGVyOnNlY3JldA==\r\n");
480
481 HttpHeaderMap expectedResponseHeaders;
482 expectedResponseHeaders["Content-Encoding"] = "gzip";
483 expectedResponseHeaders["Content-Length"] = "212";
484 expectedResponseHeaders["Content-Type"] = "text/plain";
485 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
486 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
487 expectedResponseHeaders["Www-Authenticate"] = "Basic realm=\"Fake Realm\"";
488
489 SendAuthenticatedRequest(context, testUrl, expectedResponseBody,
490 expectedResponseHeaders);
491
492 CPPUNIT_ASSERT(!context.GetCookieJar().GetIterator().HasNext());
493 // This page should not set cookies
494 }
495
496
497 void
AuthDigestTest()498 HttpTest::AuthDigestTest()
499 {
500 BUrlContext context;
501
502 BUrl testUrl(fTestServer.BaseUrl(), "/auth/digest/walter/secret");
503
504 std::string expectedResponseBody(
505 "Path: /auth/digest/walter/secret\r\n"
506 "\r\n"
507 "Headers:\r\n"
508 "--------\r\n"
509 "Host: 127.0.0.1:PORT\r\n"
510 "Accept: */*\r\n"
511 "Accept-Encoding: gzip\r\n"
512 "Connection: close\r\n"
513 "User-Agent: Services Kit (Haiku)\r\n"
514 "Referer: SCHEME://127.0.0.1:PORT/auth/digest/walter/secret\r\n"
515 "Authorization: Digest username=\"walter\","
516 " realm=\"user@shredder\","
517 " nonce=\"f3a95f20879dd891a5544bf96a3e5518\","
518 " algorithm=MD5,"
519 " opaque=\"f0bb55f1221a51b6d38117c331611799\","
520 " uri=\"/auth/digest/walter/secret\","
521 " qop=auth,"
522 " cnonce=\"60a3d95d286a732374f0f35fb6d21e79\","
523 " nc=00000001,"
524 " response=\"f4264de468aa1a91d81ac40fa73445f3\"\r\n"
525 "Cookie: stale_after=never; fake=fake_value\r\n");
526
527 HttpHeaderMap expectedResponseHeaders;
528 expectedResponseHeaders["Content-Encoding"] = "gzip";
529 expectedResponseHeaders["Content-Length"] = "403";
530 expectedResponseHeaders["Content-Type"] = "text/plain";
531 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
532 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
533 expectedResponseHeaders["Set-Cookie"] = "fake=fake_value; Path=/";
534 expectedResponseHeaders["Www-Authenticate"]
535 = "Digest realm=\"user@shredder\", "
536 "nonce=\"f3a95f20879dd891a5544bf96a3e5518\", "
537 "qop=\"auth\", "
538 "opaque=f0bb55f1221a51b6d38117c331611799, "
539 "algorithm=MD5, "
540 "stale=FALSE";
541
542 SendAuthenticatedRequest(context, testUrl, expectedResponseBody,
543 expectedResponseHeaders);
544
545 std::map<BString, BString> cookies;
546 BNetworkCookieJar::Iterator iter
547 = context.GetCookieJar().GetIterator();
548 while (iter.HasNext()) {
549 const BNetworkCookie* cookie = iter.Next();
550 cookies[cookie->Name()] = cookie->Value();
551 }
552 CPPUNIT_ASSERT_EQUAL(2, cookies.size());
553 CPPUNIT_ASSERT_EQUAL(BString("fake_value"), cookies["fake"]);
554 CPPUNIT_ASSERT_EQUAL(BString("never"), cookies["stale_after"]);
555 }
556
557
558 void
AutoRedirectTest()559 HttpTest::AutoRedirectTest()
560 {
561 _GetTest("/302");
562 }
563
564
565 /* static */ void
AddTests(BTestSuite & parent)566 HttpTest::AddTests(BTestSuite& parent)
567 {
568 {
569 CppUnit::TestSuite& suite = *new CppUnit::TestSuite("HttpTest");
570
571 HttpTest* httpTest = new HttpTest();
572 BThreadedTestCaller<HttpTest>* httpTestCaller
573 = new BThreadedTestCaller<HttpTest>("HttpTest::", httpTest);
574
575 // HTTP + HTTPs
576 AddCommonTests<HttpTest>(*httpTestCaller);
577
578 httpTestCaller->addThread("ProxyTest", &HttpTest::ProxyTest);
579
580 suite.addTest(httpTestCaller);
581 parent.addTest("HttpTest", &suite);
582 }
583
584 {
585 CppUnit::TestSuite& suite = *new CppUnit::TestSuite("HttpsTest");
586
587 HttpsTest* httpsTest = new HttpsTest();
588 BThreadedTestCaller<HttpsTest>* httpsTestCaller
589 = new BThreadedTestCaller<HttpsTest>("HttpsTest::", httpsTest);
590
591 // HTTP + HTTPs
592 AddCommonTests<HttpsTest>(*httpsTestCaller);
593
594 suite.addTest(httpsTestCaller);
595 parent.addTest("HttpsTest", &suite);
596 }
597 }
598
599
600 void
_GetTest(const BString & path)601 HttpTest::_GetTest(const BString& path)
602 {
603 BUrl testUrl(fTestServer.BaseUrl(), path);
604 BUrlContext* context = new BUrlContext();
605 context->AcquireReference();
606
607 std::string expectedResponseBody(
608 "Path: /\r\n"
609 "\r\n"
610 "Headers:\r\n"
611 "--------\r\n"
612 "Host: 127.0.0.1:PORT\r\n"
613 "Accept: */*\r\n"
614 "Accept-Encoding: gzip\r\n"
615 "Connection: close\r\n"
616 "User-Agent: Services Kit (Haiku)\r\n");
617 HttpHeaderMap expectedResponseHeaders;
618 expectedResponseHeaders["Content-Encoding"] = "gzip";
619 expectedResponseHeaders["Content-Length"] = "144";
620 expectedResponseHeaders["Content-Type"] = "text/plain";
621 expectedResponseHeaders["Date"] = "Sun, 09 Feb 2020 19:32:42 GMT";
622 expectedResponseHeaders["Server"] = "Test HTTP Server for Haiku";
623
624 TestListener listener(expectedResponseBody, expectedResponseHeaders);
625
626 ObjectDeleter<BUrlRequest> requestDeleter(
627 BUrlProtocolRoster::MakeRequest(testUrl, &listener, &listener,
628 context));
629 BHttpRequest* request = dynamic_cast<BHttpRequest*>(requestDeleter.Get());
630 CPPUNIT_ASSERT(request != NULL);
631
632 request->SetAutoReferrer(false);
633
634 CPPUNIT_ASSERT(request->Run());
635 while (request->IsRunning())
636 snooze(1000);
637
638 CPPUNIT_ASSERT_EQUAL(B_OK, request->Status());
639
640 const BHttpResult& result
641 = dynamic_cast<const BHttpResult&>(request->Result());
642 CPPUNIT_ASSERT_EQUAL(200, result.StatusCode());
643 CPPUNIT_ASSERT_EQUAL(BString("OK"), result.StatusText());
644
645 CPPUNIT_ASSERT_EQUAL(144, result.Length());
646
647 listener.Verify();
648
649 CPPUNIT_ASSERT(!context->GetCookieJar().GetIterator().HasNext());
650 // This page should not set cookies
651
652 context->ReleaseReference();
653 }
654
655
656 // # pragma mark - HTTPS
657
658
HttpsTest()659 HttpsTest::HttpsTest()
660 :
661 HttpTest(TEST_SERVER_MODE_HTTPS)
662 {
663 }
664