1 // -*- mode: c++; c-basic-offset:4 -*-
2
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5
6 // Copyright (c) 2002,2003,2013 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25 #include <cppunit/TextTestRunner.h>
26 #include <cppunit/extensions/TestFactoryRegistry.h>
27 #include <cppunit/extensions/HelperMacros.h>
28
29 #include <cstring>
30 #include <iterator>
31 #include <string>
32 #include <algorithm>
33 #include <functional>
34
35 #include "GNURegex.h"
36 #include "HTTPConnect.h"
37 #include "RCReader.h"
38
39 #include "debug.h"
40
41 #include "test_config.h"
42 #include "GetOpt.h"
43
44 using namespace CppUnit;
45 using namespace std;
46
47 // FIXME By default this should be false, but we're tracking down a
48 // potential bug in this code or test. jhrg 1/28/21
49 static bool debug = false;
50
51 #undef DBG
52 #define DBG(x) do { if (debug) (x); } while(false);
53
54 #define prolog std::string("HTTPConnectTest::").append(__func__).append("() - ")
55
56 namespace libdap {
57
58 class HTTPConnectTest: public TestFixture {
59 private:
60 HTTPConnect * http;
61 string localhost_url, localhost_pw_url, localhost_digest_pw_url;
62 string etag;
63 string lm;
64 string netcdf_das_url;
65
66 // char env_data[128];
67
68 protected:
re_match(Regex & r,const char * s)69 bool re_match(Regex & r, const char *s)
70 {
71 return r.match(s, strlen(s)) == (int) strlen(s);
72 }
73
74 struct REMatch: public unary_function<const string &, bool> {
75 Regex &d_re;
REMatchlibdap::HTTPConnectTest::REMatch76 REMatch(Regex &re) :
77 d_re(re)
78 {
79 }
~REMatchlibdap::HTTPConnectTest::REMatch80 ~REMatch()
81 {
82 }
operator ()libdap::HTTPConnectTest::REMatch83 bool operator()(const string &str)
84 {
85 const char *s = str.c_str();
86 return d_re.match(s, strlen(s)) == (int) strlen(s);
87 }
88 };
89
90 // This is defined in HTTPConnect.cc but has to be defined here as well.
91 // Don't know why... jhrg
92 class HeaderMatch: public unary_function<const string &, bool> {
93 const string &d_header;
94 public:
HeaderMatch(const string & header)95 HeaderMatch(const string &header) :
96 d_header(header)
97 {
98 }
operator ()(const string & arg)99 bool operator()(const string &arg)
100 {
101 return arg.find(d_header) == 0;
102 }
103 };
104
105 public:
HTTPConnectTest()106 HTTPConnectTest()
107 {
108 }
~HTTPConnectTest()109 ~HTTPConnectTest()
110 {
111 }
112
setUp()113 void setUp()
114 {
115 DBG(cerr << prolog << "Setting the DODS_CONF env var" << endl);
116 setenv("DODS_CONF", "cache-testsuite/dodsrc", 1);
117 http = new HTTPConnect(RCReader::instance());
118
119 localhost_url = "http://test.opendap.org/test-304.html";
120
121 // Two request header values that will generate a 304 response to the
122 // above URL. The values below much match the etag and last-modified
123 // time returned by the server. Run this test with DODS_DEBUG defined
124 // to see the values it's returning.
125 //
126 // etag = "\"a10df-157-139c2680\"";
127 // etag = "\"2a008e-157-3fbcd139c2680\"";
128 // etag = "\"181893-157-3fbcd139c2680\""; // On 10/13/14 we moved to a new httpd and the etag value changed.
129 etag ="\"157-3df1e87884680\""; // New httpd service, new etag, ndp - 01/11/21
130 lm = "Wed, 13 Jul 2005 19:32:26 GMT";
131
132 localhost_pw_url = "http://jimg:dods_test@test.opendap.org/basic/page.txt";
133 localhost_digest_pw_url = "http://jimg:dods_digest@test.opendap.org/digest/page.txt";
134 netcdf_das_url = "http://test.opendap.org/dap/data/nc/fnoc1.nc.das";
135 }
136
tearDown()137 void tearDown()
138 {
139 // normal code doesn't do this - it happens at exit() but not doing
140 // this here make valgrind think there are leaks.
141 http->d_http_cache->delete_instance();
142 delete http;
143 http = 0;
144 unsetenv("DODS_CONF");
145 }
146
147 CPPUNIT_TEST_SUITE (HTTPConnectTest);
148
149 CPPUNIT_TEST (read_url_test);
150
151 CPPUNIT_TEST (fetch_url_test_1);
152 CPPUNIT_TEST (fetch_url_test_2);
153 CPPUNIT_TEST (fetch_url_test_3);
154 CPPUNIT_TEST (fetch_url_test_4);
155
156 CPPUNIT_TEST (fetch_url_test_1_cpp);
157 CPPUNIT_TEST (fetch_url_test_2_cpp);
158 CPPUNIT_TEST (fetch_url_test_3_cpp);
159 CPPUNIT_TEST (fetch_url_test_4_cpp);
160
161 CPPUNIT_TEST (get_response_headers_test);
162 CPPUNIT_TEST (server_version_test);
163 CPPUNIT_TEST (type_test);
164
165 CPPUNIT_TEST (cache_test);
166 CPPUNIT_TEST (cache_test_cpp);
167
168 CPPUNIT_TEST (set_accept_deflate_test);
169 CPPUNIT_TEST (set_xdap_protocol_test);
170 CPPUNIT_TEST (read_url_password_test);
171 CPPUNIT_TEST (read_url_password_test2);
172
173 // CPPUNIT_TEST(read_url_password_proxy_test);
174
175 CPPUNIT_TEST_SUITE_END();
176
read_url_test()177 void read_url_test()
178 {
179 vector<string> *resp_h = new vector<string>;
180
181 try {
182 DBG(cerr << prolog << "BEGIN" << endl);
183 DBG(cerr << prolog << "Testing with URL: " << localhost_url << endl);
184
185 FILE *dump = fopen("/dev/null", "w");
186 long status = http->read_url(localhost_url, dump, resp_h);
187 CPPUNIT_ASSERT(status == 200);
188
189 vector<string> request_h;
190
191 // First test using a time with if-modified-since
192 request_h.push_back(string("If-Modified-Since: ") + lm);
193 status = http->read_url(localhost_url, dump, resp_h, &request_h);
194 DBG(cerr << prolog << "If modified since test. Returned http status: " << status << endl);
195 DBG(copy(resp_h->begin(), resp_h->end(), ostream_iterator<string>(cerr, "\n")));
196 DBG(cerr << endl);
197 CPPUNIT_ASSERT(status == 304);
198
199 // Now test an etag
200 resp_h->clear();
201 request_h.clear();
202 request_h.push_back(string("If-None-Match: ") + etag);
203 status = http->read_url(localhost_url, dump, resp_h, &request_h);
204 DBG(cerr << prolog << "If none match test. Returned http status: " << status << endl);
205 DBG(copy(resp_h->begin(), resp_h->end(), ostream_iterator<string>(cerr, "\n")));
206 DBG(cerr << endl);
207 CPPUNIT_ASSERT(status == 304);
208
209 // now test a combined etag and time4
210 resp_h->clear();
211 request_h.clear();
212 request_h.push_back(string("If-None-Match: ") + etag);
213 request_h.push_back(string("If-Modified-Since: ") + lm);
214 status = http->read_url(localhost_url, dump, resp_h, &request_h);
215 DBG(cerr << prolog << "Combined test. Returned http status: " << status << endl);
216 DBG(copy(resp_h->begin(), resp_h->end(), ostream_iterator<string>(cerr, "\n")));
217 CPPUNIT_ASSERT(status == 304);
218
219 delete resp_h;
220 resp_h = 0;
221
222 }
223 catch (Error & e) {
224 delete resp_h;
225 resp_h = 0;
226 CPPUNIT_FAIL(prolog + "Error: " + e.get_error_message());
227 }
228 }
229
fetch_url_test_1()230 void fetch_url_test_1()
231 {
232 DBG(cerr << "Entering fetch_url_test 1" << endl);
233 HTTPResponse *stuff = 0;
234 char c;
235 try {
236 stuff = http->fetch_url(localhost_url);
237 CPPUNIT_ASSERT(
238 fread(&c, 1, 1, stuff->get_stream()) == 1 && !ferror(stuff->get_stream())
239 && !feof(stuff->get_stream()));
240 delete stuff;
241 stuff = 0;
242
243 }
244 catch (InternalErr & e) {
245 delete stuff;
246 stuff = 0;
247 CPPUNIT_FAIL("Caught an InternalErr from fetch_url: " + e.get_error_message());
248 }
249 catch (Error & e) {
250 delete stuff;
251 stuff = 0;
252 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
253 }
254 // Catch the exception from a failed ASSERT and clean up. Deleting a
255 // Response object also unlocks the HTTPCache in some cases. If delete
256 // is not called, then a failed test can leave the cache with locked
257 // entries
258 catch (...) {
259 cerr << "Caught unknown exception" << endl;
260 delete stuff;
261 stuff = 0;
262 throw;
263 }
264 }
265
fetch_url_test_1_cpp()266 void fetch_url_test_1_cpp()
267 {
268 DBG(cerr << "Entering fetch_url_test 1" << endl);
269 HTTPResponse *stuff = 0;
270 http->set_use_cpp_streams(true);
271 char c;
272 try {
273 stuff = http->fetch_url(localhost_url);
274 stuff->get_cpp_stream()->read(&c, 1);
275 CPPUNIT_ASSERT(*(stuff->get_cpp_stream()));
276 CPPUNIT_ASSERT(!stuff->get_cpp_stream()->bad());
277 CPPUNIT_ASSERT(!stuff->get_cpp_stream()->eof());
278
279 delete stuff;
280 }
281 catch (InternalErr &e) {
282 delete stuff;
283 CPPUNIT_FAIL("Caught an InternalErr from fetch_url: " + e.get_error_message());
284 }
285 catch (Error &e) {
286 delete stuff;
287 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
288 }
289 catch (std::exception &e) {
290 delete stuff;
291 CPPUNIT_FAIL(string("Caught an std::exception from fetch_url: ") + e.what());
292 }
293 // Catch the exception from a failed ASSERT and clean up. Deleting a
294 // Response object also unlocks the HTTPCache in some cases. If delete
295 // is not called, then a failed test can leave the cache with locked
296 // entries
297 catch (...) {
298 cerr << "Caught unknown exception" << endl;
299 delete stuff;
300 throw;
301 }
302 }
303
fetch_url_test_2()304 void fetch_url_test_2()
305 {
306 DBG(cerr << "Entering fetch_url_test 2" << endl);
307 HTTPResponse *stuff = 0;
308 char c;
309 try {
310 stuff = http->fetch_url(netcdf_das_url);
311 DBG2(char ln[1024]; while (!feof(stuff->get_stream())) {
312 fgets(ln, 1024, stuff->get_stream()); cerr << ln;}
313 rewind(stuff->get_stream()));
314
315 CPPUNIT_ASSERT(
316 fread(&c, 1, 1, stuff->get_stream()) == 1 && !ferror(stuff->get_stream())
317 && !feof(stuff->get_stream()));
318 delete stuff;
319 stuff = 0;
320 }
321 catch (InternalErr & e) {
322 delete stuff;
323 stuff = 0;
324 CPPUNIT_FAIL("Caught an InternalErr from fetch_url: " + e.get_error_message());
325 }
326 catch (Error & e) {
327 delete stuff;
328 stuff = 0;
329 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
330 }
331 // Catch the exception from a failed ASSERT and clean up. Deleting a
332 // Response object also unlocks the HTTPCache in some cases. If delete
333 // is not called, then a failed test can leave the cache with locked
334 // entries
335 catch (...) {
336 delete stuff;
337 stuff = 0;
338 throw;
339 }
340 }
341
fetch_url_test_2_cpp()342 void fetch_url_test_2_cpp()
343 {
344 DBG(cerr << "Entering fetch_url_test 2" << endl);
345 http->set_use_cpp_streams(true);
346
347 HTTPResponse *stuff = 0;
348 char c;
349
350 try {
351 stuff = http->fetch_url(netcdf_das_url);
352
353 stuff->get_cpp_stream()->read(&c, 1);
354 CPPUNIT_ASSERT(
355 *(stuff->get_cpp_stream()) && !stuff->get_cpp_stream()->bad() && !stuff->get_cpp_stream()->eof());
356
357 delete stuff;
358 stuff = 0;
359 }
360 catch (InternalErr & e) {
361 delete stuff;
362 stuff = 0;
363 CPPUNIT_FAIL("Caught an InternalErr from fetch_url: " + e.get_error_message());
364 }
365 catch (Error & e) {
366 delete stuff;
367 stuff = 0;
368 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
369 }
370 // Catch the exception from a failed ASSERT and clean up. Deleting a
371 // Response object also unlocks the HTTPCache in some cases. If delete
372 // is not called, then a failed test can leave the cache with locked
373 // entries
374 catch (...) {
375 delete stuff;
376 stuff = 0;
377 throw;
378 }
379 }
380
fetch_url_test_3()381 void fetch_url_test_3()
382 {
383 DBG(cerr << "Entering fetch_url_test 3" << endl);
384 HTTPResponse *stuff = 0;
385 char c;
386 try {
387 stuff = http->fetch_url("file:///etc/passwd");
388 CPPUNIT_ASSERT(
389 fread(&c, 1, 1, stuff->get_stream()) == 1 && !ferror(stuff->get_stream())
390 && !feof(stuff->get_stream()));
391 delete stuff;
392 stuff = 0;
393 }
394 catch (InternalErr & e) {
395 delete stuff;
396 stuff = 0;
397 CPPUNIT_FAIL("Caught an InternalErr from fetch_url" + e.get_error_message());
398 }
399 catch (Error & e) {
400 delete stuff;
401 stuff = 0;
402 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
403 }
404 // Catch the exception from a failed ASSERT and clean up. Deleting a
405 // Response object also unlocks the HTTPCache in some cases. If delete
406 // is not called, then a failed test can leave the cache with locked
407 // entries
408 catch (...) {
409 delete stuff;
410 stuff = 0;
411 throw;
412 }
413 }
414
fetch_url_test_3_cpp()415 void fetch_url_test_3_cpp()
416 {
417 DBG(cerr << "Entering fetch_url_test 3" << endl);
418 http->set_use_cpp_streams(true);
419
420 HTTPResponse *stuff = 0;
421 char c;
422 try {
423 stuff = http->fetch_url("file:///etc/passwd");
424
425 stuff->get_cpp_stream()->read(&c, 1);
426 CPPUNIT_ASSERT(
427 *(stuff->get_cpp_stream()) && !stuff->get_cpp_stream()->bad() && !stuff->get_cpp_stream()->eof());
428
429 delete stuff;
430 stuff = 0;
431 }
432 catch (InternalErr & e) {
433 delete stuff;
434 stuff = 0;
435 CPPUNIT_FAIL("Caught an InternalErr from fetch_url" + e.get_error_message());
436 }
437 catch (Error & e) {
438 delete stuff;
439 stuff = 0;
440 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
441 }
442 // Catch the exception from a failed ASSERT and clean up. Deleting a
443 // Response object also unlocks the HTTPCache in some cases. If delete
444 // is not called, then a failed test can leave the cache with locked
445 // entries
446 catch (...) {
447 delete stuff;
448 stuff = 0;
449 throw;
450 }
451 }
452
fetch_url_test_4()453 void fetch_url_test_4()
454 {
455 DBG(cerr << "Entering fetch_url_test 4" << endl);
456 HTTPResponse *stuff = 0;
457 char c;
458 try {
459 string url = (string) "file://" + TEST_SRC_DIR + "/test_config.h";
460 stuff = http->fetch_url(url);
461 CPPUNIT_ASSERT(
462 fread(&c, 1, 1, stuff->get_stream()) == 1 && !ferror(stuff->get_stream())
463 && !feof(stuff->get_stream()));
464 delete stuff;
465 stuff = 0;
466 }
467 catch (InternalErr & e) {
468 delete stuff;
469 stuff = 0;
470 CPPUNIT_FAIL("Caught an InternalErr from fetch_url" + e.get_error_message());
471 }
472 catch (Error & e) {
473 delete stuff;
474 stuff = 0;
475 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
476 }
477 // Catch the exception from a failed ASSERT and clean up. Deleting a
478 // Response object also unlocks the HTTPCache in some cases. If delete
479 // is not called, then a failed test can leave the cache with locked
480 // entries
481 catch (...) {
482 delete stuff;
483 stuff = 0;
484 throw;
485 }
486 }
487
fetch_url_test_4_cpp()488 void fetch_url_test_4_cpp()
489 {
490 DBG(cerr << "Entering fetch_url_test_4_cpp" << endl);
491 http->set_use_cpp_streams(true);
492
493 HTTPResponse *stuff = 0;
494 char c;
495 try {
496 string url = (string) "file://" + TEST_SRC_DIR + "/test_config.h";
497 stuff = http->fetch_url(url);
498
499 stuff->get_cpp_stream()->read(&c, 1);
500 CPPUNIT_ASSERT(
501 *(stuff->get_cpp_stream()) && !stuff->get_cpp_stream()->bad() && !stuff->get_cpp_stream()->eof());
502
503 delete stuff;
504 stuff = 0;
505 }
506 catch (InternalErr & e) {
507 delete stuff;
508 stuff = 0;
509 CPPUNIT_FAIL("Caught an InternalErr from fetch_url" + e.get_error_message());
510 }
511 catch (Error & e) {
512 delete stuff;
513 stuff = 0;
514 CPPUNIT_FAIL("Caught an Error from fetch_url: " + e.get_error_message());
515 }
516 // Catch the exception from a failed ASSERT and clean up. Deleting a
517 // Response object also unlocks the HTTPCache in some cases. If delete
518 // is not called, then a failed test can leave the cache with locked
519 // entries
520 catch (...) {
521 delete stuff;
522 stuff = 0;
523 throw;
524 }
525 }
526
get_response_headers_test()527 void get_response_headers_test()
528 {
529 HTTPResponse *r = 0;
530
531 try {
532 r = http->fetch_url(netcdf_das_url);
533 vector<string> *h = r->get_headers();
534
535 DBG(copy(h->begin(), h->end(), ostream_iterator<string>(cerr, "\n")));
536
537 // Should get five or six headers back.
538 Regex header("X.*-Server: .*/.*");
539
540 CPPUNIT_ASSERT(find_if(h->begin(), h->end(), REMatch(header)) != h->end());
541
542 Regex protocol_header("X.*DAP: .*"); // Matches both XDAP and X-DAP
543 CPPUNIT_ASSERT(find_if(h->begin(), h->end(), REMatch(protocol_header)) != h->end());
544
545 delete r;
546 r = 0;
547 }
548 catch (InternalErr & e) {
549 delete r;
550 r = 0;
551 CPPUNIT_FAIL("Caught an InternalErr exception from get_response_headers: " + e.get_error_message());
552 }
553 catch (...) {
554 delete r;
555 r = 0;
556 throw;
557 }
558 }
559
server_version_test()560 void server_version_test()
561 {
562 Response *r = 0;
563 Regex protocol("^[0-9]+\\.[0-9]+$");
564 try {
565 r = http->fetch_url(netcdf_das_url);
566
567 DBG(cerr << "r->get_version().c_str(): " << r->get_protocol().c_str() << endl);
568
569 CPPUNIT_ASSERT(re_match(protocol, r->get_protocol().c_str()));
570 delete r;
571 r = 0;
572 }
573 catch (InternalErr & e) {
574 delete r;
575 r = 0;
576 CPPUNIT_FAIL("Caught an InternalErr exception from server_version: " + e.get_error_message());
577 }
578 catch (...) {
579 delete r;
580 r = 0;
581 throw;
582 }
583
584 }
585
type_test()586 void type_test()
587 {
588 Response *r = 0;
589 try {
590 r = http->fetch_url(netcdf_das_url);
591 DBG(cerr << "r->get_type(): " << r->get_type() << endl);
592 CPPUNIT_ASSERT(r->get_type() == dods_das);
593 delete r;
594 r = 0;
595 }
596 catch (InternalErr & e) {
597 delete r;
598 r = 0;
599 CPPUNIT_FAIL("Caught an InternalErr exception from type(): " + e.get_error_message());
600 }
601
602 }
603
set_credentials_test()604 void set_credentials_test()
605 {
606 http->set_credentials("jimg", "was_quit");
607 Response *stuff = http->fetch_url("http://localhost/secret");
608
609 try {
610 char c;
611 CPPUNIT_ASSERT(
612 fread(&c, 1, 1, stuff->get_stream()) == 1 && !ferror(stuff->get_stream())
613 && !feof(stuff->get_stream()));
614 delete stuff;
615 stuff = 0;
616 }
617 catch (InternalErr & e) {
618 delete stuff;
619 stuff = 0;
620 CPPUNIT_FAIL("Caught an InternalErrexception from output: " + e.get_error_message());
621 }
622 }
623
cache_test()624 void cache_test()
625 {
626 DBG(cerr << endl << "Entering Caching tests." << endl);
627 try {
628 // The cache-testsuite/dodsrc file turns this off; all the other
629 // params are set up. It used to be that HTTPConnect had an option to
630 // turn caching on, but that no longer is present. This hack enables
631 // caching for this test. 06/18/04 jhrg
632 http->d_http_cache = HTTPCache::instance(http->d_rcr->get_dods_cache_root(), true);
633 DBG(cerr << "Instantiate the cache" << endl);
634
635 CPPUNIT_ASSERT(http->d_http_cache != 0);
636 http->d_http_cache->set_cache_enabled(true);
637 DBG(cerr << "Enable the cache" << endl);
638
639 fetch_url_test_4();
640 DBG(cerr << "fetch_url_test" << endl);
641 get_response_headers_test();
642 DBG(cerr << "get_response_headers_test" << endl);
643 server_version_test();
644 DBG(cerr << "server_version_test" << endl);
645 type_test();
646 DBG(cerr << "type_test" << endl);
647 }
648 catch (Error &e) {
649 CPPUNIT_FAIL((string) "Error: " + e.get_error_message());
650 }
651 }
652
cache_test_cpp()653 void cache_test_cpp()
654 {
655 DBG(cerr << endl << "Entering Caching tests." << endl);
656 try {
657 // The cache-testsuite/dodsrc file turns this off; all the other
658 // params are set up. It used to be that HTTPConnect had an option to
659 // turn caching on, but that no longer is present. This hack enables
660 // caching for this test. 06/18/04 jhrg
661 http->d_http_cache = HTTPCache::instance(http->d_rcr->get_dods_cache_root(), true);
662 DBG(cerr << "Instantiate the cache" << endl);
663
664 CPPUNIT_ASSERT(http->d_http_cache != 0);
665 http->d_http_cache->set_cache_enabled(true);
666 DBG(cerr << "Enable the cache" << endl);
667
668 fetch_url_test_4_cpp();
669 DBG(cerr << "fetch_url_test_4_cpp" << endl);
670
671 get_response_headers_test();
672 DBG(cerr << "get_response_headers_test" << endl);
673
674 server_version_test();
675 DBG(cerr << "server_version_test" << endl);
676
677 type_test();
678 DBG(cerr << "type_test" << endl);
679 }
680 catch (Error &e) {
681 CPPUNIT_FAIL((string) "Error: " + e.get_error_message());
682 }
683 }
684
set_accept_deflate_test()685 void set_accept_deflate_test()
686 {
687 http->set_accept_deflate(false);
688 CPPUNIT_ASSERT(
689 count(http->d_request_headers.begin(), http->d_request_headers.end(),
690 "Accept-Encoding: deflate, gzip, compress") == 0);
691
692 http->set_accept_deflate(true);
693 CPPUNIT_ASSERT(
694 count(http->d_request_headers.begin(), http->d_request_headers.end(),
695 "Accept-Encoding: deflate, gzip, compress") == 1);
696
697 http->set_accept_deflate(true);
698 CPPUNIT_ASSERT(
699 count(http->d_request_headers.begin(), http->d_request_headers.end(),
700 "Accept-Encoding: deflate, gzip, compress") == 1);
701
702 http->set_accept_deflate(false);
703 CPPUNIT_ASSERT(
704 count(http->d_request_headers.begin(), http->d_request_headers.end(),
705 "Accept-Encoding: deflate, gzip, compress") == 0);
706 }
707
set_xdap_protocol_test()708 void set_xdap_protocol_test()
709 {
710 // Initially there should be no header and the protocol should be 2.0
711 CPPUNIT_ASSERT(http->d_dap_client_protocol_major == 2 && http->d_dap_client_protocol_minor == 0);
712
713 CPPUNIT_ASSERT(
714 count_if(http->d_request_headers.begin(), http->d_request_headers.end(), HeaderMatch("XDAP-Accept:")) == 0);
715
716 http->set_xdap_protocol(8, 9);
717 CPPUNIT_ASSERT(http->d_dap_client_protocol_major == 8 && http->d_dap_client_protocol_minor == 9);
718 CPPUNIT_ASSERT(count(http->d_request_headers.begin(), http->d_request_headers.end(), "XDAP-Accept: 8.9") == 1);
719
720 http->set_xdap_protocol(3, 2);
721 CPPUNIT_ASSERT(http->d_dap_client_protocol_major == 3 && http->d_dap_client_protocol_minor == 2);
722 CPPUNIT_ASSERT(count(http->d_request_headers.begin(), http->d_request_headers.end(), "XDAP-Accept: 3.2") == 1);
723 }
724
read_url_password_test()725 void read_url_password_test()
726 {
727 FILE *dump = fopen("/dev/null", "w");
728 vector<string> *resp_h = new vector<string>;
729 long status = http->read_url(localhost_pw_url, dump, resp_h);
730
731 DBG(cerr << endl << http->d_upstring << endl);
732 CPPUNIT_ASSERT(http->d_upstring == "jimg:dods_test");
733 DBG(cerr << "Status: " << status << endl);
734 CPPUNIT_ASSERT(status == 200);
735 delete resp_h;
736 resp_h = 0;
737 }
738
read_url_password_test2()739 void read_url_password_test2()
740 {
741 FILE *dump = fopen("/dev/null", "w");
742 vector<string> *resp_h = new vector<string>;
743 long status = http->read_url(localhost_digest_pw_url, dump, resp_h);
744
745 DBG(cerr << endl << http->d_upstring << endl);
746 CPPUNIT_ASSERT(http->d_upstring == "jimg:dods_digest");
747 DBG(cerr << "Status: " << status << endl);
748 CPPUNIT_ASSERT(status == 200);
749 delete resp_h;
750 resp_h = 0;
751 }
752 };
753
754 CPPUNIT_TEST_SUITE_REGISTRATION (HTTPConnectTest);
755
756 }
757
main(int argc,char * argv[])758 int main(int argc, char*argv[])
759 {
760 GetOpt getopt(argc, argv, "dh");
761 int option_char;
762
763 while ((option_char = getopt()) != -1)
764 switch (option_char) {
765 case 'd':
766 debug = 1; // debug is a static global
767 break;
768 case 'h': { // help - show test names
769 cerr << "Usage: HTTPConnectTest has the following tests:" << endl;
770 const std::vector<Test*> &tests = libdap::HTTPConnectTest::suite()->getTests();
771 unsigned int prefix_len = libdap::HTTPConnectTest::suite()->getName().append("::").length();
772 for (std::vector<Test*>::const_iterator i = tests.begin(), e = tests.end(); i != e; ++i) {
773 cerr << (*i)->getName().replace(0, prefix_len, "") << endl;
774 }
775 break;
776 }
777 default:
778 break;
779 }
780
781 CppUnit::TextTestRunner runner;
782 runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
783
784 bool wasSuccessful = true;
785 string test = "";
786 int i = getopt.optind;
787 if (i == argc) {
788 // run them all
789 wasSuccessful = runner.run("");
790 }
791 else {
792 for (; i < argc; ++i) {
793 if (debug) cerr << "Running " << argv[i] << endl;
794 test = libdap::HTTPConnectTest::suite()->getName().append("::").append(argv[i]);
795 wasSuccessful = wasSuccessful && runner.run(test);
796 }
797 }
798
799 return wasSuccessful ? 0 : 1;
800 }
801