00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "libts.h"
00036
00037 #include "Arena.h"
00038 #include "HTTP.h"
00039 #include "MIME.h"
00040 #include "Regex.h"
00041 #include "URL.h"
00042 #include "HttpCompat.h"
00043
00044 #include "HdrTest.h"
00045
00046
00047
00048
00049
00050 int
00051 HdrTest::go(RegressionTest * t, int )
00052 {
00053 HdrTest::rtest = t;
00054 int status = 1;
00055
00056 hdrtoken_init();
00057 url_init();
00058 mime_init();
00059 http_init();
00060
00061 status = status & test_error_page_selection();
00062 status = status & test_http_hdr_print_and_copy();
00063 status = status & test_comma_vals();
00064 status = status & test_parse_comma_list();
00065 status = status & test_set_comma_vals();
00066 status = status & test_delete_comma_vals();
00067 status = status & test_extend_comma_vals();
00068 status = status & test_insert_comma_vals();
00069 status = status & test_accept_language_match();
00070 status = status & test_accept_charset_match();
00071 status = status & test_parse_date();
00072 status = status & test_format_date();
00073 status = status & test_url();
00074 status = status & test_arena();
00075 status = status & test_regex();
00076 status = status & test_http_parser_eos_boundary_cases();
00077 status = status & test_http_mutation();
00078 status = status & test_mime();
00079 status = status & test_http();
00080
00081 return (status ? REGRESSION_TEST_PASSED : REGRESSION_TEST_FAILED);
00082 }
00083
00084
00085
00086
00087
00088 int
00089 HdrTest::test_error_page_selection()
00090 {
00091 static struct
00092 {
00093 const char *set_name;
00094 const char *content_language;
00095 const char *content_charset;
00096 } sets[] = {
00097 {
00098 "default", "en", "iso-8859-1"}, {
00099 "en-cockney", "en-cockney", "iso-8859-1"}, {
00100 "en", "en", "iso-8859-1"}, {
00101 "en-us", "en-us", "us-ascii"}, {
00102 "en", "en", "unicode"}, {
00103 "en-cockney-slang", "en-cockney-slang", "iso-8859-1"}, {
00104 "ko", "ko", "iso-8859-1"}, {
00105 "ko", "ko", "iso-2022-kr"}, {
00106 "jp", "jp", "shift-jis"}
00107 };
00108
00109 static struct
00110 {
00111 const char *accept_language;
00112 const char *accept_charset;
00113 const char *expected_set;
00114 float expected_Q;
00115 int expected_La;
00116 int expected_I;
00117 } tests[] = {
00118 {
00119 NULL, NULL, "default", 1, 0, INT_MAX}, {
00120 "en", NULL, "en", 1, 2, 1}, {
00121 "ko", NULL, "ko", 1, 2, 1}, {
00122 "en-us", NULL, "en-us", 1, 5, 1}, {
00123 "en-US", NULL, "en-us", 1, 5, 1}, {
00124 "en,ko", NULL, "en", 1, 2, 1}, {
00125 "ko,en", NULL, "ko", 1, 2, 1}, {
00126 "en;q=0.7,ko", NULL, "ko", 1, 2, 2}, {
00127 "en;q=.7,ko", NULL, "ko", 1, 2, 2}, {
00128 "en;q=.7,ko;q=.7", NULL, "en", 0.7, 2, 1}, {
00129 "en;q=.7,ko;q=.701", NULL, "ko", 0.701, 2, 2}, {
00130 "en;q=.7 , ko;q=.701", NULL, "ko", 0.701, 2, 2}, {
00131 "en ; q=.7 , ko ; ; ; ; q=.701", NULL, "ko", 0.701, 2, 2}, {
00132 "en,ko;q=.7", NULL, "en", 1, 2, 1}, {
00133 "en;q=1,ko;q=.7", NULL, "en", 1, 2, 1}, {
00134 "en;;;q=1,ko;q=.7", NULL, "en", 1, 2, 1}, {
00135 "en;;;q=1,,,,ko;q=.7", NULL, "en", 1, 2, 1}, {
00136 "en;;;q=.7,,,,ko;q=.7", NULL, "en", 0.7, 2, 1}, {
00137 "en;;;q=.699,,,,ko;q=.7", NULL, "ko", 0.7, 2, 5}, {
00138 "en;q=0,ko;q=1", NULL, "ko", 1, 2, 2}, {
00139 "en;q=0, ko;q=1", NULL, "ko", 1, 2, 2}, {
00140 "en;q=0,ko;q=.5", NULL, "ko", 0.5, 2, 2}, {
00141 "en;q=0, ko;q=.5", NULL, "ko", 0.5, 2, 2}, {
00142 "en;q=000000000.00000000000000000000,ko;q=1.0000000000000000000", NULL, "ko", 1, 2, 2}
00143 };
00144
00145 bri_box("test_error_page_selection");
00146
00147 int i;
00148 int failures = 0;
00149
00150 int nsets = sizeof(sets) / sizeof(sets[0]);
00151 int ntests = sizeof(tests) / sizeof(tests[0]);
00152
00153
00154
00155 RawHashTable *table_of_sets = new RawHashTable(RawHashTable_KeyType_String);
00156
00157 for (i = 0; i < nsets; i++) {
00158 HttpBodySetRawData *body_set;
00159
00160 body_set = (HttpBodySetRawData *)ats_malloc(sizeof(HttpBodySetRawData));
00161 body_set->magic = 0;
00162 body_set->set_name = (char *) (sets[i].set_name);
00163 body_set->content_language = (char *) (sets[i].content_language);
00164 body_set->content_charset = (char *) (sets[i].content_charset);
00165 body_set->table_of_pages = (RawHashTable *) 1;
00166
00167 table_of_sets->setValue((RawHashTable_Key) (body_set->set_name), (RawHashTable_Value) body_set);
00168 }
00169
00170
00171
00172 for (i = 0; i < ntests; i++) {
00173 float Q_best;
00174 int La_best, Lc_best, I_best;
00175 const char *set_best;
00176
00177 StrList accept_language_list;
00178 StrList accept_charset_list;
00179
00180 HttpCompat::parse_comma_list(&accept_language_list, tests[i].accept_language);
00181 HttpCompat::parse_comma_list(&accept_charset_list, tests[i].accept_charset);
00182
00183 printf(" test #%d: (Accept-Language='%s', Accept-Charset='%s')\n",
00184 i + 1,
00185 (tests[i].accept_language ? tests[i].accept_language : "<null>"),
00186 (tests[i].accept_charset ? tests[i].accept_charset : "<null>"));
00187
00188 set_best = HttpCompat::determine_set_by_language(table_of_sets,
00189 &(accept_language_list), &(accept_charset_list),
00190 &Q_best, &La_best, &Lc_best, &I_best);
00191
00192 if ((strcmp(set_best, tests[i].expected_set) == 0) &&
00193 (Q_best == tests[i].expected_Q) && (La_best == tests[i].expected_La) && (I_best == tests[i].expected_I)) {
00194 printf("SUCCESS: test #%d expected [ S='%s', Q=%g, La=%d, I=%d ] got [ S='%s', Q=%g, La=%d, I=%d ]\n",
00195 i + 1,
00196 tests[i].expected_set, tests[i].expected_Q, tests[i].expected_La, tests[i].expected_I,
00197 set_best, Q_best, La_best, I_best);
00198 } else {
00199 ++failures;
00200 printf(" FAILED: test #%d expected [ S='%s', Q=%g, La=%d, I=%d ] got [ S='%s', Q=%g, La=%d, I=%d ]\n",
00201 i + 1,
00202 tests[i].expected_set, tests[i].expected_Q, tests[i].expected_La, tests[i].expected_I,
00203 set_best, Q_best, La_best, I_best);
00204 }
00205 }
00206
00207 delete table_of_sets;
00208 return (failures_to_status("test_error_page_selection", failures));
00209 }
00210
00211
00212
00213
00214 int
00215 HdrTest::test_parse_date()
00216 {
00217 static struct
00218 {
00219 const char *fast;
00220 const char *slow;
00221 } dates[] = {
00222 {
00223 "Sun, 06 Nov 1994 08:49:37 GMT", "Sunday, 06-Nov-1994 08:49:37 GMT"}, {
00224 "Mon, 07 Nov 1994 08:49:37 GMT", "Monday, 07-Nov-1994 08:49:37 GMT"}, {
00225 "Tue, 08 Nov 1994 08:49:37 GMT", "Tuesday, 08-Nov-1994 08:49:37 GMT"}, {
00226 "Wed, 09 Nov 1994 08:49:37 GMT", "Wednesday, 09-Nov-1994 08:49:37 GMT"}, {
00227 "Thu, 10 Nov 1994 08:49:37 GMT", "Thursday, 10-Nov-1994 08:49:37 GMT"}, {
00228 "Fri, 11 Nov 1994 08:49:37 GMT", "Friday, 11-Nov-1994 08:49:37 GMT"}, {
00229 "Sat, 11 Nov 1994 08:49:37 GMT", "Saturday, 11-Nov-1994 08:49:37 GMT"}, {
00230 "Sun, 03 Jan 1999 08:49:37 GMT", "Sunday, 03-Jan-1999 08:49:37 GMT"}, {
00231 "Sun, 07 Feb 1999 08:49:37 GMT", "Sunday, 07-Feb-1999 08:49:37 GMT"}, {
00232 "Sun, 07 Mar 1999 08:49:37 GMT", "Sunday, 07-Mar-1999 08:49:37 GMT"}, {
00233 "Sun, 04 Apr 1999 08:49:37 GMT", "Sunday, 04-Apr-1999 08:49:37 GMT"}, {
00234 "Sun, 02 May 1999 08:49:37 GMT", "Sunday, 02-May-1999 08:49:37 GMT"}, {
00235 "Sun, 06 Jun 1999 08:49:37 GMT", "Sunday, 06-Jun-1999 08:49:37 GMT"}, {
00236 "Sun, 04 Jul 1999 08:49:37 GMT", "Sunday, 04-Jul-1999 08:49:37 GMT"}, {
00237 "Sun, 01 Aug 1999 08:49:37 GMT", "Sunday, 01-Aug-1999 08:49:37 GMT"}, {
00238 "Sun, 05 Sep 1999 08:49:37 GMT", "Sunday, 05-Sep-1999 08:49:37 GMT"}, {
00239 "Sun, 03 Oct 1999 08:49:37 GMT", "Sunday, 03-Oct-1999 08:49:37 GMT"}, {
00240 "Sun, 07 Nov 1999 08:49:37 GMT", "Sunday, 07-Nov-1999 08:49:37 GMT"}, {
00241 "Sun, 05 Dec 1999 08:49:37 GMT", "Sunday, 05-Dec-1999 08:49:37 GMT"}, {
00242 NULL, NULL}};
00243
00244 int i;
00245 int failures = 0;
00246 time_t fast_t, slow_t;
00247
00248 bri_box("test_parse_date");
00249
00250 for (i = 0; dates[i].fast; i++) {
00251 fast_t = mime_parse_date(dates[i].fast, dates[i].fast + (int) strlen(dates[i].fast));
00252 slow_t = mime_parse_date(dates[i].slow, dates[i].slow + (int) strlen(dates[i].slow));
00253
00254 if (fast_t != slow_t) {
00255 printf("FAILED: date %lu (%s) != %lu (%s)\n",
00256 (unsigned long) fast_t, dates[i].fast, (unsigned long) slow_t, dates[i].slow);
00257 ++failures;
00258 }
00259 }
00260
00261 return (failures_to_status("test_parse_date", failures));
00262 }
00263
00264
00265
00266
00267 int
00268 HdrTest::test_format_date()
00269 {
00270 static const char *dates[] = {
00271 "Sun, 06 Nov 1994 08:49:37 GMT",
00272 "Sun, 03 Jan 1999 08:49:37 GMT",
00273 "Sun, 05 Dec 1999 08:49:37 GMT",
00274 "Tue, 25 Apr 2000 20:29:53 GMT",
00275 NULL
00276 };
00277
00278 bri_box("test_format_date");
00279
00280
00281
00282 int i;
00283 time_t t, t2, t3;
00284 char buffer[128], buffer2[128];
00285 static const char *envstr = "TZ=GMT0";
00286 int failures = 0;
00287
00288
00289 putenv((char*)envstr);
00290 tzset();
00291
00292 for (i = 0; dates[i]; i++) {
00293 t = mime_parse_date(dates[i], dates[i] + (int) strlen(dates[i]));
00294
00295 cftime_replacement(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", &t);
00296 if (memcmp(dates[i], buffer, 29) != 0) {
00297 printf("FAILED: original date doesn't match cftime date\n");
00298 printf(" input date: %s\n", dates[i]);
00299 printf(" cftime date: %s\n", buffer);
00300 ++failures;
00301 }
00302
00303 mime_format_date(buffer, t);
00304 if (memcmp(dates[i], buffer, 29) != 0) {
00305 printf("FAILED: original date doesn't match mime_format_date date\n");
00306 printf(" input date: %s\n", dates[i]);
00307 printf(" cftime date: %s\n", buffer);
00308 ++failures;
00309 }
00310 }
00311
00312
00313
00314
00315 for (t = 0; t < 40 * 366 * (24 * 60 * 60); t += (int) (drand48() * (24 * 60 * 60))) {
00316 cftime_replacement(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", &t);
00317 t2 = mime_parse_date(buffer, buffer + (int) strlen(buffer));
00318 if (t2 != t) {
00319 printf("FAILED: parsed time_t doesn't match original time_t\n");
00320 printf(" input time_t: %d (%s)\n", (int) t, buffer);
00321 printf(" parsed time_t: %d\n", (int) t2);
00322 ++failures;
00323 }
00324 mime_format_date(buffer2, t);
00325 if (memcmp(buffer, buffer2, 29) != 0) {
00326 printf("FAILED: formatted date doesn't match original date\n");
00327 printf(" original date: %s\n", buffer);
00328 printf(" formatted date: %s\n", buffer2);
00329 ++failures;
00330 }
00331 t3 = mime_parse_date(buffer2, buffer2 + (int) strlen(buffer2));
00332 if (t != t3) {
00333 printf("FAILED: parsed time_t doesn't match original time_t\n");
00334 printf(" input time_t: %d (%s)\n", (int) t, buffer2);
00335 printf(" parsed time_t: %d\n", (int) t3);
00336 ++failures;
00337 }
00338
00339 if (failures > 20) {
00340
00341 break;
00342 }
00343 }
00344
00345 return (failures_to_status("test_format_date", failures));
00346 }
00347
00348
00349
00350
00351 int
00352 HdrTest::test_url()
00353 {
00354 static const char *strs[] = {
00355 "http://some.place/path;params?query#fragment",
00356
00357
00358 "http://trafficserver.apache.org/index.html",
00359
00360
00361
00362 "some.place",
00363 "some.place/",
00364 "http://some.place",
00365 "http://some.place/",
00366 "http://some.place/path",
00367 "http://some.place/path;params",
00368 "http://some.place/path;params?query",
00369 "http://some.place/path;params?query#fragment",
00370 "http://some.place/path?query#fragment",
00371 "http://some.place/path#fragment",
00372
00373 "some.place:80",
00374 "some.place:80/",
00375 "http://some.place:80",
00376 "http://some.place:80/",
00377
00378 "foo@some.place:80",
00379 "foo@some.place:80/",
00380 "http://foo@some.place:80",
00381 "http://foo@some.place:80/",
00382
00383 "foo:bar@some.place:80",
00384 "foo:bar@some.place:80/",
00385 "http://foo:bar@some.place:80",
00386 "http://foo:bar@some.place:80/",
00387
00388
00389 "http://172.16.28.101",
00390 "http://172.16.28.101:8080",
00391 "http://[::]",
00392 "http://[::1]",
00393 "http://[fc01:172:16:28::101]",
00394 "http://[fc01:172:16:28::101]:80",
00395 "http://[fc01:172:16:28:BAAD:BEEF:DEAD:101]",
00396 "http://[fc01:172:16:28:BAAD:BEEF:DEAD:101]:8080",
00397 "http://172.16.28.101/some/path",
00398 "http://172.16.28.101:8080/some/path",
00399 "http://[::1]/some/path",
00400 "http://[fc01:172:16:28::101]/some/path",
00401 "http://[fc01:172:16:28::101]:80/some/path",
00402 "http://[fc01:172:16:28:BAAD:BEEF:DEAD:101]/some/path",
00403 "http://[fc01:172:16:28:BAAD:BEEF:DEAD:101]:8080/some/path",
00404 "http://172.16.28.101/",
00405 "http://[fc01:172:16:28:BAAD:BEEF:DEAD:101]:8080/",
00406
00407
00408 "foo:bar@some.place",
00409 "foo:bar@some.place/",
00410 "http://foo:bar@some.place",
00411 "http://foo:bar@some.place/",
00412 "http://foo:bar@[::1]:8080/",
00413 "http://foo@[::1]",
00414
00415 "mms://sm02.tsqa.example.com/0102rally.asf",
00416 "pnm://foo:bar@some.place:80/path;params?query#fragment",
00417 "rtsp://foo:bar@some.place:80/path;params?query#fragment",
00418 "rtspu://foo:bar@some.place:80/path;params?query#fragment",
00419 "/finance/external/cbsm/*http://cbs.marketwatch.com/archive/19990713/news/current/net.htx?source=blq/yhoo&dist=yhoo",
00420 "http://a.b.com/xx.jpg?newpath=http://bob.dave.com"
00421 };
00422 static int nstrs = sizeof(strs) / sizeof(strs[0]);
00423
00424 static char const* bad[] = {
00425 "http://[1:2:3:4:5:6:7:8:9]",
00426 "http://1:2:3:4:5:6:7:8:A:B",
00427 "http://bob.com[::1]",
00428 "http://[::1].com"
00429 "http://foo:bar:baz@bob.com/",
00430 "http://foo:bar:baz@[::1]:8080/",
00431 "http://]",
00432 "http://:",
00433 "http:/"
00434 };
00435 static int nbad = sizeof(bad) / sizeof(bad[0]);
00436
00437 int err, failed;
00438 URL url;
00439 const char *start;
00440 const char *end;
00441 int i, old_length, new_length;
00442
00443 bri_box("test_url");
00444
00445 failed = 0;
00446 for (i = 0; i < nstrs; i++) {
00447 old_length = (int) strlen(strs[i]);
00448 start = strs[i];
00449 end = start + old_length;
00450
00451 url.create(NULL);
00452 err = url.parse(&start, end);
00453 if (err < 0) {
00454 failed = 1;
00455 break;
00456 }
00457
00458 char print_buf[1024];
00459 new_length = 0;
00460 int offset = 0;
00461 url.print(print_buf, 1024, &new_length, &offset);
00462 print_buf[new_length] = '\0';
00463
00464 const char *fail_text = NULL;
00465
00466 if (old_length == new_length) {
00467 if (memcmp(print_buf, strs[i], new_length) != 0)
00468 fail_text = "URLS DIFFER";
00469 } else if (old_length == new_length - 1) {
00470
00471
00472 if (memcmp(print_buf, strs[i], old_length) != 0 ||
00473 print_buf[new_length - 1] != '/' || (strs[i])[old_length - 1] == '/') {
00474 fail_text = "TRAILING SLASH";
00475 }
00476 } else {
00477 fail_text = "LENGTHS DIFFER";
00478 }
00479
00480 if (fail_text) {
00481 failed = 1;
00482 printf("%16s: OLD: (%4d) %s\n", fail_text, old_length, strs[i]);
00483 printf("%16s: NEW: (%4d) %s\n", "", new_length, print_buf);
00484 obj_describe(url.m_url_impl, true);
00485 } else {
00486 printf("%16s: '%s'\n", "PARSE SUCCESS", strs[i]);
00487 }
00488
00489 url.destroy();
00490 }
00491
00492 for (i = 0 ; i < nbad ; ++i) {
00493 char const* x = bad[i];
00494 url.create(NULL);
00495 err = url.parse(x, strlen(x));
00496 url.destroy();
00497 if (err == PARSE_DONE) {
00498 failed = 1;
00499 printf("Successfully parsed invalid url '%s'", x);
00500 break;
00501 }
00502 }
00503
00504 #if 0
00505 if (!failed) {
00506 Note("URL performance test start");
00507 for (int j = 0 ; j < 100000 ; ++j) {
00508 for (i = 0 ; i < nstrs ; ++i) {
00509 char const* x = strs[i];
00510 url.create(NULL);
00511 err = url.parse(x, strlen(x));
00512 url.destroy();
00513 }
00514 }
00515 Note("URL performance test end");
00516 }
00517 #endif
00518
00519 return (failures_to_status("test_url", failed));
00520 }
00521
00522
00523
00524
00525 int
00526 HdrTest::test_mime()
00527 {
00528 static const char mime[] = {
00529
00530 "Date: 6 Nov 1994 08:49:37 GMT\r\n"
00531 "Max-Forwards: 65535\r\n"
00532 "Cache-Control: private\r\n"
00533 "accept: foo\r\n"
00534 "accept: bar\n"
00535 ": (null) field name\r\n"
00536 "aCCept: \n"
00537 "ACCEPT\r\n"
00538 "foo: bar\r\n"
00539 "foo: argh\r\n"
00540 "word word: word \r\n"
00541 "accept: \"fazzle, dazzle\"\r\n"
00542 "accept: 1, 2, 3, 4, 5, 6, 7, 8\r\n"
00543 "continuation: part1\r\n" " part2\r\n" "scooby: doo\r\n" "scooby : doo\r\n" "bar: foo\r\n" "\r\n"
00544 };
00545
00546 int err;
00547 MIMEHdr hdr;
00548 MIMEParser parser;
00549 const char *start;
00550 const char *end;
00551
00552 bri_box("test_mime");
00553
00554 printf(" <<< MUST BE HAND-VERIFIED FOR FULL-BENEFIT>>>\n\n");
00555
00556 start = mime;
00557 end = start + strlen(start);
00558
00559 mime_parser_init(&parser);
00560
00561 bool must_copy_strs = 0;
00562
00563 hdr.create(NULL);
00564 err = hdr.parse(&parser, &start, end, must_copy_strs, false);
00565
00566 if (err < 0)
00567 return (failures_to_status("test_mime", 1));
00568
00569 hdr.field_delete("not_there", 9);
00570 hdr.field_delete("accept", 6);
00571 hdr.field_delete("scooby", 6);
00572 hdr.field_delete("scooby", 6);
00573 hdr.field_delete("bar", 3);
00574 hdr.field_delete("continuation", 12);
00575
00576 int count = hdr.fields_count();
00577 printf("hdr.fields_count() = %d\n", count);
00578
00579 int i_max_forwards = hdr.value_get_int("Max-Forwards", 12);
00580 int u_max_forwards = hdr.value_get_uint("Max-Forwards", 12);
00581 printf("i_max_forwards = %d u_max_forwards = %d\n", i_max_forwards, u_max_forwards);
00582
00583 hdr.set_age(9999);
00584
00585 int length = hdr.length_get();
00586 printf("hdr.length_get() = %d\n", length);
00587
00588 time_t t0, t1, t2;
00589
00590 t0 = hdr.get_date();
00591 if (t0 == 0) {
00592 printf("FAILED: Initial date is zero but shouldn't be\n");
00593 return (failures_to_status("test_mime", 1));
00594 }
00595
00596 t1 = time(NULL);
00597 hdr.set_date(t1);
00598 t2 = hdr.get_date();
00599 if (t1 != t2) {
00600 printf("FAILED: set_date(%" PRId64 ") ... get_date = %" PRId64 "\n\n", (int64_t)t1, (int64_t)t2);
00601 return (failures_to_status("test_mime", 1));
00602 }
00603
00604 hdr.value_append("Cache-Control", 13, "no-cache", 8, 1);
00605
00606 MIMEField *cc_field;
00607 StrList slist;
00608
00609 cc_field = hdr.field_find("Cache-Control", 13);
00610
00611 cc_field->value_get_comma_list(&slist);
00612
00613 mime_parser_clear(&parser);
00614
00615 hdr.print(NULL, 0, NULL, NULL);
00616 printf("\n");
00617
00618 obj_describe((HdrHeapObjImpl *) (hdr.m_mime), true);
00619
00620 hdr.fields_clear();
00621
00622 hdr.destroy();
00623
00624 return (failures_to_status("test_mime", 0));
00625 }
00626
00627
00628
00629
00630 int
00631 HdrTest::test_http_parser_eos_boundary_cases()
00632 {
00633 struct
00634 {
00635 const char *msg;
00636 int expected_result;
00637 int expected_bytes_consumed;
00638 } tests[] = {
00639 {
00640 "GET /index.html HTTP/1.0\r\n", PARSE_DONE, 26}, {
00641 "GET /index.html HTTP/1.0\r\n\r\n***BODY****", PARSE_DONE, 28}, {
00642 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n\r\n***BODY****", PARSE_DONE, 48}, {
00643 "GET", PARSE_ERROR, 3}, {
00644 "GET /index.html", PARSE_ERROR, 15}, {
00645 "GET /index.html\r\n", PARSE_DONE, 17}, {
00646 "GET /index.html HTTP/1.0", PARSE_ERROR, 24}, {
00647 "GET /index.html HTTP/1.0\r", PARSE_ERROR, 25}, {
00648 "GET /index.html HTTP/1.0\n", PARSE_DONE, 25}, {
00649 "GET /index.html HTTP/1.0\n\n", PARSE_DONE, 26}, {
00650 "GET /index.html HTTP/1.0\r\n\r\n", PARSE_DONE, 28}, {
00651 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar", PARSE_ERROR, 44}, {
00652 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar\n", PARSE_DONE, 45}, {
00653 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n", PARSE_DONE, 46}, {
00654 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n\r\n", PARSE_DONE, 48}, {
00655 "GET /index.html HTTP/1.0\nUser-Agent: foobar\n", PARSE_DONE, 44}, {
00656 "GET /index.html HTTP/1.0\nUser-Agent: foobar\nBoo: foo\n", PARSE_DONE, 53}, {
00657 "GET /index.html HTTP/1.0\r\nUser-Agent: foobar\r\n", PARSE_DONE, 46}, {
00658 "GET /index.html HTTP/1.0\r\n", PARSE_DONE, 26}, {
00659 "", PARSE_ERROR, 0}, {
00660 NULL, 0, 0}
00661 };
00662
00663 int i, ret, bytes_consumed;
00664 const char *orig_start;
00665 const char *start;
00666 const char *end;
00667 HTTPParser parser;
00668
00669 int failures = 0;
00670
00671 bri_box("test_http_parser_eos_boundary_cases");
00672
00673 http_parser_init(&parser);
00674
00675 for (i = 0; tests[i].msg != NULL; i++) {
00676 HTTPHdr req_hdr;
00677
00678 start = tests[i].msg;
00679 end = start + strlen(start);
00680
00681 req_hdr.create(HTTP_TYPE_REQUEST);
00682
00683 http_parser_clear(&parser);
00684
00685 orig_start = start;
00686 ret = req_hdr.parse_req(&parser, &start, end, true);
00687 bytes_consumed = (int) (start - orig_start);
00688
00689 printf("======== test %d (length=%d, consumed=%d)\n", i, (int)strlen(tests[i].msg), bytes_consumed);
00690 printf("[%s]\n", tests[i].msg);
00691 printf("\n[");
00692 req_hdr.print(NULL, 0, NULL, NULL);
00693 printf("]\n\n");
00694
00695 if ((ret != tests[i].expected_result) || (bytes_consumed != tests[i].expected_bytes_consumed)) {
00696 ++failures;
00697 printf("FAILED: test %d: retval <expected %d, got %d>, eaten <expected %d, got %d>\n\n",
00698 i, tests[i].expected_result, ret, tests[i].expected_bytes_consumed, bytes_consumed);
00699 }
00700
00701 req_hdr.destroy();
00702 }
00703
00704 return (failures_to_status("test_http_parser_eos_boundary_cases", failures));
00705 }
00706
00707
00708
00709
00710 int
00711 HdrTest::test_http_aux(const char *request, const char *response)
00712 {
00713 int err;
00714 HTTPHdr req_hdr, rsp_hdr;
00715 HTTPParser parser;
00716 const char *start;
00717 const char *end;
00718
00719 int status = 1;
00720
00721 printf(" <<< MUST BE HAND-VERIFIED FOR FULL BENEFIT >>>\n\n");
00722
00723
00724
00725 start = request;
00726 end = start + strlen(start);
00727
00728 http_parser_init(&parser);
00729
00730 req_hdr.create(HTTP_TYPE_REQUEST);
00731 rsp_hdr.create(HTTP_TYPE_RESPONSE);
00732
00733 printf("======== parsing\n\n");
00734 while (1) {
00735 err = req_hdr.parse_req(&parser, &start, end, true);
00736 if (err != PARSE_CONT)
00737 break;
00738 }
00739 if (err == PARSE_ERROR) {
00740 req_hdr.destroy();
00741 rsp_hdr.destroy();
00742 return (failures_to_status("test_http_aux", (status == 0)));
00743 }
00744
00745
00746
00747 HTTPHdr new_hdr;
00748 new_hdr.create(HTTP_TYPE_REQUEST);
00749 new_hdr.copy(&req_hdr);
00750 new_hdr.destroy();
00751
00752
00753
00754 printf("======== real request (length=%d)\n\n", (int)strlen(request));
00755 printf("%s\n", request);
00756
00757 printf("\n[");
00758 req_hdr.print(NULL, 0, NULL, NULL);
00759 printf("]\n\n");
00760
00761 obj_describe(req_hdr.m_http, true);
00762
00763
00764
00765
00766
00767
00768 start = response;
00769 end = start + strlen(start);
00770
00771 http_parser_clear(&parser);
00772 http_parser_init(&parser);
00773
00774 while (1) {
00775 err = rsp_hdr.parse_resp(&parser, &start, end, true);
00776 if (err != PARSE_CONT)
00777 break;
00778 }
00779 if (err == PARSE_ERROR) {
00780 req_hdr.destroy();
00781 rsp_hdr.destroy();
00782 return (failures_to_status("test_http_aux", (status == 0)));
00783 }
00784
00785 http_parser_clear(&parser);
00786
00787
00788
00789 printf("\n======== real response (length=%d)\n\n", (int)strlen(response));
00790 printf("%s\n", response);
00791
00792 printf("\n[");
00793 rsp_hdr.print(NULL, 0, NULL, NULL);
00794 printf("]\n\n");
00795
00796 obj_describe(rsp_hdr.m_http, true);
00797
00798 #define NNN 1000
00799 {
00800 char buf[NNN];
00801 int bufindex, last_bufindex;
00802 int tmp;
00803 int i;
00804
00805 bufindex = 0;
00806
00807 do {
00808 last_bufindex = bufindex;
00809 tmp = bufindex;
00810 buf[0] = '#';
00811 err = rsp_hdr.print(buf, NNN, &bufindex, &tmp);
00812
00813
00814 putchar('{');
00815 for (i = 0; i < bufindex - last_bufindex; i++) {
00816 if (!iscntrl(buf[i]))
00817 putchar(buf[i]);
00818 else
00819 printf("\\%o", buf[i]);
00820 }
00821 putchar('}');
00822 } while (!err);
00823 }
00824
00825
00826
00827 req_hdr.destroy();
00828 rsp_hdr.destroy();
00829
00830 return (failures_to_status("test_http_aux", (status == 0)));
00831 }
00832
00833
00834
00835
00836 int
00837 HdrTest::test_http_hdr_print_and_copy()
00838 {
00839 static struct
00840 {
00841 const char *req;
00842 const char *req_tgt;
00843 const char *rsp;
00844 const char *rsp_tgt;
00845 } tests[] = {
00846 {
00847 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00848 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa\r\n"
00849 "\r\n",
00850 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00851 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa\r\n"
00852 "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n"}, {
00853 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00854 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa fjfj dslkfjdslk fjsdafkl dsajfkldsa jfkldsafj klsafjs lkafjdsalk fsdjakfl sdjaflkdsaj flksdjflsd ;ffd salfdjs lf;sdaf ;dsaf jdsal;fdjsaflkjsda \r\n"
00855 "\r\n",
00856 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00857 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa fjfj dslkfjdslk fjsdafkl dsajfkldsa jfkldsafj klsafjs lkafjdsalk fsdjakfl sdjaflkdsaj flksdjflsd ;ffd salfdjs lf;sdaf ;dsaf jdsal;fdjsaflkjsda \r\n"
00858 "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n"}, {
00859 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00860 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa fjfj dslkfjdslk fjsdafkl dsajfkldsa jfkldsafj klsafjs lkafjdsalk fsdjakfl sdjaflkdsaj flksdjflsd ;ffd salfdjs lf;sdaf ;dsaf jdsal;fdjsaflkjsda kfl; fsdajfl; sdjafl;dsajlsjfl;sdafjsdal;fjds al;fdjslaf ;slajdk;f\r\n"
00861 "\r\n",
00862 "GET http://foo.com/bar.txt HTTP/1.0\r\n"
00863 "Accept-Language: fjdfjdslkf dsjkfdj flkdsfjlk sjfdlk ajfdlksa fjfj dslkfjdslk fjsdafkl dsajfkldsa jfkldsafj klsafjs lkafjdsalk fsdjakfl sdjaflkdsaj flksdjflsd ;ffd salfdjs lf;sdaf ;dsaf jdsal;fdjsaflkjsda kfl; fsdajfl; sdjafl;dsajlsjfl;sdafjsdal;fjds al;fdjslaf ;slajdk;f\r\n"
00864 "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n", "HTTP/1.0 200 OK\r\n" "\r\n"}, {
00865 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n" "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n" "Referer: chocolate fribble\r\n",
00866 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n" "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n" "Referer: chocolate fribble\r\n" "\r\n", "HTTP/1.0 200 OK\r\n" "MIME-Version: 1.0\r\n" "Server: WebSTAR/2.1 ID/30013\r\n" "Content-Type: text/html\r\n" "Content-Length: 939\r\n" "Last-Modified: Thursday, 01-Jan-04 05:00:00 GMT\r\n",
00867 "HTTP/1.0 200 OK\r\n"
00868 "MIME-Version: 1.0\r\n"
00869 "Server: WebSTAR/2.1 ID/30013\r\n"
00870 "Content-Type: text/html\r\n"
00871 "Content-Length: 939\r\n" "Last-Modified: Thursday, 01-Jan-04 05:00:00 GMT\r\n" "\r\n"}, {
00872 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n" "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n" "Referer: \r\n",
00873 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
00874 "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
00875 "Referer: \r\n"
00876 "\r\n",
00877 "HTTP/1.0 200 OK\r\n"
00878 "MIME-Version: 1.0\r\n"
00879 "Server: WebSTAR/2.1 ID/30013\r\n"
00880 "Content-Type: text/html\r\n"
00881 "Content-Length: 939\r\n"
00882 "Last-Modified: Thursday, 01-Jan-04 05:00:00 GMT\r\n"
00883 "\r\n",
00884 "HTTP/1.0 200 OK\r\n"
00885 "MIME-Version: 1.0\r\n"
00886 "Server: WebSTAR/2.1 ID/30013\r\n"
00887 "Content-Type: text/html\r\n"
00888 "Content-Length: 939\r\n" "Last-Modified: Thursday, 01-Jan-04 05:00:00 GMT\r\n" "\r\n"}, {
00889 "GET http://www.news.com:80/ HTTP/1.0\r\n"
00890 "Proxy-Connection: Keep-Alive\r\n"
00891 "User-Agent: Mozilla/4.04 [en] (X11; I; Linux 2.0.33 i586)\r\n"
00892 "Pragma: no-cache\r\n"
00893 "Host: www.news.com\r\n"
00894 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n"
00895 "Accept-Language: en\r\n"
00896 "Accept-Charset: iso-8859-1, *, utf-8\r\n"
00897 "Client-ip: D1012148\r\n"
00898 "Foo: abcdefghijklmnopqrtu\r\n"
00899 "\r\n",
00900 "GET http://www.news.com:80/ HTTP/1.0\r\n"
00901 "Proxy-Connection: Keep-Alive\r\n"
00902 "User-Agent: Mozilla/4.04 [en] (X11; I; Linux 2.0.33 i586)\r\n"
00903 "Pragma: no-cache\r\n"
00904 "Host: www.news.com\r\n"
00905 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n"
00906 "Accept-Language: en\r\n"
00907 "Accept-Charset: iso-8859-1, *, utf-8\r\n"
00908 "Client-ip: D1012148\r\n"
00909 "Foo: abcdefghijklmnopqrtu\r\n"
00910 "\r\n",
00911 "HTTP/1.0 200 OK\r\n"
00912 "Content-Length: 16428\r\n"
00913 "Content-Type: text/html\r\n"
00914 "\r\n", "HTTP/1.0 200 OK\r\n" "Content-Length: 16428\r\n" "Content-Type: text/html\r\n" "\r\n"}, {
00915 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
00916 "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
00917 "Referer: http://people.netscape.com/jwz/index.html\r\n"
00918 "Proxy-Connection: Keep-Alive\r\n"
00919 "User-Agent: Mozilla/3.01 (X11; I; Linux 2.0.28 i586)\r\n"
00920 "Pragma: no-cache\r\n"
00921 "Host: people.netscape.com\r\n"
00922 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"
00923 "\r\n",
00924 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
00925 "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
00926 "Referer: http://people.netscape.com/jwz/index.html\r\n"
00927 "Proxy-Connection: Keep-Alive\r\n"
00928 "User-Agent: Mozilla/3.01 (X11; I; Linux 2.0.28 i586)\r\n"
00929 "Pragma: no-cache\r\n"
00930 "Host: people.netscape.com\r\n"
00931 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"
00932 "\r\n",
00933 "HTTP/1.0 200 OK\r\n"
00934 "Content-Length: 16428\r\n"
00935 "Content-Type: text/html\r\n"
00936 "\r\n", "HTTP/1.0 200 OK\r\n" "Content-Length: 16428\r\n" "Content-Type: text/html\r\n" "\r\n"}
00937 };
00938
00939 int ntests = sizeof(tests) / sizeof(tests[0]);
00940 int i, failures;
00941
00942 failures = 0;
00943
00944 bri_box("test_http_hdr_print_and_copy");
00945
00946 for (i = 0; i < ntests; i++) {
00947 int status =
00948 test_http_hdr_print_and_copy_aux(i + 1, tests[i].req, tests[i].req_tgt, tests[i].rsp, tests[i].rsp_tgt);
00949 if (status == 0)
00950 ++failures;
00951 }
00952
00953 return (failures_to_status("test_http_hdr_print_and_copy", failures));
00954 }
00955
00956
00957
00958 static const char *
00959 comp_http_hdr(HTTPHdr * h1, HTTPHdr * h2)
00960 {
00961
00962 int h1_len, h2_len;
00963 int p_index, p_dumpoffset, rval;
00964 char *h1_pbuf, *h2_pbuf;
00965
00966 h1_len = h1->length_get();
00967 h2_len = h2->length_get();
00968
00969 if (h1_len != h2_len) {
00970 return "length mismatch";
00971 }
00972
00973 h1_pbuf = (char *)ats_malloc(h1_len + 1);
00974 h2_pbuf = (char *)ats_malloc(h2_len + 1);
00975
00976 p_index = p_dumpoffset = 0;
00977 rval = h1->print(h1_pbuf, h1_len, &p_index, &p_dumpoffset);
00978 if (rval != 1) {
00979 ats_free(h1_pbuf);
00980 ats_free(h2_pbuf);
00981 return "hdr print failed";
00982 }
00983
00984 p_index = p_dumpoffset = 0;
00985 rval = h2->print(h2_pbuf, h2_len, &p_index, &p_dumpoffset);
00986 if (rval != 1) {
00987 ats_free(h1_pbuf);
00988 ats_free(h2_pbuf);
00989 return "hdr print failed";
00990 }
00991
00992 rval = memcmp(h1_pbuf, h2_pbuf, h1_len);
00993 ats_free(h1_pbuf);
00994 ats_free(h2_pbuf);
00995
00996 if (rval != 0) {
00997 return "compare failed";
00998 } else {
00999 return NULL;
01000 }
01001 }
01002
01003
01004
01005
01006
01007 int
01008 HdrTest::test_http_hdr_copy_over_aux(int testnum, const char *request, const char *response)
01009 {
01010 int err;
01011 HTTPHdr req_hdr;
01012 HTTPHdr resp_hdr;
01013 HTTPHdr copy1;
01014 HTTPHdr copy2;
01015
01016 HTTPParser parser;
01017 const char *start;
01018 const char *end;
01019 const char *comp_str = NULL;
01020
01021
01022
01023 req_hdr.create(HTTP_TYPE_REQUEST);
01024
01025 start = request;
01026 end = start + strlen(start);
01027
01028 http_parser_init(&parser);
01029
01030 while (1) {
01031 err = req_hdr.parse_req(&parser, &start, end, true);
01032 if (err != PARSE_CONT)
01033 break;
01034 }
01035
01036 if (err == PARSE_ERROR) {
01037 printf("FAILED: (test #%d) parse error parsing request hdr\n", testnum);
01038 return (0);
01039 }
01040 http_parser_clear(&parser);
01041
01042
01043
01044
01045 resp_hdr.create(HTTP_TYPE_RESPONSE);
01046
01047 start = response;
01048 end = start + strlen(start);
01049
01050 http_parser_init(&parser);
01051
01052 while (1) {
01053 err = resp_hdr.parse_resp(&parser, &start, end, true);
01054 if (err != PARSE_CONT)
01055 break;
01056 }
01057
01058 if (err == PARSE_ERROR) {
01059 printf("FAILED: (test #%d) parse error parsing response hdr\n", testnum);
01060 return (0);
01061 }
01062
01063
01064 copy1.create(HTTP_TYPE_REQUEST);
01065 copy1.copy(&req_hdr);
01066 comp_str = comp_http_hdr(&req_hdr, ©1);
01067 if (comp_str)
01068 goto done;
01069
01070 copy2.create(HTTP_TYPE_RESPONSE);
01071 copy2.copy(&resp_hdr);
01072 comp_str = comp_http_hdr(&resp_hdr, ©2);
01073 if (comp_str)
01074 goto done;
01075
01076
01077
01078
01079 #if 0
01080
01081 copy1.copy(©1);
01082 comp_str = comp_http_hdr(&req_hdr, ©1);
01083 if (comp_str)
01084 goto done;
01085
01086 copy2.copy(©2);
01087 comp_str = comp_http_hdr(&resp_hdr, ©2);
01088 if (comp_str)
01089 goto done;
01090 #endif
01091
01092
01093 copy1.copy(&resp_hdr);
01094 comp_str = comp_http_hdr(&resp_hdr, ©1);
01095 if (comp_str)
01096 goto done;
01097
01098 copy2.copy(&req_hdr);
01099 comp_str = comp_http_hdr(&req_hdr, ©2);
01100 if (comp_str)
01101 goto done;
01102
01103 done:
01104 req_hdr.destroy();
01105 resp_hdr.destroy();
01106 copy1.destroy();
01107 copy2.destroy();
01108
01109 if (comp_str) {
01110 printf("FAILED: (test #%d) copy & compare: %s\n", testnum, comp_str);
01111 printf("REQ:\n[%.*s]\n", (int)strlen(request), request);
01112 printf("RESP :\n[%.*s]\n", (int)strlen(response), response);
01113 return (0);
01114 } else {
01115 return (1);
01116 }
01117 }
01118
01119
01120
01121
01122
01123 int
01124 HdrTest::test_http_hdr_print_and_copy_aux(int testnum,
01125 const char *request, const char *request_tgt,
01126 const char *response, const char *response_tgt)
01127 {
01128 int err;
01129 HTTPHdr hdr;
01130 HTTPParser parser;
01131 const char *start;
01132 const char *end;
01133
01134 char prt_buf[2048];
01135 int prt_bufsize = sizeof(prt_buf);
01136 int prt_bufindex, prt_dumpoffset, prt_ret;
01137
01138 char cpy_buf[2048];
01139 int cpy_bufsize = sizeof(cpy_buf);
01140 int cpy_bufindex, cpy_dumpoffset, cpy_ret;
01141
01142 char *marshal_buf = (char*)ats_malloc(2048);
01143 int marshal_bufsize = sizeof(cpy_buf);
01144
01145
01146
01147 hdr.create(HTTP_TYPE_REQUEST);
01148
01149 start = request;
01150 end = start + strlen(start);
01151
01152 http_parser_init(&parser);
01153
01154 while (1) {
01155 err = hdr.parse_req(&parser, &start, end, true);
01156 if (err != PARSE_CONT)
01157 break;
01158 }
01159
01160 if (err == PARSE_ERROR) {
01161 printf("FAILED: (test #%d) parse error parsing request hdr\n", testnum);
01162 return (0);
01163 }
01164
01165
01166 HTTPHdr new_hdr, marshal_hdr;
01167 RefCountObj ref;
01168 ref.m_refcount = 100;
01169 int marshal_len = hdr.m_heap->marshal(marshal_buf, marshal_bufsize);
01170 marshal_hdr.create(HTTP_TYPE_REQUEST);
01171 marshal_hdr.unmarshal(marshal_buf, marshal_len, &ref);
01172 new_hdr.create(HTTP_TYPE_REQUEST);
01173 new_hdr.copy(&marshal_hdr);
01174 ats_free(marshal_buf);
01175
01176
01177
01178 prt_bufindex = prt_dumpoffset = 0;
01179 prt_ret = hdr.print(prt_buf, prt_bufsize, &prt_bufindex, &prt_dumpoffset);
01180
01181 cpy_bufindex = cpy_dumpoffset = 0;
01182 cpy_ret = new_hdr.print(cpy_buf, cpy_bufsize, &cpy_bufindex, &cpy_dumpoffset);
01183
01184 if ((prt_ret != 1) || (cpy_ret != 1)) {
01185 printf("FAILED: (test #%d) couldn't print req hdr or copy --- prt_ret=%d, cpy_ret=%d\n", testnum, prt_ret, cpy_ret);
01186 return (0);
01187 }
01188
01189 if (((size_t) prt_bufindex != strlen(request_tgt)) || ((size_t) cpy_bufindex != strlen(request_tgt))) {
01190 printf("FAILED: (test #%d) print req output size mismatch --- tgt=%d, prt_bufsize=%d, cpy_bufsize=%d\n",
01191 testnum, (int)strlen(request_tgt), prt_bufindex, cpy_bufindex);
01192
01193 printf("ORIGINAL:\n[%.*s]\n", (int)strlen(request), request);
01194 printf("TARGET :\n[%.*s]\n", (int)strlen(request_tgt), request_tgt);
01195 printf("PRT_BUFF:\n[%.*s]\n", prt_bufindex, prt_buf);
01196 printf("CPY_BUFF:\n[%.*s]\n", cpy_bufindex, cpy_buf);
01197 return (0);
01198 }
01199
01200 if ((strncasecmp(request_tgt, prt_buf, strlen(request_tgt)) != 0) ||
01201 (strncasecmp(request_tgt, cpy_buf, strlen(request_tgt)) != 0)) {
01202 printf("FAILED: (test #%d) print req output mismatch\n", testnum);
01203 printf("ORIGINAL:\n[%.*s]\n", (int)strlen(request), request);
01204 printf("TARGET :\n[%.*s]\n", (int)strlen(request_tgt), request_tgt);
01205 printf("PRT_BUFF:\n[%.*s]\n", prt_bufindex, prt_buf);
01206 printf("CPY_BUFF:\n[%.*s]\n", cpy_bufindex, cpy_buf);
01207 return (0);
01208 }
01209
01210 hdr.destroy();
01211 new_hdr.destroy();
01212
01213
01214
01215 hdr.create(HTTP_TYPE_RESPONSE);
01216
01217 start = response;
01218 end = start + strlen(start);
01219
01220 http_parser_init(&parser);
01221
01222 while (1) {
01223 err = hdr.parse_resp(&parser, &start, end, true);
01224 if (err != PARSE_CONT)
01225 break;
01226 }
01227
01228 if (err == PARSE_ERROR) {
01229 printf("FAILED: (test #%d) parse error parsing response hdr\n", testnum);
01230 return (0);
01231 }
01232
01233
01234
01235 new_hdr.create(HTTP_TYPE_RESPONSE);
01236 new_hdr.copy(&hdr);
01237
01238
01239
01240 prt_bufindex = prt_dumpoffset = 0;
01241 prt_ret = hdr.print(prt_buf, prt_bufsize, &prt_bufindex, &prt_dumpoffset);
01242
01243 cpy_bufindex = cpy_dumpoffset = 0;
01244 cpy_ret = new_hdr.print(cpy_buf, cpy_bufsize, &cpy_bufindex, &cpy_dumpoffset);
01245
01246 if ((prt_ret != 1) || (cpy_ret != 1)) {
01247 printf("FAILED: (test #%d) couldn't print rsp hdr or copy --- prt_ret=%d, cpy_ret=%d\n", testnum, prt_ret, cpy_ret);
01248 return (0);
01249 }
01250
01251 if (((size_t) prt_bufindex != strlen(response_tgt)) || ((size_t) cpy_bufindex != strlen(response_tgt))) {
01252 printf("FAILED: (test #%d) print rsp output size mismatch --- tgt=%d, prt_bufsize=%d, cpy_bufsize=%d\n",
01253 testnum, (int)strlen(response_tgt), prt_bufindex, cpy_bufindex);
01254 printf("ORIGINAL:\n[%.*s]\n", (int)strlen(response), response);
01255 printf("TARGET :\n[%.*s]\n", (int)strlen(response_tgt), response_tgt);
01256 printf("PRT_BUFF:\n[%.*s]\n", prt_bufindex, prt_buf);
01257 printf("CPY_BUFF:\n[%.*s]\n", cpy_bufindex, cpy_buf);
01258 return (0);
01259 }
01260
01261 if ((strncasecmp(response_tgt, prt_buf, strlen(response_tgt)) != 0) ||
01262 (strncasecmp(response_tgt, cpy_buf, strlen(response_tgt)) != 0)) {
01263 printf("FAILED: (test #%d) print rsp output mismatch\n", testnum);
01264 printf("ORIGINAL:\n[%.*s]\n", (int)strlen(response), response);
01265 printf("TARGET :\n[%.*s]\n", (int)strlen(response_tgt), response_tgt);
01266 printf("PRT_BUFF:\n[%.*s]\n", prt_bufindex, prt_buf);
01267 printf("CPY_BUFF:\n[%.*s]\n", cpy_bufindex, cpy_buf);
01268 return (0);
01269 }
01270
01271 hdr.destroy();
01272 new_hdr.destroy();
01273
01274 if (test_http_hdr_copy_over_aux(testnum, request, response) == 0) {
01275 return 0;
01276 }
01277
01278 return (1);
01279 }
01280
01281
01282
01283
01284 int
01285 HdrTest::test_http()
01286 {
01287 int status = 1;
01288
01289 static const char request0[] = {
01290 "GET http://www.news.com:80/ HTTP/1.0\r\n"
01291 "Proxy-Connection: Keep-Alive\r\n"
01292 "User-Agent: Mozilla/4.04 [en] (X11; I; Linux 2.0.33 i586)\r\n"
01293 "Pragma: no-cache\r\n"
01294 "Host: www.news.com\r\n"
01295 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n"
01296 "Accept-Language: en\r\n"
01297 "Accept-Charset: iso-8859-1, *, utf-8\r\n"
01298 "Cookie: u_vid_0_0=00031ba3; s_cur_0_0=0101sisi091314775496e7d3Jx4+POyJakrMybmNOsq6XOn5bVn5Z6a4Ln5crU5M7Rxq2lm5aWpqupo20=; SC_Cnet001=Sampled; SC_Cnet002=Sampled\r\n"
01299 "Client-ip: D1012148\r\n" "Foo: abcdefghijklmnopqrtu\r\n" "\r\n"
01300 };
01301
01302 static const char request09[] = {
01303 "GET /index.html\r\n" "\r\n"
01304 };
01305
01306 static const char request1[] = {
01307 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
01308 "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
01309 "Referer: http://people.netscape.com/jwz/index.html\r\n"
01310 "Proxy-Connection: Keep-Alive\r\n"
01311 "User-Agent: Mozilla/3.01 (X11; I; Linux 2.0.28 i586)\r\n"
01312 "Pragma: no-cache\r\n"
01313 "Host: people.netscape.com\r\n" "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n" "\r\n"
01314 };
01315
01316 static const char request_no_colon[] = {
01317 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
01318 "If-Modified-Since Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
01319 "Referer http://people.netscape.com/jwz/index.html\r\n"
01320 "Proxy-Connection Keep-Alive\r\n"
01321 "User-Agent Mozilla/3.01 (X11; I; Linux 2.0.28 i586)\r\n"
01322 "Pragma no-cache\r\n"
01323 "Host people.netscape.com\r\n" "Accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n" "\r\n"
01324 };
01325
01326 static const char request_no_val[] = {
01327 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
01328 "If-Modified-Since:\r\n" "Referer: " "Proxy-Connection:\r\n" "User-Agent: \r\n" "Host:::\r\n" "\r\n"
01329 };
01330
01331 static const char request_multi_fblock[] = {
01332 "GET http://people.netscape.com/jwz/hacks-1.gif HTTP/1.0\r\n"
01333 "If-Modified-Since: Wednesday, 26-Feb-97 06:58:17 GMT; length=842\r\n"
01334 "Referer: http://people.netscape.com/jwz/index.html\r\n"
01335 "Proxy-Connection: Keep-Alive\r\n"
01336 "User-Agent: Mozilla/3.01 (X11; I; Linux 2.0.28 i586)\r\n"
01337 "Pragma: no-cache\r\n"
01338 "Host: people.netscape.com\r\n"
01339 "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"
01340 "X-1: blah\r\n"
01341 "X-2: blah\r\n"
01342 "X-3: blah\r\n"
01343 "X-4: blah\r\n"
01344 "X-5: blah\r\n"
01345 "X-6: blah\r\n"
01346 "X-7: blah\r\n"
01347 "X-8: blah\r\n"
01348 "X-9: blah\r\n"
01349 "Pragma: no-cache\r\n"
01350 "X-X-1: blah\r\n"
01351 "X-X-2: blah\r\n"
01352 "X-X-3: blah\r\n"
01353 "X-X-4: blah\r\n" "X-X-5: blah\r\n" "X-X-6: blah\r\n" "X-X-7: blah\r\n" "X-X-8: blah\r\n" "X-X-9: blah\r\n" "\r\n"
01354 };
01355
01356 static const char request_leading_space[] = {
01357 " GET http://www.news.com:80/ HTTP/1.0\r\n"
01358 "Proxy-Connection: Keep-Alive\r\n" "User-Agent: Mozilla/4.04 [en] (X11; I; Linux 2.0.33 i586)\r\n" "\r\n"
01359 };
01360
01361 static const char request_padding[] = {
01362 "GET http://www.padding.com:80/ HTTP/1.0\r\n" "X-1: blah1\r\n"
01363
01364 "X-3: blah3\r\n"
01365
01366 "X-5: blah5\r\n"
01367
01368 "X-7: blah7\r\n"
01369
01370 "X-9: blah9\r\n" "\r\n"
01371 };
01372
01373 static const char request_09p[] = {
01374 "GET http://www.news09.com/\r\n" "\r\n"
01375 };
01376
01377 static const char request_09ht[] = {
01378 "GET http://www.news09.com/ HT\r\n" "\r\n"
01379 };
01380
01381 static const char request_11[] = {
01382 "GET http://www.news.com/ HTTP/1.1\r\n" "Connection: close\r\n" "\r\n"
01383 };
01384
01385 static const char request_unterminated[] = {
01386 "GET http://www.unterminated.com/ HTTP/1.1"
01387 };
01388
01389 static const char request_blank[] = {
01390 "\r\n"
01391 };
01392
01393 static const char request_blank2[] = {
01394 "\r\n" "\r\n"
01395 };
01396
01397 static const char request_blank3[] = {
01398 " " "\r\n"
01399 };
01400
01401
01402
01403 static const char response0[] = {
01404 "HTTP/1.0 200 OK\r\n"
01405 "MIME-Version: 1.0\r\n"
01406 "Server: WebSTAR/2.1 ID/30013\r\n"
01407 "Content-Type: text/html\r\n"
01408 "Content-Length: 939\r\n" "Last-Modified: Thursday, 01-Jan-04 05:00:00 GMT\r\n" "\r\n"
01409 };
01410
01411 static const char response1[] = {
01412 "HTTP/1.0 200 OK\r\n"
01413 "Server: Netscape-Communications/1.12\r\n"
01414 "Date: Tuesday, 08-Dec-98 20:32:17 GMT\r\n" "Content-Type: text/html\r\n" "\r\n"
01415 };
01416
01417 static const char response_no_colon[] = {
01418 "HTTP/1.0 200 OK\r\n"
01419 "Server Netscape-Communications/1.12\r\n"
01420 "Date: Tuesday, 08-Dec-98 20:32:17 GMT\r\n" "Content-Type: text/html\r\n" "\r\n"
01421 };
01422
01423 static const char response_unterminated[] = {
01424 "HTTP/1.0 200 OK"
01425 };
01426
01427 static const char response09[] = {
01428 ""
01429 };
01430
01431 static const char response_blank[] = {
01432 "\r\n"
01433 };
01434
01435 static const char response_blank2[] = {
01436 "\r\n" "\r\n"
01437 };
01438
01439 static const char response_blank3[] = {
01440 " " "\r\n"
01441 };
01442
01443 status = status & test_http_aux(request0, response0);
01444 status = status & test_http_aux(request09, response09);
01445 status = status & test_http_aux(request1, response1);
01446 status = status & test_http_aux(request_no_colon, response_no_colon);
01447 status = status & test_http_aux(request_no_val, response_no_colon);
01448 status = status & test_http_aux(request_leading_space, response0);
01449 status = status & test_http_aux(request_multi_fblock, response0);
01450 status = status & test_http_aux(request_padding, response0);
01451 status = status & test_http_aux(request_09p, response0);
01452 status = status & test_http_aux(request_09ht, response0);
01453 status = status & test_http_aux(request_11, response0);
01454 status = status & test_http_aux(request_unterminated, response_unterminated);
01455 status = status & test_http_aux(request_blank, response_blank);
01456 status = status & test_http_aux(request_blank2, response_blank2);
01457 status = status & test_http_aux(request_blank3, response_blank3);
01458
01459 return (failures_to_status("test_http", (status == 0)));
01460 }
01461
01462
01463
01464
01465 int
01466 HdrTest::test_http_mutation()
01467 {
01468 int status = 1;
01469
01470 bri_box("test_http_mutation");
01471
01472 printf(" <<< MUST BE HAND-VERIFIED FOR FULL BENEFIT>>>\n\n");
01473
01474 HTTPHdr resp_hdr;
01475 int err, i;
01476 HTTPParser parser;
01477 const char base_resp[] = "HTTP/1.0 200 OK\r\n\r\n";
01478 const char *start, *end;
01479
01480
01481
01482 start = base_resp;
01483 end = start + strlen(start);
01484
01485 http_parser_init(&parser);
01486
01487 resp_hdr.create(HTTP_TYPE_RESPONSE);
01488
01489 while (1) {
01490 err = resp_hdr.parse_resp(&parser, &start, end, true);
01491 if (err != PARSE_CONT)
01492 break;
01493 }
01494
01495 printf("\n======== before mutation ==========\n\n");
01496 printf("\n[");
01497 resp_hdr.print(NULL, 0, NULL, NULL);
01498 printf("]\n\n");
01499
01500
01501 char field_name[1024];
01502 char field_value[1024];
01503 for (i = 1; i <= 100; i++) {
01504 snprintf(field_name, sizeof(field_name), "Test%d", i);
01505 snprintf(field_value, sizeof(field_value), "%d %d %d %d %d", i, i, i, i, i);
01506 resp_hdr.value_set(field_name, (int) strlen(field_name), field_value, (int) strlen(field_value));
01507 }
01508
01509
01510 for (i = 2; i <= 100; i += 2) {
01511 snprintf(field_name, sizeof(field_name), "Test%d", i);
01512 resp_hdr.field_delete(field_name, (int) strlen(field_name));
01513 }
01514
01515
01516 for (i = 3; i <= 100; i += 3) {
01517 snprintf(field_name, sizeof(field_name), "Test%d", i);
01518 MIMEField *f = resp_hdr.field_create(field_name, (int) strlen(field_name));
01519 resp_hdr.field_attach(f);
01520 snprintf(field_value, sizeof(field_value), "d %d %d %d %d %d", i, i, i, i, i);
01521 f->value_set(resp_hdr.m_heap, resp_hdr.m_mime, field_value, (int) strlen(field_value));
01522
01523 }
01524
01525
01526 for (i = 5; i <= 100; i += 5) {
01527 snprintf(field_name, sizeof(field_name), "Test%d", i);
01528 snprintf(field_value, sizeof(field_value), "a %d", i);
01529
01530 resp_hdr.value_append(field_name, (int) strlen(field_name), field_value, (int) strlen(field_value), true);
01531 }
01532
01533
01534 for (i = 9; i <= 100; i += 9) {
01535 snprintf(field_name, sizeof(field_name), "Test%d", i);
01536 resp_hdr.field_delete(field_name, (int) strlen(field_name));
01537 }
01538
01539
01540 printf("\n======== mutated response ==========\n\n");
01541 printf("\n[");
01542 resp_hdr.print(NULL, 0, NULL, NULL);
01543 printf("]\n\n");
01544
01545 resp_hdr.destroy();
01546
01547 return (failures_to_status("test_http_mutation", (status == 0)));
01548 }
01549
01550
01551
01552
01553 int
01554 HdrTest::test_arena_aux(Arena * arena, int len)
01555 {
01556 char *str = arena->str_alloc(len);
01557 int verify_len = (int) arena->str_length(str);
01558
01559 if (len != verify_len) {
01560 printf("FAILED: requested %d, got %d bytes\n", len, verify_len);
01561 return (1);
01562 } else {
01563 return (0);
01564 }
01565 }
01566
01567
01568
01569
01570 int
01571 HdrTest::test_arena()
01572 {
01573 bri_box("test_arena");
01574
01575 Arena *arena;
01576 int failures = 0;
01577
01578 arena = new Arena;
01579
01580 failures += test_arena_aux(arena, 1);
01581 failures += test_arena_aux(arena, 127);
01582 failures += test_arena_aux(arena, 128);
01583 failures += test_arena_aux(arena, 129);
01584 failures += test_arena_aux(arena, 255);
01585 failures += test_arena_aux(arena, 256);
01586 failures += test_arena_aux(arena, 16384);
01587 failures += test_arena_aux(arena, 16385);
01588 failures += test_arena_aux(arena, 16511);
01589 failures += test_arena_aux(arena, 16512);
01590 failures += test_arena_aux(arena, 2097152);
01591 failures += test_arena_aux(arena, 2097153);
01592 failures += test_arena_aux(arena, 2097279);
01593 failures += test_arena_aux(arena, 2097280);
01594
01595 delete arena;
01596
01597 return (failures_to_status("test_arena", failures));
01598 }
01599
01600
01601
01602
01603 int
01604 HdrTest::test_regex()
01605 {
01606 DFA dfa;
01607 int status = 1;
01608
01609 const char *test_harness[] = {
01610 "foo",
01611 "(.*\\.apache\\.org)",
01612 "(.*\\.example\\.com)"
01613 };
01614
01615 bri_box("test_regex");
01616
01617 dfa.compile(test_harness,SIZEOF(test_harness));
01618 status = status & (dfa.match("trafficserver.apache.org") == 1);
01619 status = status & (dfa.match("www.example.com") == 2);
01620 status = status & (dfa.match("aaaaaafooooooooinktomi....com.org") == -1);
01621 status = status & (dfa.match("foo") == 0);
01622
01623 return (failures_to_status("test_regex", (status != 1)));
01624 }
01625
01626
01627
01628
01629 int
01630 HdrTest::test_accept_language_match()
01631 {
01632 bri_box("test_accept_language_match");
01633
01634 struct
01635 {
01636 const char *content_language;
01637 const char *accept_language;
01638 float Q;
01639 int L;
01640 int I;
01641 } test_cases[] = {
01642 {
01643 "en", "*", 1.0, 1, 1}, {
01644 "en", "fr", 0.0, 0, 0}, {
01645 "en", "de, fr, en;q=0.7", 0.7, 2, 3}, {
01646 "en-cockney", "de, fr, en;q=0.7", 0.7, 2, 3}, {
01647 "en-cockney", "de, fr, en-foobar;q=0.8, en;q=0.7", 0.7, 2, 4}, {
01648 "en-cockney", "de, fr, en-cockney;q=0.8, en;q=0.7", 0.8, 10, 3}, {
01649 "en-cockney", "de, fr, en;q=0.8, en;q=0.7", 0.8, 2, 3}, {
01650 "en-cockney", "de, fr, en;q=0.7, en;q=0.8", 0.8, 2, 4}, {
01651 "en-cockney", "de, fr, en;q=0.8, en;q=0.8", 0.8, 2, 3}, {
01652 "en-cockney", "de, fr, en-cockney;q=0.7, en;q=0.8", 0.7, 10, 3}, {
01653 "en-cockney", "de, fr, en;q=0.8, en-cockney;q=0.7", 0.7, 10, 4}, {
01654 "en-cockney", "de, fr, en-cockney;q=0.8, en;q=0.8", 0.8, 10, 3}, {
01655 "en-cockney", "de, fr, en-cockney;q=0.8, en;q=0.7", 0.8, 10, 3}, {
01656 "en-cockney", "de, fr, en-american", 0.0, 0, 0}, {
01657 "en-cockney", "de, fr, en;q=0.8, en;q=0.8, *", 0.8, 2, 3}, {
01658 "en-cockney", "de, fr, en;q=0.8, en;q=0.8, *;q=0.9", 0.8, 2, 3}, {
01659 "en-foobar", "de, fr, en;q=0.8, en;q=0.8, *;q=0.9", 0.8, 2, 3}, {
01660 "oo-foobar", "de, fr, en;q=0.8, en;q=0.8, *;q=0.9", 0.9, 1, 5}, {
01661 "oo-foobar", "de, fr, en;q=0.8, en;q=0.8, *;q=0.9, *", 1.0, 1, 6}, {
01662 "oo-foobar", "de, fr, en;q=0.8, en;q=0.8, *, *;q=0.9", 1.0, 1, 5}, {
01663 "fr-belgian", "de, fr;hi-there;q=0.9, fr;q=0.8, en", 0.9, 2, 2}, {
01664 "fr-belgian", "de, fr;q=0.8, fr;hi-there;q=0.9, en", 0.9, 2, 3}, {
01665 NULL, NULL, 0.0}
01666 };
01667
01668 int i, I, L;
01669 float Q;
01670 int failures = 0;
01671
01672 for (i = 0; test_cases[i].accept_language; i++) {
01673 StrList acpt_lang_list(false);
01674 HttpCompat::parse_comma_list(&acpt_lang_list, test_cases[i].accept_language,
01675 (int) strlen(test_cases[i].accept_language));
01676
01677 Q = HttpCompat::match_accept_language(test_cases[i].content_language,
01678 (int) strlen(test_cases[i].content_language), &acpt_lang_list, &L, &I);
01679
01680 if ((Q != test_cases[i].Q) || (L != test_cases[i].L) || (I != test_cases[i].I)) {
01681 printf
01682 ("FAILED: (#%d) got { Q = %.3f; L = %d; I = %d; }, expected { Q = %.3f; L = %d; I = %d; }, from matching\n '%s' against '%s'\n",
01683 i, Q, L, I, test_cases[i].Q, test_cases[i].L, test_cases[i].I, test_cases[i].content_language,
01684 test_cases[i].accept_language);
01685 ++failures;
01686 }
01687 }
01688
01689 return (failures_to_status("test_accept_language_match", failures));
01690 }
01691
01692
01693
01694
01695
01696 int
01697 HdrTest::test_accept_charset_match()
01698 {
01699 bri_box("test_accept_charset_match");
01700
01701 struct
01702 {
01703 const char *content_charset;
01704 const char *accept_charset;
01705 float Q;
01706 int I;
01707 } test_cases[] = {
01708 {
01709 "iso-8859-1", "*", 1.0, 1}, {
01710 "iso-8859-1", "iso-8859-2", 0.0, 0}, {
01711 "iso-8859-1", "iso-8859", 0.0, 0}, {
01712 "iso-8859-1", "iso-8859-12", 0.0, 0}, {
01713 "iso-8859-1", "koi-8-r", 0.0, 0}, {
01714 "euc-jp", "shift_jis, iso-2022-jp, euc-jp;q=0.7", 0.7, 3}, {
01715 "euc-jp", "shift_jis, iso-2022-jp, euc-jp;q=0.7", 0.7, 3}, {
01716 "euc-jp", "shift_jis, iso-2022-jp, euc-jp;q=0.8, euc-jp;q=0.7", 0.8, 3}, {
01717 "euc-jp", "shift_jis, iso-2022-jp, euc-jp;q=0.7, euc-jp;q=0.8", 0.8, 4}, {
01718 "euc-jp", "euc-jp;q=0.9, shift_jis, iso-2022-jp, euc-jp;q=0.7, euc-jp;q=0.8", 0.9, 1}, {
01719 "EUC-JP", "euc-jp;q=0.9, shift_jis, iso-2022-jp, euc-jp, euc-jp;q=0.8", 1.0, 4}, {
01720 "euc-jp", "euc-jp;q=0.9, shift_jis, iso-2022-jp, EUC-JP, euc-jp;q=0.8", 1.0, 4}, {
01721 "euc-jp", "shift_jis, iso-2022-jp, euc-jp-foobar", 0.0, 0}, {
01722 "euc-jp", "shift_jis, iso-2022-jp, euc-jp-foobar, *", 1.0, 4}, {
01723 "euc-jp", "shift_jis, iso-2022-jp, euc-jp-foobar, *;q=0.543", 0.543, 4}, {
01724 "euc-jp", "shift_jis, iso-2022-jp, euc-jp-foobar, *;q=0.0", 0.0, 4}, {
01725 "euc-jp", "shift_jis, iso-2022-jp, *;q=0.0, euc-jp-foobar, *;q=0.0", 0.0, 3}, {
01726 "euc-jp", "shift_jis, iso-2022-jp, *;q=0.0, euc-jp-foobar, *;q=0.5", 0.5, 5}, {
01727 "euc-jp", "shift_jis, iso-2022-jp, *;q=0.5, euc-jp-foobar, *;q=0.0", 0.5, 3}, {
01728 "euc-jp", "shift_jis, iso-2022-jp, *;q=0.5, euc-jp-foobar, *, *;q=0.0", 1.0, 5}, {
01729 "euc-jp", "shift_jis, euc-jp;hi-there;q=0.5, iso-2022-jp", 0.5, 2}, {
01730 "euc-jp", "shift_jis, euc-jp;hi-there;q= 0.5, iso-2022-jp", 0.5, 2}, {
01731 "euc-jp", "shift_jis, euc-jp;hi-there;q = 0.5, iso-2022-jp", 0.5, 2}, {
01732 "euc-jp", "shift_jis, euc-jp;hi-there ; q = 0.5, iso-2022-jp", 0.5, 2}, {
01733 "euc-jp", "shift_jis, euc-jp;hi-there ;; q = 0.5, iso-2022-jp", 0.5, 2}, {
01734 "euc-jp", "shift_jis, euc-jp;hi-there ;; Q = 0.5, iso-2022-jp", 0.5, 2}, {
01735 NULL, NULL, 0.0, 0}
01736 };
01737
01738 int i, I;
01739 float Q;
01740 int failures = 0;
01741
01742 for (i = 0; test_cases[i].accept_charset; i++) {
01743 StrList acpt_lang_list(false);
01744 HttpCompat::parse_comma_list(&acpt_lang_list, test_cases[i].accept_charset,
01745 (int) strlen(test_cases[i].accept_charset));
01746
01747 Q = HttpCompat::match_accept_charset(test_cases[i].content_charset,
01748 (int) strlen(test_cases[i].content_charset), &acpt_lang_list, &I);
01749
01750 if ((Q != test_cases[i].Q) || (I != test_cases[i].I)) {
01751 printf
01752 ("FAILED: (#%d) got { Q = %.3f; I = %d; }, expected { Q = %.3f; I = %d; }, from matching\n '%s' against '%s'\n",
01753 i, Q, I, test_cases[i].Q, test_cases[i].I, test_cases[i].content_charset, test_cases[i].accept_charset);
01754 ++failures;
01755 }
01756 }
01757
01758 return (failures_to_status("test_accept_charset_match", failures));
01759 }
01760
01761
01762
01763
01764 int
01765 HdrTest::test_comma_vals()
01766 {
01767 static struct
01768 {
01769 const char *value;
01770 int value_count;
01771 struct
01772 {
01773 int offset;
01774 int len;
01775 } pieces[4];
01776 } tests[] = {
01777 {
01778 ",", 2, { {
01779 0, 0}, {
01780 1, 0}, {
01781 -1, 0}, {
01782 -1, 0}}}, {
01783 "", 1, { {
01784 0, 0}, {
01785 -1, 0}, {
01786 -1, 0}, {
01787 -1, 0}}}, {
01788 " ", 1, { {
01789 0, 0}, {
01790 -1, 0}, {
01791 -1, 0}, {
01792 -1, 0}}}, {
01793 ", ", 2, { {
01794 0, 0}, {
01795 1, 0}, {
01796 -1, 0}, {
01797 -1, 0}}}, {
01798 ",,", 3, { {
01799 0, 0}, {
01800 1, 0}, {
01801 2, 0}, {
01802 -1, 0}}}, {
01803 " ,", 2, { {
01804 0, 0}, {
01805 2, 0}, {
01806 -1, 0}, {
01807 -1, 0}}}, {
01808 " , ", 2, { {
01809 0, 0}, {
01810 2, 0}, {
01811 -1, 0}, {
01812 -1, 0}}}, {
01813 "a, ", 2, { {
01814 0, 1}, {
01815 2, 0}, {
01816 -1, 0}, {
01817 -1, 0}}}, {
01818 " a, ", 2, { {
01819 1, 1}, {
01820 3, 0}, {
01821 -1, 0}, {
01822 -1, 0}}}, {
01823 " ,a", 2, { {
01824 0, 0}, {
01825 2, 1}, {
01826 -1, 0}, {
01827 -1, 0}}}, {
01828 " , a", 2, { {
01829 0, 0}, {
01830 3, 1}, {
01831 -1, 0}, {
01832 -1, 0}}}, {
01833 "a,a", 2, { {
01834 0, 1}, {
01835 2, 1}, {
01836 -1, 0}, {
01837 -1, 0}}}, {
01838 "foo", 1, { {
01839 0, 3}, {
01840 -1, 0}, {
01841 -1, 0}, {
01842 -1, 0}}}, {
01843 "foo,", 2, { {
01844 0, 3}, {
01845 4, 0}, {
01846 -1, 0}, {
01847 -1, 0}}}, {
01848 "foo, ", 2, { {
01849 0, 3}, {
01850 4, 0}, {
01851 -1, 0}, {
01852 -1, 0}}}, {
01853 "foo, bar", 2, { {
01854 0, 3}, {
01855 5, 3}, {
01856 -1, 0}, {
01857 -1, 0}}}, {
01858 "foo, bar,", 3, { {
01859 0, 3}, {
01860 5, 3}, {
01861 9, 0}, {
01862 -1, 0}}}, {
01863 "foo, bar, ", 3, { {
01864 0, 3}, {
01865 5, 3}, {
01866 9, 0}, {
01867 -1, 0}}}, {
01868 ",foo,bar,", 4, { {
01869 0, 0}, {
01870 1, 3}, {
01871 5, 3}, {
01872 9, 0}}}
01873 };
01874
01875 bri_box("test_comma_vals");
01876
01877 HTTPHdr hdr;
01878 char field_name[32];
01879 int i, j, len, failures, ntests, ncommavals;
01880
01881 failures = 0;
01882 ntests = sizeof(tests) / sizeof(tests[0]);
01883
01884 hdr.create(HTTP_TYPE_REQUEST);
01885
01886 for (i = 0; i < ntests; i++) {
01887 snprintf(field_name, sizeof(field_name), "Test%d", i);
01888
01889 MIMEField *f = hdr.field_create(field_name, (int) strlen(field_name));
01890 ink_release_assert(f->m_ptr_value == NULL);
01891
01892 hdr.field_attach(f);
01893 ink_release_assert(f->m_ptr_value == NULL);
01894
01895 hdr.field_value_set(f, tests[i].value, strlen(tests[i].value));
01896 ink_release_assert(f->m_ptr_value != tests[i].value);
01897 ink_release_assert(f->m_len_value == strlen(tests[i].value));
01898 ink_release_assert(memcmp(f->m_ptr_value, tests[i].value, f->m_len_value) == 0);
01899
01900 ncommavals = mime_field_value_get_comma_val_count(f);
01901 if (ncommavals != tests[i].value_count) {
01902 ++failures;
01903 printf("FAILED: test #%d (field value '%s') expected val count %d, got %d\n",
01904 i + 1, tests[i].value, tests[i].value_count, ncommavals);
01905 }
01906
01907 for (j = 0; j < tests[i].value_count; j++) {
01908 const char *val = mime_field_value_get_comma_val(f, &len, j);
01909 int offset = ((val == NULL) ? -1 : (val - f->m_ptr_value));
01910
01911 if ((offset != tests[i].pieces[j].offset) || (len != tests[i].pieces[j].len)) {
01912 ++failures;
01913 printf
01914 ("FAILED: test #%d (field value '%s', commaval idx %d) expected [offset %d, len %d], got [offset %d, len %d]\n",
01915 i + 1, tests[i].value, j, tests[i].pieces[j].offset, tests[i].pieces[j].len, offset, len);
01916 }
01917 }
01918 }
01919
01920 hdr.destroy();
01921 return (failures_to_status("test_comma_vals", failures));
01922 }
01923
01924
01925
01926
01927 int
01928 HdrTest::test_set_comma_vals()
01929 {
01930 static struct
01931 {
01932 const char *old_raw;
01933 int idx;
01934 const char *slice;
01935 const char *new_raw;
01936 } tests[] = {
01937 {
01938 "a,b,c", 0, "fred", "fred, b, c"}, {
01939 "a,b,c", 1, "fred", "a, fred, c"}, {
01940 "a,b,c", 2, "fred", "a, b, fred"}, {
01941 "a,b,c", 3, "fred", "a,b,c"}, {
01942 "", 0, "", ""}, {
01943 "", 0, "foo", "foo"}, {
01944 "", 1, "foo", ""}, {
01945 " ", 0, "", ""}, {
01946 " ", 0, "foo", "foo"}, {
01947 " ", 1, "foo", " "}, {
01948 ",", 0, "foo", "foo, "}, {
01949 ",", 1, "foo", ", foo"}, {
01950 ",,", 0, "foo", "foo, , "}, {
01951 ",,", 1, "foo", ", foo, "}, {
01952 ",,", 2, "foo", ", , foo"}, {
01953 "foo", 0, "abc", "abc"}, {
01954 "foo", 1, "abc", "foo"}, {
01955 "foo", 0, "abc,", "abc,"}, {
01956 "foo", 0, ",abc", ",abc"}, {
01957 ",,", 1, ",,,", ", ,,,, "}, {
01958 " a , b , c", 0, "fred", "fred, b, c"}, {
01959 " a , b , c", 1, "fred", "a, fred, c"}, {
01960 " a , b , c", 2, "fred", "a, b, fred"}, {
01961 " a , b , c", 3, "fred", " a , b , c"}, {
01962 " a , b ", 0, "fred", "fred, b"}, {
01963 " a , b ", 1, "fred", "a, fred"}, {
01964 " a , b ", 1, "fred", "a, fred"}, {
01965 " a ,b ", 1, "fred", "a, fred"}, {
01966 "a, , , , e, , g,", 0, "fred", "fred, , , , e, , g, "}, {
01967 "a, , , , e, , g,", 1, "fred", "a, fred, , , e, , g, "}, {
01968 "a, , , , e, , g,", 2, "fred", "a, , fred, , e, , g, "}, {
01969 "a, , , , e, , g,", 5, "fred", "a, , , , e, fred, g, "}, {
01970 "a, , , , e, , g,", 7, "fred", "a, , , , e, , g, fred"}, {
01971 "a, , , , e, , g,", 8, "fred", "a, , , , e, , g,"}, {
01972 "a, \"boo,foo\", c", 0, "wawa", "wawa, \"boo,foo\", c"}, {
01973 "a, \"boo,foo\", c", 1, "wawa", "a, wawa, c"}, {
01974 "a, \"boo,foo\", c", 2, "wawa", "a, \"boo,foo\", wawa"},};
01975
01976 bri_box("test_set_comma_vals");
01977
01978 HTTPHdr hdr;
01979 char field_name[32];
01980 int i, failures, ntests;
01981
01982 failures = 0;
01983 ntests = sizeof(tests) / sizeof(tests[0]);
01984
01985 hdr.create(HTTP_TYPE_REQUEST);
01986
01987 for (i = 0; i < ntests; i++) {
01988 snprintf(field_name, sizeof(field_name), "Test%d", i);
01989
01990 MIMEField *f = hdr.field_create(field_name, (int) strlen(field_name));
01991 hdr.field_value_set(f, tests[i].old_raw, strlen(tests[i].old_raw));
01992 mime_field_value_set_comma_val(hdr.m_heap, hdr.m_mime, f, tests[i].idx, tests[i].slice, strlen(tests[i].slice));
01993 ink_release_assert(f->m_ptr_value != NULL);
01994
01995 if ((f->m_len_value != strlen(tests[i].new_raw)) || (memcmp(f->m_ptr_value, tests[i].new_raw, f->m_len_value) != 0)) {
01996 ++failures;
01997 printf("FAILED: test #%d (setting idx %d of '%s' to '%s') expected '%s' len %d, got '%.*s' len %d\n",
01998 i + 1, tests[i].idx, tests[i].old_raw, tests[i].slice,
01999 tests[i].new_raw, (int)strlen(tests[i].new_raw), f->m_len_value, f->m_ptr_value, f->m_len_value);
02000 }
02001 }
02002
02003 hdr.destroy();
02004 return (failures_to_status("test_set_comma_vals", failures));
02005 }
02006
02007
02008
02009
02010 int
02011 HdrTest::test_delete_comma_vals()
02012 {
02013 bri_box("test_delete_comma_vals");
02014 rprintf(rtest, " HdrTest test_delete_comma_vals: TEST NOT IMPLEMENTED\n");
02015 return (1);
02016 }
02017
02018
02019
02020
02021 int
02022 HdrTest::test_extend_comma_vals()
02023 {
02024 bri_box("test_extend_comma_vals");
02025 rprintf(rtest, " HdrTest test_extend_comma_vals: TEST NOT IMPLEMENTED\n");
02026 return (1);
02027 }
02028
02029
02030
02031
02032 int
02033 HdrTest::test_insert_comma_vals()
02034 {
02035 bri_box("test_insert_comma_vals");
02036 rprintf(rtest, " HdrTest test_insert_comma_vals: TEST NOT IMPLEMENTED\n");
02037 return (1);
02038 }
02039
02040
02041
02042
02043 int
02044 HdrTest::test_parse_comma_list()
02045 {
02046 static struct
02047 {
02048 const char *value;
02049 int count;
02050 struct
02051 {
02052 int offset;
02053 int len;
02054 } pieces[3];
02055 } tests[] = {
02056 {
02057 "", 1, { {
02058 0, 0}, {
02059 -1, 0}, {
02060 -1, 0}}}, {
02061 ",", 2, { {
02062 0, 0}, {
02063 1, 0}, {
02064 -1, 0}}}, {
02065 " ,", 2, { {
02066 0, 0}, {
02067 2, 0}, {
02068 -1, 0}}}, {
02069 ", ", 2, { {
02070 0, 0}, {
02071 1, 0}, {
02072 -1, 0}}}, {
02073 " , ", 2, { {
02074 0, 0}, {
02075 2, 0}, {
02076 -1, 0}}}, {
02077 "abc,", 2, { {
02078 0, 3}, {
02079 4, 0}, {
02080 -1, 0}}}, {
02081 "abc, ", 2, { {
02082 0, 3}, {
02083 4, 0}, {
02084 -1, 0}}}, {
02085 "", 1, { {
02086 0, 0}, {
02087 -1, 0}, {
02088 -1, 0}}}, {
02089 " ", 1, { {
02090 0, 0}, {
02091 -1, 0}, {
02092 -1, 0}}}, {
02093 " ", 1, { {
02094 0, 0}, {
02095 -1, 0}, {
02096 -1, 0}}}, {
02097 "a", 1, { {
02098 0, 1}, {
02099 -1, 0}, {
02100 -1, 0}}}, {
02101 " a", 1, { {
02102 1, 1}, {
02103 -1, 0}, {
02104 -1, 0}}}, {
02105 " a ", 1, { {
02106 2, 1}, {
02107 -1, 0}, {
02108 -1, 0}}}, {
02109 "abc,defg", 2, { {
02110 0, 3}, {
02111 4, 4}, {
02112 -1, 0}}}, {
02113 " abc,defg", 2, { {
02114 1, 3}, {
02115 5, 4}, {
02116 -1, 0}}}, {
02117 " abc, defg", 2, { {
02118 1, 3}, {
02119 6, 4}, {
02120 -1, 0}}}, {
02121 " abc , defg", 2, { {
02122 1, 3}, {
02123 7, 4}, {
02124 -1, 0}}}, {
02125 " abc , defg ", 2, { {
02126 1, 3}, {
02127 7, 4}, {
02128 -1, 0}}}, {
02129 " abc , defg, ", 3, { {
02130 1, 3}, {
02131 7, 4}, {
02132 12, 0}}}, {
02133 " abc , defg ,", 3, { {
02134 1, 3}, {
02135 7, 4}, {
02136 13, 0}}}, {
02137 ", abc , defg ", 3, { {
02138 0, 0}, {
02139 2, 3}, {
02140 8, 4}}}, {
02141 " ,abc , defg ", 3, { {
02142 0, 0}, {
02143 2, 3}, {
02144 8, 4}}}, {
02145 "a,b", 2, { {
02146 0, 1}, {
02147 2, 1}, {
02148 -1, 0}}}, {
02149 "a,,b", 3, { {
02150 0, 1}, {
02151 2, 0}, {
02152 3, 1}}}, {
02153 "a, ,b", 3, { {
02154 0, 1}, {
02155 2, 0}, {
02156 4, 1}}}, {
02157 "a ,,b", 3, { {
02158 0, 1}, {
02159 3, 0}, {
02160 4, 1}}}, {
02161 ",", 2, { {
02162 0, 0}, {
02163 1, 0}, {
02164 -1, 0}}}, {
02165 " ,", 2, { {
02166 0, 0}, {
02167 2, 0}, {
02168 -1, 0}}}, {
02169 ", ", 2, { {
02170 0, 0}, {
02171 1, 0}, {
02172 -1, 0}}}, {
02173 " , ", 2, { {
02174 0, 0}, {
02175 2, 0}, {
02176 -1, 0}}}, {
02177 "a,b,", 3, { {
02178 0, 1}, {
02179 2, 1}, {
02180 4, 0}}}, {
02181 "a,b, ", 3, { {
02182 0, 1}, {
02183 2, 1}, {
02184 4, 0}}}, {
02185 "a,b, ", 3, { {
02186 0, 1}, {
02187 2, 1}, {
02188 4, 0}}}, {
02189 "a,b, c", 3, { {
02190 0, 1}, {
02191 2, 1}, {
02192 6, 1}}}, {
02193 "a,b, c ", 3, { {
02194 0, 1}, {
02195 2, 1}, {
02196 6, 1}}}, {
02197 "a,\"b,c\",d", 3, { {
02198 0, 1}, {
02199 3, 3}, {
02200 8, 1}}}
02201 };
02202
02203 bri_box("test_parse_comma_list");
02204
02205 int i, j, failures, ntests, offset;
02206
02207 failures = (offset = 0);
02208 ntests = sizeof(tests) / sizeof(tests[0]);
02209
02210 for (i = 0; i < ntests; i++) {
02211 StrList list(false);
02212 HttpCompat::parse_comma_list(&list, tests[i].value);
02213 if (list.count != tests[i].count) {
02214 ++failures;
02215 printf("FAILED: test #%d (string '%s') expected list count %d, got %d\n",
02216 i + 1, tests[i].value, tests[i].count, list.count);
02217 }
02218
02219 for (j = 0; j < tests[i].count; j++) {
02220 Str *cell = list.get_idx(j);
02221 if (cell != NULL)
02222 offset = cell->str - tests[i].value;
02223
02224 if (tests[i].pieces[j].offset == -1)
02225 {
02226 if (cell != NULL) {
02227 ++failures;
02228 printf("FAILED: test #%d (string '%s', idx %d) expected NULL piece, got [offset %d len %d]\n",
02229 i + 1, tests[i].value, j, offset, (int)cell->len);
02230 }
02231 } else
02232 {
02233 if (cell == NULL) {
02234 ++failures;
02235 printf("FAILED: test #%d (string '%s', idx %d) expected [offset %d len %d], got NULL piece\n",
02236 i + 1, tests[i].value, j, tests[i].pieces[j].offset, tests[i].pieces[j].len);
02237 } else if ((offset != tests[i].pieces[j].offset) || (cell->len != (size_t) tests[i].pieces[j].len)) {
02238 ++failures;
02239 printf("FAILED: test #%d (string '%s', idx %d) expected [offset %d len %d], got [offset %d len %d]\n",
02240 i + 1, tests[i].value, j, tests[i].pieces[j].offset, tests[i].pieces[j].len, offset, (int)cell->len);
02241 }
02242 }
02243 }
02244 }
02245
02246 return (failures_to_status("test_parse_comma_list", failures));
02247 }
02248
02249
02250
02251
02252 void
02253 HdrTest::bri_box(const char *s)
02254 {
02255 int i, len;
02256
02257 len = (int) strlen(s);
02258 printf("\n+-");
02259 for (i = 0; i < len; i++)
02260 putchar('-');
02261 printf("-+\n");
02262 printf("| %s |\n", s);
02263 printf("+-");
02264 for (i = 0; i < len; i++)
02265 putchar('-');
02266 printf("-+\n\n");
02267 }
02268
02269
02270
02271
02272 int
02273 HdrTest::failures_to_status(const char *testname, int nfail)
02274 {
02275 rprintf(rtest, " HdrTest %s: %s\n", testname, ((nfail > 0) ? "FAILED" : "PASSED"));
02276 return ((nfail > 0) ? 0 : 1);
02277 }
02278