aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2019-11-13 16:48:03 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2019-11-13 16:48:03 -0500
commit244fa85e98fa6f325025f49aca6e1fbb1e440582 (patch)
tree502ab3bbfb49749fad1cfaa5f2e20268d3f5c5e4
parente801b594a18dbaf9283ad860c86e4a07b2b1e866 (diff)
downloadreloc-244fa85e98fa6f325025f49aca6e1fbb1e440582.tar.gz
Decouple main program and add initial tests
-rw-r--r--CMakeLists.txt16
-rw-r--r--main.c72
-rw-r--r--reloc.c69
-rw-r--r--test/CMakeLists.txt12
-rw-r--r--test/myassert.h11
-rw-r--r--test/test_reloc_match.c90
-rw-r--r--test/test_reloc_read.c38
7 files changed, 236 insertions, 72 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 583d65c..c718375 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,12 +1,22 @@
cmake_minimum_required(VERSION 2.8.11)
-project(reloc C)
+project(relocate C)
set(VERSION "1.0.0")
-
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra")
+enable_testing()
+add_subdirectory(test)
+
configure_file(version.h.in version.h)
+
include_directories("${CMAKE_BINARY_DIR}")
-add_executable(reloc main.c reloc.h)
+
+add_library(relocate
+ STATIC reloc.c)
+
+add_executable(reloc main.c)
+
+target_link_libraries(reloc relocate)
+
install(TARGETS reloc
RUNTIME DESTINATION bin)
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..07b9864
--- /dev/null
+++ b/main.c
@@ -0,0 +1,72 @@
+#include "reloc.h"
+
+
+void show_version() {
+ printf("%s\n", VERSION);
+}
+
+
+int main(int argc, char *argv[]) {
+ char *program = argv[0];
+ char *program_relative = strrchr(program, DIRSEP);
+ if (program_relative) {
+ program = program_relative + 1;
+ }
+
+ for (int i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-V")) {
+ show_version();
+ exit(0);
+ }
+ }
+
+ if (argc < 5) {
+ printf("usage: %s [-V] <str1> <str2> <input_file> <output_file>\n"
+ "\n"
+ "Options:\n"
+ "--version (-V) - Display version and exit\n"
+ "\n"
+ "Positional arguments:\n"
+ "str1 - Search string\n"
+ "str2 - Replacement string\n"
+ "input_file - Input file name\n"
+ "output_file - Output file name\n"
+ "\n"
+ "Example:\n"
+ "%s /original/string /new/string input.bin output.bin\n"
+ "\n", program, program);
+ exit(1);
+ }
+
+ char *needle = strdup(argv[1]);
+ char *replacement = strdup(argv[2]);
+ char *input_file = strdup(argv[3]);
+ char *output_file = strdup(argv[4]);
+ RelocData *info = reloc_read(input_file);
+ size_t records = 0;
+
+ for (size_t i = 0; i < info->size; i++) {
+ RelocMatch *match = NULL;
+ if (!(match = reloc_match(&info->data[i], needle))) {
+ // No match found
+ continue;
+ }
+ // Replace string
+ reloc_replace(match, replacement);
+ free(match);
+ records++;
+ }
+
+ // Write output file to disk
+ reloc_write(info, output_file);
+
+ // Report number of strings processed
+ printf(SIZE_T_FMT"\n", records);
+
+ free(needle);
+ free(replacement);
+ free(input_file);
+ free(output_file);
+ reloc_deinit_data(info);
+ return 0;
+}
diff --git a/reloc.c b/reloc.c
index ee3cc0b..f4d9ee2 100644
--- a/reloc.c
+++ b/reloc.c
@@ -113,72 +113,3 @@ void reloc_replace(RelocMatch *match, const char *rstr) {
// Destroy bytes between the end of the original data and the end of the replaced string
memset(data, '\0', post - data);
}
-
-
-void show_version() {
- printf("%s\n", VERSION);
-}
-
-
-int main(int argc, char *argv[]) {
- char *program = argv[0];
- char *program_relative = strrchr(program, DIRSEP);
- if (program_relative) {
- program = program_relative + 1;
- }
-
- for (int i = 0; i < argc; i++) {
- if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-V")) {
- show_version();
- exit(0);
- }
- }
-
- if (argc < 5) {
- printf("%s [-V] <str1> <str2> <input_file> <output_file>\n"
- "\n"
- "Arguments:\n"
- "--version (-V) - Display version and exit\n"
- "str1 - Pattern to search for\n"
- "str2 - Replace str1 with contents of str2\n"
- "input_file - Path to input file\n"
- "output_file - Path to output file\n"
- "\n"
- "Example:\n"
- "%s /original/path /new/path input.bin output.bin\n"
- "\n", program, program);
- exit(1);
- }
-
- char *needle = strdup(argv[1]);
- char *replacement = strdup(argv[2]);
- char *input_file = strdup(argv[3]);
- char *output_file = strdup(argv[4]);
- RelocData *info = reloc_read(input_file);
- size_t records = 0;
-
- for (size_t i = 0; i < info->size; i++) {
- RelocMatch *match = NULL;
- if (!(match = reloc_match(&info->data[i], needle))) {
- // No match found
- continue;
- }
- // Replace string
- reloc_replace(match, replacement);
- free(match);
- records++;
- }
-
- // Write output file to disk
- reloc_write(info, output_file);
-
- // Report number of strings processed
- printf(SIZE_T_FMT"\n", records);
-
- free(needle);
- free(replacement);
- free(input_file);
- free(output_file);
- reloc_deinit_data(info);
- return 0;
-}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..6b79d98
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,12 @@
+project(tests)
+
+include_directories("${CMAKE_SOURCE_DIR}")
+include_directories("${CMAKE_BINARY_DIR}")
+add_executable(test_reloc_match test_reloc_match.c)
+add_executable(test_reloc_read test_reloc_read.c)
+
+target_link_libraries(test_reloc_match relocate)
+target_link_libraries(test_reloc_read relocate)
+
+add_test(test_reloc_match test_reloc_match)
+add_test(test_reloc_read test_reloc_read)
diff --git a/test/myassert.h b/test/myassert.h
new file mode 100644
index 0000000..01e567e
--- /dev/null
+++ b/test/myassert.h
@@ -0,0 +1,11 @@
+#define myassert(message, condition) \
+ do { \
+ if (!(condition)) { \
+ fprintf(stderr, "%s:%d:%s :: %s\n", \
+ __FILE__, \
+ __LINE__, \
+ __FUNCTION__, \
+ message); \
+ return 1; \
+ } \
+ } while (0);
diff --git a/test/test_reloc_match.c b/test/test_reloc_match.c
new file mode 100644
index 0000000..bb9d6b0
--- /dev/null
+++ b/test/test_reloc_match.c
@@ -0,0 +1,90 @@
+#include "reloc.h"
+#include "myassert.h"
+
+char *test_cases[] = {
+ "I have a yellow pencil\x00",
+ "/one/two/three/four/five\x00\xAB\xCD\x00",
+ "\x09\x09\x09 1234567890\x00",
+ "123456789/0\x00",
+ NULL,
+};
+
+const char *test_patterns[] = {
+ "yellow",
+ "three",
+ "1234567890",
+ "/",
+ NULL,
+};
+
+const char *test_solution_begin[] = {
+ "yellow pencil",
+ "three/four/five",
+ "1234567890",
+ "/0",
+ NULL,
+};
+
+const char *test_solution_post[] = {
+ " pencil",
+ "/four/five",
+ "",
+ "0",
+ NULL,
+};
+
+const size_t test_solution_length[] = {
+ 6,
+ 5,
+ 10,
+ 1,
+};
+
+const size_t test_solution_post_length[] = {
+ 7,
+ 10,
+ 0,
+ 1,
+};
+
+const size_t test_solution_total_length[] = {
+ 13,
+ 15,
+ 10,
+ 2,
+};
+
+int test_reloc_match() {
+ for (int i = 0; test_cases[i] != NULL; i++) {
+ RelocMatch *match = NULL;
+ char *ptr = test_cases[i];
+
+ printf("case %d:\n", i);
+ while (*ptr != '\0') {
+ if (match) break;
+ printf("\tpattern=\"%s\", data=\"%s\"\n", test_patterns[i], ptr);
+ match = reloc_match(ptr, test_patterns[i]);
+ ptr++;
+ }
+ myassert("Failed to find pattern", match != NULL);
+ myassert("Invalid match->begin", !strcmp(match->begin, test_solution_begin[i]));
+ printf("\tend=\"%s\", data=\"%s\"\n", match->end, match->begin);
+ myassert("Invalid match->end", match->end != NULL);
+ printf("\tpost=\"%s\", data=\"%s\"\n", match->post, match->begin);
+ myassert("Invalid match->post", !strcmp(match->post, test_solution_post[i]));
+ printf("\tlength=%lu\n", match->length);
+ myassert("Invalid match->length", match->length == test_solution_length[i]);
+ printf("\tpost_length=%lu\n", match->post_length);
+ myassert("Invalid match->post_length", match->post_length == test_solution_post_length[i]);
+ printf("\ttotal_length=%lu\n", match->total_length);
+ myassert("Invalid match->total_length", match->total_length == test_solution_total_length[i]);
+ if (match) {
+ free(match);
+ }
+ }
+ return 0;
+}
+
+int main() {
+ return test_reloc_match();
+}
diff --git a/test/test_reloc_read.c b/test/test_reloc_read.c
new file mode 100644
index 0000000..310370d
--- /dev/null
+++ b/test/test_reloc_read.c
@@ -0,0 +1,38 @@
+#include "reloc.h"
+#include "myassert.h"
+
+const char *input_file = "input.bin";
+const char *output_file = "output.bin";
+char test_case[] =
+ "\xAB\xCD\xEF the quick brown fox\n\x00"
+ "jumps over\n\x00 \xEE\x09"
+ "\xAB\xCD\xEF the quick brown fox\n\x00"
+ "jumps over\n\x00 \xEE\x09"
+ "\xBBthe lazy\n\x00 dog\n"
+ "\xAB\xCD\xEF the quick brown fox\n\x00"
+ "\xBBthe lazy\n\x00 dog\n";
+
+
+int test_reloc_read() {
+ RelocData *info = NULL;
+ if (!(info = reloc_read(input_file))) {
+ fprintf(stderr, "Failed to open '%s' for writing\n", input_file);
+ return 1;
+ }
+ myassert("info->size is incorrect", info->size == sizeof(test_case));
+ myassert("info->path is incorrect", !strcmp(info->path, input_file));
+ myassert("info->data is uninitialized", info->data);
+ return 0;
+}
+
+int main() {
+ FILE *fp;
+ if (!(fp = fopen(input_file, "w+b"))) {
+ fprintf(stderr, "Failed to open '%s' for writing\n", input_file);
+ return 1;
+ }
+ fwrite(test_case, sizeof(char), sizeof(test_case), fp);
+ fclose(fp);
+
+ return test_reloc_read();
+}