| 1 | import v.pref |
| 2 | import v.vmod |
| 3 | import os |
| 4 | |
| 5 | const vexe = @VEXE |
| 6 | const vroot = os.dir(vexe) |
| 7 | |
| 8 | fn test_check_parametes() { |
| 9 | // reproducing issue https://github.com/vlang/v/issues/13983 |
| 10 | _, cmd := pref.parse_args_and_show_errors(['help'], [''], true) |
| 11 | // no command found from args |
| 12 | assert cmd == '' |
| 13 | } |
| 14 | |
| 15 | fn test_version_flag() { |
| 16 | v_ver := vmod.from_file(os.join_path(vroot, 'v.mod'))!.version |
| 17 | v_ver_cmd_res := os.execute_opt('${vexe} --version')!.output |
| 18 | assert v_ver_cmd_res.starts_with('V ${v_ver}'), v_ver_cmd_res |
| 19 | |
| 20 | v_retry_ver_cmd_res := os.execute_opt('${vexe} retry --version')!.output |
| 21 | assert v_retry_ver_cmd_res != v_ver_cmd_res |
| 22 | |
| 23 | v_git_ver_subcmd_res := os.execute_opt('${vexe} retry -- git --version')!.output |
| 24 | assert v_git_ver_subcmd_res !in [v_ver_cmd_res, v_retry_ver_cmd_res] |
| 25 | |
| 26 | // Test version / verbosity toggle. |
| 27 | assert os.execute_opt('${vexe} -v')!.output == v_ver_cmd_res |
| 28 | assert os.execute_opt('${vexe} -cc tcc -v')!.output == v_ver_cmd_res |
| 29 | |
| 30 | example_path := os.join_path(vroot, 'examples', 'hello_world.v') |
| 31 | v_verbose_cmd_res := os.execute_opt('${vexe} -v run ${example_path}')!.output |
| 32 | assert v_verbose_cmd_res != v_ver_cmd_res |
| 33 | assert v_verbose_cmd_res.contains('v.pref.lookup_path:') |
| 34 | |
| 35 | v_verbose_cmd_with_additional_args_res := os.execute_opt('${vexe} -g -v run ${example_path}')!.output |
| 36 | assert v_verbose_cmd_with_additional_args_res != v_ver_cmd_res |
| 37 | assert v_verbose_cmd_with_additional_args_res.contains('v.pref.lookup_path:') |
| 38 | } |
| 39 | |
| 40 | fn test_cross_compile_keeps_explicit_cc() { |
| 41 | target_os := if pref.get_host_os() == .linux { 'macos' } else { 'linux' } |
| 42 | custom_cc := 'cosmocc' |
| 43 | |
| 44 | first, _ := pref.parse_args_and_show_errors(['help'], ['', '-cc', custom_cc, '-os', target_os], |
| 45 | false) |
| 46 | assert first.ccompiler_set_by_flag |
| 47 | assert first.ccompiler == custom_cc |
| 48 | |
| 49 | second, _ := pref.parse_args_and_show_errors(['help'], |
| 50 | ['', '-os', target_os, '-cc', custom_cc], false) |
| 51 | assert second.ccompiler_set_by_flag |
| 52 | assert second.ccompiler == custom_cc |
| 53 | } |
| 54 | |
| 55 | fn test_mac_is_alias_for_macos() { |
| 56 | os_kind := pref.os_from_string('mac') or { |
| 57 | assert false, err.msg() |
| 58 | return |
| 59 | } |
| 60 | assert os_kind == .macos |
| 61 | assert pref.OS.macos.is_target_of('mac') |
| 62 | assert !pref.OS.linux.is_target_of('mac') |
| 63 | } |
| 64 | |
| 65 | fn test_bsd_target_matches_macos_and_bsd_systems() { |
| 66 | for os_kind in [pref.OS.macos, .freebsd, .openbsd, .netbsd, .dragonfly] { |
| 67 | assert os_kind.is_target_of('bsd') |
| 68 | } |
| 69 | assert !pref.OS.linux.is_target_of('bsd') |
| 70 | assert !pref.OS.windows.is_target_of('bsd') |
| 71 | } |
| 72 | |
| 73 | fn test_disable_explicit_mutability_flag() { |
| 74 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 75 | prefs, _ := pref.parse_args_and_show_errors([], ['-disable-explicit-mutability', target], false) |
| 76 | assert prefs.disable_explicit_mutability |
| 77 | assert prefs.build_options.contains('-disable-explicit-mutability') |
| 78 | |
| 79 | prefs2, _ := pref.parse_args_and_show_errors([], ['--disable-explicit-mutability', target], |
| 80 | false) |
| 81 | assert prefs2.disable_explicit_mutability |
| 82 | assert prefs2.build_options.contains('--disable-explicit-mutability') |
| 83 | } |
| 84 | |
| 85 | fn test_profile_flag_does_not_consume_direct_compile_target() { |
| 86 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 87 | prefs, command := pref.parse_args_and_show_errors([], ['-profile', target], false) |
| 88 | assert command == target |
| 89 | assert prefs.path == target |
| 90 | assert prefs.is_prof |
| 91 | assert prefs.profile_file == '-' |
| 92 | } |
| 93 | |
| 94 | fn test_profile_flag_does_not_consume_run_command() { |
| 95 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 96 | prefs, command := pref.parse_args_and_show_errors([], ['-profile', 'run', target], false) |
| 97 | assert command == 'run' |
| 98 | assert prefs.path == target |
| 99 | assert prefs.is_run |
| 100 | assert prefs.is_prof |
| 101 | assert prefs.profile_file == '-' |
| 102 | } |
| 103 | |
| 104 | fn test_profile_flag_still_accepts_explicit_output_file() { |
| 105 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 106 | prefs, command := pref.parse_args_and_show_errors([], ['-profile', 'profile.txt', target], |
| 107 | false) |
| 108 | assert command == target |
| 109 | assert prefs.path == target |
| 110 | assert prefs.is_prof |
| 111 | assert prefs.profile_file == 'profile.txt' |
| 112 | } |
| 113 | |
| 114 | fn new_wasm_preferences() pref.Preferences { |
| 115 | return pref.Preferences{ |
| 116 | backend: .wasm |
| 117 | os: .browser |
| 118 | arch: .wasm32 |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | fn new_c_preferences() pref.Preferences { |
| 123 | return pref.Preferences{ |
| 124 | backend: .c |
| 125 | os: .linux |
| 126 | arch: .amd64 |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | fn test_c_backend_filters_backend_specific_files() { |
| 131 | prefs := new_c_preferences() |
| 132 | dir := os.join_path(os.vtmp_dir(), 'c_backend_filters') |
| 133 | filtered := prefs.should_compile_filtered_files(dir, [ |
| 134 | 'mod.c.v', |
| 135 | 'mod.js.v', |
| 136 | 'mod.v', |
| 137 | 'mod.wasm.v', |
| 138 | ]) |
| 139 | assert filtered == [ |
| 140 | os.join_path(dir, 'mod.c.v'), |
| 141 | os.join_path(dir, 'mod.v'), |
| 142 | ] |
| 143 | } |
| 144 | |
| 145 | fn test_c_backend_skips_modules_with_only_non_c_variants() { |
| 146 | prefs := new_c_preferences() |
| 147 | filtered := prefs.should_compile_filtered_files('sus', ['sus.js.v', 'sus.wasm.v']) |
| 148 | assert filtered.len == 0 |
| 149 | } |
| 150 | |
| 151 | fn test_wasm_backend_filters_backend_specific_files() { |
| 152 | prefs := new_wasm_preferences() |
| 153 | dir := os.join_path(os.vtmp_dir(), 'wasm_backend_filters') |
| 154 | filtered := prefs.should_compile_filtered_files(dir, [ |
| 155 | 'mod.c.v', |
| 156 | 'mod.js.v', |
| 157 | 'mod.v', |
| 158 | 'mod.wasm.v', |
| 159 | ]) |
| 160 | assert filtered == [ |
| 161 | os.join_path(dir, 'mod.v'), |
| 162 | os.join_path(dir, 'mod.wasm.v'), |
| 163 | ] |
| 164 | } |
| 165 | |
| 166 | fn test_wasm_backend_skips_modules_with_only_c_and_js_variants() { |
| 167 | prefs := new_wasm_preferences() |
| 168 | filtered := prefs.should_compile_filtered_files('sus', ['sus.c.v', 'sus.js.v']) |
| 169 | assert filtered.len == 0 |
| 170 | } |
| 171 | |
| 172 | fn filtered_file_names_for_os(os_kind pref.OS, files []string) []string { |
| 173 | prefs := pref.Preferences{ |
| 174 | os: os_kind |
| 175 | } |
| 176 | dir := os.join_path(os.vtmp_dir(), 'environment_specific_files') |
| 177 | mut res := []string{} |
| 178 | for file in prefs.should_compile_filtered_files(dir, files) { |
| 179 | res << os.base(file) |
| 180 | } |
| 181 | return res |
| 182 | } |
| 183 | |
| 184 | fn test_bsd_specific_files_are_filtered_by_target_os() { |
| 185 | for os_kind in [pref.OS.macos, .freebsd, .openbsd, .netbsd, .dragonfly] { |
| 186 | assert filtered_file_names_for_os(os_kind, ['mod_bsd.c.v', 'mod_bsd.v']) == [ |
| 187 | 'mod_bsd.c.v', |
| 188 | 'mod_bsd.v', |
| 189 | ] |
| 190 | } |
| 191 | assert filtered_file_names_for_os(.linux, ['mod_bsd.c.v', 'mod_bsd.v']).len == 0 |
| 192 | assert filtered_file_names_for_os(.windows, ['mod_bsd.c.v', 'mod_bsd.v']).len == 0 |
| 193 | } |
| 194 | |
| 195 | fn test_bsd_specific_files_prefer_more_specific_variants() { |
| 196 | mut files := [ |
| 197 | 'main.v', |
| 198 | 'something_default.c.v', |
| 199 | 'something_windows.c.v', |
| 200 | ] |
| 201 | assert filtered_file_names_for_os(.freebsd, files) == ['main.v', 'something_default.c.v'] |
| 202 | |
| 203 | files << 'something_nix.c.v' |
| 204 | assert filtered_file_names_for_os(.freebsd, files) == ['main.v', 'something_nix.c.v'] |
| 205 | |
| 206 | files << 'something_bsd.c.v' |
| 207 | assert filtered_file_names_for_os(.freebsd, files) == ['main.v', 'something_bsd.c.v'] |
| 208 | |
| 209 | files << 'something_freebsd.c.v' |
| 210 | assert filtered_file_names_for_os(.freebsd, files) == ['main.v', 'something_freebsd.c.v'] |
| 211 | } |
| 212 | |
| 213 | fn test_bsd_specific_files_prefer_darwin_on_macos() { |
| 214 | files := [ |
| 215 | 'main.v', |
| 216 | 'something_nix.c.v', |
| 217 | 'something_bsd.v', |
| 218 | 'something_darwin.v', |
| 219 | ] |
| 220 | assert filtered_file_names_for_os(.macos, files) == ['main.v', 'something_darwin.v'] |
| 221 | } |
| 222 | |
| 223 | fn test_explicit_gc_mode_is_forwarded_to_build_module() { |
| 224 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 225 | for gc_mode in ['none', 'boehm', 'boehm_full', 'boehm_incr', 'boehm_full_opt', 'boehm_incr_opt', |
| 226 | 'boehm_leak'] { |
| 227 | prefs, _ := pref.parse_args_and_show_errors([], ['-usecache', '-gc', gc_mode, target], |
| 228 | false) |
| 229 | assert prefs.build_options.contains('-gc ${gc_mode}') |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | fn test_cross_compile_defaults_windows_to_the_cross_compiler_arch() { |
| 234 | if pref.get_host_os() == .windows { |
| 235 | return |
| 236 | } |
| 237 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 238 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-os', 'windows', target], false) |
| 239 | assert prefs.arch == .amd64 |
| 240 | assert prefs.ccompiler == 'x86_64-w64-mingw32-gcc' |
| 241 | } |
| 242 | |
| 243 | fn test_cross_compile_windows_m32_uses_i386_arch_and_compiler() { |
| 244 | if pref.get_host_os() == .windows { |
| 245 | return |
| 246 | } |
| 247 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 248 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-os', 'windows', '-m32', target], false) |
| 249 | assert !prefs.m64 |
| 250 | assert prefs.arch == .i386 |
| 251 | assert prefs.ccompiler == 'i686-w64-mingw32-gcc' |
| 252 | assert prefs.build_options.contains('-m32') |
| 253 | } |
| 254 | |
| 255 | fn test_cross_compile_defaults_linux_to_amd64() { |
| 256 | if pref.get_host_os() == .linux { |
| 257 | return |
| 258 | } |
| 259 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 260 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-os', 'linux', target], false) |
| 261 | assert prefs.arch == .amd64 |
| 262 | assert prefs.ccompiler == 'clang' |
| 263 | } |
| 264 | |
| 265 | fn test_cross_compile_infers_android_arch_from_vcross_compiler_name() { |
| 266 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 267 | old_cross_compiler := os.getenv('VCROSS_COMPILER_NAME') |
| 268 | defer { |
| 269 | os.setenv('VCROSS_COMPILER_NAME', old_cross_compiler, true) |
| 270 | } |
| 271 | for compiler_name, expected_arch in { |
| 272 | 'aarch64-linux-android21-clang': pref.Arch.arm64 |
| 273 | 'armv7a-linux-androideabi21-clang': pref.Arch.arm32 |
| 274 | 'i686-linux-android21-clang': pref.Arch.i386 |
| 275 | 'x86_64-linux-android21-clang': pref.Arch.amd64 |
| 276 | } { |
| 277 | os.setenv('VCROSS_COMPILER_NAME', compiler_name, true) |
| 278 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-os', 'android', target], false) |
| 279 | assert prefs.arch == expected_arch |
| 280 | assert prefs.ccompiler == compiler_name |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | fn test_musl_defaults_to_no_gc() { |
| 285 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 286 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-musl', target], false) |
| 287 | assert prefs.is_musl |
| 288 | assert prefs.gc_mode == .no_gc |
| 289 | } |
| 290 | |
| 291 | fn test_musl_keeps_explicit_gc_selection() { |
| 292 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 293 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-musl', '-gc', 'boehm', target], false) |
| 294 | assert prefs.is_musl |
| 295 | assert prefs.gc_mode == .boehm_full_opt |
| 296 | } |
| 297 | |
| 298 | fn test_prealloc_defaults_to_no_gc() { |
| 299 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 300 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-prealloc', target], false) |
| 301 | assert prefs.prealloc |
| 302 | assert prefs.gc_mode == .no_gc |
| 303 | } |
| 304 | |
| 305 | fn test_prealloc_overrides_explicit_gc_selection() { |
| 306 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 307 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-gc', 'boehm', '-prealloc', target], |
| 308 | false) |
| 309 | assert prefs.prealloc |
| 310 | assert prefs.gc_mode == .no_gc |
| 311 | assert 'gcboehm' !in prefs.compile_defines |
| 312 | assert prefs.build_options.join(' ').contains('-gc none') |
| 313 | } |
| 314 | |
| 315 | fn stale_windows_gc_prefs(gc_set_by_flag bool) pref.Preferences { |
| 316 | mut prefs := pref.Preferences{ |
| 317 | os: .windows |
| 318 | ccompiler_type: .msvc |
| 319 | gc_mode: .boehm_full_opt |
| 320 | gc_set_by_flag: gc_set_by_flag |
| 321 | compile_defines: ['gcboehm', 'gcboehm_full', 'gcboehm_opt', 'custom'] |
| 322 | compile_defines_all: ['gcboehm', 'gcboehm_full', 'gcboehm_opt', 'custom'] |
| 323 | compile_values: map[string]string{} |
| 324 | build_options: ['-prod', '-d gcboehm', '-d gcboehm_full', '-d gcboehm_opt'] |
| 325 | } |
| 326 | prefs.compile_values['gcboehm'] = 'true' |
| 327 | prefs.compile_values['gcboehm_full'] = 'true' |
| 328 | prefs.compile_values['gcboehm_opt'] = 'true' |
| 329 | prefs.compile_values['custom'] = 'true' |
| 330 | return prefs |
| 331 | } |
| 332 | |
| 333 | fn test_windows_msvc_gc_defaults_are_cleared_after_compiler_resolution() { |
| 334 | mut prefs := stale_windows_gc_prefs(false) |
| 335 | |
| 336 | prefs.normalize_gc_defaults_for_resolved_ccompiler() |
| 337 | |
| 338 | assert prefs.gc_mode == .no_gc |
| 339 | assert prefs.build_options == ['-prod', '-gc', 'none'] |
| 340 | assert prefs.compile_defines == ['custom'] |
| 341 | assert prefs.compile_defines_all == ['custom'] |
| 342 | assert prefs.compile_values == { |
| 343 | 'custom': 'true' |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | fn test_windows_msvc_gc_defaults_keep_explicit_gc_selection() { |
| 348 | mut prefs := stale_windows_gc_prefs(true) |
| 349 | prefs.build_options = ['-prod', '-gc', 'boehm', '-d gcboehm', '-d gcboehm_full', '-d gcboehm_opt'] |
| 350 | |
| 351 | prefs.normalize_gc_defaults_for_resolved_ccompiler() |
| 352 | |
| 353 | assert prefs.gc_mode == .boehm_full_opt |
| 354 | assert prefs.build_options == ['-prod', '-gc', 'boehm', '-d gcboehm', '-d gcboehm_full', |
| 355 | '-d gcboehm_opt'] |
| 356 | assert prefs.compile_defines == ['gcboehm', 'gcboehm_full', 'gcboehm_opt', 'custom'] |
| 357 | assert prefs.compile_defines_all == ['gcboehm', 'gcboehm_full', 'gcboehm_opt', 'custom'] |
| 358 | assert prefs.compile_values == { |
| 359 | 'custom': 'true' |
| 360 | 'gcboehm': 'true' |
| 361 | 'gcboehm_full': 'true' |
| 362 | 'gcboehm_opt': 'true' |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | fn test_m32_sets_i386_arch_when_not_explicitly_set() { |
| 367 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 368 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-m32', target], false) |
| 369 | assert !prefs.m64 |
| 370 | assert prefs.arch == .i386 |
| 371 | assert prefs.build_options.contains('-m32') |
| 372 | } |
| 373 | |
| 374 | fn test_m32_does_not_override_explicit_arch() { |
| 375 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 376 | prefs, _ := pref.parse_args_and_show_errors([], ['', '-arch', 'amd64', '-m32', target], false) |
| 377 | assert !prefs.m64 |
| 378 | assert prefs.arch == .amd64 |
| 379 | assert prefs.build_options.contains('-m32') |
| 380 | } |
| 381 | |
| 382 | fn test_v_cmds_and_flags() { |
| 383 | build_cmd_res := os.execute('${vexe} build ${vroot}/examples/hello_world.v') |
| 384 | assert build_cmd_res.output.trim_space() == 'Use `v ${vroot}/examples/hello_world.v` instead.' |
| 385 | |
| 386 | too_many_targets_res := |
| 387 | os.execute('${vexe} ${vroot}/examples/hello_world.v ${vroot}/examples/fizz_buzz.v') |
| 388 | assert too_many_targets_res.output.trim_space() == 'Too many targets. Specify just one target: <target.v|target_directory>.' |
| 389 | |
| 390 | unknown_arg_res := os.execute('${vexe} -xyz') |
| 391 | assert unknown_arg_res.output.trim_space() == 'Unknown argument `-xyz`' |
| 392 | |
| 393 | unknown_arg_for_cmd_res := os.execute('${vexe} build-module -xyz ${vroot}/vlib/math') |
| 394 | assert unknown_arg_for_cmd_res.output.trim_space() == 'Unknown argument `-xyz` for command `build-module`' |
| 395 | |
| 396 | eval_removed_message := 'use v -v2 -eval file.v' |
| 397 | eval_flag_res := os.execute('${vexe} -eval ${vroot}/examples/hello_world.v') |
| 398 | assert eval_flag_res.exit_code == 1 |
| 399 | assert eval_flag_res.output.trim_space() == eval_removed_message |
| 400 | |
| 401 | eval_backend_res := os.execute('${vexe} -backend eval ${vroot}/examples/hello_world.v') |
| 402 | assert eval_backend_res.exit_code == 1 |
| 403 | assert eval_backend_res.output.trim_space() == eval_removed_message |
| 404 | |
| 405 | interpret_flag_res := os.execute('${vexe} -interpret ${vroot}/examples/hello_world.v') |
| 406 | assert interpret_flag_res.exit_code == 1 |
| 407 | assert interpret_flag_res.output.trim_space() == eval_removed_message |
| 408 | |
| 409 | interpret_command_res := os.execute('${vexe} interpret ${vroot}/examples/hello_world.v') |
| 410 | assert interpret_command_res.exit_code == 1 |
| 411 | assert interpret_command_res.output.trim_space() == eval_removed_message |
| 412 | |
| 413 | no_run_files_res := os.execute('${vexe} run') |
| 414 | assert no_run_files_res.output.trim_space() == 'v run: no v files listed' |
| 415 | |
| 416 | no_bm_files_res := os.execute('${vexe} build-module') |
| 417 | assert no_bm_files_res.output.trim_space() == 'v build-module: no module specified' |
| 418 | } |
| 419 | |
| 420 | fn test_build_command_compiles_vsh_without_running_it() { |
| 421 | test_dir := os.join_path(os.vtmp_dir(), 'v_pref_build_vsh_${os.getpid()}') |
| 422 | os.rmdir_all(test_dir) or {} |
| 423 | os.mkdir_all(test_dir)! |
| 424 | defer { |
| 425 | os.rmdir_all(test_dir) or {} |
| 426 | } |
| 427 | script_path := os.join_path(test_dir, 'build_only.vsh') |
| 428 | marker_path := os.join_path(test_dir, 'marker.txt') |
| 429 | mut exe_path := os.join_path(test_dir, 'build_only') |
| 430 | $if windows { |
| 431 | exe_path += '.exe' |
| 432 | } |
| 433 | os.write_file(script_path, "import os |
| 434 | |
| 435 | fn main() { |
| 436 | marker_path := os.join_path(@DIR, 'marker.txt') |
| 437 | os.write_file(marker_path, 'ran') or { panic(err) } |
| 438 | println('ran') |
| 439 | } |
| 440 | ")! |
| 441 | build_res := os.execute('${os.quoted_path(vexe)} -silent build ${os.quoted_path(script_path)}') |
| 442 | assert build_res.exit_code == 0, build_res.output |
| 443 | assert build_res.output == '' |
| 444 | assert !os.exists(marker_path) |
| 445 | assert os.is_file(exe_path) |
| 446 | |
| 447 | run_res := os.execute(os.quoted_path(exe_path)) |
| 448 | assert run_res.exit_code == 0, run_res.output |
| 449 | assert run_res.output.trim_space() == 'ran' |
| 450 | assert os.read_file(marker_path)! == 'ran' |
| 451 | } |
| 452 | |
| 453 | const tfile = os.join_path(os.vtmp_dir(), 'unknown_options_output.c') |
| 454 | |
| 455 | fn test_unknown_option_flags_no_run() { |
| 456 | os.chdir(os.dir(@VEXE))! |
| 457 | os.rm(tfile) or {} |
| 458 | |
| 459 | res1 := |
| 460 | os.execute('${os.quoted_path(@VEXE)} -o ${os.quoted_path(tfile)} examples/hello_world.v --an-unknown-option') |
| 461 | assert res1.exit_code == 1, res1.output |
| 462 | assert res1.output.starts_with('Unknown argument') |
| 463 | assert res1.output.contains('--an-unknown-option') |
| 464 | assert !os.exists(tfile) |
| 465 | |
| 466 | res2 := |
| 467 | os.execute('${os.quoted_path(@VEXE)} -o ${os.quoted_path(tfile)} --an-unknown-option examples/hello_world.v') |
| 468 | assert res2.exit_code == 1, res2.output |
| 469 | assert res2.output.starts_with('Unknown argument') |
| 470 | assert res2.output.contains('--an-unknown-option') |
| 471 | assert !os.exists(tfile) |
| 472 | } |
| 473 | |
| 474 | fn test_unknown_option_flags_with_run() { |
| 475 | res_run_o := |
| 476 | os.execute('${os.quoted_path(@VEXE)} -o ${os.quoted_path(tfile)} run examples/hello_world.v --an-unknown-option') |
| 477 | assert res_run_o.exit_code == 0, res_run_o.output |
| 478 | assert res_run_o.output == '' // because of -o, there should not be an actual run, since compilation stopped after generating the .c file |
| 479 | assert os.exists(tfile) |
| 480 | os.rm(tfile) or {} |
| 481 | |
| 482 | res_run_no_o_unknown_before_run := |
| 483 | os.execute('${os.quoted_path(@VEXE)} --an-unknown-option run examples/hello_world.v ') |
| 484 | assert res_run_no_o_unknown_before_run.exit_code == 1, res_run_no_o_unknown_before_run.output |
| 485 | assert res_run_no_o_unknown_before_run.output.starts_with('Unknown argument') |
| 486 | assert res_run_no_o_unknown_before_run.output.contains('--an-unknown-option') |
| 487 | assert !os.exists(tfile) |
| 488 | |
| 489 | res_run_no_o := |
| 490 | os.execute('${os.quoted_path(@VEXE)} run examples/hello_world.v --an-unknown-option') |
| 491 | assert res_run_no_o.exit_code == 0, res_run_no_o.output |
| 492 | assert res_run_no_o.output.trim_space() == 'Hello, World!' |
| 493 | assert !os.exists(tfile) |
| 494 | } |
| 495 | |
| 496 | fn test_missing_explicit_ccompiler_reports_error() { |
| 497 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 498 | missing_cc := 'missing_compiler_17126_for_pref_test' |
| 499 | output := os.join_path(os.vtmp_dir(), 'missing_explicit_ccompiler_output') |
| 500 | mut expected_output := output |
| 501 | $if windows { |
| 502 | expected_output += '.exe' |
| 503 | } |
| 504 | os.rm(expected_output) or {} |
| 505 | res := |
| 506 | os.execute('${os.quoted_path(@VEXE)} -cc ${missing_cc} -o ${os.quoted_path(output)} ${os.quoted_path(target)}') |
| 507 | assert res.exit_code != 0 |
| 508 | assert res.output.contains(missing_cc), res.output |
| 509 | assert res.output.to_lower().contains('not found') || res.output.to_lower().contains('missing'), res.output |
| 510 | |
| 511 | assert !os.exists(expected_output) |
| 512 | } |
| 513 | |
| 514 | fn test_generate_c_project_flag_parsing() { |
| 515 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 516 | prefs, _ := pref.parse_args_and_show_errors([], ['-generate-c-project', 'cproj', target], false) |
| 517 | assert prefs.generate_c_project == 'cproj' |
| 518 | assert prefs.use_cache == false |
| 519 | } |
| 520 | |
| 521 | fn test_generate_c_project_creates_build_files() { |
| 522 | output_dir := os.join_path(os.vtmp_dir(), 'v_generate_c_project_json') |
| 523 | os.rmdir_all(output_dir) or {} |
| 524 | defer { |
| 525 | os.rmdir_all(output_dir) or {} |
| 526 | } |
| 527 | target := os.join_path(vroot, 'examples', 'json.v') |
| 528 | cmd := '${os.quoted_path(vexe)} -generate-c-project ${os.quoted_path(output_dir)} ${os.quoted_path(target)}' |
| 529 | res := os.execute(cmd) |
| 530 | assert res.exit_code == 0, res.output |
| 531 | for rel_path in ['json.c', 'build_command.txt', 'build.sh', 'build.bat', 'Makefile'] { |
| 532 | assert os.is_file(os.join_path(output_dir, rel_path)) |
| 533 | } |
| 534 | build_command := os.read_file(os.join_path(output_dir, 'build_command.txt')) or { panic(err) } |
| 535 | generated_c_path := os.join_path(output_dir, 'json.c') |
| 536 | normalized_build_command := normalized_build_path(build_command) |
| 537 | assert normalized_build_command.contains(normalized_build_path(generated_c_path)) |
| 538 | || normalized_build_command.contains(normalized_build_path(os.short_path(generated_c_path))) |
| 539 | assert build_command.contains('cJSON.c') |
| 540 | assert !build_command.contains('.tmp.c') |
| 541 | assert !build_command.contains('.module.') |
| 542 | } |
| 543 | |
| 544 | fn normalized_build_path(path string) string { |
| 545 | mut normalized := path.replace('\\', '/') |
| 546 | for normalized.contains('//') { |
| 547 | normalized = normalized.replace('//', '/') |
| 548 | } |
| 549 | return normalized |
| 550 | } |
| 551 | |
| 552 | fn test_output_flag_accepts_directory_path() { |
| 553 | output_dir := os.join_path(os.vtmp_dir(), 'v_output_flag_directory') |
| 554 | os.rmdir_all(output_dir) or {} |
| 555 | defer { |
| 556 | os.rmdir_all(output_dir) or {} |
| 557 | } |
| 558 | target := os.join_path(vroot, 'examples', 'hello_world.v') |
| 559 | output_arg := output_dir + os.path_separator |
| 560 | res := |
| 561 | os.execute('${os.quoted_path(vexe)} -o ${os.quoted_path(output_arg)} ${os.quoted_path(target)}') |
| 562 | assert res.exit_code == 0, res.output |
| 563 | assert os.is_dir(output_dir) |
| 564 | mut expected_output := os.join_path(output_dir, 'hello_world') |
| 565 | $if windows { |
| 566 | expected_output += '.exe' |
| 567 | } |
| 568 | assert os.is_file(expected_output) |
| 569 | } |
| 570 | |
| 571 | fn test_tcc_shared_builds_disable_backtraces() { |
| 572 | mut shared_prefs := &pref.Preferences{ |
| 573 | path: 'libfoo.v' |
| 574 | is_shared: true |
| 575 | ccompiler: 'tinyc' |
| 576 | } |
| 577 | shared_prefs.fill_with_defaults() |
| 578 | assert 'no_backtrace' in shared_prefs.compile_defines_all |
| 579 | |
| 580 | mut regular_prefs := &pref.Preferences{ |
| 581 | path: 'main.v' |
| 582 | ccompiler: 'tinyc' |
| 583 | } |
| 584 | regular_prefs.fill_with_defaults() |
| 585 | assert 'no_backtrace' !in regular_prefs.compile_defines_all |
| 586 | } |
| 587 | |
| 588 | fn test_late_resolved_tcc_shared_builds_disable_backtraces() { |
| 589 | mut shared_prefs := &pref.Preferences{ |
| 590 | path: 'libfoo.v' |
| 591 | is_shared: true |
| 592 | ccompiler: 'gcc' |
| 593 | } |
| 594 | shared_prefs.fill_with_defaults() |
| 595 | assert 'no_backtrace' !in shared_prefs.compile_defines_all |
| 596 | |
| 597 | shared_prefs.ccompiler_type = .tinyc |
| 598 | shared_prefs.normalize_gc_defaults_for_resolved_ccompiler() |
| 599 | |
| 600 | assert 'no_backtrace' in shared_prefs.compile_defines_all |
| 601 | assert shared_prefs.build_options.contains('-d no_backtrace') |
| 602 | } |
| 603 | |
| 604 | fn test_wayland_only_linux_session_surfaces_a_v_error_for_gg() { |
| 605 | if os.user_os() == 'windows' { |
| 606 | return |
| 607 | } |
| 608 | pid := os.getpid() |
| 609 | test_dir := os.join_path(os.vtmp_dir(), 'v_issue_18030_gg_wayland_${pid}') |
| 610 | source_path := os.join_path(test_dir, 'main.v') |
| 611 | exe_path := os.join_path(test_dir, 'app') |
| 612 | source := 'import gg as _\n\nfn main() {}\n' |
| 613 | os.mkdir_all(test_dir) or { panic(err) } |
| 614 | os.write_file(source_path, source) or { panic(err) } |
| 615 | defer { |
| 616 | os.rmdir_all(test_dir) or {} |
| 617 | } |
| 618 | cmd := 'DISPLAY= WAYLAND_DISPLAY=wayland-0 XDG_SESSION_TYPE=wayland ${os.quoted_path(vexe)} -os linux -o ${os.quoted_path(exe_path)} ${os.quoted_path(source_path)}' |
| 619 | res := os.execute(cmd) |
| 620 | output := res.output.replace('\r', '') |
| 621 | if res.exit_code == 0 { |
| 622 | eprintln('> failed command: ${cmd}') |
| 623 | } |
| 624 | assert res.exit_code != 0 |
| 625 | assert output.contains('Wayland-only Linux session without `-d sokol_wayland`') |
| 626 | assert !output.contains('C error. This should never happen.') |
| 627 | } |
| 628 | |