Mercurial
comparison mrjunejune/test/integration_test.c @ 94:092afa595764
[MrJuneJune] Added Integration tests.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Fri, 02 Jan 2026 18:13:32 -0800 |
| parents | 6626ec933933 |
| children | 96628cf126a0 |
comparison
equal
deleted
inserted
replaced
| 93:be91a73d801a | 94:092afa595764 |
|---|---|
| 378 free(response); | 378 free(response); |
| 379 Seobeo_Handle_Destroy(client); | 379 Seobeo_Handle_Destroy(client); |
| 380 return 0; | 380 return 0; |
| 381 } | 381 } |
| 382 | 382 |
| 383 // Helper: Send POST request with file data | |
| 384 int send_post_file(Seobeo_Handle *client, const char *path, const char *file_data, size_t file_size) | |
| 385 { | |
| 386 char request_buffer[8192]; | |
| 387 int header_len = snprintf( | |
| 388 request_buffer, sizeof(request_buffer), | |
| 389 "POST %s HTTP/1.1\r\n" | |
| 390 "Host: %s\r\n" | |
| 391 "Content-Type: application/octet-stream\r\n" | |
| 392 "Content-Length: %zu\r\n" | |
| 393 "Connection: close\r\n" | |
| 394 "\r\n", | |
| 395 path, TEST_HOST, file_size | |
| 396 ); | |
| 397 | |
| 398 if (header_len < 0 || header_len >= sizeof(request_buffer)) | |
| 399 { | |
| 400 fprintf(stderr, "Request header too large\n"); | |
| 401 return -1; | |
| 402 } | |
| 403 | |
| 404 // Send headers | |
| 405 Seobeo_Handle_Queue(client, (uint8*)request_buffer, (uint32)header_len); | |
| 406 | |
| 407 // Send file data in chunks if needed | |
| 408 size_t remaining = file_size; | |
| 409 const char *ptr = file_data; | |
| 410 while (remaining > 0) | |
| 411 { | |
| 412 size_t chunk_size = remaining > 4096 ? 4096 : remaining; | |
| 413 Seobeo_Handle_Queue(client, (uint8*)ptr, (uint32)chunk_size); | |
| 414 ptr += chunk_size; | |
| 415 remaining -= chunk_size; | |
| 416 } | |
| 417 | |
| 418 return Seobeo_Handle_Flush(client); | |
| 419 } | |
| 420 | |
| 421 // Helper: Extract JSON field value from response body | |
| 422 char* extract_json_field(const char *json, const char *field, char *buffer, size_t buffer_size) | |
| 423 { | |
| 424 char search_pattern[256]; | |
| 425 snprintf(search_pattern, sizeof(search_pattern), "\"%s\":\"", field); | |
| 426 | |
| 427 const char *start = strstr(json, search_pattern); | |
| 428 if (!start) | |
| 429 { | |
| 430 return NULL; | |
| 431 } | |
| 432 | |
| 433 start += strlen(search_pattern); | |
| 434 const char *end = strchr(start, '"'); | |
| 435 if (!end) | |
| 436 { | |
| 437 return NULL; | |
| 438 } | |
| 439 | |
| 440 size_t len = end - start; | |
| 441 if (len >= buffer_size) | |
| 442 { | |
| 443 len = buffer_size - 1; | |
| 444 } | |
| 445 | |
| 446 memcpy(buffer, start, len); | |
| 447 buffer[len] = '\0'; | |
| 448 | |
| 449 return buffer; | |
| 450 } | |
| 451 | |
| 452 // Helper: Test POST file conversion | |
| 453 int test_file_conversion(const char *endpoint, const char *test_file_path, | |
| 454 const char *expected_format, pid_t server_pid) | |
| 455 { | |
| 456 printf(" Testing: POST %s\n", endpoint); | |
| 457 | |
| 458 // Read test file | |
| 459 size_t file_size; | |
| 460 char *file_data = read_file(test_file_path, &file_size); | |
| 461 if (!file_data) | |
| 462 { | |
| 463 printf(" ✗ Failed to read test file: %s\n", test_file_path); | |
| 464 return -1; | |
| 465 } | |
| 466 | |
| 467 printf(" → Loaded test file (%zu bytes)\n", file_size); | |
| 468 | |
| 469 // Create client and send request | |
| 470 Seobeo_Handle *client = create_test_client(); | |
| 471 if (!client) | |
| 472 { | |
| 473 printf(" ✗ Failed to create client connection\n"); | |
| 474 free(file_data); | |
| 475 return -1; | |
| 476 } | |
| 477 | |
| 478 if (send_post_file(client, endpoint, file_data, file_size) < 0) | |
| 479 { | |
| 480 printf(" ✗ Failed to send POST request\n"); | |
| 481 free(file_data); | |
| 482 Seobeo_Handle_Destroy(client); | |
| 483 return -1; | |
| 484 } | |
| 485 | |
| 486 free(file_data); | |
| 487 | |
| 488 // Read response | |
| 489 char *response = NULL; | |
| 490 size_t response_len = 0; | |
| 491 if (read_http_response(client, &response, &response_len) < 0) | |
| 492 { | |
| 493 printf(" ✗ Failed to read response\n"); | |
| 494 Seobeo_Handle_Destroy(client); | |
| 495 return -1; | |
| 496 } | |
| 497 | |
| 498 Seobeo_Handle_Destroy(client); | |
| 499 | |
| 500 // Parse status | |
| 501 int status = parse_http_status(response); | |
| 502 if (status != 200) | |
| 503 { | |
| 504 printf(" ✗ Conversion failed with status: %d\n", status); | |
| 505 printf(" Response: %s\n", response); | |
| 506 free(response); | |
| 507 return -1; | |
| 508 } | |
| 509 | |
| 510 printf(" ✓ Status code: 200\n"); | |
| 511 | |
| 512 // Extract download URL from JSON response | |
| 513 const char *body = strstr(response, "\r\n\r\n"); | |
| 514 if (!body) | |
| 515 { | |
| 516 printf(" ✗ No response body found\n"); | |
| 517 free(response); | |
| 518 return -1; | |
| 519 } | |
| 520 body += 4; | |
| 521 | |
| 522 char download_url[512]; | |
| 523 if (!extract_json_field(body, "download_url", download_url, sizeof(download_url))) | |
| 524 { | |
| 525 printf(" ✗ Failed to extract download_url from response\n"); | |
| 526 printf(" Response body: %s\n", body); | |
| 527 free(response); | |
| 528 return -1; | |
| 529 } | |
| 530 | |
| 531 printf(" ✓ Conversion succeeded\n"); | |
| 532 printf(" ✓ Download URL: %s\n", download_url); | |
| 533 free(response); | |
| 534 | |
| 535 // Test downloading the converted file | |
| 536 printf(" → Testing download: GET %s\n", download_url); | |
| 537 | |
| 538 client = create_test_client(); | |
| 539 if (!client) | |
| 540 { | |
| 541 printf(" ✗ Failed to create client for download\n"); | |
| 542 return -1; | |
| 543 } | |
| 544 | |
| 545 if (send_http_request(client, download_url, NULL) < 0) | |
| 546 { | |
| 547 printf(" ✗ Failed to send download request\n"); | |
| 548 Seobeo_Handle_Destroy(client); | |
| 549 return -1; | |
| 550 } | |
| 551 | |
| 552 response = NULL; | |
| 553 response_len = 0; | |
| 554 if (read_http_response(client, &response, &response_len) < 0) | |
| 555 { | |
| 556 printf(" ✗ Failed to read download response\n"); | |
| 557 Seobeo_Handle_Destroy(client); | |
| 558 return -1; | |
| 559 } | |
| 560 | |
| 561 Seobeo_Handle_Destroy(client); | |
| 562 | |
| 563 status = parse_http_status(response); | |
| 564 if (status != 200) | |
| 565 { | |
| 566 printf(" ✗ Download failed with status: %d\n", status); | |
| 567 free(response); | |
| 568 return -1; | |
| 569 } | |
| 570 | |
| 571 // Find body in download response | |
| 572 body = strstr(response, "\r\n\r\n"); | |
| 573 if (!body) | |
| 574 { | |
| 575 printf(" ✗ No file data in download response\n"); | |
| 576 free(response); | |
| 577 return -1; | |
| 578 } | |
| 579 body += 4; | |
| 580 | |
| 581 size_t downloaded_size = response_len - (body - response); | |
| 582 | |
| 583 // Verify content type in response headers | |
| 584 const char *content_type = strstr(response, "Content-Type: "); | |
| 585 if (!content_type) | |
| 586 { | |
| 587 printf(" ✗ No Content-Type header in download\n"); | |
| 588 free(response); | |
| 589 return -1; | |
| 590 } | |
| 591 | |
| 592 if (strstr(content_type, expected_format) == NULL) | |
| 593 { | |
| 594 printf(" ✗ Wrong content type (expected %s)\n", expected_format); | |
| 595 free(response); | |
| 596 return -1; | |
| 597 } | |
| 598 | |
| 599 printf(" ✓ Downloaded converted file (%zu bytes)\n", downloaded_size); | |
| 600 printf(" ✓ Content-Type: %s\n", expected_format); | |
| 601 | |
| 602 free(response); | |
| 603 return 0; | |
| 604 } | |
| 605 | |
| 383 // Helper: Start test server | 606 // Helper: Start test server |
| 384 pid_t start_test_server(const char *server_binary) | 607 pid_t start_test_server(const char *server_binary) |
| 385 { | 608 { |
| 386 pid_t server_pid = fork(); | 609 pid_t server_pid = fork(); |
| 387 | 610 |
| 496 int passed_tests = 0; | 719 int passed_tests = 0; |
| 497 | 720 |
| 498 // Define test cases - paths that should succeed (200 OK) | 721 // Define test cases - paths that should succeed (200 OK) |
| 499 TestCase success_tests[] = { | 722 TestCase success_tests[] = { |
| 500 {"/", 200, NULL, NULL, NULL, 0}, | 723 {"/", 200, NULL, NULL, NULL, 0}, |
| 501 {"/index.html", 200, NULL, NULL, NULL, 0}, | 724 {"/resume", 200, NULL, NULL, NULL, 0}, |
| 725 {"/tools", 200, NULL, NULL, NULL, 0}, | |
| 726 {"/tools/markdown_to_html", 200, NULL, NULL, NULL, 0}, | |
| 727 {"/tools/file_converter", 200, NULL, NULL, NULL, 0}, | |
| 502 }; | 728 }; |
| 503 int num_success_tests = sizeof(success_tests) / sizeof(success_tests[0]); | 729 int num_success_tests = sizeof(success_tests) / sizeof(success_tests[0]); |
| 730 | |
| 731 // Define test cases - paths that should redirect (301) | |
| 732 TestCase redirect_tests[] = { | |
| 733 {"/index.html", 301, NULL, NULL, NULL, 0}, | |
| 734 {"/resume/index.html", 301, NULL, NULL, NULL, 0}, | |
| 735 {"/tools/index.html", 301, NULL, NULL, NULL, 0}, | |
| 736 {"/tools/markdown_to_html/index.html", 301, NULL, NULL, NULL, 0}, | |
| 737 {"/tools/file_converter/index.html", 301, NULL, NULL, NULL, 0}, | |
| 738 }; | |
| 739 int num_redirect_tests = sizeof(redirect_tests) / sizeof(redirect_tests[0]); | |
| 504 | 740 |
| 505 // Define test cases - paths that should fail (404) | 741 // Define test cases - paths that should fail (404) |
| 506 TestCase failure_tests[] = { | 742 TestCase failure_tests[] = { |
| 507 {"/nonexistent", 404, NULL, NULL, NULL, 0}, | 743 {"/nonexistent", 404, NULL, NULL, NULL, 0}, |
| 508 {"/does/not/exist", 404, NULL, NULL, NULL, 0}, | 744 {"/does/not/exist", 404, NULL, NULL, NULL, 0}, |
| 513 // Initialize all test cases | 749 // Initialize all test cases |
| 514 for (int i = 0; i < num_success_tests; i++) | 750 for (int i = 0; i < num_success_tests; i++) |
| 515 { | 751 { |
| 516 init_test_case(&success_tests[i]); | 752 init_test_case(&success_tests[i]); |
| 517 } | 753 } |
| 754 for (int i = 0; i < num_redirect_tests; i++) | |
| 755 { | |
| 756 init_test_case(&redirect_tests[i]); | |
| 757 } | |
| 518 for (int i = 0; i < num_failure_tests; i++) | 758 for (int i = 0; i < num_failure_tests; i++) |
| 519 { | 759 { |
| 520 init_test_case(&failure_tests[i]); | 760 init_test_case(&failure_tests[i]); |
| 521 } | 761 } |
| 522 | 762 |
| 523 // Run success tests | 763 // Run success tests |
| 524 printf("Running tests for paths that should succeed:\n"); | 764 printf("Running tests for paths that should succeed:\n"); |
| 525 for (int i = 0; i < num_success_tests; i++) | 765 for (int i = 0; i < num_success_tests; i++) |
| 526 { | 766 { |
| 527 if (execute_test_case(&success_tests[i], server_pid) == 0) | 767 if (execute_test_case(&success_tests[i], server_pid) == 0) |
| 768 { | |
| 769 passed_tests++; | |
| 770 } | |
| 771 else | |
| 772 { | |
| 773 failed_tests++; | |
| 774 } | |
| 775 } | |
| 776 | |
| 777 printf("\n"); | |
| 778 | |
| 779 // Run redirect tests | |
| 780 printf("Running tests for paths that should redirect:\n"); | |
| 781 for (int i = 0; i < num_redirect_tests; i++) | |
| 782 { | |
| 783 if (execute_test_case(&redirect_tests[i], server_pid) == 0) | |
| 528 { | 784 { |
| 529 passed_tests++; | 785 passed_tests++; |
| 530 } | 786 } |
| 531 else | 787 else |
| 532 { | 788 { |
| 570 else | 826 else |
| 571 { | 827 { |
| 572 failed_tests++; | 828 failed_tests++; |
| 573 } | 829 } |
| 574 | 830 |
| 831 printf("\n"); | |
| 832 | |
| 833 // Test POST endpoints | |
| 834 printf("Running tests for POST conversion endpoints:\n"); | |
| 835 | |
| 836 // Test image-to-webp conversion | |
| 837 if (test_file_conversion("/api/convert/image-to-webp", | |
| 838 "mrjunejune/test/shiba.webp", | |
| 839 "image/webp", | |
| 840 server_pid) == 0) | |
| 841 { | |
| 842 passed_tests++; | |
| 843 } | |
| 844 else | |
| 845 { | |
| 846 failed_tests++; | |
| 847 } | |
| 848 | |
| 849 printf("\n"); | |
| 850 | |
| 851 // Test video-to-mp4 conversion | |
| 852 if (test_file_conversion("/api/convert/video-to-mp4", | |
| 853 "mrjunejune/test/test_avi.avi", | |
| 854 "video/mp4", | |
| 855 server_pid) == 0) | |
| 856 { | |
| 857 passed_tests++; | |
| 858 } | |
| 859 else | |
| 860 { | |
| 861 failed_tests++; | |
| 862 } | |
| 863 | |
| 575 // Cleanup test cases | 864 // Cleanup test cases |
| 576 for (int i = 0; i < num_success_tests; i++) | 865 for (int i = 0; i < num_success_tests; i++) |
| 577 { | 866 { |
| 578 cleanup_test_case(&success_tests[i]); | 867 cleanup_test_case(&success_tests[i]); |
| 868 } | |
| 869 for (int i = 0; i < num_redirect_tests; i++) | |
| 870 { | |
| 871 cleanup_test_case(&redirect_tests[i]); | |
| 579 } | 872 } |
| 580 for (int i = 0; i < num_failure_tests; i++) | 873 for (int i = 0; i < num_failure_tests; i++) |
| 581 { | 874 { |
| 582 cleanup_test_case(&failure_tests[i]); | 875 cleanup_test_case(&failure_tests[i]); |
| 583 } | 876 } |