feat: add http implementation test suite

This commit is contained in:
retoor 2025-11-05 11:08:18 +01:00
parent ddbcba3cd6
commit c8e03e3c3d
2 changed files with 294 additions and 0 deletions

View File

@ -2,6 +2,14 @@
## Version 0.2.0 - 2025-11-05
Updated documentation files. This includes changes to the project's release notes and a header file.
**Changes:** 2 files, 103 lines
**Languages:** C (93 lines), Markdown (10 lines)
## Version 0.1.0 - 2025-11-05 ## Version 0.1.0 - 2025-11-05
Automated versioning and changelog updates are now available when you commit code. This simplifies release management and ensures accurate changelog entries. Automated versioning and changelog updates are now available when you commit code. This simplifies release management and ensures accurate changelog entries.

286
http.c Normal file
View File

@ -0,0 +1,286 @@
// HTTP Implementation Test Suite
// Copyright (c) 2023 retoor
// Licensed under MIT License
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "http.h"
double get_current_time_in_milliseconds() {
struct timeval time_value;
gettimeofday(&time_value, NULL);
return (time_value.tv_sec * 1000.0) + (time_value.tv_usec / 1000.0);
}
void print_response_preview(const char *response, size_t maximum_length) {
if (!response) {
printf("Response: NULL\n");
return;
}
size_t response_length = strlen(response);
printf("Response length: %zu bytes\n", response_length);
printf("First %zu chars: %.100s%s\n",
maximum_length, response, response_length > maximum_length ? "..." : "");
}
void test_https_get() {
printf("\n=== Testing HTTPS GET ===\n");
const char * const test_urls[] = {
"https://httpbin.org/get",
"https://jsonplaceholder.typicode.com/posts/1",
"https://api.github.com/repos/torvalds/linux",
"https://www.example.com/",
"https://httpbin.org/bytes/1024"
};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: GET %s\n", index + 1, test_urls[index]);
double start_time = get_current_time_in_milliseconds();
char *response = https_get((char *)test_urls[index]);
double end_time = get_current_time_in_milliseconds();
printf("Time taken: %.2f ms\n", end_time - start_time);
print_response_preview(response, 100);
if (response) {
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
void test_https_post() {
printf("\n=== Testing HTTPS POST ===\n");
const char * const test_urls[] = {
"https://httpbin.org/post",
"https://jsonplaceholder.typicode.com/posts",
"https://httpbin.org/anything"
};
const char * const test_payloads[] = {
"{\"test\": \"data\", \"number\": 123}",
"{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}",
"{\"key1\": \"value1\", \"key2\": [1, 2, 3], \"key3\": {\"nested\": true}}"
};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: POST %s\n", index + 1, test_urls[index]);
printf("Payload: %s\n", test_payloads[index]);
double start_time = get_current_time_in_milliseconds();
char *response = https_post((char *)test_urls[index], (char *)test_payloads[index]);
double end_time = get_current_time_in_milliseconds();
printf("Time taken: %.2f ms\n", end_time - start_time);
print_response_preview(response, 100);
if (response) {
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
void test_http_get() {
printf("\n=== Testing HTTP GET ===\n");
const char * const test_urls[] = {
"http://httpbin.org/get",
"http://httpbin.org/headers",
"http://httpbin.org/user-agent"
};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: GET %s\n", index + 1, test_urls[index]);
double start_time = get_current_time_in_milliseconds();
char *response = http_get((char *)test_urls[index]);
double end_time = get_current_time_in_milliseconds();
printf("Time taken: %.2f ms\n", end_time - start_time);
print_response_preview(response, 100);
if (response) {
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
void test_http_post() {
printf("\n=== Testing HTTP POST ===\n");
const char * const test_urls[] = {
"http://httpbin.org/post",
"http://httpbin.org/anything"
};
const char * const test_payloads[] = {
"{\"message\": \"Hello World\"}",
"{\"test\": true, \"count\": 42}"
};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: POST %s\n", index + 1, test_urls[index]);
printf("Payload: %s\n", test_payloads[index]);
double start_time = get_current_time_in_milliseconds();
char *response = http_post((char *)test_urls[index], (char *)test_payloads[index]);
double end_time = get_current_time_in_milliseconds();
printf("Time taken: %.2f ms\n", end_time - start_time);
print_response_preview(response, 100);
if (response) {
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
void test_chunked_response() {
printf("\n=== Testing Chunked Transfer Encoding ===\n");
const char * const test_urls[] = {
"https://httpbin.org/stream/5",
"https://httpbin.org/drip?duration=2&numbytes=10&code=200",
"http://httpbin.org/stream-bytes/1024"
};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: GET %s\n", index + 1, test_urls[index]);
double start_time = get_current_time_in_milliseconds();
char *response = NULL;
if (strncmp(test_urls[index], "https://", 8) == 0) {
response = https_get((char *)test_urls[index]);
} else {
response = http_get((char *)test_urls[index]);
}
double end_time = get_current_time_in_milliseconds();
printf("Time taken: %.2f ms\n", end_time - start_time);
print_response_preview(response, 100);
if (response) {
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
void benchmark_requests() {
printf("\n=== Benchmarking Performance ===\n");
const char * const benchmark_url = "https://httpbin.org/get";
size_t number_of_requests = 10;
double total_time = 0.0;
size_t successful_requests = 0;
printf("Benchmarking %zu requests to %s\n", number_of_requests, benchmark_url);
for (size_t index = 0; index < number_of_requests; index++) {
double start_time = get_current_time_in_milliseconds();
char *response = https_get((char *)benchmark_url);
double end_time = get_current_time_in_milliseconds();
double request_time = end_time - start_time;
total_time += request_time;
if (response) {
successful_requests++;
free(response);
printf("Request %2zu: %.2f ms\n", index + 1, request_time);
} else {
printf("Request %2zu: FAILED\n", index + 1);
}
}
printf("\nBenchmark Results:\n");
printf("Total requests: %zu\n", number_of_requests);
printf("Successful: %zu\n", successful_requests);
printf("Failed: %zu\n", number_of_requests - successful_requests);
printf("Total time: %.2f ms\n", total_time);
printf("Average time per request: %.2f ms\n", total_time / number_of_requests);
printf("Success rate: %.1f%%\n", (successful_requests * 100.0) / number_of_requests);
}
void test_large_response() {
printf("\n=== Testing Large Response Handling ===\n");
const char * const test_urls[] = {
"https://httpbin.org/bytes/10240", // 10 KB
"https://httpbin.org/bytes/102400", // 100 KB
"https://httpbin.org/base64/SFRUUEJJTiBpcyBhd2Vzb21l" // Base64 response
};
const char * const size_descriptions[] = {"10 KB", "100 KB", "Base64"};
size_t number_of_tests = sizeof(test_urls) / sizeof(test_urls[0]);
for (size_t index = 0; index < number_of_tests; index++) {
printf("\nTest %zu: Large response (%s) from %s\n", index + 1, size_descriptions[index], test_urls[index]);
double start_time = get_current_time_in_milliseconds();
char *response = https_get((char *)test_urls[index]);
double end_time = get_current_time_in_milliseconds();
if (response) {
size_t response_length = strlen(response);
printf("Response size: %zu bytes\n", response_length);
printf("Time taken: %.2f ms\n", end_time - start_time);
printf("Transfer rate: %.2f KB/s\n", (response_length / 1024.0) / ((end_time - start_time) / 1000.0));
free(response);
printf("Status: SUCCESS\n");
} else {
printf("Status: FAILED\n");
}
}
}
int main(int argument_count, char *argument_values[]) {
printf("HTTP Implementation Test Suite\n");
printf("==============================\n");
test_https_get();
test_https_post();
test_http_get();
test_http_post();
test_chunked_response();
test_large_response();
benchmark_requests();
printf("\n\nAll tests completed!\n");
return 0;
}