From 226222c9c52fd2b73eac3855b3ddaf5f02d7dc02 Mon Sep 17 00:00:00 2001 From: rexim Date: Mon, 26 Jan 2026 21:22:31 +0700 Subject: [PATCH 1/4] Init v3.2.0 --- nob.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nob.h b/nob.h index eb0a140..5067643 100644 --- a/nob.h +++ b/nob.h @@ -1,4 +1,4 @@ -/* nob - v3.1.0 - Public Domain - https://github.com/tsoding/nob.h +/* nob - v3.2.0 - Public Domain - https://github.com/tsoding/nob.h This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea. @@ -2651,6 +2651,7 @@ NOBDEF char *nob_temp_running_executable_path(void) /* Revision history: + 3.2.0 ( ) 3.1.0 (2026-01-22) Make nob_delete_file() be able to delete empty dir on Windows (by @rexim) Introduce Directory Entry API - similar to POSIX dirent but with names that don't collide - Nob_Dir_Entry From 708e421a3559c1d593bcb3726fb075b21e15a822 Mon Sep 17 00:00:00 2001 From: rexim Date: Mon, 26 Jan 2026 21:25:42 +0700 Subject: [PATCH 2/4] Introduce Chain API --- nob.c | 1 + nob.h | 272 ++++++++++++++++++++++++++++++++++++++++- tests/chain.c | 120 ++++++++++++++++++ tests/chain.stderr.txt | 6 + tests/chain.stdout.txt | 3 + 5 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 tests/chain.c create mode 100644 tests/chain.stderr.txt create mode 100644 tests/chain.stdout.txt diff --git a/nob.c b/nob.c index 40e45ce..e271df5 100644 --- a/nob.c +++ b/nob.c @@ -27,6 +27,7 @@ const char *test_names[] = { "temp_running_executable_path", "no_echo", "cmd_run_dont_reset", + "chain", }; #define test_names_count ARRAY_LEN(test_names) diff --git a/nob.h b/nob.h index 5067643..0dce610 100644 --- a/nob.h +++ b/nob.h @@ -411,6 +411,11 @@ NOBDEF void nob_dir_entry_close(Nob_Dir_Entry dir); // ``` #define nob_da_foreach(Type, it, da) for (Type *it = (da)->items; it < (da)->items + (da)->count; ++it) +// The Fixed Array append. `items` fields must be a fixed size array. Its size determines the capacity. +#define nob_fa_append(fa, item) \ + (NOB_ASSERT((fa)->count < NOB_ARRAY_LEN((fa)->items)), \ + (fa)->items[(fa)->count++] = (item)) + typedef struct { char *items; size_t count; @@ -470,6 +475,13 @@ NOBDEF Nob_Fd nob_fd_open_for_read(const char *path); NOBDEF Nob_Fd nob_fd_open_for_write(const char *path); NOBDEF void nob_fd_close(Nob_Fd fd); +typedef struct { + Nob_Fd read; + Nob_Fd write; +} Nob_Pipe; + +NOBDEF bool nob_pipe_create(Nob_Pipe *pp); + typedef struct { Nob_Proc *items; size_t count; @@ -519,6 +531,71 @@ typedef struct { // Run the command with options. NOBDEF bool nob_cmd_run_opt(Nob_Cmd *cmd, Nob_Cmd_Opt opt); +// Command Chains (in Shell Scripting they are know as Pipes) +// +// Usage: +// ```c +// Nob_Cmd cmd = {0}; +// Nob_Chain chain = {0}; +// if (!nob_chain_begin(&chain)) return 1; +// { +// nob_cmd_append(&cmd, "echo", "Hello, World"); +// if (!nob_chain_cmd(&chain, &cmd)) return 1; +// +// nob_cmd_append(&cmd, "rev"); +// if (!nob_chain_cmd(&chain, &cmd)) return 1; +// +// nob_cmd_append(&cmd, "xxd"); +// if (!nob_chain_cmd(&chain, &cmd)) return 1; +// } +// if (!nob_chain_end(&chain)) return 1; +// ``` +// +// The above is equivalent to a shell command: +// +// ```sh +// echo "Hello, World" | rev | xxd +// ``` +// +// After nob_chain_end() the Nob_Chain struct can be reused again. +// +// The fields of the Nob_Chain struct contain the intermediate state of the Command +// Chain that is being built with the nob_chain_cmd() calls and generally have no +// particular use for the user. +// +// The only memory dynamically allocated within Nob_Chain belongs to the .cmd field. +// So if you want to clean it all up you can just do free(chain.cmd.items). +typedef struct { + // The file descriptor of the output of the previous command. Will be used as the input for the next command. + Nob_Fd fdin; + // The command from the last nob_chain_cmd() call. + Nob_Cmd cmd; + // The value of the optional .err2out parameter from the last nob_chain_cmd() call. + bool err2out; +} Nob_Chain; + +typedef struct { + const char *stdin_path; +} Nob_Chain_Begin_Opt; +#define nob_chain_begin(chain, ...) nob_chain_begin_opt((chain), (Nob_Chain_Begin_Opt) { __VA_ARGS__ }) +NOBDEF bool nob_chain_begin_opt(Nob_Chain *chain, Nob_Chain_Begin_Opt opt); + +typedef struct { + bool err2out; + bool dont_reset; +} Nob_Chain_Cmd_Opt; +#define nob_chain_cmd(chain, cmd, ...) nob_chain_cmd_opt((chain), (cmd), (Nob_Chain_Cmd_Opt) { __VA_ARGS__ }) +NOBDEF bool nob_chain_cmd_opt(Nob_Chain *chain, Nob_Cmd *cmd, Nob_Chain_Cmd_Opt opt); + +typedef struct { + Nob_Procs *async; + size_t max_procs; + const char *stdout_path; + const char *stderr_path; +} Nob_Chain_End_Opt; +#define nob_chain_end(chain, ...) nob_chain_end_opt((chain), (Nob_Chain_End_Opt) { __VA_ARGS__ }) +NOBDEF bool nob_chain_end_opt(Nob_Chain *chain, Nob_Chain_End_Opt opt); + // Get amount of processors on the machine. NOBDEF int nob_nprocs(void); @@ -1169,6 +1246,143 @@ NOBDEF bool nob_cmd_run_opt(Nob_Cmd *cmd, Nob_Cmd_Opt opt) return result; } +NOBDEF bool nob_chain_begin_opt(Nob_Chain *chain, Nob_Chain_Begin_Opt opt) +{ + chain->cmd.count = 0; + chain->err2out = false; + chain->fdin = NOB_INVALID_FD; + if (opt.stdin_path) { + chain->fdin = nob_fd_open_for_read(opt.stdin_path); + if (chain->fdin == NOB_INVALID_FD) return false; + } + return true; +} + +NOBDEF bool nob_chain_cmd_opt(Nob_Chain *chain, Nob_Cmd *cmd, Nob_Chain_Cmd_Opt opt) +{ + bool result = true; + Nob_Pipe pp = {0}; + struct { + Nob_Fd items[5]; // should be no more than 3, but we allocate 5 just in case + size_t count; + } fds = {0}; + + NOB_ASSERT(cmd->count > 0); + + if (chain->cmd.count != 0) { // not first cmd in the chain + Nob_Fd *pfdin = NULL; + if (chain->fdin != NOB_INVALID_FD) { + nob_fa_append(&fds, chain->fdin); + pfdin = &chain->fdin; + } + if (!nob_pipe_create(&pp)) nob_return_defer(false); + nob_fa_append(&fds, pp.write); + Nob_Fd *pfdout = &pp.write; + Nob_Fd *pfderr = chain->err2out ? pfdout : NULL; + + Nob_Proc proc = nob__cmd_start_process(chain->cmd, pfdin, pfdout, pfderr); + chain->cmd.count = 0; + if (proc == NOB_INVALID_PROC) { + nob_fa_append(&fds, pp.read); + nob_return_defer(false); + } + chain->fdin = pp.read; + } + + nob_da_append_many(&chain->cmd, cmd->items, cmd->count); + chain->err2out = opt.err2out; + +defer: + for (size_t i = 0; i < fds.count; ++i) { + nob_fd_close(fds.items[i]); + } + if (!opt.dont_reset) cmd->count = 0; + return result; +} + +static Nob_Fd nob__fd_stdout(void) +{ +#ifdef _WIN32 + return GetStdHandle(STD_OUTPUT_HANDLE); +#else + return STDOUT_FILENO; +#endif // _WIN32 +} + +NOBDEF bool nob_chain_end_opt(Nob_Chain *chain, Nob_Chain_End_Opt opt) +{ + bool result = true; + + Nob_Fd *pfdin = NULL; + struct { + Nob_Fd items[5]; // should be no more than 3, but we allocate 5 just in case + size_t count; + } fds = {0}; + + if (chain->fdin != NOB_INVALID_FD) { + nob_fa_append(&fds, chain->fdin); + pfdin = &chain->fdin; + } + + if (chain->cmd.count != 0) { // Non-empty chain case + size_t max_procs = opt.max_procs > 0 ? opt.max_procs : (size_t) nob_nprocs() + 1; + + if (opt.async && max_procs > 0) { + while (opt.async->count >= max_procs) { + for (size_t i = 0; i < opt.async->count; ++i) { + int ret = nob__proc_wait_async(opt.async->items[i], 1); + if (ret < 0) nob_return_defer(false); + if (ret) { + nob_da_remove_unordered(opt.async, i); + break; + } + } + } + } + + Nob_Fd fdout = nob__fd_stdout(); + if (opt.stdout_path) { + fdout = nob_fd_open_for_write(opt.stdout_path); + if (fdout == NOB_INVALID_FD) nob_return_defer(false); + nob_fa_append(&fds, fdout); + } + + Nob_Fd fderr = 0; + Nob_Fd *pfderr = NULL; + if (chain->err2out) pfderr = &fdout; + if (opt.stderr_path) { + if (pfderr == NULL) { + fderr = nob_fd_open_for_write(opt.stderr_path); + if (fderr == NOB_INVALID_FD) nob_return_defer(false); + nob_fa_append(&fds, fderr); + pfderr = &fderr; + } else { + // There was err2out set for the last command. + // All the stderr will go to stdout. + // So the stderr file is going to be empty. + NOB_ASSERT(chain->err2out); + if (!nob_write_entire_file(opt.stderr_path, NULL, 0)) nob_return_defer(false); + } + } + + Nob_Proc proc = nob__cmd_start_process(chain->cmd, pfdin, &fdout, pfderr); + chain->cmd.count = 0; + + if (opt.async) { + if (proc == NOB_INVALID_PROC) nob_return_defer(false); + nob_da_append(opt.async, proc); + } else { + if (!nob_proc_wait(proc)) nob_return_defer(false); + } + } + +defer: + for (size_t i = 0; i < fds.count; ++i) { + nob_fd_close(fds.items[i]); + } + return result; +} + // The maximum time span representable is 584 years. NOBDEF uint64_t nob_nanos_since_unspecified_epoch(void) { @@ -1398,6 +1612,35 @@ NOBDEF void nob_fd_close(Nob_Fd fd) #endif // _WIN32 } +NOBDEF bool nob_pipe_create(Nob_Pipe *pp) +{ +#ifdef _WIN32 + // https://docs.microsoft.com/en-us/windows/win32/ProcThread/creating-a-child-process-with-redirected-input-and-output + + SECURITY_ATTRIBUTES saAttr = {0}; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + + if (!CreatePipe(&pp->read, &pp->write, &saAttr, 0)) { + nob_log(NOB_ERROR, "Could not create pipe: %s", nob_win32_error_message(GetLastError())); + return false; + } + + return true; +#else + int pipefd[2]; + if (pipe(pipefd) < 0) { + nob_log(NOB_ERROR, "Could not create pipe: %s\n", strerror(errno)); + return false; + } + + pp->read = pipefd[0]; + pp->write = pipefd[1]; + + return true; +#endif // _WIN32 +} + NOBDEF bool nob_procs_wait(Nob_Procs procs) { bool success = true; @@ -2568,6 +2811,7 @@ NOBDEF char *nob_temp_running_executable_path(void) #define da_last nob_da_last #define da_remove_unordered nob_da_remove_unordered #define da_foreach nob_da_foreach + #define fa_append nob_fa_append #define swap nob_swap #define String_Builder Nob_String_Builder #define read_entire_file nob_read_entire_file @@ -2581,6 +2825,18 @@ NOBDEF char *nob_temp_running_executable_path(void) #define Proc Nob_Proc #define INVALID_PROC NOB_INVALID_PROC #define Fd Nob_Fd + #define Pipe Nob_Pipe + #define pipe_create nob_pipe_create + #define Chain Nob_Chain + #define Chain_Begin_Opt Nob_Chain_Begin_Opt + #define chain_begin nob_chain_begin + #define chain_begin_opt nob_chain_begin_opt + #define Chain_Cmd_Opt Nob_Chain_Cmd_Opt + #define chain_cmd nob_chain_cmd + #define chain_cmd_opt nob_chain_cmd_opt + #define Chain_End_Opt Nob_Chain_End_Opt + #define chain_end nob_chain_end + #define chain_end_opt nob_chain_end_opt #define INVALID_FD NOB_INVALID_FD #define fd_open_for_read nob_fd_open_for_read #define fd_open_for_write nob_fd_open_for_write @@ -2651,7 +2907,21 @@ NOBDEF char *nob_temp_running_executable_path(void) /* Revision history: - 3.2.0 ( ) + 3.2.0 ( ) Introduce Chain API + - Nob_Chain + - Nob_Chain_Begin_Opt + - nob_chain_begin() + - nob_chain_begin_opt() + - Nob_Chain_Cmd_Opt + - nob_chain_cmd() + - nob_chain_cmd_opt() + - Nob_Chain_End_Opt + - nob_chain_end() + - nob_chain_end_opt() + Introduce some auxiliary things that were used in Chain API implementation, but might be useful outside of it: + - Nob_Pipe + - nob_pipe_create() + - nob_fa_append() 3.1.0 (2026-01-22) Make nob_delete_file() be able to delete empty dir on Windows (by @rexim) Introduce Directory Entry API - similar to POSIX dirent but with names that don't collide - Nob_Dir_Entry diff --git a/tests/chain.c b/tests/chain.c new file mode 100644 index 0000000..12e1d92 --- /dev/null +++ b/tests/chain.c @@ -0,0 +1,120 @@ +#define NOB_IMPLEMENTATION +#include "nob.h" + +Cmd cmd = {0}; +Chain chain = {0}; +Procs procs = {0}; + +const char *hello_src = + "#include \n" + "\n" + "int main()\n" + "{\n" + " fprintf(stdout, \"Hello to stdout\\n\");\n" + " fprintf(stderr, \"Hello to stderr\\n\");\n" + " return 0;\n" + "}\n"; + +const char *rot13_src = + "#include \n" + "\n" + "char rot13(char x)\n" + "{\n" + " if ('a' <= x && x <= 'z') return ((x - 'a') + 13) % 26 + 'a';\n" + " if ('A' <= x && x <= 'Z') return ((x - 'A') + 13) % 26 + 'A';\n" + " return x;\n" + "}\n" + "\n" + "#define BUFFER_SIZE (1024)\n" + "\n" + "char buffer[BUFFER_SIZE];\n" + "\n" + "int main(void)\n" + "{\n" + " while (!feof(stdin)) {\n" + " size_t n = fread(buffer, sizeof(buffer[0]), BUFFER_SIZE, stdin);\n" + " for (size_t i = 0; i < n; ++i) {\n" + " buffer[i] = rot13(buffer[i]);\n" + " }\n" + " fwrite(buffer, sizeof(buffer[0]), n, stdout);\n" + " }\n" + "\n" + " return 0;\n" + "}\n"; + +const char *hex_src = + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#define COLUMNS 16\n" + "#define PADDING 6\n" + "\n" + "uint8_t buffer[COLUMNS];\n" + "\n" + "int main(void)\n" + "{\n" + " while (!feof(stdin)) {\n" + " size_t n = fread(buffer, sizeof(buffer[0]), COLUMNS, stdin);\n" + "\n" + " for (size_t i = 0; i < n; ++i) {\n" + " printf(\"%02X \", buffer[i]);\n" + " if (!isprint(buffer[i])) buffer[i] = '.';\n" + " }\n" + "\n" + " assert(n <= COLUMNS);\n" + " printf(\"%*s\", (int) (PADDING + (COLUMNS - n) * 3), \"\");\n" + "\n" + " fwrite(buffer, sizeof(buffer[0]), n, stdout);\n" + " printf(\"\\n\");\n" + " }\n" + "\n" + " return 0;\n" + "}\n"; + +bool build_tool_async(const char *bin_path, const char *src_path, const char *src) +{ + if (!write_entire_file(src_path, src, strlen(src))) return 1; + + nob_cc(&cmd); + nob_cc_flags(&cmd); + nob_cc_output(&cmd, bin_path); + nob_cc_inputs(&cmd, src_path); + return cmd_run(&cmd, .async = &procs); +} + +int main(void) +{ + if (!build_tool_async("./hello", "hello.c", hello_src)) return 1; + if (!build_tool_async("./rot13", "rot13.c", rot13_src)) return 1; + if (!build_tool_async("./hex", "hex.c", hex_src)) return 1; + if (!procs_flush(&procs)) return 1; + + if (!chain_begin(&chain)) return 1; + { + cmd_append(&cmd, "./hello"); + if (!chain_cmd(&chain, &cmd, .err2out = true)) return 1; + + cmd_append(&cmd, "./rot13"); + if (!chain_cmd(&chain, &cmd)) return 1; + + cmd_append(&cmd, "./hex"); + if (!chain_cmd(&chain, &cmd)) return 1; + } + if (!chain_end(&chain, + .async = &procs, + .stdout_path = "output.txt", + )) return 1; + + if (!procs_flush(&procs)) return 1; + + String_Builder sb = {0}; + if (!read_entire_file("output.txt", &sb)) return 1; + + String_View sv = sb_to_sv(sb); + printf(SV_Fmt, SV_Arg(sv)); + + return 0; +} diff --git a/tests/chain.stderr.txt b/tests/chain.stderr.txt new file mode 100644 index 0000000..b8f8298 --- /dev/null +++ b/tests/chain.stderr.txt @@ -0,0 +1,6 @@ +[INFO] CMD: cc -Wall -Wextra -o ./hello hello.c +[INFO] CMD: cc -Wall -Wextra -o ./rot13 rot13.c +[INFO] CMD: cc -Wall -Wextra -o ./hex hex.c +[INFO] CMD: ./hello +[INFO] CMD: ./rot13 +[INFO] CMD: ./hex diff --git a/tests/chain.stdout.txt b/tests/chain.stdout.txt new file mode 100644 index 0000000..e80fc8a --- /dev/null +++ b/tests/chain.stdout.txt @@ -0,0 +1,3 @@ +55 72 79 79 62 20 67 62 20 66 67 71 72 65 65 0A Uryyb gb fgqree. +55 72 79 79 62 20 67 62 20 66 67 71 62 68 67 0A Uryyb gb fgqbhg. + From 69ee28f86d7e522fbca90159392bce5597a29549 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 27 Jan 2026 05:45:51 +0700 Subject: [PATCH 3/4] Implement record/replay for Windows --- .gitignore | 4 +- how_to/nob.c | 4 - nob.c | 144 ++++++++++-------- shared.h | 29 +++- tests/chain.c | 20 +-- tests/chain.stderr.txt | 6 - tests/chain.win32.stdout.txt | 3 + tests/cmd_args_passing.c | 11 +- tests/cmd_args_passing.stderr.txt | 2 - tests/cmd_args_passing.win32.stdout.txt | 5 + tests/cmd_redirect.c | 31 +--- tests/cmd_redirect.stderr.txt | 3 - tests/cmd_redirect.stdout.txt | 1 + tests/cmd_redirect.win32.stdout.txt | 1 + tests/cmd_run_dont_reset.c | 25 +-- tests/cmd_run_dont_reset.stderr.txt | 10 -- tests/cmd_run_dont_reset.stdout.txt | 6 + tests/cmd_run_dont_reset.win32.stdout.txt | 6 + tests/da_append.c | 5 +- tests/da_append.stderr.txt | 10 -- tests/da_append.stdout.txt | 10 ++ tests/da_append.win32.stdout.txt | 10 ++ tests/da_foreach.c | 5 +- tests/da_foreach.stderr.txt | 3 - tests/da_foreach.stdout.txt | 3 + tests/da_foreach.win32.stdout.txt | 3 + tests/da_last.c | 5 +- tests/da_last.stderr.txt | 6 - tests/da_last.stdout.txt | 5 + tests/da_last.win32.stdout.txt | 5 + tests/da_remove_unordered.c | 5 +- tests/da_remove_unordered.stderr.txt | 4 - tests/da_remove_unordered.stdout.txt | 4 + tests/da_remove_unordered.win32.stdout.txt | 4 + tests/da_resize.c | 9 +- tests/da_resize.stderr.txt | 3 - tests/da_resize.stdout.txt | 3 + tests/da_resize.win32.stdout.txt | 3 + tests/minimal_log_level.c | 22 --- tests/minimal_log_level.stderr.txt | 6 - tests/minimal_log_level.stdout.txt | 0 tests/no_echo.c | 25 +-- tests/no_echo.stderr.txt | 0 tests/no_echo.stdout.txt | 1 + tests/no_echo.win32.stdout.txt | 1 + tests/nob_sv_end_with.c | 42 ++--- tests/nob_sv_end_with.stderr.txt | 8 - tests/nob_sv_end_with.stdout.txt | 8 + tests/nob_sv_end_with.win32.stdout.txt | 8 + tests/read_entire_dir.c | 6 +- tests/read_entire_dir.stderr.txt | 4 - tests/read_entire_dir.stdout.txt | 4 + tests/read_entire_dir.win32.stdout.txt | 4 + tests/sb_appendf.c | 7 +- tests/sb_appendf.stderr.txt | 2 - tests/sb_appendf.stdout.txt | 2 + tests/sb_appendf.win32.stdout.txt | 2 + tests/set_get_current_dir.c | 15 -- tests/set_get_current_dir.stderr.txt | 2 - tests/set_get_current_dir.stdout.txt | 0 tests/temp_aligned_alloc.c | 3 +- tests/temp_aligned_alloc.stderr.txt | 0 tests/temp_aligned_alloc.win32.stdout.txt | 12 ++ tests/temp_path_comps.c | 15 +- tests/temp_path_comps.stderr.txt | 27 ---- tests/temp_path_comps.stdout.txt | 27 ++++ tests/temp_path_comps.win32.stdout.txt | 21 +++ tests/temp_running_executable_path.c | 5 +- tests/temp_running_executable_path.stderr.txt | 1 - tests/temp_running_executable_path.stdout.txt | 1 + ...p_running_executable_path.win32.stdout.txt | 1 + tests/win32_error.c | 9 -- 72 files changed, 350 insertions(+), 357 deletions(-) delete mode 100644 tests/chain.stderr.txt create mode 100644 tests/chain.win32.stdout.txt delete mode 100644 tests/cmd_args_passing.stderr.txt create mode 100644 tests/cmd_args_passing.win32.stdout.txt delete mode 100644 tests/cmd_redirect.stderr.txt create mode 100644 tests/cmd_redirect.win32.stdout.txt delete mode 100644 tests/cmd_run_dont_reset.stderr.txt create mode 100644 tests/cmd_run_dont_reset.win32.stdout.txt delete mode 100644 tests/da_append.stderr.txt create mode 100644 tests/da_append.win32.stdout.txt delete mode 100644 tests/da_foreach.stderr.txt create mode 100644 tests/da_foreach.win32.stdout.txt delete mode 100644 tests/da_last.stderr.txt create mode 100644 tests/da_last.win32.stdout.txt delete mode 100644 tests/da_remove_unordered.stderr.txt create mode 100644 tests/da_remove_unordered.win32.stdout.txt delete mode 100644 tests/da_resize.stderr.txt create mode 100644 tests/da_resize.win32.stdout.txt delete mode 100644 tests/minimal_log_level.c delete mode 100644 tests/minimal_log_level.stderr.txt delete mode 100644 tests/minimal_log_level.stdout.txt delete mode 100644 tests/no_echo.stderr.txt create mode 100644 tests/no_echo.win32.stdout.txt delete mode 100644 tests/nob_sv_end_with.stderr.txt create mode 100644 tests/nob_sv_end_with.win32.stdout.txt delete mode 100644 tests/read_entire_dir.stderr.txt create mode 100644 tests/read_entire_dir.win32.stdout.txt delete mode 100644 tests/sb_appendf.stderr.txt create mode 100644 tests/sb_appendf.win32.stdout.txt delete mode 100644 tests/set_get_current_dir.c delete mode 100644 tests/set_get_current_dir.stderr.txt delete mode 100644 tests/set_get_current_dir.stdout.txt delete mode 100644 tests/temp_aligned_alloc.stderr.txt create mode 100644 tests/temp_aligned_alloc.win32.stdout.txt delete mode 100644 tests/temp_path_comps.stderr.txt create mode 100644 tests/temp_path_comps.win32.stdout.txt delete mode 100644 tests/temp_running_executable_path.stderr.txt create mode 100644 tests/temp_running_executable_path.win32.stdout.txt delete mode 100644 tests/win32_error.c diff --git a/.gitignore b/.gitignore index 4dc4215..6dc2d3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ nob nob.old nob.exe -build/ \ No newline at end of file +nob.exe.old +nob.obj +build/ diff --git a/how_to/nob.c b/how_to/nob.c index 714fe16..76524cf 100644 --- a/how_to/nob.c +++ b/how_to/nob.c @@ -1,9 +1,5 @@ // Makes sure the examples are buildable. Used usually on CI. #include "../shared.h" -#define NOB_IMPLEMENTATION -#define NOB_EXPERIMENTAL_DELETE_OLD -#define NOB_WARN_DEPRECATED -#include "../nob.h" const char *examples[] = { "001_basic_usage", diff --git a/nob.c b/nob.c index e271df5..7461465 100644 --- a/nob.c +++ b/nob.c @@ -1,20 +1,9 @@ #include "shared.h" -#define NOBDEF static inline -#define NOB_IMPLEMENTATION -#define NOB_EXPERIMENTAL_DELETE_OLD -#define NOB_WARN_DEPRECATED -#include "nob.h" -#undef rename // Testing for backward compatibility after v1.20.6 const char *test_names[] = { - "minimal_log_level", "nob_sv_end_with", - "set_get_current_dir", "cmd_redirect", "cmd_args_passing", -#ifdef _WIN32 - "win32_error", -#endif //_WIN32 "read_entire_dir", "da_resize", "da_last", @@ -42,58 +31,74 @@ bool delete_directory_recursively(const char *dir_path) return walk_dir(dir_path, delete_walk_entry, .post_order = true); } -bool build_and_run_test(Cmd *cmd, const char *test_name, bool record) +bool build_and_run_test(const char *test_name, bool record) { - size_t mark = temp_save(); + bool result = true; + Cmd cmd = {0}; + String_Builder src = {0}; + String_Builder dst = {0}; + String_View src_sv = {0}; + String_View dst_sv = {0}; +#ifdef _WIN32 + const char *src_stdout_path = temp_sprintf("%s%s.win32.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name); + const char *dst_stdout_path = temp_sprintf("%s%s.win32.stdout.txt", TESTS_FOLDER, test_name); + const char *test_stdout_path = temp_sprintf("../%s.win32.stdout.txt", test_name); +#else + const char *src_stdout_path = temp_sprintf("%s%s.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name); + const char *dst_stdout_path = temp_sprintf("%s%s.stdout.txt", TESTS_FOLDER, test_name); + const char *test_stdout_path = temp_sprintf("../%s.stdout.txt", test_name); +#endif // _WIN32 + const char *bin_path = temp_sprintf("%s%s", BUILD_FOLDER TESTS_FOLDER, test_name); + const char *src_path = temp_sprintf("%s%s.c", TESTS_FOLDER, test_name); + const char *test_cwd_path = temp_sprintf("%s%s%s.cwd", BUILD_FOLDER, TESTS_FOLDER, test_name); - const char *bin_path = temp_sprintf("%s%s", BUILD_FOLDER TESTS_FOLDER, test_name); - const char *src_path = temp_sprintf("%s%s.c", TESTS_FOLDER, test_name); - nob_cc(cmd); - nob_cc_flags(cmd); - nob_cc_output(cmd, bin_path); - nob_cc_inputs(cmd, src_path); - if (!cmd_run(cmd)) return false; + nob_cc(&cmd); + nob_cc_flags(&cmd); + nob_cc_output(&cmd, bin_path); + nob_cc_inputs(&cmd, src_path); + if (!cmd_run(&cmd)) return_defer(false); - const char *test_cwd_path = temp_sprintf("%s%s%s.cwd", BUILD_FOLDER, TESTS_FOLDER, test_name); if (file_exists(test_cwd_path)) { - if (!delete_directory_recursively(test_cwd_path)) return false; + if (!delete_directory_recursively(test_cwd_path)) return_defer(false); } - if (!mkdir_if_not_exists(test_cwd_path)) return false; - if (!set_current_dir(test_cwd_path)) return false; - cmd_append(cmd, temp_sprintf("../%s", test_name)); - const char *test_stdout_path = temp_sprintf("../%s.stdout.txt", test_name); - const char *test_stderr_path = temp_sprintf("../%s.stderr.txt", test_name); - if (!cmd_run(cmd, .stdout_path = test_stdout_path, .stderr_path = test_stderr_path)) return false; - if (!set_current_dir("../../../")) return false; + if (!mkdir_if_not_exists(test_cwd_path)) return_defer(false); + if (!set_current_dir(test_cwd_path)) return_defer(false); +#ifdef _WIN32 + cmd_append(&cmd, temp_sprintf("../%s.exe", test_name)); +#else + cmd_append(&cmd, temp_sprintf("../%s", test_name)); +#endif // _WIN32 + if (!cmd_run(&cmd, .stdout_path = test_stdout_path)) return_defer(false); + if (!set_current_dir("../../../")) return_defer(false); // TODO: implement record/replay testing for windows -#ifndef _WIN32 - const char *src_stdout_path = temp_sprintf("%s%s.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name); - const char *src_stderr_path = temp_sprintf("%s%s.stderr.txt", BUILD_FOLDER TESTS_FOLDER, test_name); - const char *dst_stdout_path = temp_sprintf("%s%s.stdout.txt", TESTS_FOLDER, test_name); - const char *dst_stderr_path = temp_sprintf("%s%s.stderr.txt", TESTS_FOLDER, test_name); if (record) { - if (!copy_file(src_stdout_path, dst_stdout_path)) return 1; - if (!copy_file(src_stderr_path, dst_stderr_path)) return 1; + if (!copy_file(src_stdout_path, dst_stdout_path)) return_defer(false); } else { - cmd_append(cmd, "diff"); - cmd_append(cmd, "-u"); - cmd_append(cmd, dst_stdout_path); - cmd_append(cmd, src_stdout_path); - if (!cmd_run(cmd)) return false; - - cmd_append(cmd, "diff"); - cmd_append(cmd, "-u"); - cmd_append(cmd, dst_stderr_path); - cmd_append(cmd, src_stderr_path); - if (!cmd_run(cmd)) return false; + // TODO: it would be cool to have a portable diff utility in here. + if (!read_entire_file(src_stdout_path, &src)) return_defer(false); + if (!read_entire_file(dst_stdout_path, &dst)) return_defer(false); + + src_sv = sb_to_sv(src); + dst_sv = sb_to_sv(dst); + + if (!sv_eq(src_sv, dst_sv)) { + nob_log(ERROR, "UNEXPECTED OUTPUT!"); + nob_log(ERROR, "EXPECTED:"); + fprintf(stderr, SV_Fmt, SV_Arg(dst_sv)); + nob_log(ERROR, "ACTUAL:"); + fprintf(stderr, SV_Fmt, SV_Arg(src_sv)); + return_defer(false); + } } -#endif // _WIN32 nob_log(INFO, "--- %s finished ---", bin_path); - temp_rewind(mark); - return true; +defer: + free(dst.items); + free(src.items); + free(cmd.items); + return result; } typedef struct { @@ -158,8 +163,6 @@ void print_available_commands(Commands commands) int main(int argc, char **argv) { - set_log_handler(cancer_log_handler); - GO_REBUILD_URSELF_PLUS(argc, argv, "nob.h", "shared.h"); Cmd cmd = {0}; @@ -176,17 +179,22 @@ int main(int argc, char **argv) if (!mkdir_if_not_exists(BUILD_FOLDER)) return 1; if (!mkdir_if_not_exists(BUILD_FOLDER TESTS_FOLDER)) return 1; + size_t failed_count = 0; if (argc <= 0) { for (size_t i = 0; i < test_names_count; ++i) { - if (!build_and_run_test(&cmd, test_names[i], false)) return 1; + size_t mark = temp_save(); + if (!build_and_run_test(test_names[i], false)) failed_count += 1; + temp_rewind(mark); + } + } else { + while (argc > 0) { + size_t mark = temp_save(); + const char *test_name = shift(argv, argc); + if (!build_and_run_test(test_name, false)) failed_count += 1; + temp_rewind(mark); } - return 0; - } - - while (argc > 0) { - const char *test_name = shift(argv, argc); - if (!build_and_run_test(&cmd, test_name, false)) return 1; } + if (failed_count > 0) return 1; return 0; } @@ -195,17 +203,23 @@ int main(int argc, char **argv) if (!mkdir_if_not_exists(BUILD_FOLDER)) return 1; if (!mkdir_if_not_exists(BUILD_FOLDER TESTS_FOLDER)) return 1; + size_t failed_count = 0; if (argc <= 0) { for (size_t i = 0; i < test_names_count; ++i) { - if (!build_and_run_test(&cmd, test_names[i], true)) return 1; + size_t mark = temp_save(); + if (!build_and_run_test(test_names[i], true)) failed_count += 1; + temp_rewind(mark); + } + } else { + while (argc > 0) { + size_t mark = temp_save(); + const char *test_name = shift(argv, argc); + if (!build_and_run_test(test_name, true)) failed_count += 1; + temp_rewind(mark); } - return 0; } + if (failed_count > 0) return 1; - while (argc > 0) { - const char *test_name = shift(argv, argc); - if (!build_and_run_test(&cmd, test_name, true)) return 1; - } return 0; } diff --git a/shared.h b/shared.h index a5c43c7..6678551 100644 --- a/shared.h +++ b/shared.h @@ -5,8 +5,8 @@ #define SHARED_H_ // Folder must end with forward slash / -#define BUILD_FOLDER "build/" -#define TESTS_FOLDER "tests/" +#define BUILD_FOLDER "./build/" +#define TESTS_FOLDER "./tests/" // TODO: we should test on C++ compilers too @@ -32,6 +32,31 @@ #endif #endif // __cplusplus +#define NOBDEF static inline +#define NOB_IMPLEMENTATION +#define NOB_EXPERIMENTAL_DELETE_OLD +#define NOB_WARN_DEPRECATED +#define NOB_STRIP_PREFIX // Testing for backward compatibility after v3.0.0 +#include "nob.h" +#undef rename // Testing for backward compatibility after v1.20.6 +// Utility that tests use to build the tools they need +bool build_tool(Cmd *cmd, Procs *procs, const char *bin_path, const char *src_path, const char *src) +{ + if (!write_entire_file(src_path, src, strlen(src))) return 1; + + nob_cc(cmd); + nob_cc_flags(cmd); + nob_cc_output(cmd, bin_path); + nob_cc_inputs(cmd, src_path); + return cmd_run( + cmd, + .async = procs, + // To make sure no compiler output pollutes the test output. + // This is needed specifically for cl.exe cause it has + // a tendency to output compiled source files to stdout. + .stdout_path = temp_sprintf("%s.comp.txt", bin_path), + ); +} #endif // SHARED_H_ diff --git a/tests/chain.c b/tests/chain.c index 12e1d92..7767e39 100644 --- a/tests/chain.c +++ b/tests/chain.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" Cmd cmd = {0}; Chain chain = {0}; @@ -74,22 +73,11 @@ const char *hex_src = " return 0;\n" "}\n"; -bool build_tool_async(const char *bin_path, const char *src_path, const char *src) -{ - if (!write_entire_file(src_path, src, strlen(src))) return 1; - - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, bin_path); - nob_cc_inputs(&cmd, src_path); - return cmd_run(&cmd, .async = &procs); -} - int main(void) { - if (!build_tool_async("./hello", "hello.c", hello_src)) return 1; - if (!build_tool_async("./rot13", "rot13.c", rot13_src)) return 1; - if (!build_tool_async("./hex", "hex.c", hex_src)) return 1; + if (!build_tool(&cmd, &procs, "./hello", "hello.c", hello_src)) return 1; + if (!build_tool(&cmd, &procs, "./rot13", "rot13.c", rot13_src)) return 1; + if (!build_tool(&cmd, &procs, "./hex", "hex.c", hex_src)) return 1; if (!procs_flush(&procs)) return 1; if (!chain_begin(&chain)) return 1; diff --git a/tests/chain.stderr.txt b/tests/chain.stderr.txt deleted file mode 100644 index b8f8298..0000000 --- a/tests/chain.stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -[INFO] CMD: cc -Wall -Wextra -o ./hello hello.c -[INFO] CMD: cc -Wall -Wextra -o ./rot13 rot13.c -[INFO] CMD: cc -Wall -Wextra -o ./hex hex.c -[INFO] CMD: ./hello -[INFO] CMD: ./rot13 -[INFO] CMD: ./hex diff --git a/tests/chain.win32.stdout.txt b/tests/chain.win32.stdout.txt new file mode 100644 index 0000000..9847d01 --- /dev/null +++ b/tests/chain.win32.stdout.txt @@ -0,0 +1,3 @@ +55 72 79 79 62 20 67 62 20 66 67 71 72 65 65 0A Uryyb gb fgqree. +55 72 79 79 62 20 67 62 20 66 67 71 62 68 67 0A Uryyb gb fgqbhg. + diff --git a/tests/cmd_args_passing.c b/tests/cmd_args_passing.c index 6bb13a3..920648e 100644 --- a/tests/cmd_args_passing.c +++ b/tests/cmd_args_passing.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main(void) { @@ -14,13 +13,7 @@ int main(void) " }\n" " return 0;\n" "}\n"; - if (!write_entire_file("print_args.c", print_args_src, strlen(print_args_src))) return 1; - - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, "print_args"); - nob_cc_inputs(&cmd, "print_args.c"); - if (!cmd_run(&cmd)) return 1; + if (!build_tool(&cmd, NULL, "print_args", "print_args.c", print_args_src)) return 1; cmd_append(&cmd, "./print_args"); cmd_append(&cmd, "foo"); diff --git a/tests/cmd_args_passing.stderr.txt b/tests/cmd_args_passing.stderr.txt deleted file mode 100644 index e296315..0000000 --- a/tests/cmd_args_passing.stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -[INFO] CMD: cc -Wall -Wextra -o print_args print_args.c -[INFO] CMD: ./print_args foo bar 'Hello, world' '"Hello, world"' '"\` %$*@' diff --git a/tests/cmd_args_passing.win32.stdout.txt b/tests/cmd_args_passing.win32.stdout.txt new file mode 100644 index 0000000..5a3ce63 --- /dev/null +++ b/tests/cmd_args_passing.win32.stdout.txt @@ -0,0 +1,5 @@ +1: foo +2: bar +3: Hello, world +4: "Hello, world" +5: "\` %$*@ diff --git a/tests/cmd_redirect.c b/tests/cmd_redirect.c index 1006a74..bb552d2 100644 --- a/tests/cmd_redirect.c +++ b/tests/cmd_redirect.c @@ -1,12 +1,10 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main(void) { int result = 0; Cmd cmd = {0}; - Fd fdout = INVALID_FD; String_Builder sb = {0}; String_View actual_message = {0}; const char *message = NULL; @@ -27,34 +25,17 @@ int main(void) " printf(\"\\n\");\n" " return 0;\n" "}\n"; - if (!write_entire_file("./echo.c", echo_src, strlen(echo_src))) return 1; + if (!build_tool(&cmd, NULL, "echo", "echo.c", echo_src)) return 1; - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, "./echo"); - nob_cc_inputs(&cmd, "./echo.c"); - if (!cmd_run(&cmd)) return_defer(1); - - message = "Hello, World"; + message = "Redirected message"; message_file_path = "./echo_message.txt"; cmd_append(&cmd, "./echo", message); - if (!cmd_run(&cmd, .stdout_path = message_file_path)) return_defer(1); + if (!cmd_run(&cmd, .stdout_path = message_file_path)) return 1; - if (!read_entire_file(message_file_path, &sb)) return_defer(1); + if (!read_entire_file(message_file_path, &sb)) return 1; actual_message = sb_to_sv(sb); - if (!sv_eq(sv_trim(actual_message), sv_from_cstr(message))) { - nob_log(ERROR, "Unexpected message"); - nob_log(ERROR, "Expected: %s", message); - nob_log(ERROR, "Actual: " SV_Fmt, SV_Arg(actual_message)); - return_defer(1); - } - - nob_log(INFO, "OK"); + printf(SV_Fmt, SV_Arg(actual_message)); -defer: - free(cmd.items); - free(sb.items); - if (fdout != INVALID_FD) fd_close(fdout); return result; } diff --git a/tests/cmd_redirect.stderr.txt b/tests/cmd_redirect.stderr.txt deleted file mode 100644 index 2203174..0000000 --- a/tests/cmd_redirect.stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -[INFO] CMD: cc -Wall -Wextra -o ./echo ./echo.c -[INFO] CMD: ./echo 'Hello, World' -[INFO] OK diff --git a/tests/cmd_redirect.stdout.txt b/tests/cmd_redirect.stdout.txt index e69de29..ba52613 100644 --- a/tests/cmd_redirect.stdout.txt +++ b/tests/cmd_redirect.stdout.txt @@ -0,0 +1 @@ +Redirected message diff --git a/tests/cmd_redirect.win32.stdout.txt b/tests/cmd_redirect.win32.stdout.txt new file mode 100644 index 0000000..693d6a9 --- /dev/null +++ b/tests/cmd_redirect.win32.stdout.txt @@ -0,0 +1 @@ +Redirected message diff --git a/tests/cmd_run_dont_reset.c b/tests/cmd_run_dont_reset.c index 7006836..6b7a807 100644 --- a/tests/cmd_run_dont_reset.c +++ b/tests/cmd_run_dont_reset.c @@ -1,33 +1,24 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main() { Cmd cmd = {0}; const char *empty_src = "int main() { return 0; }"; - if (!write_entire_file("empty.c", empty_src, strlen(empty_src))) return 1; + if (!build_tool(&cmd, NULL, "./empty", "./empty.c", empty_src)) return 1; - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, "empty"); - nob_cc_inputs(&cmd, "empty.c"); + cmd_append(&cmd, "./empty", "foo", "bar", "baz"); if (!cmd_run(&cmd)) return 1; - - nob_log(INFO, "Reset:"); + printf("Reset:\n"); for (size_t i = 0; i < cmd.count; ++i) { - nob_log(INFO, " %s", cmd.items[i]); + printf(" %s\n", cmd.items[i]); } - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, "empty"); - nob_cc_inputs(&cmd, "empty.c"); + cmd_append(&cmd, "./empty", "foo", "bar", "baz"); if (!cmd_run(&cmd, .dont_reset = true)) return 1; - - nob_log(INFO, "Don't Reset:"); + printf("Don't Reset:\n"); for (size_t i = 0; i < cmd.count; ++i) { - nob_log(INFO, " %s", cmd.items[i]); + printf(" %s\n", cmd.items[i]); } return 0; diff --git a/tests/cmd_run_dont_reset.stderr.txt b/tests/cmd_run_dont_reset.stderr.txt deleted file mode 100644 index c9207fa..0000000 --- a/tests/cmd_run_dont_reset.stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -[INFO] CMD: cc -Wall -Wextra -o empty empty.c -[INFO] Reset: -[INFO] CMD: cc -Wall -Wextra -o empty empty.c -[INFO] Don't Reset: -[INFO] cc -[INFO] -Wall -[INFO] -Wextra -[INFO] -o -[INFO] empty -[INFO] empty.c diff --git a/tests/cmd_run_dont_reset.stdout.txt b/tests/cmd_run_dont_reset.stdout.txt index e69de29..3ceaf03 100644 --- a/tests/cmd_run_dont_reset.stdout.txt +++ b/tests/cmd_run_dont_reset.stdout.txt @@ -0,0 +1,6 @@ +Reset: +Don't Reset: + ./empty + foo + bar + baz diff --git a/tests/cmd_run_dont_reset.win32.stdout.txt b/tests/cmd_run_dont_reset.win32.stdout.txt new file mode 100644 index 0000000..7a8cb94 --- /dev/null +++ b/tests/cmd_run_dont_reset.win32.stdout.txt @@ -0,0 +1,6 @@ +Reset: +Don't Reset: + ./empty + foo + bar + baz diff --git a/tests/da_append.c b/tests/da_append.c index 1ed56e9..02d9df5 100644 --- a/tests/da_append.c +++ b/tests/da_append.c @@ -1,6 +1,5 @@ -#define NOB_IMPLEMENTATION #define NOB_DA_INIT_CAP 4 -#include "nob.h" +#include "shared.h" typedef struct { int *items; @@ -13,7 +12,7 @@ int main(void) Numbers xs = {0}; for (int x = 0; x < 10; ++x) { da_append(&xs, x); - nob_log(INFO, "count = %zu, capacity = %zu", xs.count, xs.capacity); + printf("count = %zu, capacity = %zu\n", xs.count, xs.capacity); } return 0; } diff --git a/tests/da_append.stderr.txt b/tests/da_append.stderr.txt deleted file mode 100644 index fa8ff3a..0000000 --- a/tests/da_append.stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -[INFO] count = 1, capacity = 4 -[INFO] count = 2, capacity = 4 -[INFO] count = 3, capacity = 4 -[INFO] count = 4, capacity = 4 -[INFO] count = 5, capacity = 8 -[INFO] count = 6, capacity = 8 -[INFO] count = 7, capacity = 8 -[INFO] count = 8, capacity = 8 -[INFO] count = 9, capacity = 16 -[INFO] count = 10, capacity = 16 diff --git a/tests/da_append.stdout.txt b/tests/da_append.stdout.txt index e69de29..1f09ed0 100644 --- a/tests/da_append.stdout.txt +++ b/tests/da_append.stdout.txt @@ -0,0 +1,10 @@ +count = 1, capacity = 4 +count = 2, capacity = 4 +count = 3, capacity = 4 +count = 4, capacity = 4 +count = 5, capacity = 8 +count = 6, capacity = 8 +count = 7, capacity = 8 +count = 8, capacity = 8 +count = 9, capacity = 16 +count = 10, capacity = 16 diff --git a/tests/da_append.win32.stdout.txt b/tests/da_append.win32.stdout.txt new file mode 100644 index 0000000..91551d3 --- /dev/null +++ b/tests/da_append.win32.stdout.txt @@ -0,0 +1,10 @@ +count = 1, capacity = 4 +count = 2, capacity = 4 +count = 3, capacity = 4 +count = 4, capacity = 4 +count = 5, capacity = 8 +count = 6, capacity = 8 +count = 7, capacity = 8 +count = 8, capacity = 8 +count = 9, capacity = 16 +count = 10, capacity = 16 diff --git a/tests/da_foreach.c b/tests/da_foreach.c index 5875616..abe17f5 100644 --- a/tests/da_foreach.c +++ b/tests/da_foreach.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main() { @@ -16,7 +15,7 @@ int main() // `x` here is a pointer to the current element. You can get its index by taking a difference // between `x` and the start of the array which is `x.items`. size_t index = x - xs.items; - nob_log(INFO, "%zu: %d", index, *x); + printf("%zu: %d\n", index, *x); } return 0; } diff --git a/tests/da_foreach.stderr.txt b/tests/da_foreach.stderr.txt deleted file mode 100644 index 68e617c..0000000 --- a/tests/da_foreach.stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -[INFO] 0: 69 -[INFO] 1: 420 -[INFO] 2: 1337 diff --git a/tests/da_foreach.stdout.txt b/tests/da_foreach.stdout.txt index e69de29..0d2c202 100644 --- a/tests/da_foreach.stdout.txt +++ b/tests/da_foreach.stdout.txt @@ -0,0 +1,3 @@ +0: 69 +1: 420 +2: 1337 diff --git a/tests/da_foreach.win32.stdout.txt b/tests/da_foreach.win32.stdout.txt new file mode 100644 index 0000000..7ad7299 --- /dev/null +++ b/tests/da_foreach.win32.stdout.txt @@ -0,0 +1,3 @@ +0: 69 +1: 420 +2: 1337 diff --git a/tests/da_last.c b/tests/da_last.c index 8bbb35a..987e43f 100644 --- a/tests/da_last.c +++ b/tests/da_last.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" typedef struct { int *items; @@ -14,7 +13,7 @@ int main(void) for (int i = 12; i <= 16; ++i) da_append(&xs, i); while (xs.count > 0) { da_last(&xs) += 1; // as an rvalue - nob_log(INFO, "%d", da_last(&xs)); // as an lvalue + printf("%d\n", da_last(&xs)); // as an lvalue xs.count--; } return 0; diff --git a/tests/da_last.stderr.txt b/tests/da_last.stderr.txt deleted file mode 100644 index fea6223..0000000 --- a/tests/da_last.stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -[INFO] da_last: -[INFO] 17 -[INFO] 16 -[INFO] 15 -[INFO] 14 -[INFO] 13 diff --git a/tests/da_last.stdout.txt b/tests/da_last.stdout.txt index e69de29..cd6a0c3 100644 --- a/tests/da_last.stdout.txt +++ b/tests/da_last.stdout.txt @@ -0,0 +1,5 @@ +17 +16 +15 +14 +13 diff --git a/tests/da_last.win32.stdout.txt b/tests/da_last.win32.stdout.txt new file mode 100644 index 0000000..5b6e8ca --- /dev/null +++ b/tests/da_last.win32.stdout.txt @@ -0,0 +1,5 @@ +17 +16 +15 +14 +13 diff --git a/tests/da_remove_unordered.c b/tests/da_remove_unordered.c index 9f21892..12b304c 100644 --- a/tests/da_remove_unordered.c +++ b/tests/da_remove_unordered.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" typedef struct { int *items; @@ -24,7 +23,7 @@ int main(void) while (xs.count > 0) { sb.count = 0; render_numbers(xs, &sb); - nob_log(INFO, "%s", sb.items); + printf("%s\n", sb.items); da_remove_unordered(&xs, 0); } return 0; diff --git a/tests/da_remove_unordered.stderr.txt b/tests/da_remove_unordered.stderr.txt deleted file mode 100644 index b0ec60b..0000000 --- a/tests/da_remove_unordered.stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -[INFO] 12, 13, 14, 15 -[INFO] 15, 13, 14 -[INFO] 14, 13 -[INFO] 13 diff --git a/tests/da_remove_unordered.stdout.txt b/tests/da_remove_unordered.stdout.txt index e69de29..d673d2d 100644 --- a/tests/da_remove_unordered.stdout.txt +++ b/tests/da_remove_unordered.stdout.txt @@ -0,0 +1,4 @@ +12, 13, 14, 15 +15, 13, 14 +14, 13 +13 diff --git a/tests/da_remove_unordered.win32.stdout.txt b/tests/da_remove_unordered.win32.stdout.txt new file mode 100644 index 0000000..77ee960 --- /dev/null +++ b/tests/da_remove_unordered.win32.stdout.txt @@ -0,0 +1,4 @@ +12, 13, 14, 15 +15, 13, 14 +14, 13 +13 diff --git a/tests/da_resize.c b/tests/da_resize.c index 926e3c4..c89798a 100644 --- a/tests/da_resize.c +++ b/tests/da_resize.c @@ -1,6 +1,5 @@ -#define NOB_IMPLEMENTATION #define NOB_DA_INIT_CAP 4 -#include "nob.h" +#include "shared.h" typedef struct { int *items; @@ -14,10 +13,10 @@ int main(void) da_append(&xs, 69); da_append(&xs, 420); da_append(&xs, 1337); - nob_log(INFO, "count = %zu, capacity = %zu", xs.count, xs.capacity); + printf("count = %zu, capacity = %zu\n", xs.count, xs.capacity); nob_da_resize(&xs, 1); - nob_log(INFO, "count = %zu, capacity = %zu", xs.count, xs.capacity); + printf("count = %zu, capacity = %zu\n", xs.count, xs.capacity); nob_da_resize(&xs, 10); - nob_log(INFO, "count = %zu, capacity = %zu", xs.count, xs.capacity); + printf("count = %zu, capacity = %zu\n", xs.count, xs.capacity); return 0; } diff --git a/tests/da_resize.stderr.txt b/tests/da_resize.stderr.txt deleted file mode 100644 index 53a22ca..0000000 --- a/tests/da_resize.stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -[INFO] count = 3, capacity = 4 -[INFO] count = 1, capacity = 4 -[INFO] count = 10, capacity = 16 diff --git a/tests/da_resize.stdout.txt b/tests/da_resize.stdout.txt index e69de29..d204767 100644 --- a/tests/da_resize.stdout.txt +++ b/tests/da_resize.stdout.txt @@ -0,0 +1,3 @@ +count = 3, capacity = 4 +count = 1, capacity = 4 +count = 10, capacity = 16 diff --git a/tests/da_resize.win32.stdout.txt b/tests/da_resize.win32.stdout.txt new file mode 100644 index 0000000..6070ed5 --- /dev/null +++ b/tests/da_resize.win32.stdout.txt @@ -0,0 +1,3 @@ +count = 3, capacity = 4 +count = 1, capacity = 4 +count = 10, capacity = 16 diff --git a/tests/minimal_log_level.c b/tests/minimal_log_level.c deleted file mode 100644 index d6c9020..0000000 --- a/tests/minimal_log_level.c +++ /dev/null @@ -1,22 +0,0 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" - -void log_test_messages(void) -{ - nob_log(NOB_INFO, "Info Test Message"); - nob_log(NOB_WARNING, "Warning Test Message"); - nob_log(NOB_ERROR, "Error Test Message"); - nob_log(NOB_NO_LOGS, "YOU SHOULD NEVER SEE THIS"); -} - -int main(void) -{ - log_test_messages(); - nob_minimal_log_level = NOB_WARNING; - log_test_messages(); - nob_minimal_log_level = NOB_ERROR; - log_test_messages(); - nob_minimal_log_level = NOB_NO_LOGS; - log_test_messages(); - return 0; -} diff --git a/tests/minimal_log_level.stderr.txt b/tests/minimal_log_level.stderr.txt deleted file mode 100644 index 04efd5e..0000000 --- a/tests/minimal_log_level.stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -[INFO] Info Test Message -[WARNING] Warning Test Message -[ERROR] Error Test Message -[WARNING] Warning Test Message -[ERROR] Error Test Message -[ERROR] Error Test Message diff --git a/tests/minimal_log_level.stdout.txt b/tests/minimal_log_level.stdout.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/no_echo.c b/tests/no_echo.c index 5ee1fcd..1eefaf3 100644 --- a/tests/no_echo.c +++ b/tests/no_echo.c @@ -1,22 +1,29 @@ -#define NOB_IMPLEMENTATION #define NOB_NO_ECHO -#include "nob.h" +#include "shared.h" + +size_t log_count = 0; + +void counting_log_handler(Nob_Log_Level level, const char *fmt, va_list args) +{ + UNUSED(level); + UNUSED(fmt); + UNUSED(args); + log_count += 1; +} int main(void) { + set_log_handler(counting_log_handler); + Cmd cmd = {0}; const char *empty_src = "int main() { return 0; }"; - if (!write_entire_file("empty.c", empty_src, strlen(empty_src))) return 1; - - nob_cc(&cmd); - nob_cc_flags(&cmd); - nob_cc_output(&cmd, "empty"); - nob_cc_inputs(&cmd, "empty.c"); - if (!cmd_run(&cmd)) return 1; + if (!build_tool(&cmd, NULL, "./empty", "./empty.c", empty_src)) return 1; cmd_append(&cmd, "./empty"); if (!cmd_run(&cmd)) return 1; + printf("Log entries issued: %zu\n", log_count); + return 0; } diff --git a/tests/no_echo.stderr.txt b/tests/no_echo.stderr.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/no_echo.stdout.txt b/tests/no_echo.stdout.txt index e69de29..de2e860 100644 --- a/tests/no_echo.stdout.txt +++ b/tests/no_echo.stdout.txt @@ -0,0 +1 @@ +Log entries issued: 0 diff --git a/tests/no_echo.win32.stdout.txt b/tests/no_echo.win32.stdout.txt new file mode 100644 index 0000000..dc89f5f --- /dev/null +++ b/tests/no_echo.win32.stdout.txt @@ -0,0 +1 @@ +Log entries issued: 0 diff --git a/tests/nob_sv_end_with.c b/tests/nob_sv_end_with.c index 105c49c..e6387fc 100644 --- a/tests/nob_sv_end_with.c +++ b/tests/nob_sv_end_with.c @@ -1,38 +1,24 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" -void assert_true(const char *test_case, bool result) +void trace_case(String_View sv, const char *suffix) { - if (result) { - nob_log(NOB_INFO, "[SUCCESS] %s", test_case); - } else { - nob_log(NOB_ERROR, "[FAIL] %s", test_case); - } -} - -void assert_false(const char *test_case, bool result) -{ - if (!result) { - nob_log(NOB_INFO, "[SUCCESS] %s", test_case); - } else { - nob_log(NOB_ERROR, "[FAIL] %s", test_case); - } + bool result = sv_end_with(sv, suffix); + printf("sv_end_with(\"" SV_Fmt "\", \"%s\") => %s\n", SV_Arg(sv), suffix, result ? "true" : "false"); } int main(void) { - Nob_String_View sv1 = nob_sv_from_cstr("./example.exe"); - Nob_String_View sv2 = nob_sv_from_cstr(""); - - assert_true("nob_sv_end_with(sv1, \"./example.exe\")", nob_sv_end_with(sv1, "./example.exe")); - assert_true("nob_sv_end_with(sv1, \".exe\")", nob_sv_end_with(sv1, ".exe")); - assert_true("nob_sv_end_with(sv1, \"e\")", nob_sv_end_with(sv1, "e")); - assert_true("nob_sv_end_with(sv1, \"\")", nob_sv_end_with(sv1, "")); - assert_true("nob_sv_end_with(sv2, \"\")", nob_sv_end_with(sv2, "")); + String_View sv1 = sv_from_cstr("./example.exe"); + String_View sv2 = sv_from_cstr(""); - assert_false("nob_sv_end_with(sv1, \".png\")", nob_sv_end_with(sv1, ".png")); - assert_false("nob_sv_end_with(sv1, \"/path/to/example.exe\")", nob_sv_end_with(sv1, "/path/to/example.exe")); - assert_false("nob_sv_end_with(sv2, \".obj\")", nob_sv_end_with(sv2, ".obj")); + trace_case(sv1, "./example.exe"); + trace_case(sv1, ".exe"); + trace_case(sv1, "e"); + trace_case(sv1, ""); + trace_case(sv2, ""); + trace_case(sv1, ".png"); + trace_case(sv1, "/path/to/example.exe"); + trace_case(sv2, ".obj"); return 0; } diff --git a/tests/nob_sv_end_with.stderr.txt b/tests/nob_sv_end_with.stderr.txt deleted file mode 100644 index cb1d1f5..0000000 --- a/tests/nob_sv_end_with.stderr.txt +++ /dev/null @@ -1,8 +0,0 @@ -[INFO] [SUCCESS] nob_sv_end_with(sv1, "./example.exe") -[INFO] [SUCCESS] nob_sv_end_with(sv1, ".exe") -[INFO] [SUCCESS] nob_sv_end_with(sv1, "e") -[INFO] [SUCCESS] nob_sv_end_with(sv1, "") -[INFO] [SUCCESS] nob_sv_end_with(sv2, "") -[INFO] [SUCCESS] nob_sv_end_with(sv1, ".png") -[INFO] [SUCCESS] nob_sv_end_with(sv1, "/path/to/example.exe") -[INFO] [SUCCESS] nob_sv_end_with(sv2, ".obj") diff --git a/tests/nob_sv_end_with.stdout.txt b/tests/nob_sv_end_with.stdout.txt index e69de29..14b8cc2 100644 --- a/tests/nob_sv_end_with.stdout.txt +++ b/tests/nob_sv_end_with.stdout.txt @@ -0,0 +1,8 @@ +sv_end_with("./example.exe", "./example.exe") => true +sv_end_with("./example.exe", ".exe") => true +sv_end_with("./example.exe", "e") => true +sv_end_with("./example.exe", "") => true +sv_end_with("", "") => true +sv_end_with("./example.exe", ".png") => false +sv_end_with("./example.exe", "/path/to/example.exe") => false +sv_end_with("", ".obj") => false diff --git a/tests/nob_sv_end_with.win32.stdout.txt b/tests/nob_sv_end_with.win32.stdout.txt new file mode 100644 index 0000000..6019864 --- /dev/null +++ b/tests/nob_sv_end_with.win32.stdout.txt @@ -0,0 +1,8 @@ +sv_end_with("./example.exe", "./example.exe") => true +sv_end_with("./example.exe", ".exe") => true +sv_end_with("./example.exe", "e") => true +sv_end_with("./example.exe", "") => true +sv_end_with("", "") => true +sv_end_with("./example.exe", ".png") => false +sv_end_with("./example.exe", "/path/to/example.exe") => false +sv_end_with("", ".obj") => false diff --git a/tests/read_entire_dir.c b/tests/read_entire_dir.c index 460d028..ae014b6 100644 --- a/tests/read_entire_dir.c +++ b/tests/read_entire_dir.c @@ -1,6 +1,4 @@ #include "shared.h" -#define NOB_IMPLEMENTATION -#include "nob.h" int compar_paths(const void *a, const void *b) { @@ -18,10 +16,10 @@ int main(void) Nob_File_Paths children = {0}; if (!nob_read_entire_dir(".", &children)) return 1; qsort(children.items, children.count, sizeof(*children.items), compar_paths); - nob_log(INFO, "Tests:"); + printf("Tests:\n"); for (size_t i = 0; i < children.count; ++i) { if (*children.items[i] == '.') continue; - nob_log(INFO, " %s", children.items[i]); + printf(" %s\n", children.items[i]); } return 0; } diff --git a/tests/read_entire_dir.stderr.txt b/tests/read_entire_dir.stderr.txt deleted file mode 100644 index b0254eb..0000000 --- a/tests/read_entire_dir.stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -[INFO] Tests: -[INFO] bar.txt -[INFO] baz.txt -[INFO] foo.txt diff --git a/tests/read_entire_dir.stdout.txt b/tests/read_entire_dir.stdout.txt index e69de29..6002cbc 100644 --- a/tests/read_entire_dir.stdout.txt +++ b/tests/read_entire_dir.stdout.txt @@ -0,0 +1,4 @@ +Tests: + bar.txt + baz.txt + foo.txt diff --git a/tests/read_entire_dir.win32.stdout.txt b/tests/read_entire_dir.win32.stdout.txt new file mode 100644 index 0000000..826c9a2 --- /dev/null +++ b/tests/read_entire_dir.win32.stdout.txt @@ -0,0 +1,4 @@ +Tests: + bar.txt + baz.txt + foo.txt diff --git a/tests/sb_appendf.c b/tests/sb_appendf.c index bc676aa..22c63ca 100644 --- a/tests/sb_appendf.c +++ b/tests/sb_appendf.c @@ -1,12 +1,11 @@ -#define NOB_IMPLEMENTATION #define NOB_DA_INIT_CAP 4 -#include "nob.h" +#include "shared.h" int main(void) { String_Builder sb = {0}; - nob_log(INFO, "count = %zu, capacity = %zu, items = \"%.*s\"", sb.count, sb.capacity, (int)sb.count, sb.items); + printf("count = %zu, capacity = %zu, items = \"%.*s\"\n", sb.count, sb.capacity, (int)sb.count, sb.items); sb_appendf(&sb, "Hello, %d.", 69); - nob_log(INFO, "count = %zu, capacity = %zu, items = \"%.*s\"", sb.count, sb.capacity, (int)sb.count, sb.items); + printf("count = %zu, capacity = %zu, items = \"%.*s\"\n", sb.count, sb.capacity, (int)sb.count, sb.items); return 0; } diff --git a/tests/sb_appendf.stderr.txt b/tests/sb_appendf.stderr.txt deleted file mode 100644 index f766918..0000000 --- a/tests/sb_appendf.stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -[INFO] count = 0, capacity = 0, items = "" -[INFO] count = 10, capacity = 16, items = "Hello, 69." diff --git a/tests/sb_appendf.stdout.txt b/tests/sb_appendf.stdout.txt index e69de29..61cc6ee 100644 --- a/tests/sb_appendf.stdout.txt +++ b/tests/sb_appendf.stdout.txt @@ -0,0 +1,2 @@ +count = 0, capacity = 0, items = "" +count = 10, capacity = 16, items = "Hello, 69." diff --git a/tests/sb_appendf.win32.stdout.txt b/tests/sb_appendf.win32.stdout.txt new file mode 100644 index 0000000..f5cd73d --- /dev/null +++ b/tests/sb_appendf.win32.stdout.txt @@ -0,0 +1,2 @@ +count = 0, capacity = 0, items = "" +count = 10, capacity = 16, items = "Hello, 69." diff --git a/tests/set_get_current_dir.c b/tests/set_get_current_dir.c deleted file mode 100644 index eb0f86c..0000000 --- a/tests/set_get_current_dir.c +++ /dev/null @@ -1,15 +0,0 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" - -int main(void) -{ - const char *test_current_dir = "/"; - - nob_log(INFO, "Setting Current Dir to %s", test_current_dir); - if (!set_current_dir(test_current_dir)) return 1; - - const char *current_dir = get_current_dir_temp(); - if (current_dir == NULL) return 1; - nob_log(INFO, "Current Dir: %s", current_dir); - return 0; -} diff --git a/tests/set_get_current_dir.stderr.txt b/tests/set_get_current_dir.stderr.txt deleted file mode 100644 index c142958..0000000 --- a/tests/set_get_current_dir.stderr.txt +++ /dev/null @@ -1,2 +0,0 @@ -[INFO] Setting Current Dir to / -[INFO] Current Dir: / diff --git a/tests/set_get_current_dir.stdout.txt b/tests/set_get_current_dir.stdout.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/temp_aligned_alloc.c b/tests/temp_aligned_alloc.c index a96dde4..b0a7007 100644 --- a/tests/temp_aligned_alloc.c +++ b/tests/temp_aligned_alloc.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" #define trace_temp_alloc(requested_size) \ (temp_alloc(requested_size), \ diff --git a/tests/temp_aligned_alloc.stderr.txt b/tests/temp_aligned_alloc.stderr.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/temp_aligned_alloc.win32.stdout.txt b/tests/temp_aligned_alloc.win32.stdout.txt new file mode 100644 index 0000000..21d1d77 --- /dev/null +++ b/tests/temp_aligned_alloc.win32.stdout.txt @@ -0,0 +1,12 @@ +temp_alloc( 0) → temp_size == 0 +temp_alloc( 2) → temp_size == 8 +temp_alloc( 3) → temp_size == 16 +temp_alloc( 5) → temp_size == 24 +temp_alloc( 7) → temp_size == 32 +temp_alloc( 11) → temp_size == 48 +temp_alloc( 13) → temp_size == 64 +temp_alloc( 11) → temp_size == 80 +temp_alloc( 7) → temp_size == 88 +temp_alloc( 5) → temp_size == 96 +temp_alloc( 3) → temp_size == 104 +temp_alloc( 2) → temp_size == 112 diff --git a/tests/temp_path_comps.c b/tests/temp_path_comps.c index b1a58dd..07de77b 100644 --- a/tests/temp_path_comps.c +++ b/tests/temp_path_comps.c @@ -1,5 +1,4 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main(void) { @@ -20,17 +19,17 @@ int main(void) NULL, }; - nob_log(INFO, "temp_dir_name:"); + printf("temp_dir_name:\n"); for (size_t i = 0; i < ARRAY_LEN(paths); ++i) { - nob_log(INFO, " %s => %s", paths[i], temp_dir_name(paths[i])); + printf(" %s => %s\n", paths[i], temp_dir_name(paths[i])); } - nob_log(INFO, "temp_file_name:"); + printf("temp_file_name:\n"); for (size_t i = 0; i < ARRAY_LEN(paths); ++i) { - nob_log(INFO, " %s => %s", paths[i], temp_file_name(paths[i])); + printf(" %s => %s\n", paths[i], temp_file_name(paths[i])); } - nob_log(INFO, "temp_file_ext:"); + printf("temp_file_ext:\n"); for (size_t i = 0; i < ARRAY_LEN(paths); ++i) { - nob_log(INFO, " %s => %s", paths[i], temp_file_ext(paths[i])); + printf(" %s => %s\n", paths[i], temp_file_ext(paths[i])); } return 0; } diff --git a/tests/temp_path_comps.stderr.txt b/tests/temp_path_comps.stderr.txt deleted file mode 100644 index c465e59..0000000 --- a/tests/temp_path_comps.stderr.txt +++ /dev/null @@ -1,27 +0,0 @@ -[INFO] temp_dir_name: -[INFO] / => / -[INFO] /home/rexim => /home -[INFO] /home/rexim/ => /home -[INFO] /home/rexim//// => /home -[INFO] /home/rexim/file.txt => /home/rexim -[INFO] => . -[INFO] . => . -[INFO] (null) => . -[INFO] temp_file_name: -[INFO] / => / -[INFO] /home/rexim => rexim -[INFO] /home/rexim/ => rexim -[INFO] /home/rexim//// => rexim -[INFO] /home/rexim/file.txt => file.txt -[INFO] => . -[INFO] . => . -[INFO] (null) => . -[INFO] temp_file_ext: -[INFO] / => (null) -[INFO] /home/rexim => (null) -[INFO] /home/rexim/ => (null) -[INFO] /home/rexim//// => (null) -[INFO] /home/rexim/file.txt => .txt -[INFO] => . -[INFO] . => . -[INFO] (null) => . diff --git a/tests/temp_path_comps.stdout.txt b/tests/temp_path_comps.stdout.txt index e69de29..75ad8e9 100644 --- a/tests/temp_path_comps.stdout.txt +++ b/tests/temp_path_comps.stdout.txt @@ -0,0 +1,27 @@ +temp_dir_name: + / => / + /home/rexim => /home + /home/rexim/ => /home + /home/rexim//// => /home + /home/rexim/file.txt => /home/rexim + => . + . => . + (null) => . +temp_file_name: + / => / + /home/rexim => rexim + /home/rexim/ => rexim + /home/rexim//// => rexim + /home/rexim/file.txt => file.txt + => . + . => . + (null) => . +temp_file_ext: + / => (null) + /home/rexim => (null) + /home/rexim/ => (null) + /home/rexim//// => (null) + /home/rexim/file.txt => .txt + => . + . => . + (null) => . diff --git a/tests/temp_path_comps.win32.stdout.txt b/tests/temp_path_comps.win32.stdout.txt new file mode 100644 index 0000000..c115066 --- /dev/null +++ b/tests/temp_path_comps.win32.stdout.txt @@ -0,0 +1,21 @@ +temp_dir_name: + C: => C: + C:\Program Files\Aboba => C:\Program Files\ + C:\Program Files\Aboba\File.exe => C:\Program Files\Aboba\ + => + . => + (null) => +temp_file_name: + C: => + C:\Program Files\Aboba => Aboba + C:\Program Files\Aboba\File.exe => File.exe + => + . => . + (null) => +temp_file_ext: + C: => + C:\Program Files\Aboba => + C:\Program Files\Aboba\File.exe => .exe + => + . => . + (null) => diff --git a/tests/temp_running_executable_path.c b/tests/temp_running_executable_path.c index 96c90ea..425f044 100644 --- a/tests/temp_running_executable_path.c +++ b/tests/temp_running_executable_path.c @@ -1,8 +1,7 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" +#include "shared.h" int main(void) { - nob_log(INFO, "%s", temp_file_name(temp_running_executable_path())); + printf("%s\n", temp_file_name(temp_running_executable_path())); return 0; } diff --git a/tests/temp_running_executable_path.stderr.txt b/tests/temp_running_executable_path.stderr.txt deleted file mode 100644 index 2c02346..0000000 --- a/tests/temp_running_executable_path.stderr.txt +++ /dev/null @@ -1 +0,0 @@ -[INFO] temp_running_executable_path diff --git a/tests/temp_running_executable_path.stdout.txt b/tests/temp_running_executable_path.stdout.txt index e69de29..0d43220 100644 --- a/tests/temp_running_executable_path.stdout.txt +++ b/tests/temp_running_executable_path.stdout.txt @@ -0,0 +1 @@ +temp_running_executable_path diff --git a/tests/temp_running_executable_path.win32.stdout.txt b/tests/temp_running_executable_path.win32.stdout.txt new file mode 100644 index 0000000..e5262c2 --- /dev/null +++ b/tests/temp_running_executable_path.win32.stdout.txt @@ -0,0 +1 @@ +temp_running_executable_path.exe diff --git a/tests/win32_error.c b/tests/win32_error.c deleted file mode 100644 index cc86920..0000000 --- a/tests/win32_error.c +++ /dev/null @@ -1,9 +0,0 @@ -#define NOB_IMPLEMENTATION -#include "nob.h" - -int main(void) { - nob_log(NOB_ERROR, "First 100 Win32 API Errors:"); - for (DWORD i = 0; i < 100; i++) - nob_log(NOB_ERROR, "%lu (0x%X): \"%s\"", i, i, nob_win32_error_message(i)); - return 0; -} From ed3f4f88e0fba5794969e335240d3e915a70bfd3 Mon Sep 17 00:00:00 2001 From: rexim Date: Wed, 28 Jan 2026 10:23:52 +0700 Subject: [PATCH 4/4] Release v3.2.0 --- nob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nob.h b/nob.h index 0dce610..0e59e09 100644 --- a/nob.h +++ b/nob.h @@ -2907,7 +2907,7 @@ NOBDEF char *nob_temp_running_executable_path(void) /* Revision history: - 3.2.0 ( ) Introduce Chain API + 3.2.0 (2026-01-28) Introduce Chain API - Nob_Chain - Nob_Chain_Begin_Opt - nob_chain_begin()