v2 / cmd / tools / vdoc / vdoc_file_test.v
143 lines · 132 sloc · 4.81 KB · d61fbe874cf6995c981b3182f120c0de55a91f61
Raw
1// vtest retry: 3
2import os
3import rand
4import term
5import v.util.vtest
6import v.util.diff
7
8const vexe_path = @VEXE
9const vexe = os.quoted_path(vexe_path)
10const vroot = os.dir(vexe_path)
11const should_autofix = os.getenv('VAUTOFIX') != ''
12
13fn test_output() {
14 os.setenv('VCOLORS', 'never', true)
15 os.chdir(vroot)!
16 mut total_fails := 0
17 test_files := vtest.filter_vtest_only(os.walk_ext('cmd/tools/vdoc/testdata', '.v'),
18 basepath: vroot
19 )
20 for path in test_files {
21 mut fails := 0
22 qpath := os.quoted_path(path)
23 path_no_ext := path.all_before_last('.')
24 print(path + ' ')
25 fails += check_output('${vexe} doc ${qpath}', path_no_ext + '.out')
26 fails += check_output('${vexe} doc -comments ${qpath}', '${path_no_ext}.unsorted.out',
27 should_sort: false
28 )
29 fails += check_output('${vexe} doc -comments ${qpath}', '${path_no_ext}.comments.out')
30 fails += check_output('${vexe} doc -readme -comments ${qpath}',
31 '${path_no_ext}.readme.comments.out')
32 // test the main 3 different formats:
33 program_dir := os.quoted_path(if os.is_dir(path) { path } else { os.dir(path) })
34 for fmt in ['html', 'ansi', 'text'] {
35 fails += check_output('${vexe} doc -no-timestamp -f ${fmt} -o - -html-only-contents -readme -comments ${program_dir}',
36 '${path_no_ext}.${fmt}')
37 }
38 fails += check_output('${vexe} doc -no-timestamp -f md -o - ${program_dir}',
39 '${path_no_ext}.md')
40 if fails == 0 {
41 println(term.green('OK'))
42 } else {
43 total_fails += fails
44 }
45 flush_stdout()
46 }
47 assert total_fails == 0
48}
49
50const small_pure_v_vlib_module = 'bitfield'
51
52fn test_out_path() {
53 // Work around CI issues covering v doc generation for relative input paths in tmp dir.
54 // Instead just generate documentation in the v source dir.
55 if os.getenv('CI') == 'true' {
56 default_output_path := os.join_path(vroot, 'vlib', small_pure_v_vlib_module, '_docs')
57 os.execute_opt('${vexe} doc -f html -m vlib/${small_pure_v_vlib_module}')!
58 final_html_path := os.join_path(default_output_path, '${small_pure_v_vlib_module}.html')
59 assert os.exists(final_html_path), final_html_path
60
61 // Custom out path (no `_docs` subdir).
62 out_dir := os.join_path(vroot, 'vlib', small_pure_v_vlib_module, 'docs')
63 os.execute_opt('${vexe} doc -f html -m -o ${out_dir} ${small_pure_v_vlib_module}')!
64 out_html_path := os.join_path(out_dir, '${small_pure_v_vlib_module}.html')
65 assert os.exists(out_html_path), out_html_path
66 os.rmdir_all(out_dir) or {}
67 os.rmdir_all(default_output_path) or {}
68 return
69 }
70
71 // Copy a *small* vlib module, that is written in pure V, for the test:
72 test_path := os.join_path(os.vtmp_dir(), 'vdoc_test_${rand.ulid()}')
73 test_mod_path := os.join_path(test_path, small_pure_v_vlib_module)
74 os.mkdir_all(test_path)!
75 // Sentinel v.mod so that vdoc's get_parent_mod() stops climbing here instead of
76 // picking up stray .v files in ancestor tmp dirs (e.g. /private/tmp on macOS).
77 os.write_file(os.join_path(test_path, 'v.mod'), "Module { name: 'vdoc_test' }\n")!
78 defer {
79 os.chdir(vroot) or {}
80 os.rmdir_all(test_path) or {}
81 }
82 os.chdir(test_path)!
83 mod_path := os.join_path(vroot, 'vlib', small_pure_v_vlib_module)
84 os.cp_all(mod_path, test_mod_path, true) or {}
85
86 // Relative input with default output path.
87 os.execute_opt('${vexe} doc -f html -m ${small_pure_v_vlib_module}')!
88 output_path := os.join_path(test_mod_path, '_docs', '${small_pure_v_vlib_module}.html')
89 assert os.exists(output_path), output_path
90
91 // Custom out path (no `_docs` subdir).
92 out_dir := os.join_path(os.vtmp_dir(), 'docs_test')
93 defer {
94 os.rmdir_all(out_dir) or {}
95 }
96 os.execute_opt('${vexe} doc -f html -m -o ${out_dir} ${small_pure_v_vlib_module}')!
97 html_path := os.join_path(out_dir, '${small_pure_v_vlib_module}.html')
98 assert os.exists(html_path), html_path
99}
100
101fn print_compare(expected string, found string) {
102 println(term.red('FAIL'))
103 println('============')
104 if diff_ := diff.compare_text(expected, found) {
105 println('diff:')
106 println(diff_)
107 println('============\n')
108 } else {
109 println('expected:')
110 println(expected)
111 println('============')
112 println('found:')
113 println(found)
114 println('============\n')
115 }
116}
117
118@[params]
119struct CheckOutputParams {
120 should_sort bool = true
121}
122
123fn check_output(cmd string, out_path string, opts CheckOutputParams) int {
124 if !os.exists(out_path) {
125 return 0
126 }
127 mut fails := 0
128 os.setenv('VDOC_SORT', opts.should_sort.str(), true)
129 expected := os.read_file(out_path) or { panic(err) }.replace('\r\n', '\n').trim_space()
130 res := os.execute_opt(cmd) or { panic(err) }
131 found := res.output.replace('\r\n', '\n').trim_space()
132 if expected != found {
133 print_compare(expected, found)
134 eprintln('>>> cmd: VDOC_SORT=${opts.should_sort} ${cmd}')
135 eprintln('>>> out_file_path: `${out_path}`')
136 eprintln('>>> fix: VDOC_SORT=${opts.should_sort} ${cmd} > ${out_path}')
137 fails++
138 }
139 if should_autofix {
140 os.write_file(out_path, res.output) or {}
141 }
142 return fails
143}
144