From a51036bf447a699511452da773dc4fad02192849 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Tue, 28 Jun 2022 17:44:01 +0200 Subject: add unit tests for vdf & md5, allow escaped quotes --- src/CMakeLists.txt | 4 +++ src/cli/updater.c | 4 +-- src/hash/md5/CMakeLists.txt | 4 +++ src/hash/md5/tests/CMakeLists.txt | 7 ++++++ src/hash/md5/tests/md5cmp.c | 38 +++++++++++++++++++++++++++++ src/vdf/CMakeLists.txt | 6 ++++- src/vdf/tests/CMakeLists.txt | 22 +++++++++++++++++ src/vdf/tests/files/registry.vdf | 47 ++++++++++++++++++++++++++++++++++++ src/vdf/tests/index.c | 51 +++++++++++++++++++++++++++++++++++++++ src/vdf/tests/reparse.c | 35 +++++++++++++++++++++++++++ src/vdf/vdf.c | 7 +++++- 11 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 src/hash/md5/tests/CMakeLists.txt create mode 100644 src/hash/md5/tests/md5cmp.c create mode 100644 src/vdf/tests/CMakeLists.txt create mode 100644 src/vdf/tests/files/registry.vdf create mode 100644 src/vdf/tests/index.c create mode 100644 src/vdf/tests/reparse.c (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e11530..26279e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,6 +37,10 @@ target_link_libraries(tvn LINK_PUBLIC ${JSONC_LIBRARIES}) target_link_libraries(tvn LINK_PUBLIC md5) target_link_libraries(tvn LINK_PUBLIC vdf) +# frontends are included last so they will be +# put in the root of the build directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + if(BUILD_CLI) add_subdirectory(cli) endif() diff --git a/src/cli/updater.c b/src/cli/updater.c index 8b0cc03..ae86aa1 100644 --- a/src/cli/updater.c +++ b/src/cli/updater.c @@ -34,11 +34,11 @@ static void* thread_download(void* pinfo) struct file_info* file = &rev->files[i]; if (file->type == TYPE_WRITE) { - fprintf(stderr, "\rChecking %lu/%lu (%s)", i+1, rev->file_count, file->object); + fprintf(stderr, "\rChecking %zu/%zu (%s)", i+1, rev->file_count, file->object); if (verifyFileHash(of_dir, file)) { - fprintf(stderr, "\rDownloading %lu/%lu (%s)", i+1, rev->file_count, file->object); + fprintf(stderr, "\rDownloading %zu/%zu (%s)", i+1, rev->file_count, file->object); downloadObject(of_dir, remote, file); } } diff --git a/src/hash/md5/CMakeLists.txt b/src/hash/md5/CMakeLists.txt index ff560b1..6e2cb57 100644 --- a/src/hash/md5/CMakeLists.txt +++ b/src/hash/md5/CMakeLists.txt @@ -10,3 +10,7 @@ add_library(md5 STATIC ${MD5_SOURCES}) target_compile_options(md5 PUBLIC ${CFLAGS}) target_include_directories(md5 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/src/hash/md5/tests/CMakeLists.txt b/src/hash/md5/tests/CMakeLists.txt new file mode 100644 index 0000000..8b03af4 --- /dev/null +++ b/src/hash/md5/tests/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_executable(md5cmp md5cmp.c) +target_link_libraries(md5cmp md5) + +add_test(NAME md5_hash_test + COMMAND md5cmp ABCDEF 8827a41122a5028b9808c7bf84b9fcf6 + ) \ No newline at end of file diff --git a/src/hash/md5/tests/md5cmp.c b/src/hash/md5/tests/md5cmp.c new file mode 100644 index 0000000..a34de3a --- /dev/null +++ b/src/hash/md5/tests/md5cmp.c @@ -0,0 +1,38 @@ +/** + * Compares the hash of a given string against a + * given hash + * + * Used for testing to ensure we don't run into + * Windows weirdness again + */ +#include +#include +#include + +#include "md5.h" + + +int main(int argc, char** argv) +{ + if (argc < 3) + { + puts("md5cmp input expected-hash"); + return 1; + } + + MD5_CTX context; + MD5_Init(&context); + MD5_Update(&context, argv[1], strlen(argv[1])); + + unsigned char digest[16]; + MD5_Final(digest, &context); + + char md5string[33]; + for(int i = 0; i < 16; ++i) + snprintf(&md5string[i*2], 3, "%02x", (unsigned int)digest[i]); + + if (!strncmp(md5string, argv[2], sizeof(md5string))) + return 0; + + return 1; +} \ No newline at end of file diff --git a/src/vdf/CMakeLists.txt b/src/vdf/CMakeLists.txt index a3a4387..bb1412d 100644 --- a/src/vdf/CMakeLists.txt +++ b/src/vdf/CMakeLists.txt @@ -1,6 +1,6 @@ list(APPEND - VDF_SOURCES + VDF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/vdf.h ${CMAKE_CURRENT_SOURCE_DIR}/vdf.c ) @@ -9,3 +9,7 @@ add_library(vdf STATIC ${VDF_SOURCES}) target_compile_options(vdf PUBLIC ${CFLAGS}) target_include_directories(vdf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/src/vdf/tests/CMakeLists.txt b/src/vdf/tests/CMakeLists.txt new file mode 100644 index 0000000..c055c64 --- /dev/null +++ b/src/vdf/tests/CMakeLists.txt @@ -0,0 +1,22 @@ + +add_executable(vdf_reparse reparse.c) +target_link_libraries(vdf_reparse vdf) + +add_test(NAME vdf_reparse_run + COMMAND + vdf_reparse ${CMAKE_CURRENT_SOURCE_DIR}/files/registry.vdf reparsed_registry.vdf + ) + +add_test(NAME vdf_reparse_compare + COMMAND + ${CMAKE_COMMAND} -E compare_files --ignore-eol ${CMAKE_CURRENT_SOURCE_DIR}/files/registry.vdf reparsed_registry.vdf + ) + +add_executable(vdf_index index.c) +target_link_libraries(vdf_index vdf) + +add_test(NAME vdf_index_test + COMMAND + vdf_index ${CMAKE_CURRENT_SOURCE_DIR}/files/registry.vdf HKCU Software Valve Steam steamglobal language + ) + diff --git a/src/vdf/tests/files/registry.vdf b/src/vdf/tests/files/registry.vdf new file mode 100644 index 0000000..0e400bf --- /dev/null +++ b/src/vdf/tests/files/registry.vdf @@ -0,0 +1,47 @@ +"Registry" +{ + "HKCU" + { + "Software" + { + "Valve" + { + "Steam" + { + "empty" + { + } + "slash-test" + { + "key\"string" "value\"string" + } + "steamglobal" + { + "language" "english" + } + "Apps" + { + "10090" + { + "installed" "1" + "Updating" "0" + "Running" "0" + } + "1245040" + { + "installed" "1" + "Updating" "0" + "Running" "0" + } + "287700" + { + "installed" "1" + "Updating" "0" + "Running" "0" + } + } + } + } + } + } +} diff --git a/src/vdf/tests/index.c b/src/vdf/tests/index.c new file mode 100644 index 0000000..c3f96b1 --- /dev/null +++ b/src/vdf/tests/index.c @@ -0,0 +1,51 @@ +/** + * a command line utility that parses a given + * vdf file and indexes requested values by key + * + * Returns 0 if value is a string otherwise 1 + * + * Used for testing to ensure indexing works reliably + * on a known file + */ +#include + +#include "vdf.h" + +int main(int argc, char** argv) +{ + if (argc < 2) + { + puts("vdf_index file index [index...]"); + return 1; + } + + struct vdf_object* o = vdf_parse_file(argv[1]); + + if (!o) + { + puts("Invalid File"); + return 1; + } + + struct vdf_object* k = o; + for (int i = 2; i < argc; ++i) + { + k = vdf_object_index_array_str(k, argv[i]); + if (!k) + { + printf("Invalid index '%s'\n", argv[i]); + break; + } + } + + int retval = k->type != VDF_TYPE_STRING; + + if (retval) + vdf_print_object(k); + else + puts(k->data.data_string.str); + + vdf_free_object(o); + + return retval; +} \ No newline at end of file diff --git a/src/vdf/tests/reparse.c b/src/vdf/tests/reparse.c new file mode 100644 index 0000000..94da4ca --- /dev/null +++ b/src/vdf/tests/reparse.c @@ -0,0 +1,35 @@ +/** + * a command line utility that parses a given + * vdf file and and output it pretty printed + * onto stdout or a specified file + * + * Used for testing to ensure we parse a VDF + * file correctly and can output the same + */ +#include + +#include "vdf.h" + +int main(int argc, char** argv) +{ + if (argc < 2) + { + puts("vdf_reparse file [output]"); + return 1; + } + else if (argc > 2) + { + freopen(argv[2], "w", stdout); + } + + struct vdf_object* o = vdf_parse_file(argv[1]); + + if (!o) + { + puts("Invalid File"); + return 1; + } + vdf_print_object(o); + + vdf_free_object(o); +} \ No newline at end of file diff --git a/src/vdf/vdf.c b/src/vdf/vdf.c index 160577f..2708a5d 100644 --- a/src/vdf/vdf.c +++ b/src/vdf/vdf.c @@ -43,6 +43,9 @@ struct vdf_object* vdf_parse_buffer(const char* buffer, size_t size) switch (*tail) { case CHAR_DOUBLE_QUOTE: + if (tail > buffer && *(tail-1) == CHAR_BACKSLASH) + break; + if (!buf) { buf = tail+1; @@ -115,7 +118,9 @@ struct vdf_object* vdf_parse_buffer(const char* buffer, size_t size) else { size_t len = tail - buf; - o->key = strndup(buf, len); + o->key = malloc(len+1); + strncpy(o->key, buf, len); + o->key[len] = '\0'; buf = NULL; } break; -- cgit v1.2.3