diff --git a/test/unit_test.c b/test/unit_test.c index 2b777b35b93bdec899b94a3543c48286bb3d7e71..1ffd0debda1a0b57c959200ebf52b7408135ebe9 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -24,11 +24,18 @@ #define USE_LUA #include "mongoose.c" -#define FATAL(str, line) do { \ +static int s_total_tests = 0; +static int s_failed_tests = 0; + +#define FAIL(str, line) do { \ printf("Fail on line %d: [%s]\n", line, str); \ - abort(); \ + s_failed_tests++; \ +} while (0) + +#define ASSERT(expr) do { \ + s_total_tests++; \ + if (!(expr)) FAIL(#expr, __LINE__); \ } while (0) -#define ASSERT(expr) do { if (!(expr)) FATAL(#expr, __LINE__); } while (0) #define HTTP_PORT "56789" #define HTTPS_PORT "56790" @@ -187,6 +194,7 @@ static char *read_file(const char *path, int *size) { static const char *fetch_data = "hello world!\n"; static const char *inmemory_file_data = "hi there"; static const char *upload_filename = "upload_test.txt"; +static const char *upload_filename2 = "upload_test2.txt"; static const char *upload_ok_message = "upload successful"; static const char *open_file_cb(const struct mg_connection *conn, @@ -200,16 +208,39 @@ static const char *open_file_cb(const struct mg_connection *conn, } static void upload_cb(struct mg_connection *conn, const char *path) { + const struct mg_request_info *ri = mg_get_request_info(conn); char *p1, *p2; int len1, len2; - ASSERT(!strcmp(path, "./upload_test.txt")); - ASSERT((p1 = read_file("mongoose.c", &len1)) != NULL); - ASSERT((p2 = read_file(path, &len2)) != NULL); - ASSERT(len1 == len2); - ASSERT(memcmp(p1, p2, len1) == 0); - free(p1), free(p2); - remove(upload_filename); + if (atoi(ri->query_string) == 1) { + ASSERT(!strcmp(path, "./upload_test.txt")); + ASSERT((p1 = read_file("mongoose.c", &len1)) != NULL); + ASSERT((p2 = read_file(path, &len2)) != NULL); + ASSERT(len1 == len2); + ASSERT(memcmp(p1, p2, len1) == 0); + free(p1), free(p2); + remove(upload_filename); + } else if (atoi(ri->query_string) == 2) { + if (!strcmp(path, "./upload_test.txt")) { + ASSERT((p1 = read_file("mongoose.h", &len1)) != NULL); + ASSERT((p2 = read_file(path, &len2)) != NULL); + ASSERT(len1 == len2); + ASSERT(memcmp(p1, p2, len1) == 0); + free(p1), free(p2); + remove(upload_filename); + } else if (!strcmp(path, "./upload_test2.txt")) { + ASSERT((p1 = read_file("README.md", &len1)) != NULL); + ASSERT((p2 = read_file(path, &len2)) != NULL); + ASSERT(len1 == len2); + ASSERT(memcmp(p1, p2, len1) == 0); + free(p1), free(p2); + remove(upload_filename); + } else { + ASSERT(0); + } + } else { + ASSERT(0); + } mg_printf(conn, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n\r\n%s", (int) strlen(upload_ok_message), upload_ok_message); @@ -227,7 +258,8 @@ static int begin_request_handler_cb(struct mg_connection *conn) { } if (!strcmp(ri->uri, "/upload")) { - ASSERT(mg_upload(conn, ".") == 1); + ASSERT(ri->query_string != NULL); + ASSERT(mg_upload(conn, ".") == atoi(ri->query_string)); } return 0; @@ -348,24 +380,27 @@ static void test_mg_upload(void) { static const char *boundary = "OOO___MY_BOUNDARY___OOO"; struct mg_context *ctx; struct mg_connection *conn; - char ebuf[100], buf[20], *file_data, *post_data = NULL; - int file_len, post_data_len; + char ebuf[100], buf[20], *file_data, *file2_data, *post_data; + int file_len, file2_len, post_data_len; ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL); + + // Upload one file ASSERT((file_data = read_file("mongoose.c", &file_len)) != NULL); + post_data = NULL; post_data_len = alloc_printf(&post_data, 0, "--%s\r\n" "Content-Disposition: form-data; " "name=\"file\"; " "filename=\"%s\"\r\n\r\n" "%.*s\r\n" - "--%s\r\n", + "--%s--\r\n", boundary, upload_filename, file_len, file_data, boundary); ASSERT(post_data_len > 0); ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1, ebuf, sizeof(ebuf), - "POST /upload HTTP/1.1\r\n" + "POST /upload?1 HTTP/1.1\r\n" "Content-Length: %d\r\n" "Content-Type: multipart/form-data; " "boundary=%s\r\n\r\n" @@ -375,6 +410,47 @@ static void test_mg_upload(void) { ASSERT(mg_read(conn, buf, sizeof(buf)) == (int) strlen(upload_ok_message)); ASSERT(memcmp(buf, upload_ok_message, strlen(upload_ok_message)) == 0); mg_close_connection(conn); + + // Upload two files + ASSERT((file_data = read_file("mongoose.h", &file_len)) != NULL); + ASSERT((file2_data = read_file("README.md", &file2_len)) != NULL); + post_data = NULL; + post_data_len = alloc_printf(&post_data, 0, + // First file + "--%s\r\n" + "Content-Disposition: form-data; " + "name=\"file\"; " + "filename=\"%s\"\r\n\r\n" + "%.*s\r\n" + + // Second file + "--%s\r\n" + "Content-Disposition: form-data; " + "name=\"file\"; " + "filename=\"%s\"\r\n\r\n" + "%.*s\r\n" + + // Final boundary + "--%s--\r\n", + boundary, upload_filename, + file_len, file_data, + boundary, upload_filename2, + file2_len, file2_data, + boundary); + ASSERT(post_data_len > 0); + ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1, + ebuf, sizeof(ebuf), + "POST /upload?2 HTTP/1.1\r\n" + "Content-Length: %d\r\n" + "Content-Type: multipart/form-data; " + "boundary=%s\r\n\r\n" + "%.*s", post_data_len, boundary, + post_data_len, post_data)) != NULL); + free(file_data), free(file2_data), free(post_data); + ASSERT(mg_read(conn, buf, sizeof(buf)) == (int) strlen(upload_ok_message)); + ASSERT(memcmp(buf, upload_ok_message, strlen(upload_ok_message)) == 0); + mg_close_connection(conn); + mg_stop(ctx); } @@ -666,6 +742,7 @@ int __cdecl main(void) { test_lua(); #endif - printf("%s\n", "PASSED"); - return 0; + printf("TOTAL TESTS: %d, FAILED: %d\n", s_total_tests, s_failed_tests); + + return s_failed_tests == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }