vxx2 / cmd / tools / vwatch_test.v
103 lines · 87 sloc · 3.24 KB · e52df340fa322ab5c6d5d83e8e18685c95f6c092
Raw
1import os
2import time
3
4const vexe = @VEXE
5const vroot = os.dir(vexe)
6const tdir = os.join_path(os.vtmp_dir(), 'vwatch_test_24571')
7const tsource_dir = os.join_path(tdir, 'src')
8const toutput_dir = os.join_path(tdir, 'out')
9
10fn testsuite_begin() {
11 os.rmdir_all(tdir) or {}
12 os.mkdir_all(tsource_dir)!
13 os.mkdir_all(toutput_dir)!
14}
15
16fn testsuite_end() {
17 os.rmdir_all(tdir) or {}
18}
19
20fn test_watch_keeps_backend_flag_intact() {
21 source_path := os.join_path(tsource_dir, 'hello.v')
22 output_path := os.join_path(toutput_dir, 'hello.js')
23 os.write_file(source_path, "fn main() {\n\tprintln('Hello world')\n}\n")!
24
25 mut process := os.new_process(vexe)
26 process.set_work_folder(vroot)
27 process.set_redirect_stdio()
28 process.use_pgroup = true
29 process.set_args(['watch', '-backend', 'js_browser', '-output', output_path, source_path])
30 process.run()
31
32 for _ in 0 .. 300 {
33 if os.exists(output_path) || !process.is_alive() {
34 break
35 }
36 time.sleep(100 * time.millisecond)
37 }
38 if process.is_alive() {
39 process.signal_pgkill()
40 }
41 process.wait()
42 output := process.stdout_slurp() + process.stderr_slurp()
43 process.close()
44
45 assert os.exists(output_path), output
46 assert output.contains(' -backend js_browser '), output
47 assert !output.contains('-baend'), output
48 assert !output.contains('Unknown argument `-baend`'), output
49}
50
51// Regression test for https://github.com/vlang/v/issues/27463 :
52// `v watch run main.v` should recompile and rerun the program, when its source changes.
53fn test_watch_run_reloads_on_source_change() {
54 source_path := os.join_path(tsource_dir, 'reload.v')
55 marker_path := os.join_path(toutput_dir, 'reload_marker.txt')
56 os.rm(marker_path) or {}
57 write_versioned_source(source_path, 'V1')!
58
59 mut process := os.new_process(vexe)
60 process.set_work_folder(vroot)
61 process.set_redirect_stdio()
62 process.use_pgroup = true
63 // the marker_path argument is passed through to the compiled and run program (see write_versioned_source):
64 process.set_args(['watch', 'run', source_path, marker_path])
65 process.run()
66
67 // wait for the first compile+run to write the marker file:
68 first_run_done := wait_for_marker(marker_path, 'V1')
69
70 // os.file_last_mod_unix has a 1 second resolution, so make sure the edit lands in a later second,
71 // otherwise the change detection loop can not notice that the source file was modified at all:
72 time.sleep(1500 * time.millisecond)
73 write_versioned_source(source_path, 'V2')!
74
75 // the watcher should detect the change, recompile, and rerun, updating the marker to V2:
76 reloaded := wait_for_marker(marker_path, 'V2')
77
78 if process.is_alive() {
79 process.signal_pgkill()
80 }
81 process.wait()
82 output := process.stdout_slurp() + process.stderr_slurp()
83 process.close()
84
85 assert first_run_done, 'the watched program was never compiled and run\n${output}'
86 assert reloaded, 'the watcher did not recompile and rerun after the source file changed\n${output}'
87}
88
89fn write_versioned_source(source_path string, version string) ! {
90 os.write_file(source_path,
91 "import os\nfn main() {\n\tos.write_file(os.args[1], '${version}') or { panic(err) }\n}\n")!
92}
93
94fn wait_for_marker(marker_path string, expected string) bool {
95 for _ in 0 .. 300 {
96 content := os.read_file(marker_path) or { '' }
97 if content == expected {
98 return true
99 }
100 time.sleep(100 * time.millisecond)
101 }
102 return false
103}
104