Skip to content

Commit 8d5b688

Browse files
committed
tests: make first_run.v work with current V and on Windows
- Use x.json2 (import x.json2 as json), so the generic json.decode[T](...) or {} calls compile with the current V compiler (vlib/json expects json.decode(T, s)). - Compile gitly with -d sqlite, so the test uses the embedded sqlite backend instead of the default PostgreSQL one and needs no external database. - Start/stop gitly via os.new_process instead of a Unix-only './gitly.exe &' plus 'pkill', so the test works on Windows, macOS and Linux, and reliably shuts the server down (releasing the sqlite file before it is removed). - Skip -d use_libbacktrace/-d use_openssl on Windows (libbacktrace is not available there; the native schannel https backend is used instead). - Add GITLY_TEST_SKIP_REMOTE_REPO to skip the network/git-heavy tests that clone a remote GitHub repo, so the pure 'serves the expected HTML' checks can run as a fast, reliable smoke test (e.g. in vlang/v's Windows CI).
1 parent a1720ed commit 8d5b688

1 file changed

Lines changed: 92 additions & 47 deletions

File tree

tests/first_run.v

Lines changed: 92 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import os
22
import log
33
import net.http
44
import time
5-
import json
5+
import x.json2 as json
66
import api
7-
import term
87

98
const gitly_url = 'http://127.0.0.1:8080'
109

@@ -16,8 +15,14 @@ const test_github_repo_url = 'https://github.com/vlang/pcre'
1615

1716
const test_github_repo_primary_branch = 'master'
1817

18+
// When GITLY_TEST_SKIP_REMOTE_REPO is set, the tests that clone a remote GitHub
19+
// repository (and therefore need network access + a working outbound git/https
20+
// stack) are skipped. This keeps the pure "gitly serves the expected HTML"
21+
// checks usable as a fast, reliable smoke test (e.g. in vlang/v's Windows CI).
22+
const skip_remote_repo = os.getenv('GITLY_TEST_SKIP_REMOTE_REPO') != ''
23+
1924
fn main() {
20-
before()!
25+
mut gitly_process := before()!
2126

2227
test_index_page()
2328

@@ -43,36 +48,42 @@ fn main() {
4348
assert get_repo_issue_count(token, test_username, 'test1') == 0
4449
assert get_repo_branch_count(token, test_username, 'test1') == 0
4550

46-
repo_name := 'test2'
47-
test_create_repo(token, repo_name, test_github_repo_url)
48-
// wait while repo is cloning
49-
time.sleep(5 * time.second)
50-
// get repo
51-
assert get_repo_commit_count(token, test_username, repo_name, test_github_repo_primary_branch) > 0
52-
assert get_repo_issue_count(token, test_username, repo_name) == 0
53-
assert get_repo_branch_count(token, test_username, repo_name) > 0
54-
test_repo_page(test_username, repo_name)
55-
test_branch_page(test_username, repo_name, test_github_repo_primary_branch)
56-
test_repos_page(test_username)
57-
test_repo_settings_page(test_username, repo_name)
58-
test_contributors_page(test_username, repo_name)
59-
// test_issues_page(test_username)
60-
test_stars_page(test_username)
61-
test_settings_page(test_username)
62-
test_commits_page(test_username, repo_name, test_github_repo_primary_branch)
63-
test_branches_page(test_username, repo_name)
64-
test_repo_tree(test_username, repo_name, test_github_repo_primary_branch, 'c')
65-
// this makes sure that the blob (and the tree?) is ready
66-
test_repo_tree(test_username, repo_name, test_github_repo_primary_branch, 'examples')
67-
test_blob_page(test_username, repo_name, test_github_repo_primary_branch, 'examples/hello.v')
68-
// test_refs_page(test_username, repo_name)
69-
// test_api_branches_count(test_username, repo_name)
51+
if skip_remote_repo {
52+
ilog('Skipping the remote repository clone tests (GITLY_TEST_SKIP_REMOTE_REPO is set)')
53+
} else {
54+
repo_name := 'test2'
55+
test_create_repo(token, repo_name, test_github_repo_url)
56+
// wait while repo is cloning
57+
time.sleep(5 * time.second)
58+
// get repo
59+
assert get_repo_commit_count(token, test_username, repo_name,
60+
test_github_repo_primary_branch) > 0
61+
assert get_repo_issue_count(token, test_username, repo_name) == 0
62+
assert get_repo_branch_count(token, test_username, repo_name) > 0
63+
test_repo_page(test_username, repo_name)
64+
test_branch_page(test_username, repo_name, test_github_repo_primary_branch)
65+
test_repos_page(test_username)
66+
test_repo_settings_page(test_username, repo_name)
67+
test_contributors_page(test_username, repo_name)
68+
// test_issues_page(test_username)
69+
test_stars_page(test_username)
70+
test_settings_page(test_username)
71+
test_commits_page(test_username, repo_name, test_github_repo_primary_branch)
72+
test_branches_page(test_username, repo_name)
73+
test_repo_tree(test_username, repo_name, test_github_repo_primary_branch, 'c')
74+
// this makes sure that the blob (and the tree?) is ready
75+
test_repo_tree(test_username, repo_name, test_github_repo_primary_branch, 'examples')
76+
test_blob_page(test_username, repo_name, test_github_repo_primary_branch,
77+
'examples/hello.v')
78+
// test_refs_page(test_username, repo_name)
79+
// test_api_branches_count(test_username, repo_name)
80+
}
7081
ilog('all tests passed!')
7182

72-
after()!
83+
after(mut gitly_process)!
7384
}
7485

75-
fn before() ! {
86+
fn before() !&os.Process {
7687
cd_executable_dir()!
7788

7889
ilog('Make sure gitly is not running')
@@ -83,24 +94,37 @@ fn before() ! {
8394
compile_gitly()
8495

8596
ilog('Start gitly in the background, then wait till gitly starts and is responding to requests')
86-
spawn run_gitly()
97+
mut gitly_process := start_gitly()
8798

88-
wait_gitly()
89-
}
99+
wait_gitly(mut gitly_process)
90100

91-
fn after() ! {
92-
remove_database_if_exists()!
93-
remove_repos_dir_if_exists()!
101+
return gitly_process
102+
}
94103

104+
fn after(mut gitly_process os.Process) ! {
95105
ilog('Ensure gitly is stopped')
106+
if gitly_process.is_alive() {
107+
gitly_process.signal_kill()
108+
}
109+
gitly_process.wait()
110+
// A best effort fallback, in case an older instance is still lingering:
96111
kill_gitly_processes()
112+
113+
// Only remove the DB/repos after gitly has released them, otherwise the
114+
// files are still locked on Windows and the removal fails.
115+
remove_database_if_exists()!
116+
remove_repos_dir_if_exists()!
97117
}
98118

99-
fn run_gitly() {
100-
gitly_process := os.execute('./gitly.exe &')
101-
if gitly_process.exit_code != 0 {
102-
exit_with_message(gitly_process.str())
103-
}
119+
// start_gitly launches the freshly compiled gitly.exe as a background process.
120+
// It uses os.new_process (instead of a shell `&`), so that it works the same
121+
// way on Windows, macOS and Linux, and so the process can be stopped later.
122+
fn start_gitly() &os.Process {
123+
gitly_exe := os.join_path(os.getwd(), 'gitly.exe')
124+
mut gitly_process := os.new_process(gitly_exe)
125+
gitly_process.set_work_folder(os.getwd())
126+
gitly_process.run()
127+
return gitly_process
104128
}
105129

106130
@[noreturn]
@@ -122,7 +146,11 @@ fn cd_executable_dir() ! {
122146
}
123147

124148
fn kill_gitly_processes() {
125-
os.execute('pkill -9 gitly.exe')
149+
$if windows {
150+
os.execute('taskkill /F /IM gitly.exe')
151+
} $else {
152+
os.execute('pkill -9 gitly.exe')
153+
}
126154
}
127155

128156
fn remove_database_if_exists() ! {
@@ -143,18 +171,35 @@ fn remove_repos_dir_if_exists() ! {
143171

144172
fn compile_gitly() {
145173
ilog('Compile gitly')
146-
// Note that using `-d use_openssl` prevents tcc from working, so the compilation will be much slower:
147-
os.execute('v -d use_libbacktrace -cg -keepc -d use_openssl -o gitly.exe .')
174+
// Use the same V compiler that is running this test.
175+
vexe := os.getenv_opt('VEXE') or { @VEXE }
176+
// `-d sqlite` makes gitly use an embedded sqlite database instead of the
177+
// default PostgreSQL backend, so the test needs no external database.
178+
// Note that using `-d use_openssl` prevents tcc from working, so the compilation will be much slower.
179+
// On Windows, -d use_libbacktrace is skipped (libbacktrace is not available there) and the native
180+
// schannel https backend is used, so -d use_openssl is skipped as well.
181+
mut compile_cmd := '${os.quoted_path(vexe)} -d sqlite -keepc -o gitly.exe .'
182+
$if !windows {
183+
compile_cmd = '${os.quoted_path(vexe)} -d sqlite -d use_libbacktrace -cg -keepc -d use_openssl -o gitly.exe .'
184+
}
185+
res := os.execute(compile_cmd)
186+
if res.exit_code != 0 {
187+
exit_with_message('failed to compile gitly:\n${res.output}')
188+
}
148189
ilog('Compiled gitly.exe, size: ${os.file_size('gitly.exe')}')
149190
}
150191

151-
fn wait_gitly() {
152-
for waiting_cycles := 0; waiting_cycles < 50; waiting_cycles++ {
192+
fn wait_gitly(mut gitly_process os.Process) {
193+
for waiting_cycles := 0; waiting_cycles < 100; waiting_cycles++ {
153194
ilog('\twait: ${waiting_cycles}')
154-
time.sleep(100 * time.millisecond)
195+
if !gitly_process.is_alive() {
196+
exit_with_message('gitly exited before answering any request (exit code ${gitly_process.code}); this indicates a crash')
197+
}
198+
time.sleep(200 * time.millisecond)
155199
http.get(prepare_url('')) or { continue }
156-
break
200+
return
157201
}
202+
exit_with_message('gitly did not start listening on ${gitly_url} in time')
158203
}
159204

160205
fn prepare_url(path string) string {

0 commit comments

Comments
 (0)