v4 / vlib / v3 / tests / c_directive_order_codegen_test.v
191 lines · 162 sloc · 6.13 KB · 288feee4702b35beadb4037d02b96b5c8674156b
Raw
1import os
2
3const directive_order_vexe = @VEXE
4const directive_order_tests_dir = os.dir(@FILE)
5const directive_order_v3_dir = os.dir(directive_order_tests_dir)
6const directive_order_vlib_dir = os.dir(directive_order_v3_dir)
7const directive_order_v3_src = os.join_path(directive_order_v3_dir, 'v3.v')
8
9fn directive_order_build_v3() string {
10 v3_bin := os.join_path(os.temp_dir(), 'v3_c_directive_order_test')
11 build :=
12 os.execute('${directive_order_vexe} -gc none -path "${directive_order_vlib_dir}|@vlib|@vmodules" -o ${v3_bin} ${directive_order_v3_src}')
13 assert build.exit_code == 0, build.output
14 return v3_bin
15}
16
17fn directive_order_write_file(root string, rel string, src string) {
18 path := os.join_path(root, rel)
19 os.mkdir_all(os.dir(path)) or { panic(err) }
20 os.write_file(path, src) or { panic(err) }
21}
22
23fn directive_order_gen_c(v3_bin string) string {
24 root := os.join_path(os.temp_dir(), 'v3_c_directive_order_project')
25 os.rmdir_all(root) or {}
26 os.mkdir_all(root) or { panic(err) }
27 directive_order_write_file(root, 'v.mod', "Module { name: 'directive_order' }\n")
28 directive_order_write_file(root, 'main.v', 'module main
29
30import sokol.f as _
31
32fn main() {}
33')
34 directive_order_write_file(root, 'sokol/c/c.v', 'module c
35
36#define SOKOL_GFX_IMPL
37#include "sokol_gfx.h"
38')
39 directive_order_write_file(root, 'sokol/f/f.v', 'module f
40
41import sokol.c as _
42
43#define SOKOL_FONTSTASH_IMPL
44#include "util/sokol_fontstash.h"
45#include "sokol_gfx.h"
46#ifdef KEEP_DUPLICATE_INCLUDE
47#include "sokol_gfx.h"
48#endif
49')
50 c_out := os.join_path(os.temp_dir(), 'v3_c_directive_order.c')
51 os.rm(c_out) or {}
52 result := os.execute('${v3_bin} ${os.join_path(root, 'main.v')} -b c -o ${c_out}')
53 assert result.exit_code == 0, result.output
54 return os.read_file(c_out) or { panic(err) }
55}
56
57fn directive_order_gen_c_dotted_collision(v3_bin string) string {
58 root := os.join_path(os.temp_dir(), 'v3_c_directive_order_dotted_collision_project')
59 os.rmdir_all(root) or {}
60 os.mkdir_all(root) or { panic(err) }
61 directive_order_write_file(root, 'v.mod',
62 "Module { name: 'directive_order_dotted_collision' }\n")
63 directive_order_write_file(root, 'main.v', 'module main
64
65import foo.user as _
66import bar as _
67
68fn main() {}
69')
70 directive_order_write_file(root, 'bar/bar.v', 'module bar
71
72#define SHORT_BAR
73')
74 directive_order_write_file(root, 'foo/bar/bar.v', 'module bar
75
76#define FOO_BAR
77')
78 directive_order_write_file(root, 'foo/user/user.v', 'module user
79
80import foo.bar as _
81
82#define FOO_USER
83')
84 c_out := os.join_path(os.temp_dir(), 'v3_c_directive_order_dotted_collision.c')
85 os.rm(c_out) or {}
86 result := os.execute('${v3_bin} ${os.join_path(root, 'main.v')} -b c -o ${c_out}')
87 assert result.exit_code == 0, result.output
88 return os.read_file(c_out) or { panic(err) }
89}
90
91fn directive_order_gen_and_run_importer_macro(v3_bin string) string {
92 root := os.join_path(os.temp_dir(), 'v3_c_directive_order_importer_macro_project')
93 os.rmdir_all(root) or {}
94 os.mkdir_all(root) or { panic(err) }
95 directive_order_write_file(root, 'v.mod', "Module { name: 'directive_order_importer_macro' }\n")
96 directive_order_write_file(root, 'main.v', 'module main
97
98#define USE_FOO
99
100import wrapper
101
102fn main() {
103 println(wrapper.value().str())
104}
105')
106 directive_order_write_file(root, 'wrapper/wrapper.v', 'module wrapper
107
108#include "@DIR/foo.h"
109
110fn C.foo_value() int
111
112pub fn value() int {
113 return C.foo_value()
114}
115')
116 directive_order_write_file(root, 'wrapper/foo.h', '#ifndef USE_FOO
117#error "USE_FOO must be defined before foo.h"
118#endif
119
120static inline int foo_value(void) {
121 return 42;
122}
123')
124 bin_out := os.join_path(os.temp_dir(), 'v3_c_directive_order_importer_macro')
125 os.rm(bin_out) or {}
126 os.rm(bin_out + '.c') or {}
127 result := os.execute('${v3_bin} ${os.join_path(root, 'main.v')} -b c -o ${bin_out}')
128 assert result.exit_code == 0, result.output
129 run := os.execute(bin_out)
130 assert run.exit_code == 0, run.output
131 assert run.output.trim_space() == '42', run.output
132 return os.read_file(bin_out + '.c') or { panic(err) }
133}
134
135fn directive_order_index(c_code string, needle string) int {
136 return c_code.index(needle) or { -1 }
137}
138
139fn directive_order_count(c_code string, needle string) int {
140 mut count := 0
141 mut rest := c_code
142 for {
143 idx := rest.index(needle) or { break }
144 count++
145 rest = rest[idx + needle.len..]
146 }
147 return count
148}
149
150fn test_c_directives_follow_import_dependency_order() {
151 c_code := directive_order_gen_c(directive_order_build_v3())
152 gfx_define := directive_order_index(c_code, '#define SOKOL_GFX_IMPL')
153 gfx_include := directive_order_index(c_code, '#include "sokol_gfx.h"')
154 fontstash_define := directive_order_index(c_code, '#define SOKOL_FONTSTASH_IMPL')
155 fontstash_include := directive_order_index(c_code, '#include "util/sokol_fontstash.h"')
156 block_start := directive_order_index(c_code, '#ifdef KEEP_DUPLICATE_INCLUDE')
157 assert gfx_define >= 0, c_code
158 assert gfx_include >= 0, c_code
159 assert fontstash_define >= 0, c_code
160 assert fontstash_include >= 0, c_code
161 assert block_start >= 0, c_code
162 assert gfx_define < gfx_include, c_code
163 assert gfx_include < fontstash_define, c_code
164 assert fontstash_define < fontstash_include, c_code
165 assert directive_order_count(c_code, '#include "sokol_gfx.h"') == 2, c_code
166 block_tail := c_code[block_start..]
167 block_include := directive_order_index(block_tail, '#include "sokol_gfx.h"')
168 block_end := directive_order_index(block_tail, '#endif')
169 assert block_include >= 0, c_code
170 assert block_end > block_include, c_code
171}
172
173fn test_c_directives_preserve_dotted_import_module_identity() {
174 c_code := directive_order_gen_c_dotted_collision(directive_order_build_v3())
175 short_bar := directive_order_index(c_code, '#define SHORT_BAR')
176 foo_bar := directive_order_index(c_code, '#define FOO_BAR')
177 foo_user := directive_order_index(c_code, '#define FOO_USER')
178 assert short_bar >= 0, c_code
179 assert foo_bar >= 0, c_code
180 assert foo_user >= 0, c_code
181 assert foo_bar < foo_user, c_code
182}
183
184fn test_importer_macro_is_emitted_before_dependency_include() {
185 c_code := directive_order_gen_and_run_importer_macro(directive_order_build_v3())
186 use_foo := directive_order_index(c_code, '#define USE_FOO')
187 foo_header := directive_order_index(c_code, 'foo.h"')
188 assert use_foo >= 0, c_code
189 assert foo_header >= 0, c_code
190 assert use_foo < foo_header, c_code
191}
192