From 795c8720e54e3460f28d5310763463e500f7c46f Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Fri, 26 Jun 2026 18:57:58 +0300 Subject: [PATCH] testing: file_upload --- src/components/file_p/file_p.c | 13 ++- test/file_p/CMakeLists.txt | 21 +++- test/file_p/clear_file_from_sess.c | 2 +- test/file_p/extract_names_from_hash.c | 2 +- test/file_p/file_download.c | 17 +-- test/file_p/file_list.c | 2 +- test/file_p/file_receive_prepare.c | 2 +- test/file_p/file_send_prepare.c | 2 +- test/file_p/file_upload.c | 153 ++++++++++++++++++++++++++ 9 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 test/file_p/file_upload.c diff --git a/src/components/file_p/file_p.c b/src/components/file_p/file_p.c index b46128a..b346baf 100644 --- a/src/components/file_p/file_p.c +++ b/src/components/file_p/file_p.c @@ -366,7 +366,9 @@ void file_upload(session *sess) { int source_d = sess->sd; int dest_d = sess->fd; char buf[INBUFSIZE]; + int rlen = read(source_d, buf, INBUFSIZE); + if (rlen == 0) { if (sess->file->rest) { print_log(stdout, pl_error, "Error uploading file %s!\n", @@ -377,17 +379,26 @@ void file_upload(session *sess) { sess->state = OP_WAIT; return; } + if (sess->file->package_rest < rlen) { + /* TODO: wrap write function to give a proper response if the write is failed */ write(dest_d, buf, sess->file->package_rest); rlen -= sess->file->package_rest; sess->file->rest -= sess->file->package_rest; if (rlen == 0) return; + if (sess->file->rest == 0) + goto fin; s_file_pd_t *fpd = (s_file_pd_t *)(buf + sess->file->package_rest); switch (fpd->signal) { case sig_continue: rlen -= sizeof(s_file_pd_t); if (rlen > 0) { + if (rlen > sess->file->rest) { + rlen = sess->file->rest; + /* TODO: return back the extra data to the buffer in order to process + * it */ + } write(dest_d, buf + sess->file->package_rest + sizeof(s_file_pd_t), rlen); sess->file->rest -= rlen; @@ -412,7 +423,7 @@ void file_upload(session *sess) { sess->file->rest -= rlen; sess->file->package_rest -= rlen; } - +fin: if (!sess->file->rest) { print_log(stdout, pl_info, "File %s is uploaded to the server\n", sess->file->name); diff --git a/test/file_p/CMakeLists.txt b/test/file_p/CMakeLists.txt index a13c7de..196b871 100644 --- a/test/file_p/CMakeLists.txt +++ b/test/file_p/CMakeLists.txt @@ -100,4 +100,23 @@ target_link_libraries(file_download target_link_options(file_download PRIVATE -Wl,--wrap=print_log,--wrap=read,--wrap=write) -add_test(NAME file_p_file_download_test_1 COMMAND file_download) \ No newline at end of file +add_test(NAME file_p_file_download_test_1 COMMAND file_download) + +# ---/ file_upload /------------------------------------------- + +add_executable(file_upload + file_upload.c +) + +target_link_libraries(file_upload + cmocka + file_p + main + utils + client + test_utils +) + +target_link_options(file_upload PRIVATE -Wl,--wrap=print_log,--wrap=read,--wrap=write,--wrap=db_save_file,--wrap=session_send_string,--wrap=unlink) + +add_test(NAME file_p_file_upload_test_1 COMMAND file_upload) \ No newline at end of file diff --git a/test/file_p/clear_file_from_sess.c b/test/file_p/clear_file_from_sess.c index b50efa7..9a16977 100644 --- a/test/file_p/clear_file_from_sess.c +++ b/test/file_p/clear_file_from_sess.c @@ -7,7 +7,7 @@ #include #include -#include "utils.h" + #include #include #include diff --git a/test/file_p/extract_names_from_hash.c b/test/file_p/extract_names_from_hash.c index 6cbaaa1..cc4218d 100644 --- a/test/file_p/extract_names_from_hash.c +++ b/test/file_p/extract_names_from_hash.c @@ -7,7 +7,7 @@ #include #include -#include "utils.h" + #include #include #include diff --git a/test/file_p/file_download.c b/test/file_p/file_download.c index 80c338f..d4bb91e 100644 --- a/test/file_p/file_download.c +++ b/test/file_p/file_download.c @@ -1,5 +1,4 @@ #include "main.h" -#include "utils.h" #include #include #include @@ -8,22 +7,23 @@ #include #include #include -#include #include +#include dbuf_t *dbuf = NULL; #define FNAME "Test file" #define ITERATIONS 100 -#define FSIZE PACKAGE_SIZE *ITERATIONS +#define FSIZE PACKAGE_SIZE * ITERATIONS int read_ret_zero = 0; int write_ret_m_1 = 0; extern char *print_str; extern void *print_str_arr; ssize_t __wrap_read(int __fd, void *__buf, size_t __nbytes) { - if (read_ret_zero) + if (read_ret_zero) { + read_ret_zero = 0; return 0; - ssize_t _size = __nbytes; + } memset(__buf, 'e', __nbytes); return __nbytes; } @@ -62,7 +62,6 @@ void test__file_download__normal(void **state) { } assert_int_equal(sess.state, OP_WAIT); assert_ptr_equal(sess.file, NULL); - clear_file_from_sess(&sess); } void test__file_download__normal_alt_buf_size(void **state) { @@ -92,7 +91,6 @@ void test__file_download__normal_alt_buf_size(void **state) { } assert_int_equal(sess.state, OP_WAIT); assert_ptr_equal(sess.file, NULL); - clear_file_from_sess(&sess); } void test__file_download__cancel(void **state) { @@ -106,13 +104,11 @@ void test__file_download__cancel(void **state) { sess.file->path = malloc(sizeof(char) * INBUFSIZE); sess.file->description = malloc(sizeof(char) * INBUFSIZE); strcpy(sess.file->name, FNAME); - const char *fmt_args[] = {"Downloading of %s is canceled by the client\n", FNAME, NULL}; print_str_arr = fmt_args; - + while (sess.state != OP_WAIT) { - read_ret_zero = false; file_download(&sess); if (sess.state == OP_DOWNLOAD_WAIT_CONFIRM_PACKAGE) { download_confirm("cancel", &sess, NULL); @@ -139,7 +135,6 @@ void test__file_download__read_zero(void **state) { file_download(&sess); assert_int_equal(sess.state, OP_WAIT); assert_ptr_equal(sess.file, NULL); - read_ret_zero = false; } void test__file_download__read_write_m_1(void **state) { diff --git a/test/file_p/file_list.c b/test/file_p/file_list.c index a746128..9a45838 100644 --- a/test/file_p/file_list.c +++ b/test/file_p/file_list.c @@ -7,7 +7,7 @@ #include #include -#include "utils.h" + #include #include #include diff --git a/test/file_p/file_receive_prepare.c b/test/file_p/file_receive_prepare.c index 64da95e..3a77571 100644 --- a/test/file_p/file_receive_prepare.c +++ b/test/file_p/file_receive_prepare.c @@ -10,7 +10,7 @@ #include #include -#include "utils.h" + #include #include #include diff --git a/test/file_p/file_send_prepare.c b/test/file_p/file_send_prepare.c index 79f2171..be84756 100644 --- a/test/file_p/file_send_prepare.c +++ b/test/file_p/file_send_prepare.c @@ -7,7 +7,7 @@ #include #include -#include "utils.h" + #include #include #include diff --git a/test/file_p/file_upload.c b/test/file_p/file_upload.c new file mode 100644 index 0000000..d61e09a --- /dev/null +++ b/test/file_p/file_upload.c @@ -0,0 +1,153 @@ +#include "main.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FNAME "Test file" +#define ITERATIONS 100 +#define FSIZE PACKAGE_SIZE * ITERATIONS + +dbuf_t *dbuf = NULL; +int read_ret_zero = 0; +int write_ret_m_1 = 0; +size_t package_rest = 0; /* indicator for the write function */ +enum package_signal signal; +extern char *print_str; +extern void *print_str_arr; +char *str2snd; + +/* TODO: complete tasks in function and write new tests for them */ + +void __wrap_session_send_string(struct session *sess, const char *fmt, ...) { + assert_string_equal(fmt, str2snd); +} + +int __wrap_unlink(const char *__name) { + return 0; +} + +ssize_t __wrap_read(int __fd, void *__buf, size_t __nbytes) { + if (read_ret_zero) { + read_ret_zero = 0; + return 0; + } + + if (package_rest < __nbytes) { + size_t cp_rest = __nbytes - package_rest; + memset(__buf, 'e', package_rest); + s_file_pd_t fpd = {.signal = signal, .package_size = PACKAGE_SIZE}; + memcpy(__buf + package_rest, &fpd, sizeof(s_file_pd_t)); + memset(__buf + package_rest + sizeof(s_file_pd_t), 'e', cp_rest); + package_rest = PACKAGE_SIZE; + package_rest -= cp_rest - sizeof(s_file_pd_t); + size_t _package_rest = package_rest; + return __nbytes; + } + + package_rest -= __nbytes; + memset(__buf, 'e', __nbytes); + + return __nbytes; +} + +ssize_t __wrap_write(int __fd, const void *__buf, size_t __n) { + if (write_ret_m_1) + return -1; + dbuf_write(__buf, __n, &dbuf); + return __n; +} + +int32_t __wrap_db_save_file(session *s) { return 1; } + +void test__file_upload__normal(void **state) { + dbuf = dbuf_init(INBUFSIZE); + + session sess = {.state = OP_DOWNLOAD}; + sess.file = malloc(sizeof(s_file_t)); + sess.file->name = malloc(sizeof FNAME); + sess.file->size = sess.file->rest = FSIZE; + sess.file->package_rest = package_rest = PACKAGE_SIZE; + sess.file->path = malloc(sizeof(char) * INBUFSIZE); + sess.file->description = malloc(sizeof(char) * INBUFSIZE); + strcpy(sess.file->name, FNAME); + char cont_mes[64]; + str2snd = "finished\n"; + + const char *fmt_args[] = {"File %s is uploaded to the server\n", FNAME, NULL}; + print_str_arr = fmt_args; + + for (int i = 0; (sess.state != OP_WAIT) && (i < 2000000000); i++) { + file_upload(&sess); + } + assert_int_equal(sess.state, OP_WAIT); + assert_ptr_equal(sess.file, NULL); +} + +void test__file_upload__no_read(void **state) { + dbuf = dbuf_init(INBUFSIZE); + + session sess = {.state = OP_DOWNLOAD}; + sess.file = malloc(sizeof(s_file_t)); + sess.file->name = malloc(sizeof FNAME); + sess.file->size = sess.file->rest = FSIZE; + sess.file->package_rest = package_rest = PACKAGE_SIZE; + sess.file->path = malloc(sizeof(char) * INBUFSIZE); + sess.file->description = malloc(sizeof(char) * INBUFSIZE); + strcpy(sess.file->name, FNAME); + char cont_mes[64]; + read_ret_zero = true; + + const char *fmt_args[] = {"Error uploading file %s!\n", FNAME, NULL}; + print_str_arr = fmt_args; + + for (int i = 0; (sess.state != OP_WAIT) && (i < 2000000000); i++) { + file_upload(&sess); + } + assert_int_equal(sess.state, OP_WAIT); + assert_ptr_equal(sess.file, NULL); +} + +void test__file_upload__canceled(void **state) { + dbuf = dbuf_init(INBUFSIZE); + + session sess = {.state = OP_DOWNLOAD}; + sess.file = malloc(sizeof(s_file_t)); + sess.file->name = malloc(sizeof FNAME); + sess.file->size = sess.file->rest = FSIZE; + sess.file->package_rest = package_rest = PACKAGE_SIZE; + sess.file->path = malloc(sizeof(char) * INBUFSIZE); + sess.file->description = malloc(sizeof(char) * INBUFSIZE); + strcpy(sess.file->name, FNAME); + char cont_mes[64]; + + const char *fmt_args[] = {"Upload of %s is cancelled!\n", FNAME, NULL}; + print_str_arr = fmt_args; + + for (int i = 0; (sess.state != OP_WAIT) && (i < 2000000000); i++) { + if (i == 100) signal = sig_cancel; + file_upload(&sess); + } + assert_int_equal(sess.state, OP_WAIT); + assert_ptr_equal(sess.file, NULL); +} + +int setup(void **state) { return 0; } +int tear_down(void **state) { return 0; } + +int main(int argc, char **argv) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test__file_upload__normal), + cmocka_unit_test(test__file_upload__no_read), + cmocka_unit_test(test__file_upload__canceled), + }; + + return cmocka_run_group_tests(tests, setup, tear_down); +}