mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
vweb: make vweb_test.v more robust and faster, by embedding its server as a module
This commit is contained in:
parent
34e435313f
commit
3a66355d5d
@ -1,60 +1,19 @@
|
||||
import os
|
||||
import time
|
||||
import io
|
||||
import json
|
||||
import time
|
||||
import net
|
||||
import net.http
|
||||
import io
|
||||
import vweb.tests.vweb_test_server
|
||||
|
||||
const sport = 12380
|
||||
const localserver = '127.0.0.1:${sport}'
|
||||
const exit_after_time = 12000 // milliseconds
|
||||
const exit_after_time = 12 * time.second
|
||||
|
||||
const vexe = os.getenv('VEXE')
|
||||
const vweb_logfile = os.getenv('VWEB_LOGFILE')
|
||||
const vroot = os.dir(vexe)
|
||||
const serverexe = os.join_path(os.cache_dir(), 'vweb_test_server.exe')
|
||||
const tcp_r_timeout = 30 * time.second
|
||||
const tcp_w_timeout = 30 * time.second
|
||||
|
||||
// setup of vweb webserver
|
||||
fn testsuite_begin() {
|
||||
os.chdir(vroot) or {}
|
||||
if os.exists(serverexe) {
|
||||
os.rm(serverexe) or {}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_a_simple_vweb_app_can_be_compiled() {
|
||||
// did_server_compile := os.system('${os.quoted_path(vexe)} -g -o ${os.quoted_path(serverexe)} vlib/vweb/tests/vweb_test_server.v')
|
||||
// TODO: find out why it does not compile with -usecache and -g
|
||||
did_server_compile := os.system('${os.quoted_path(vexe)} -o ${os.quoted_path(serverexe)} vlib/vweb/tests/vweb_test_server.v')
|
||||
assert did_server_compile == 0
|
||||
assert os.exists(serverexe)
|
||||
}
|
||||
|
||||
fn test_a_simple_vweb_app_runs_in_the_background() {
|
||||
mut suffix := ''
|
||||
$if !windows {
|
||||
suffix = ' > /dev/null &'
|
||||
}
|
||||
if vweb_logfile != '' {
|
||||
suffix = ' 2>> ${os.quoted_path(vweb_logfile)} >> ${os.quoted_path(vweb_logfile)} &'
|
||||
}
|
||||
server_exec_cmd := '${os.quoted_path(serverexe)} ${sport} ${exit_after_time} ${suffix}'
|
||||
$if debug_net_socket_client ? {
|
||||
eprintln('running:\n${server_exec_cmd}')
|
||||
}
|
||||
$if windows {
|
||||
spawn os.system(server_exec_cmd)
|
||||
} $else {
|
||||
res := os.system(server_exec_cmd)
|
||||
assert res == 0
|
||||
}
|
||||
$if macos {
|
||||
time.sleep(1000 * time.millisecond)
|
||||
} $else {
|
||||
time.sleep(100 * time.millisecond)
|
||||
}
|
||||
vweb_test_server.start_in_background(sport, exit_after_time)!
|
||||
}
|
||||
|
||||
// web client tests follow
|
||||
|
@ -1,54 +1,60 @@
|
||||
module main
|
||||
module vweb_test_server
|
||||
|
||||
import os
|
||||
import log
|
||||
import vweb
|
||||
import time
|
||||
|
||||
@[if verbose_vweb_server ?]
|
||||
fn linfo(s string) {
|
||||
log.info(s)
|
||||
}
|
||||
|
||||
pub fn start_in_background(http_port int, timeout time.Duration) ! {
|
||||
linfo('>> ${@FN}, http_port: ${http_port}, timeout: ${timeout}')
|
||||
assert http_port > 0
|
||||
assert timeout > 0
|
||||
//
|
||||
spawn fn (timeout time.Duration) {
|
||||
time.sleep(timeout)
|
||||
linfo('>> webserver: pid: ${os.getpid()}, exiting cleanly after ${timeout.milliseconds()}ms ...')
|
||||
exit(0)
|
||||
}(timeout)
|
||||
shared config := &Config{
|
||||
max_ping: 50
|
||||
}
|
||||
app := &App{
|
||||
port: http_port
|
||||
global_config: config
|
||||
}
|
||||
linfo('>> webserver: pid: ${os.getpid()}, started on http://localhost:${app.port}/ , with maximum runtime of ${timeout.milliseconds()} ms.')
|
||||
spawn fn (app &App, http_port int) {
|
||||
vweb.run_at(app, host: 'localhost', port: http_port, family: .ip) or {}
|
||||
}(app, http_port)
|
||||
_ := <-app.is_ready
|
||||
log.info('>> ${@FN} finished, http_port: ${http_port}, timeout: ${timeout}')
|
||||
}
|
||||
|
||||
const known_users = ['bilbo', 'kent']
|
||||
|
||||
struct App {
|
||||
vweb.Context
|
||||
port int
|
||||
timeout int
|
||||
global_config shared Config
|
||||
is_ready chan bool
|
||||
}
|
||||
|
||||
struct Config {
|
||||
max_ping int
|
||||
}
|
||||
|
||||
fn exit_after_timeout(timeout_in_ms int) {
|
||||
time.sleep(timeout_in_ms * time.millisecond)
|
||||
println('>> webserver: pid: ${os.getpid()}, exiting ...')
|
||||
exit(0)
|
||||
pub fn (mut app App) before_accept_loop() {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
app.is_ready <- true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if os.args.len != 3 {
|
||||
panic('Usage: `vweb_test_server.exe PORT TIMEOUT_IN_MILLISECONDS`')
|
||||
}
|
||||
http_port := os.args[1].int()
|
||||
assert http_port > 0
|
||||
timeout := os.args[2].int()
|
||||
assert timeout > 0
|
||||
spawn exit_after_timeout(timeout)
|
||||
//
|
||||
shared config := &Config{
|
||||
max_ping: 50
|
||||
}
|
||||
app := &App{
|
||||
port: http_port
|
||||
timeout: timeout
|
||||
global_config: config
|
||||
}
|
||||
eprintln('>> webserver: pid: ${os.getpid()}, started on http://localhost:${app.port}/ , with maximum runtime of ${app.timeout} milliseconds.')
|
||||
vweb.run_at(app, host: 'localhost', port: http_port, family: .ip)!
|
||||
}
|
||||
|
||||
// pub fn (mut app App) init_server() {
|
||||
//}
|
||||
|
||||
pub fn (mut app App) index() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
rlock app.global_config {
|
||||
assert app.global_config.max_ping == 50
|
||||
}
|
||||
@ -56,17 +62,20 @@ pub fn (mut app App) index() vweb.Result {
|
||||
}
|
||||
|
||||
pub fn (mut app App) simple() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
return app.text('A simple result')
|
||||
}
|
||||
|
||||
pub fn (mut app App) html_page() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
return app.html('<h1>ok</h1>')
|
||||
}
|
||||
|
||||
// the following serve custom routes
|
||||
@['/:user/settings']
|
||||
pub fn (mut app App) settings(username string) vweb.Result {
|
||||
if username !in known_users {
|
||||
linfo('>>>>> ${@LOCATION}, username: ${username}')
|
||||
if username !in vweb_test_server.known_users {
|
||||
return app.not_found()
|
||||
}
|
||||
return app.html('username: ${username}')
|
||||
@ -74,7 +83,8 @@ pub fn (mut app App) settings(username string) vweb.Result {
|
||||
|
||||
@['/:user/:repo/settings']
|
||||
pub fn (mut app App) user_repo_settings(username string, repository string) vweb.Result {
|
||||
if username !in known_users {
|
||||
linfo('>>>>> ${@LOCATION}, username: ${username}, repository: ${repository}')
|
||||
if username !in vweb_test_server.known_users {
|
||||
return app.not_found()
|
||||
}
|
||||
return app.html('username: ${username} | repository: ${repository}')
|
||||
@ -82,24 +92,27 @@ pub fn (mut app App) user_repo_settings(username string, repository string) vweb
|
||||
|
||||
@['/json_echo'; post]
|
||||
pub fn (mut app App) json_echo() vweb.Result {
|
||||
// eprintln('>>>>> received http request at /json_echo is: $app.req')
|
||||
linfo('>>>>> ${@LOCATION} received http request at /json_echo is: ${app.req}')
|
||||
app.set_content_type(app.req.header.get(.content_type) or { '' })
|
||||
return app.ok(app.req.data)
|
||||
}
|
||||
|
||||
@['/login'; post]
|
||||
pub fn (mut app App) login_form(username string, password string) vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}, username: ${username}, password: ${password}')
|
||||
return app.html('username: x${username}x | password: x${password}x')
|
||||
}
|
||||
|
||||
@['/form_echo'; post]
|
||||
pub fn (mut app App) form_echo() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
app.set_content_type(app.req.header.get(.content_type) or { '' })
|
||||
return app.ok(app.form['foo'])
|
||||
}
|
||||
|
||||
@['/file_echo'; post]
|
||||
pub fn (mut app App) file_echo() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
if 'file' !in app.files {
|
||||
app.set_status(500, '')
|
||||
return app.text('no file')
|
||||
@ -111,13 +124,14 @@ pub fn (mut app App) file_echo() vweb.Result {
|
||||
// Make sure [post] works without the path
|
||||
@[post]
|
||||
pub fn (mut app App) json() vweb.Result {
|
||||
// eprintln('>>>>> received http request at /json is: $app.req')
|
||||
linfo('>>>>> ${@LOCATION} received http request is: ${app.req}')
|
||||
app.set_content_type(app.req.header.get(.content_type) or { '' })
|
||||
return app.ok(app.req.data)
|
||||
}
|
||||
|
||||
// Custom 404 page
|
||||
pub fn (mut app App) not_found() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
app.set_status(404, 'Not Found')
|
||||
return app.html('404 on "${app.req.url}"')
|
||||
}
|
||||
@ -125,10 +139,12 @@ pub fn (mut app App) not_found() vweb.Result {
|
||||
@[host: 'example.com']
|
||||
@['/with_host']
|
||||
pub fn (mut app App) with_host() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
return app.ok('')
|
||||
}
|
||||
|
||||
pub fn (mut app App) shutdown() vweb.Result {
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
session_key := app.get_cookie('skey') or { return app.not_found() }
|
||||
if session_key != 'superman' {
|
||||
return app.not_found()
|
||||
@ -138,7 +154,7 @@ pub fn (mut app App) shutdown() vweb.Result {
|
||||
}
|
||||
|
||||
fn (mut app App) exit_gracefully() {
|
||||
eprintln('>> webserver: exit_gracefully')
|
||||
linfo('>>>>> ${@LOCATION}')
|
||||
time.sleep(100 * time.millisecond)
|
||||
exit(0)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user