diff --git a/CMakeLists.txt b/CMakeLists.txt index b3c29b9..d064ff7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) add_subdirectory(src) # Testing -enable_testing() +include(CTest) include(cmake/OptionsCMocka.cmake) add_subdirectory(external/cmocka) add_subdirectory(test) diff --git a/CMakePresets.json b/CMakePresets.json index 9948b42..f0935e1 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -10,7 +10,7 @@ "ZBBS_DEBUG": "ON", "CMAKE_BUILD_TYPE": "Debug" } - }, + }, { "name": "release", "displayName": "Release", diff --git a/Testing/Temporary/CTestCostData.txt b/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/Testing/Temporary/LastTest.log b/Testing/Temporary/LastTest.log new file mode 100644 index 0000000..4d976b1 --- /dev/null +++ b/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: Jun 12 15:32 EEST +---------------------------------------------------------- +End testing: Jun 12 15:32 EEST diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c4b247..e71b1a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(zbbs-server ) add_library(main INTERFACE) +add_library(types INTERFACE) target_sources(main PUBLIC @@ -18,6 +19,13 @@ target_sources(main main.h ) +target_sources(types + PUBLIC + FILE_SET HEADERS + FILES + types.h +) + add_subdirectory(libs) add_subdirectory(db) @@ -29,6 +37,9 @@ target_link_libraries(zbbs-server client db murmur3 + types + server + utils OpenSSL::Crypto ) diff --git a/src/components/CMakeLists.txt b/src/components/CMakeLists.txt index b57db15..1902ea3 100644 --- a/src/components/CMakeLists.txt +++ b/src/components/CMakeLists.txt @@ -1,2 +1,6 @@ add_subdirectory(client) -add_subdirectory(session) \ No newline at end of file +add_subdirectory(file_p) +add_subdirectory(session) +add_subdirectory(server) +add_subdirectory(utils) +add_subdirectory(user) \ No newline at end of file diff --git a/src/components/client/CMakeLists.txt b/src/components/client/CMakeLists.txt index 382b1d1..a72fbac 100644 --- a/src/components/client/CMakeLists.txt +++ b/src/components/client/CMakeLists.txt @@ -4,6 +4,9 @@ target_link_libraries(client PRIVATE db main + file_p + session + utils murmur3 OpenSSL::Crypto ) diff --git a/src/components/client/client.c b/src/components/client/client.c index c78c1b3..4be086b 100644 --- a/src/components/client/client.c +++ b/src/components/client/client.c @@ -1,11 +1,11 @@ /* SPDX-License-Identifier: MIT */ /* Copyright (c) 2026 Oleksandr Zhylin */ -#include "client.h" -#include "file_p.h" +#include +#include #include -#include "session.h" -#include "utils.h" +#include +#include #include #include #include diff --git a/src/components/file_p/CMakeLists.txt b/src/components/file_p/CMakeLists.txt new file mode 100644 index 0000000..45b5754 --- /dev/null +++ b/src/components/file_p/CMakeLists.txt @@ -0,0 +1,20 @@ +add_library(file_p STATIC) + +target_link_libraries(file_p + PRIVATE + db + main + murmur3 + utils + session + OpenSSL::Crypto +) + +target_sources(file_p + PRIVATE + file_p.c + PUBLIC + FILE_SET HEADERS + FILES + file_p.h +) diff --git a/src/file_p.c b/src/components/file_p/file_p.c similarity index 99% rename from src/file_p.c rename to src/components/file_p/file_p.c index cdf9b24..a05052f 100644 --- a/src/file_p.c +++ b/src/components/file_p/file_p.c @@ -1,16 +1,15 @@ /* SPDX-License-Identifier: MIT */ /* Copyright (c) 2026 Oleksandr Zhylin */ -#include "file_p.h" -#include "main.h" -#include "session.h" -#include "utils.h" #include #include #include #include +#include +#include #include #include +#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include char *extract_second_arg(char *); size_t get_file_size(char *, char *); diff --git a/src/file_p.h b/src/components/file_p/file_p.h similarity index 97% rename from src/file_p.h rename to src/components/file_p/file_p.h index 2033e40..0d02857 100644 --- a/src/file_p.h +++ b/src/components/file_p/file_p.h @@ -3,7 +3,7 @@ #ifndef FILEP_H #define FILEP_H -#include "main.h" +#include #include typedef struct { diff --git a/src/components/server/CMakeLists.txt b/src/components/server/CMakeLists.txt new file mode 100644 index 0000000..07b55a7 --- /dev/null +++ b/src/components/server/CMakeLists.txt @@ -0,0 +1,21 @@ +add_library(server STATIC) + +target_link_libraries(server + PRIVATE + db + main + utils + file_p + session + murmur3 + OpenSSL::Crypto +) + +target_sources(server + PRIVATE + server.c + PUBLIC + FILE_SET HEADERS + FILES + server.h +) diff --git a/src/server.c b/src/components/server/server.c similarity index 97% rename from src/server.c rename to src/components/server/server.c index cb1a07d..4d97533 100644 --- a/src/server.c +++ b/src/components/server/server.c @@ -1,11 +1,11 @@ /* SPDX-License-Identifier: MIT */ /* Copyright (c) 2026 Oleksandr Zhylin */ -#include "db.h" -#include "file_p.h" -#include "main.h" -#include "session.h" -#include "utils.h" +#include +#include +#include +#include +#include #include #include #include diff --git a/src/server.h b/src/components/server/server.h similarity index 93% rename from src/server.h rename to src/components/server/server.h index 4c759ba..c9c1ea6 100644 --- a/src/server.h +++ b/src/components/server/server.h @@ -3,7 +3,7 @@ #ifndef SERVER_H #define SERVER_H -#include "main.h" +#include int start_server(void); char *get_welcome_mes(void); void server_main_loop(server_data_t *); diff --git a/src/components/session/CMakeLists.txt b/src/components/session/CMakeLists.txt index 4fc88c6..712edcc 100644 --- a/src/components/session/CMakeLists.txt +++ b/src/components/session/CMakeLists.txt @@ -2,8 +2,12 @@ add_library(session STATIC) target_link_libraries(session PRIVATE - client db + user + main + utils + client + file_p murmur3 OpenSSL::Crypto ) diff --git a/src/components/session/session.c b/src/components/session/session.c index a46436a..feb9071 100644 --- a/src/components/session/session.c +++ b/src/components/session/session.c @@ -2,11 +2,11 @@ /* Copyright (c) 2026 Oleksandr Zhylin */ #include "session.h" -#include "../../client.h" -#include "../../file_p.h" -#include "../../main.h" -#include "../../user.h" -#include "../../utils.h" +#include +#include +#include +#include +#include #include #include #include @@ -94,45 +94,51 @@ int session_do_read(session *sess, char **read_str) { return 1; } +int query_extract_from_buf_2(char *buf, ssize_t *buf_used, char **output_line); + int query_extract_from_buf(session *sess, char **output_line) { - char *line; - int pos = -1; + // char *line; + // int pos = -1; - if (sess->buf_used > 0) { - char *cptr = strchr(sess->buf, '\n'); - if (cptr != NULL) - pos = cptr - sess->buf; - } else { - return 0; - } + // if (sess->buf_used > 0) { + // char *cptr = strchr(sess->buf, '\n'); + // if (cptr != NULL) + // pos = cptr - sess->buf; + // } else { + // return 0; + // } - if (pos == -1) { - int b_used = sess->buf_used; - sess->buf_used = 0; - line = malloc(b_used + 1); - strncpy(line, sess->buf, b_used); + // if (pos == -1) { + // int b_used = sess->buf_used; + // sess->buf_used = 0; + // line = malloc(b_used + 1); + // strncpy(line, sess->buf, b_used); - line[b_used] = 0; + // line[b_used] = 0; - *output_line = line; - return b_used; - } else { - line = malloc(pos + 2); - strncpy(line, sess->buf, pos + 1); - line[++pos] = 0; - sess->buf_used -= (pos); - if (!pos) - pos++; - memmove(sess->buf, sess->buf + pos, sess->buf_used); - sess->buf[sess->buf_used] = 0; - if (line[pos - 2] == '\r') { - line[pos - 2] = line[pos - 1]; - pos--; - line[pos - 1] = 0; - } - *output_line = line; - } - return pos + 1; + // *output_line = line; + // return b_used; + // } else { + // line = malloc(pos + 2); + // strncpy(line, sess->buf, pos + 1); + // line[++pos] = 0; + // sess->buf_used -= (pos); + // if (!pos) + // pos++; + // memmove(sess->buf, sess->buf + pos, sess->buf_used); + // sess->buf[sess->buf_used] = 0; + // if (line[pos - 2] == '\r') { + // line[pos - 2] = line[pos - 1]; + // pos--; + // line[pos] = 0; + // } + // *output_line = line; + // } + // return pos + 1; + ssize_t buf_used = sess->buf_used; + int ret = query_extract_from_buf_2(sess->buf, &buf_used, output_line); + sess->buf_used = buf_used; + return ret; } int query_extract_from_buf_2(char *buf, ssize_t *buf_used, char **output_line) { @@ -170,7 +176,7 @@ int query_extract_from_buf_2(char *buf, ssize_t *buf_used, char **output_line) { if (line[pos - 2] == '\r') { line[pos - 2] = line[pos - 1]; pos--; - line[pos - 1] = 0; + line[pos] = 0; } *output_line = line; *buf_used = _buf_used; diff --git a/src/components/session/session.h b/src/components/session/session.h index 3d992db..f296f57 100644 --- a/src/components/session/session.h +++ b/src/components/session/session.h @@ -3,7 +3,7 @@ #ifndef SESSION_H #define SESSION_H -#include "../../main.h" +#include #include int accept_client(int ls, session *connections[], char *wm); void session_send_string(struct session *sess, const char *str, ...); diff --git a/src/components/user/CMakeLists.txt b/src/components/user/CMakeLists.txt new file mode 100644 index 0000000..30c73f2 --- /dev/null +++ b/src/components/user/CMakeLists.txt @@ -0,0 +1,20 @@ +add_library(user STATIC) + +target_link_libraries(user + PRIVATE + client + db + murmur3 + main + session + OpenSSL::Crypto +) + +target_sources(user + PRIVATE + user.c + PUBLIC + FILE_SET HEADERS + FILES + user.h +) diff --git a/src/user.c b/src/components/user/user.c similarity index 98% rename from src/user.c rename to src/components/user/user.c index 9e4cc98..d286c42 100644 --- a/src/user.c +++ b/src/components/user/user.c @@ -2,8 +2,8 @@ /* Copyright (c) 2026 Oleksandr Zhylin */ #include -#include "main.h" -#include "session.h" +#include +#include #include #include #include diff --git a/src/user.h b/src/components/user/user.h similarity index 77% rename from src/user.h rename to src/components/user/user.h index 33e09bb..a94d3a3 100644 --- a/src/user.h +++ b/src/components/user/user.h @@ -7,4 +7,7 @@ #include "main.h" int login(session *sess, char *pass); int process_user_name(char *uname, session *sess); + +/* Testing */ +int32_t create_user(session *sess, char *line); #endif \ No newline at end of file diff --git a/src/components/utils/CMakeLists.txt b/src/components/utils/CMakeLists.txt new file mode 100644 index 0000000..19a3dfc --- /dev/null +++ b/src/components/utils/CMakeLists.txt @@ -0,0 +1,18 @@ +add_library(utils STATIC) + +target_link_libraries(utils + PRIVATE + client + db + murmur3 + OpenSSL::Crypto +) + +target_sources(utils + PRIVATE + utils.c + PUBLIC + FILE_SET HEADERS + FILES + utils.h +) diff --git a/src/utils.c b/src/components/utils/utils.c similarity index 100% rename from src/utils.c rename to src/components/utils/utils.c diff --git a/src/utils.h b/src/components/utils/utils.h similarity index 100% rename from src/utils.h rename to src/components/utils/utils.h diff --git a/src/db/CMakeLists.txt b/src/db/CMakeLists.txt index 8f799af..512661d 100644 --- a/src/db/CMakeLists.txt +++ b/src/db/CMakeLists.txt @@ -5,11 +5,15 @@ if (USE_POSTGRESQL) target_link_libraries(db PRIVATE PostgreSQL::PostgreSQL + main + utils ) else() target_link_libraries(db PRIVATE SQLite3::SQLite3 + main + utils ) endif() diff --git a/src/db/db_sqlite.c b/src/db/db_sqlite.c index 8a8f357..246d985 100644 --- a/src/db/db_sqlite.c +++ b/src/db/db_sqlite.c @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: MIT */ /* Copyright (c) 2026 Oleksandr Zhylin */ -#include "../main.h" -#include "../utils.h" +#include +#include #include "db_common.h" #include #include diff --git a/src/main.c b/src/main.c index 20a9de8..8058ba0 100644 --- a/src/main.c +++ b/src/main.c @@ -2,8 +2,8 @@ /* Copyright (c) 2026 Oleksandr Zhylin */ #include "main.h" -#include "server.h" -#include "utils.h" +#include +#include #include /* *** MAIN *** */ diff --git a/src/main.h b/src/main.h index 6ad81dd..d7d7ce2 100644 --- a/src/main.h +++ b/src/main.h @@ -5,7 +5,7 @@ #define MAIN_H #include #include -#include "types.h" +#include #define PORT 2000 #define MAX_CONNECTIONS 1024 #define INBUFSIZE 1024 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a5cc086..2b61e4c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(session) \ No newline at end of file +add_subdirectory(session) +add_subdirectory(user) \ No newline at end of file diff --git a/test/session/CMakeLists.txt b/test/session/CMakeLists.txt index 569a53a..1833746 100644 --- a/test/session/CMakeLists.txt +++ b/test/session/CMakeLists.txt @@ -1,12 +1,29 @@ -add_executable(session_app - session.c +# ---/ session_do_read /--------------------------------------------- + +add_executable(session_do_read + session_do_read.c ) -target_link_libraries(session_app +target_link_libraries(session_do_read cmocka session + main ) -target_link_options(session_app PRIVATE -Wl,--wrap=read) +target_link_options(session_do_read PRIVATE -Wl,--wrap=read) -add_test(session_test session_app) +add_test(NAME session_test_1 COMMAND session_do_read) + +# ---/ query_extract_from_buf /-------------------------------------- + +add_executable(query_extract_from_buf + query_extract_from_buf.c +) + +target_link_libraries(query_extract_from_buf + cmocka + session + main +) + +add_test(NAME session_test_2 COMMAND query_extract_from_buf) \ No newline at end of file diff --git a/test/session/query_extract_from_buf.c b/test/session/query_extract_from_buf.c new file mode 100644 index 0000000..11e6f02 --- /dev/null +++ b/test/session/query_extract_from_buf.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEST_BUF "First line\nThe second line\r\nThe third line\nFourth line\0" +#define SUBSTR_NUM 4 + +void test_query_extract_from_buf_filled(void **state) { + session sess = {.buf = TEST_BUF, .buf_used = sizeof TEST_BUF}; + char *lines[SUBSTR_NUM]; + for (int i = 0; i < SUBSTR_NUM; i++) { + query_extract_from_buf(&sess, &lines[i]); + } + assert_memory_equal("First line\n", lines[0], strlen(lines[0])); + assert_memory_equal("The second line\n", lines[1], strlen(lines[1])); + assert_memory_equal("The third line\n", lines[2], strlen(lines[2])); + assert_memory_equal("Fourth line", lines[3], strlen(lines[3])); + + for (int i = 0; i < SUBSTR_NUM; i++) { + free(lines[i]); + } +} + +void test_query_extract_from_buf_empty(void **state) { + session sess = {.buf = "", .buf_used = 0}; + char *line = NULL; + int ret = query_extract_from_buf(&sess, &line); + assert_null(line); + assert_int_equal(ret, 0); +} + +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_query_extract_from_buf_filled), + cmocka_unit_test(test_query_extract_from_buf_empty) + }; + + return cmocka_run_group_tests(tests, setup, tear_down); +} diff --git a/test/session/session.c b/test/session/session.c deleted file mode 100644 index a1bb0cf..0000000 --- a/test/session/session.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include "../../src/main.h" - -#define TEST_BUF "Hello world!\n" - -int __wrap_read(int fd, void *buf, size_t nbytes) { - return sizeof TEST_BUF - 1; -} - -void test_session_do_read(void** state) { - session sess = { - .buf = TEST_BUF, - .buf_used = sizeof TEST_BUF, - .sd = 2, - }; - char *str; - session_do_read(NULL, &str); - assert_memory_equal(str, TEST_BUF, sizeof (TEST_BUF)-1); -} - -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_session_do_read)}; - - return cmocka_run_group_tests(tests, setup, tear_down); -} diff --git a/test/session/session_do_read.c b/test/session/session_do_read.c new file mode 100644 index 0000000..9f57380 --- /dev/null +++ b/test/session/session_do_read.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TEST_BUF_USED "Voluptas voluptate reprehenderit eum voluptatibus.\n" +#define TEST_BUF_UNUSED \ + "Impedit et rerum ut aut vel nisi. Animi et vero nihil aut possimus " \ + "commodi. Autem dolorem et officia provident.\n" +#define TEST_BUF TEST_BUF_USED TEST_BUF_UNUSED + +int __wrap_read(int fd, void *buf, size_t nbytes) { + return sizeof TEST_BUF - 1; +} + +void test_session_do_read(void **state) { + session sess = { + .buf = TEST_BUF, + .buf_used = sizeof TEST_BUF, + .sd = 2, + }; + char *line; + session_do_read(&sess, &line); + assert_memory_equal(line, TEST_BUF_USED, sizeof(TEST_BUF_USED)); + free(line); +} + +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_session_do_read)}; + + return cmocka_run_group_tests(tests, setup, tear_down); +} diff --git a/test/user/CMakeLists.txt b/test/user/CMakeLists.txt new file mode 100644 index 0000000..8a04e92 --- /dev/null +++ b/test/user/CMakeLists.txt @@ -0,0 +1,33 @@ +# ---/ create_user /------------------------------------------------- + +add_executable(create_user + create_user.c +) + +target_link_libraries(create_user + cmocka + user + main + db +) + +target_link_options(create_user PRIVATE -Wl,--wrap=db_user_create,--wrap=session_send_string) + +add_test(NAME user_test_1 COMMAND create_user) + +# ---/ db_user_create /------------------------------------------------- + +add_executable(db_user_create + db_user_create.c +) + +target_link_libraries(db_user_create + cmocka + user + main + db +) + +target_link_options(db_user_create PRIVATE -Wl,--wrap=db_user_create,--wrap=session_send_string) + +add_test(NAME user_test_2 COMMAND db_user_create) diff --git a/test/user/create_user.c b/test/user/create_user.c new file mode 100644 index 0000000..cf3e187 --- /dev/null +++ b/test/user/create_user.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define UNAME "test_user" +#define PASS "1234" +#define EMAIL "test_user@test.com" + +int32_t __wrap_db_user_create(i_db_user_create *args) { return mock_type(int); } + +void __wrap_session_send_string(struct session *sess, const char *fmt, ...) {} + +/* TODO: divide into separate cases and check messages */ + +void test_create_user(void **state) { + session sess = {}; + i_db_user_create p; + int32_t ret = 0; + char line[sizeof "register" + sizeof UNAME + sizeof PASS + sizeof EMAIL + 5]; + sprintf(line, "register %s %s %s\n", UNAME, PASS, EMAIL); + /* Case: success */ + will_return(__wrap_db_user_create, 123); + ret = create_user(&sess, line); + assert_int_equal(ret, 123); + /* Case: username exist */ + will_return(__wrap_db_user_create, -2); + ret = create_user(&sess, line); + assert_int_equal(ret, -2); + /* Case: email exist */ + will_return(__wrap_db_user_create, -3); + ret = create_user(&sess, line); + assert_int_equal(ret, -3); + /* Case: error */ + will_return(__wrap_db_user_create, -4); + ret = create_user(&sess, line); + assert_int_equal(ret, -4); +} + +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_create_user)}; + + return cmocka_run_group_tests(tests, setup, tear_down); +} diff --git a/test/user/db_user_create.c b/test/user/db_user_create.c new file mode 100644 index 0000000..be71341 --- /dev/null +++ b/test/user/db_user_create.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define UNAME "test_user" +#define PASS "1234" +#define EMAIL "test_user@test.com" + +void __wrap_session_send_string(struct session *sess, const char *fmt, ...) {} + +int32_t __wrap_db_user_create(i_db_user_create *args) { + assert_memory_equal(args->uname, UNAME, strlen(args->uname)); + assert_memory_equal(args->pass, PASS, strlen(args->pass)); + assert_memory_equal(args->email, EMAIL, strlen(args->email)); + return mock_type(int); +} + +void test_create_user(void **state) { + session sess = {}; + i_db_user_create p; + int32_t ret = 0; + char line[sizeof "register" + sizeof UNAME + sizeof PASS + sizeof EMAIL + 5]; + sprintf(line, "register %s %s %s\n", UNAME, PASS, EMAIL); + will_return(__wrap_db_user_create, 123); + ret = create_user(&sess, line); + assert_int_equal(ret, 123); +} + +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_create_user)}; + + return cmocka_run_group_tests(tests, setup, tear_down); +}