Skip to content

Commit 09addea

Browse files
committed
Implement record/replay for Windows
1 parent a655381 commit 09addea

File tree

72 files changed

+350
-357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+350
-357
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
nob
22
nob.old
33
nob.exe
4-
build/
4+
nob.exe.old
5+
nob.obj
6+
build/

how_to/nob.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
// Makes sure the examples are buildable. Used usually on CI.
22
#include "../shared.h"
3-
#define NOB_IMPLEMENTATION
4-
#define NOB_EXPERIMENTAL_DELETE_OLD
5-
#define NOB_WARN_DEPRECATED
6-
#include "../nob.h"
73

84
const char *examples[] = {
95
"001_basic_usage",

nob.c

Lines changed: 79 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
#include "shared.h"
2-
#define NOBDEF static inline
3-
#define NOB_IMPLEMENTATION
4-
#define NOB_EXPERIMENTAL_DELETE_OLD
5-
#define NOB_WARN_DEPRECATED
6-
#include "nob.h"
7-
#undef rename // Testing for backward compatibility after v1.20.6
82

93
const char *test_names[] = {
10-
"minimal_log_level",
114
"nob_sv_end_with",
12-
"set_get_current_dir",
135
"cmd_redirect",
146
"cmd_args_passing",
15-
#ifdef _WIN32
16-
"win32_error",
17-
#endif //_WIN32
187
"read_entire_dir",
198
"da_resize",
209
"da_last",
@@ -42,58 +31,74 @@ bool delete_directory_recursively(const char *dir_path)
4231
return walk_dir(dir_path, delete_walk_entry, .post_order = true);
4332
}
4433

45-
bool build_and_run_test(Cmd *cmd, const char *test_name, bool record)
34+
bool build_and_run_test(const char *test_name, bool record)
4635
{
47-
size_t mark = temp_save();
36+
bool result = true;
37+
Cmd cmd = {0};
38+
String_Builder src = {0};
39+
String_Builder dst = {0};
40+
String_View src_sv = {0};
41+
String_View dst_sv = {0};
42+
#ifdef _WIN32
43+
const char *src_stdout_path = temp_sprintf("%s%s.win32.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name);
44+
const char *dst_stdout_path = temp_sprintf("%s%s.win32.stdout.txt", TESTS_FOLDER, test_name);
45+
const char *test_stdout_path = temp_sprintf("../%s.win32.stdout.txt", test_name);
46+
#else
47+
const char *src_stdout_path = temp_sprintf("%s%s.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name);
48+
const char *dst_stdout_path = temp_sprintf("%s%s.stdout.txt", TESTS_FOLDER, test_name);
49+
const char *test_stdout_path = temp_sprintf("../%s.stdout.txt", test_name);
50+
#endif // _WIN32
51+
const char *bin_path = temp_sprintf("%s%s", BUILD_FOLDER TESTS_FOLDER, test_name);
52+
const char *src_path = temp_sprintf("%s%s.c", TESTS_FOLDER, test_name);
53+
const char *test_cwd_path = temp_sprintf("%s%s%s.cwd", BUILD_FOLDER, TESTS_FOLDER, test_name);
4854

49-
const char *bin_path = temp_sprintf("%s%s", BUILD_FOLDER TESTS_FOLDER, test_name);
50-
const char *src_path = temp_sprintf("%s%s.c", TESTS_FOLDER, test_name);
51-
nob_cc(cmd);
52-
nob_cc_flags(cmd);
53-
nob_cc_output(cmd, bin_path);
54-
nob_cc_inputs(cmd, src_path);
55-
if (!cmd_run(cmd)) return false;
55+
nob_cc(&cmd);
56+
nob_cc_flags(&cmd);
57+
nob_cc_output(&cmd, bin_path);
58+
nob_cc_inputs(&cmd, src_path);
59+
if (!cmd_run(&cmd)) return_defer(false);
5660

57-
const char *test_cwd_path = temp_sprintf("%s%s%s.cwd", BUILD_FOLDER, TESTS_FOLDER, test_name);
5861
if (file_exists(test_cwd_path)) {
59-
if (!delete_directory_recursively(test_cwd_path)) return false;
62+
if (!delete_directory_recursively(test_cwd_path)) return_defer(false);
6063
}
61-
if (!mkdir_if_not_exists(test_cwd_path)) return false;
62-
if (!set_current_dir(test_cwd_path)) return false;
63-
cmd_append(cmd, temp_sprintf("../%s", test_name));
64-
const char *test_stdout_path = temp_sprintf("../%s.stdout.txt", test_name);
65-
const char *test_stderr_path = temp_sprintf("../%s.stderr.txt", test_name);
66-
if (!cmd_run(cmd, .stdout_path = test_stdout_path, .stderr_path = test_stderr_path)) return false;
67-
if (!set_current_dir("../../../")) return false;
64+
if (!mkdir_if_not_exists(test_cwd_path)) return_defer(false);
65+
if (!set_current_dir(test_cwd_path)) return_defer(false);
66+
#ifdef _WIN32
67+
cmd_append(&cmd, temp_sprintf("../%s.exe", test_name));
68+
#else
69+
cmd_append(&cmd, temp_sprintf("../%s", test_name));
70+
#endif // _WIN32
71+
if (!cmd_run(&cmd, .stdout_path = test_stdout_path)) return_defer(false);
72+
if (!set_current_dir("../../../")) return_defer(false);
6873

6974
// TODO: implement record/replay testing for windows
70-
#ifndef _WIN32
71-
const char *src_stdout_path = temp_sprintf("%s%s.stdout.txt", BUILD_FOLDER TESTS_FOLDER, test_name);
72-
const char *src_stderr_path = temp_sprintf("%s%s.stderr.txt", BUILD_FOLDER TESTS_FOLDER, test_name);
73-
const char *dst_stdout_path = temp_sprintf("%s%s.stdout.txt", TESTS_FOLDER, test_name);
74-
const char *dst_stderr_path = temp_sprintf("%s%s.stderr.txt", TESTS_FOLDER, test_name);
7575
if (record) {
76-
if (!copy_file(src_stdout_path, dst_stdout_path)) return 1;
77-
if (!copy_file(src_stderr_path, dst_stderr_path)) return 1;
76+
if (!copy_file(src_stdout_path, dst_stdout_path)) return_defer(false);
7877
} else {
79-
cmd_append(cmd, "diff");
80-
cmd_append(cmd, "-u");
81-
cmd_append(cmd, dst_stdout_path);
82-
cmd_append(cmd, src_stdout_path);
83-
if (!cmd_run(cmd)) return false;
84-
85-
cmd_append(cmd, "diff");
86-
cmd_append(cmd, "-u");
87-
cmd_append(cmd, dst_stderr_path);
88-
cmd_append(cmd, src_stderr_path);
89-
if (!cmd_run(cmd)) return false;
78+
// TODO: it would be cool to have a portable diff utility in here.
79+
if (!read_entire_file(src_stdout_path, &src)) return_defer(false);
80+
if (!read_entire_file(dst_stdout_path, &dst)) return_defer(false);
81+
82+
src_sv = sb_to_sv(src);
83+
dst_sv = sb_to_sv(dst);
84+
85+
if (!sv_eq(src_sv, dst_sv)) {
86+
nob_log(ERROR, "UNEXPECTED OUTPUT!");
87+
nob_log(ERROR, "EXPECTED:");
88+
fprintf(stderr, SV_Fmt, SV_Arg(dst_sv));
89+
nob_log(ERROR, "ACTUAL:");
90+
fprintf(stderr, SV_Fmt, SV_Arg(src_sv));
91+
return_defer(false);
92+
}
9093
}
91-
#endif // _WIN32
9294

9395
nob_log(INFO, "--- %s finished ---", bin_path);
9496

95-
temp_rewind(mark);
96-
return true;
97+
defer:
98+
free(dst.items);
99+
free(src.items);
100+
free(cmd.items);
101+
return result;
97102
}
98103

99104
typedef struct {
@@ -158,8 +163,6 @@ void print_available_commands(Commands commands)
158163

159164
int main(int argc, char **argv)
160165
{
161-
set_log_handler(cancer_log_handler);
162-
163166
GO_REBUILD_URSELF_PLUS(argc, argv, "nob.h", "shared.h");
164167

165168
Cmd cmd = {0};
@@ -176,17 +179,22 @@ int main(int argc, char **argv)
176179
if (!mkdir_if_not_exists(BUILD_FOLDER)) return 1;
177180
if (!mkdir_if_not_exists(BUILD_FOLDER TESTS_FOLDER)) return 1;
178181

182+
size_t failed_count = 0;
179183
if (argc <= 0) {
180184
for (size_t i = 0; i < test_names_count; ++i) {
181-
if (!build_and_run_test(&cmd, test_names[i], false)) return 1;
185+
size_t mark = temp_save();
186+
if (!build_and_run_test(test_names[i], false)) failed_count += 1;
187+
temp_rewind(mark);
188+
}
189+
} else {
190+
while (argc > 0) {
191+
size_t mark = temp_save();
192+
const char *test_name = shift(argv, argc);
193+
if (!build_and_run_test(test_name, false)) failed_count += 1;
194+
temp_rewind(mark);
182195
}
183-
return 0;
184-
}
185-
186-
while (argc > 0) {
187-
const char *test_name = shift(argv, argc);
188-
if (!build_and_run_test(&cmd, test_name, false)) return 1;
189196
}
197+
if (failed_count > 0) return 1;
190198

191199
return 0;
192200
}
@@ -195,17 +203,23 @@ int main(int argc, char **argv)
195203
if (!mkdir_if_not_exists(BUILD_FOLDER)) return 1;
196204
if (!mkdir_if_not_exists(BUILD_FOLDER TESTS_FOLDER)) return 1;
197205

206+
size_t failed_count = 0;
198207
if (argc <= 0) {
199208
for (size_t i = 0; i < test_names_count; ++i) {
200-
if (!build_and_run_test(&cmd, test_names[i], true)) return 1;
209+
size_t mark = temp_save();
210+
if (!build_and_run_test(test_names[i], true)) failed_count += 1;
211+
temp_rewind(mark);
212+
}
213+
} else {
214+
while (argc > 0) {
215+
size_t mark = temp_save();
216+
const char *test_name = shift(argv, argc);
217+
if (!build_and_run_test(test_name, true)) failed_count += 1;
218+
temp_rewind(mark);
201219
}
202-
return 0;
203220
}
221+
if (failed_count > 0) return 1;
204222

205-
while (argc > 0) {
206-
const char *test_name = shift(argv, argc);
207-
if (!build_and_run_test(&cmd, test_name, true)) return 1;
208-
}
209223
return 0;
210224
}
211225

shared.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#define SHARED_H_
66

77
// Folder must end with forward slash /
8-
#define BUILD_FOLDER "build/"
9-
#define TESTS_FOLDER "tests/"
8+
#define BUILD_FOLDER "./build/"
9+
#define TESTS_FOLDER "./tests/"
1010

1111
// TODO: we should test on C++ compilers too
1212

@@ -32,6 +32,31 @@
3232
#endif
3333
#endif // __cplusplus
3434

35+
#define NOBDEF static inline
36+
#define NOB_IMPLEMENTATION
37+
#define NOB_EXPERIMENTAL_DELETE_OLD
38+
#define NOB_WARN_DEPRECATED
39+
#define NOB_STRIP_PREFIX // Testing for backward compatibility after v3.0.0
40+
#include "nob.h"
41+
#undef rename // Testing for backward compatibility after v1.20.6
3542

43+
// Utility that tests use to build the tools they need
44+
bool build_tool(Cmd *cmd, Procs *procs, const char *bin_path, const char *src_path, const char *src)
45+
{
46+
if (!write_entire_file(src_path, src, strlen(src))) return 1;
47+
48+
nob_cc(cmd);
49+
nob_cc_flags(cmd);
50+
nob_cc_output(cmd, bin_path);
51+
nob_cc_inputs(cmd, src_path);
52+
return cmd_run(
53+
cmd,
54+
.async = procs,
55+
// To make sure no compiler output pollutes the test output.
56+
// This is needed specifically for cl.exe cause it has
57+
// a tendency to output compiled source files to stdout.
58+
.stdout_path = temp_sprintf("%s.comp.txt", bin_path),
59+
);
60+
}
3661

3762
#endif // SHARED_H_

tests/chain.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#define NOB_IMPLEMENTATION
2-
#include "nob.h"
1+
#include "shared.h"
32

43
Cmd cmd = {0};
54
Chain chain = {0};
@@ -74,22 +73,11 @@ const char *hex_src =
7473
" return 0;\n"
7574
"}\n";
7675

77-
bool build_tool_async(const char *bin_path, const char *src_path, const char *src)
78-
{
79-
if (!write_entire_file(src_path, src, strlen(src))) return 1;
80-
81-
nob_cc(&cmd);
82-
nob_cc_flags(&cmd);
83-
nob_cc_output(&cmd, bin_path);
84-
nob_cc_inputs(&cmd, src_path);
85-
return cmd_run(&cmd, .async = &procs);
86-
}
87-
8876
int main(void)
8977
{
90-
if (!build_tool_async("./hello", "hello.c", hello_src)) return 1;
91-
if (!build_tool_async("./rot13", "rot13.c", rot13_src)) return 1;
92-
if (!build_tool_async("./hex", "hex.c", hex_src)) return 1;
78+
if (!build_tool(&cmd, &procs, "./hello", "hello.c", hello_src)) return 1;
79+
if (!build_tool(&cmd, &procs, "./rot13", "rot13.c", rot13_src)) return 1;
80+
if (!build_tool(&cmd, &procs, "./hex", "hex.c", hex_src)) return 1;
9381
if (!procs_flush(&procs)) return 1;
9482

9583
if (!chain_begin(&chain)) return 1;

tests/chain.stderr.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/chain.win32.stdout.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
55 72 79 79 62 20 67 62 20 66 67 71 72 65 65 0A Uryyb gb fgqree.
2+
55 72 79 79 62 20 67 62 20 66 67 71 62 68 67 0A Uryyb gb fgqbhg.
3+

tests/cmd_args_passing.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#define NOB_IMPLEMENTATION
2-
#include "nob.h"
1+
#include "shared.h"
32

43
int main(void)
54
{
@@ -14,13 +13,7 @@ int main(void)
1413
" }\n"
1514
" return 0;\n"
1615
"}\n";
17-
if (!write_entire_file("print_args.c", print_args_src, strlen(print_args_src))) return 1;
18-
19-
nob_cc(&cmd);
20-
nob_cc_flags(&cmd);
21-
nob_cc_output(&cmd, "print_args");
22-
nob_cc_inputs(&cmd, "print_args.c");
23-
if (!cmd_run(&cmd)) return 1;
16+
if (!build_tool(&cmd, NULL, "print_args", "print_args.c", print_args_src)) return 1;
2417

2518
cmd_append(&cmd, "./print_args");
2619
cmd_append(&cmd, "foo");

tests/cmd_args_passing.stderr.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
1: foo
2+
2: bar
3+
3: Hello, world
4+
4: "Hello, world"
5+
5: "\` %$*@

0 commit comments

Comments
 (0)