00001 // $Id: fast__test_8c-example.html,v 1.2 2006/02/09 19:12:40 Daniel.May Exp $ 00002 // The fast_test utility is a unit testing facility to assist in verifying a fast implementation on different 00003 // target platforms. It performs a variety of tests on the core fastapi functions. 00004 // 00005 // Copyright (c), Pantor Engineering AB, 2005 00006 // All rights reserved. 00007 00013 #include <signal.h> 00014 #include <setjmp.h> 00015 00016 #include "fastapi.h" 00017 00018 static fast_codec_t* decoder = NULL; 00019 static fast_codec_t* encoder = NULL; 00020 00021 static int curr_id = 0; 00022 static int curr_mode = 0; 00023 static int curr_code = 0; 00024 00025 static const char* curr_text = NULL; 00026 00027 static int execed_count = 0; 00028 static int failed_count = 0; 00029 static int passed_count = 0; 00030 00031 #define MAKE_I32_TAG(o,t,s) MAKE_TAG (FAST_TYPE_I32, o, t, s) 00032 #define MAKE_STR_TAG(o,t,s) MAKE_TAG (FAST_TYPE_STR, o, t, s) 00033 #define MAKE_U32_TAG(o,t,s) MAKE_TAG (FAST_TYPE_U32, o, t, s) 00034 00036 00037 static void cleanup (void) 00038 { 00039 if (decoder != NULL && decoder->magic == FAST_CODEC_MAGIC) 00040 { 00041 fast_destroy_codec (decoder); 00042 decoder = NULL; 00043 } 00044 00045 if (encoder != NULL && encoder->magic == FAST_CODEC_MAGIC) 00046 { 00047 fast_destroy_codec (encoder); 00048 encoder = NULL; 00049 } 00050 } 00051 00052 static void started (void) 00053 { 00054 fprintf (stderr, "%04d [started] '%s'\n", curr_id, curr_text); 00055 00056 execed_count ++; 00057 } 00058 00059 static int failed (void) 00060 { 00061 fprintf (stderr, "%04d [failed]\n\n", curr_id); 00062 cleanup (); 00063 00064 failed_count ++; 00065 return 0; 00066 } 00067 00068 static int passed (void) 00069 { 00070 fprintf (stderr, "%04d [passed]\n\n", curr_id); 00071 cleanup (); 00072 00073 passed_count ++; 00074 return 0; 00075 } 00076 00077 #define FAIL 0 00078 #define PASS 1 00079 00080 typedef int (*test_fn) (void); 00081 00082 static void execute (int id, int mode, test_fn fn, const char* text) 00083 { 00084 curr_id = id; 00085 curr_text = text; 00086 curr_mode = mode; 00087 curr_code = 0; 00088 00089 started (); 00090 (void) (fn () == 0 ? passed () : failed ()); 00091 } 00092 00093 static int expect (fast_codec_t* codec, fast_error_t error_code, int code) 00094 { 00095 if (codec == NULL || codec->magic != FAST_CODEC_MAGIC) 00096 { 00097 if (code == 0) 00098 { 00099 fprintf (stderr, " unexpected: NULL codec undetected\n"); 00100 return -1; 00101 } 00102 else if (error_code == FAST_ERR_CODEC) 00103 { 00104 fprintf (stderr, " expected: NULL codec\n"); 00105 return 0; 00106 } 00107 else 00108 { 00109 fprintf (stderr, " unexpected: NULL codec\n"); 00110 return -1; 00111 } 00112 } 00113 00114 if (error_code != FAST_ERR_NONE) 00115 { 00116 if (code == 0) 00117 { 00118 fprintf (stderr, " unexpected success\n"); 00119 return -1; 00120 } 00121 else 00122 { 00123 const char* text = fast_error_string (codec); 00124 00125 if (codec->error->code == error_code) 00126 { 00127 fprintf (stderr, " expected: %s\n", text); 00128 return 0; 00129 } 00130 else 00131 { 00132 fprintf (stderr, " unexpected: %s\n", text); 00133 return -1; 00134 } 00135 } 00136 } 00137 else if (code < 0) 00138 { 00139 fprintf (stderr, " unexpected: %s\n", 00140 fast_error_string (codec)); 00141 return -1; 00142 } 00143 return 0; 00144 } 00145 00147 00148 #if 0 00149 static void test_0001 (void) // Destroy without create 00150 { 00151 //_expect (encoder, FAST_ERR_CODEC, fast_destroy_codec (encoder)); 00152 } 00153 00154 static void test_0002 (void) // Call fast_destroy_codec twice 00155 { 00156 encoder = fast_create_codec (); 00157 00158 fast_destroy_codec (encoder); 00159 fast_destroy_codec (encoder); 00160 } 00161 #endif 00162 00164 00165 static void insert_into_buffer (fast_buffer_t* buffer, u8* data, int size) 00166 { 00167 assert (size <= buffer->end - buffer->tail); 00168 00169 memcpy (buffer->head, data, size); 00170 buffer->tail += size; 00171 } 00172 00173 static void copy_buffer (fast_buffer_t* source, fast_buffer_t* target) 00174 { 00175 int size = source->tail - source->head; 00176 00177 assert (size <= target->end - target->tail); 00178 00179 memcpy (target->tail, source->head, size); 00180 target->tail += size; 00181 } 00182 00183 static void dump_buffer (fast_buffer_t* b, const char* msg) 00184 { 00185 fprintf (stderr, " '%s' head=%d tail=%d used=%d\n", 00186 msg, b->head - b->data, b->tail - b->data, 00187 b->tail - b->head); 00188 } 00189 00191 00192 static int encode_decode_i32_none (void) 00193 { 00194 static i32 data [12] = 00195 { 00196 -65, -64, -3, -2, -1, 0, 1, 2, 3, 62, 63, 64 00197 }; 00198 00199 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_NONE, 0, 0); 00200 00201 i32 temp [12]; 00202 00203 int count = 12; 00204 int code; 00205 int p1; 00206 00207 encoder = fast_create_codec (); 00208 decoder = fast_create_codec (); 00209 00210 encoder->skip_io = 1; 00211 decoder->skip_io = 1; 00212 00213 // Start encoding a message 00214 if (expect (encoder, FAST_ERR_NONE, 00215 fast_encode_new_msg (encoder, tag)) < 0) 00216 return -1; 00217 00218 for (p1 = 0 ; p1 < count ; p1 ++) 00219 { 00220 code = fast_encode_i32 (encoder, tag, data [p1]); 00221 if (code < 0) break; 00222 } 00223 00224 if (p1 < count) 00225 return expect (encoder, FAST_ERR_NONE, -1); 00226 00227 // Message encoding done 00228 if (expect (encoder, FAST_ERR_NONE, 00229 fast_encode_end_msg (encoder, tag)) < 0) 00230 return -1; 00231 00232 // Copy encoder output to decoder input 00233 copy_buffer (encoder->output, decoder->input); 00234 00235 // Start decoding a message 00236 if (expect (decoder, FAST_ERR_NONE, 00237 fast_decode_new_msg (decoder, tag)) < 0) 00238 return -1; 00239 00240 for (p1 = 0 ; p1 < count ; p1 ++) 00241 { 00242 code = fast_decode_i32 (decoder, tag, & temp [p1]); 00243 if (code < 0) break; 00244 } 00245 00246 if (p1 < count) 00247 return expect (decoder, FAST_ERR_NONE, -1); 00248 00249 // Message decoding done 00250 if (expect (decoder, FAST_ERR_NONE, 00251 fast_decode_end_msg (decoder, tag)) < 0) 00252 return -1; 00253 00254 { 00255 int errors = 0; 00256 00257 for (p1 = 0 ; p1 < count ; p1 ++) 00258 { 00259 if (data [p1] != temp [p1]) 00260 { 00261 fprintf (stderr, " unexpected: data=%d != temp=%d\n", 00262 data [p1], temp [p1]); 00263 00264 errors ++; 00265 } 00266 } 00267 00268 if (errors > 0) 00269 return -1; 00270 } 00271 00272 return 0; 00273 } 00274 00275 static int encode_decode_u32_none (void) 00276 { 00277 static u32 data [12] = 00278 { 00279 0, 1, 2, 3, 62, 63, 64, 127, 128, 16383, 16384, 16385 00280 }; 00281 00282 fast_tag_t tag = MAKE_U32_TAG (FAST_OP_NONE, 0, 0); 00283 00284 u32 temp [12]; 00285 00286 int count = 12; 00287 int code; 00288 int p1; 00289 00290 encoder = fast_create_codec (); 00291 decoder = fast_create_codec (); 00292 00293 encoder->skip_io = 1; 00294 decoder->skip_io = 1; 00295 00296 // Start encoding a message 00297 if (expect (encoder, FAST_ERR_NONE, 00298 fast_encode_new_msg (encoder, tag)) < 0) 00299 return -1; 00300 00301 for (p1 = 0 ; p1 < count ; p1 ++) 00302 { 00303 code = fast_encode_u32 (encoder, tag, data [p1]); 00304 if (code < 0) break; 00305 } 00306 00307 if (p1 < count) 00308 return expect (encoder, FAST_ERR_NONE, -1); 00309 00310 // Message encoding done 00311 if (expect (encoder, FAST_ERR_NONE, 00312 fast_encode_end_msg (encoder, tag)) < 0) 00313 return -1; 00314 00315 // Copy encoder output to decoder input 00316 copy_buffer (encoder->output, decoder->input); 00317 00318 // Start decoding a message 00319 if (expect (decoder, FAST_ERR_NONE, 00320 fast_decode_new_msg (decoder, tag)) < 0) 00321 return -1; 00322 00323 for (p1 = 0 ; p1 < count ; p1 ++) 00324 { 00325 code = fast_decode_u32 (decoder, tag, & temp [p1]); 00326 if (code < 0) break; 00327 } 00328 00329 if (p1 < count) 00330 return expect (decoder, FAST_ERR_NONE, -1); 00331 00332 // Message decoding done 00333 if (expect (decoder, FAST_ERR_NONE, 00334 fast_decode_end_msg (decoder, tag)) < 0) 00335 return -1; 00336 00337 { 00338 int errors = 0; 00339 00340 for (p1 = 0 ; p1 < count ; p1 ++) 00341 { 00342 if (data [p1] != temp [p1]) 00343 { 00344 fprintf (stderr, " unexpected: data=%d != temp=%d\n", 00345 data [p1], temp [p1]); 00346 00347 errors ++; 00348 } 00349 } 00350 00351 if (errors > 0) 00352 return -1; 00353 } 00354 00355 return 0; 00356 } 00357 00359 00360 static int decode_i32_bad_size (void) 00361 { 00362 static u8 data [7] = 00363 { 00364 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 00365 }; 00366 00367 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_NONE, 0, 0); 00368 i32 temp; 00369 00370 decoder = fast_create_codec (); 00371 decoder->skip_io = 1; 00372 00373 insert_into_buffer (decoder->input, data, sizeof (data)); 00374 00375 fast_decode_new_msg (decoder, tag); 00376 00377 if (expect (decoder, FAST_ERR_SIZE, 00378 fast_decode_i32 (decoder, tag, & temp)) < 0) 00379 return -1; 00380 00381 return 0; 00382 } 00383 00384 static int decode_i32_none_no_value (void) 00385 { 00386 static u8 data [1] = { 0x80 }; 00387 00388 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_NONE, 0, 0); 00389 i32 temp; 00390 00391 decoder = fast_create_codec (); 00392 decoder->skip_io = 1; 00393 00394 insert_into_buffer (decoder->input, data, sizeof (data)); 00395 00396 if (expect (decoder, FAST_ERR_VALUE, 00397 fast_decode_i32 (decoder, tag, & temp)) < 0) 00398 return -1; 00399 00400 return 0; 00401 } 00402 00403 static int decode_i32_incr_no_value (void) 00404 { 00405 static u8 data [1] = { 0x80 }; 00406 00407 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_INCR, 0, 0); 00408 i32 temp; 00409 00410 decoder = fast_create_codec (); 00411 decoder->skip_io = 1; 00412 00413 insert_into_buffer (decoder->input, data, sizeof (data)); 00414 00415 if (expect (decoder, FAST_ERR_VALUE, 00416 fast_decode_i32 (decoder, tag, & temp)) < 0) 00417 return -1; 00418 00419 return 0; 00420 } 00421 00423 00424 static int encode_i32_bad_slot (void) 00425 { 00426 fast_tag_t tag = MAKE_TAG (FAST_TYPE_I32, FAST_OP_COPY, 0, 00427 MAX_PMAP_BITS + 1); 00428 00429 encoder = fast_create_codec (); 00430 00431 if (expect (encoder, FAST_ERR_SIZE, 00432 fast_encode_i32 (encoder, tag, 0)) < 0) 00433 return -1; 00434 00435 return 0; 00436 } 00437 00438 static int encode_i32_delta_bad_op (void) 00439 { 00440 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_DELTA, 0, 0); 00441 00442 encoder = fast_create_codec (); 00443 00444 if (expect (encoder, FAST_ERR_TAG_OP, 00445 fast_encode_i32 (encoder, tag, 3)) < 0) 00446 return -1; 00447 00448 return 0; 00449 } 00450 00451 static int encode_i32_incr_bad_op (void) 00452 { 00453 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_INCR, 0, 0); 00454 00455 encoder = fast_create_codec (); 00456 00457 if (expect (encoder, FAST_ERR_TAG_OP, 00458 fast_encode_i32 (encoder, tag, 0)) < 0) 00459 return -1; 00460 00461 return 0; 00462 } 00463 00464 static int encode_i32_null_codec (void) 00465 { 00466 if (expect (encoder, FAST_ERR_CODEC, 00467 fast_encode_i32 (NULL, 0, 0)) < 0) 00468 return -1; 00469 00470 return 0; 00471 } 00472 00473 static int encode_i32_str_tag (void) 00474 { 00475 fast_tag_t tag = MAKE_TAG (FAST_TYPE_STR, FAST_OP_NONE, 0, 0); 00476 00477 encoder = fast_create_codec (); 00478 00479 if (expect (encoder, FAST_ERR_TAG_TYPE, 00480 fast_encode_i32 (encoder, tag, 0)) < 0) 00481 return -1; 00482 00483 return 0; 00484 } 00485 00486 static int encode_i32_u32_tag (void) 00487 { 00488 fast_tag_t tag = MAKE_TAG (FAST_TYPE_U32, FAST_OP_NONE, 0, 0); 00489 00490 encoder = fast_create_codec (); 00491 00492 if (expect (encoder, FAST_ERR_TAG_TYPE, 00493 fast_encode_i32 (encoder, tag, 0)) < 0) 00494 return -1; 00495 00496 return 0; 00497 } 00498 00500 00501 static int encode_str_incr (void) 00502 { 00503 fast_tag_t tag = MAKE_STR_TAG (FAST_OP_INCR, 0, 0); 00504 00505 encoder = fast_create_codec (); 00506 00507 if (expect (encoder, FAST_ERR_TAG_OP, 00508 fast_encode_str (encoder, tag, (u8*) "foo", 3)) < 0) 00509 return -1; 00510 00511 return 0; 00512 } 00513 00514 #if 0 // not checked in fast_encode_str 00515 static int encode_str_oversized (void) 00516 { 00517 fast_tag_t tag = MAKE_STR_TAG (FAST_OP_NONE, 0, 0); 00518 00519 encoder = fast_create_codec (); 00520 00521 if (expect (encoder, FAST_ERR_SIZE, 00522 fast_encode_str (encoder, tag, (u8*) "", 1025)) < 0) 00523 return -1; 00524 00525 return 0; 00526 } 00527 #endif 00528 00529 static int encode_str_zero_length (void) 00530 { 00531 fast_tag_t tag = MAKE_STR_TAG (FAST_OP_NONE, 0, 0); 00532 00533 encoder = fast_create_codec (); 00534 00535 if (expect (encoder, FAST_ERR_SIZE, 00536 fast_encode_str (encoder, tag, (u8*) "", 0)) < 0) 00537 return -1; 00538 00539 return 0; 00540 } 00541 00543 00544 static int encode_end_msg_only (void) 00545 { 00546 encoder = fast_create_codec (); 00547 00548 if (expect (encoder, FAST_ERR_CALL_SEQ, 00549 fast_encode_end_msg (encoder, 0)) < 0) 00550 return -1; 00551 00552 return 0; 00553 } 00554 00555 static int encode_new_msg_twice (void) 00556 { 00557 encoder = fast_create_codec (); 00558 00559 if (expect (encoder, FAST_ERR_NONE, 00560 fast_encode_new_msg (encoder, 0)) < 0) 00561 return -1; 00562 00563 if (expect (encoder, FAST_ERR_CALL_SEQ, 00564 fast_encode_new_msg (encoder, 0)) < 0) 00565 return -1; 00566 00567 return 0; 00568 } 00569 00570 static int encode_msg_buffer_overflow (void) 00571 { 00572 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_NONE, 0, 0); 00573 00574 int code; 00575 int p1; 00576 00577 encoder = fast_create_codec (); 00578 00579 for (p1 = 0 ; p1 < 10000 ; p1 ++) 00580 { 00581 code = fast_encode_i32 (encoder, tag, p1); 00582 00583 if (code < 0) 00584 break; 00585 } 00586 00587 if (expect (encoder, FAST_ERR_SIZE, code) < 0) 00588 return -1; 00589 00590 return 0; 00591 } 00592 00593 static int encode_output_buffer_overflow (void) 00594 { 00595 fast_tag_t tag = MAKE_I32_TAG (FAST_OP_NONE, 0, 0); 00596 00597 int code; 00598 int p1; 00599 00600 encoder = fast_create_codec (); 00601 00602 encoder->skip_io = 1; 00603 00604 for (p1 = 0 ; p1 < 10000 ; p1 ++) 00605 { 00606 code = fast_encode_new_msg (encoder, tag); 00607 00608 if (code < 0) 00609 break; 00610 00611 code = fast_encode_i32 (encoder, tag, p1); 00612 00613 if (code < 0) 00614 break; 00615 00616 code = fast_encode_end_msg (encoder, tag); 00617 00618 if (code < 0) 00619 break; 00620 } 00621 00622 if (expect (encoder, FAST_ERR_SIZE, code) < 0) 00623 return -1; 00624 00625 return 0; 00626 } 00627 00629 00630 #define ENTRY(result, name) { result, name, #name } 00631 00632 typedef struct test_entry 00633 { 00634 int result; 00635 test_fn fn; 00636 const char* name; 00637 } 00638 test_entry; 00639 00640 static test_entry test_array [] = 00641 { 00642 ENTRY (FAIL, decode_i32_bad_size), 00643 ENTRY (FAIL, decode_i32_none_no_value), 00644 ENTRY (FAIL, decode_i32_incr_no_value), 00645 00646 ENTRY (FAIL, encode_i32_bad_slot), 00647 ENTRY (FAIL, encode_i32_delta_bad_op), 00648 ENTRY (FAIL, encode_i32_incr_bad_op), 00649 ENTRY (FAIL, encode_i32_null_codec), 00650 ENTRY (FAIL, encode_i32_str_tag), 00651 ENTRY (FAIL, encode_i32_u32_tag), 00652 00653 ENTRY (FAIL, encode_str_incr), 00654 //_ENTRY (FAIL, encode_str_oversized), 00655 ENTRY (FAIL, encode_str_zero_length), 00656 00657 ENTRY (FAIL, encode_end_msg_only), 00658 ENTRY (FAIL, encode_new_msg_twice), 00659 ENTRY (FAIL, encode_msg_buffer_overflow), 00660 ENTRY (FAIL, encode_output_buffer_overflow), 00661 00662 ENTRY (PASS, encode_decode_i32_none), 00663 ENTRY (PASS, encode_decode_u32_none), 00664 00665 { 0, NULL }, 00666 }; 00667 00668 int main (int argc, char* argv []) 00669 { 00670 int p1; 00671 00672 for (p1 = 0 ; test_array [p1].fn != NULL ; p1 ++) 00673 { 00674 test_entry* entry = & test_array [p1]; 00675 00676 execute (p1, entry->result, entry->fn, entry->name); 00677 } 00678 00679 fprintf (stderr, "== all tests done, %s passed.\n", 00680 passed_count == execed_count ? "ALL" : "NOT all"); 00681 fprintf (stderr, "== executed %8d\n", execed_count); 00682 fprintf (stderr, "== passed %8d\n", passed_count); 00683 fprintf (stderr, "== failed %8d\n", failed_count); 00684 00685 return 0; 00686 }