1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/net/tcp_self_dial_from_many_clients_test.v

139 lines
3.1 KiB
V

module main
import net
import time
const xport = 15523
struct Context {
mut:
ok_client_dials int
fail_client_dials int
//
ok_client_close int
fail_client_close int
////
ok_server_accepts int
fail_server_accepts int
//
ok_server_close int
fail_server_close int
//
received []int
}
fn elog(msg string) {
eprintln('${time.now().format_ss_micro()} | ${msg}')
}
fn receive_data(mut con net.TcpConn, shared ctx Context) {
mut buf := []u8{len: 5}
for {
bytes := con.read(mut buf) or { -1 }
if bytes < 0 {
break
}
if bytes > 0 {
lock ctx {
ctx.received << buf[0]
}
}
}
con.close() or {
lock ctx {
ctx.fail_server_close++
}
return
}
lock ctx {
ctx.ok_server_close++
}
}
fn start_server(schannel chan int, shared ctx Context) {
elog('server: start_server')
mut tcp_listener := net.listen_tcp(net.AddrFamily.ip, ':${xport}') or {
elog('server: start server error ${err}')
return
}
elog('server: server started listening at port :${xport}')
schannel <- 0
for {
mut tcp_con := tcp_listener.accept() or {
elog('server: accept error: ${err}')
lock ctx {
ctx.fail_server_accepts++
}
continue
}
spawn receive_data(mut tcp_con, shared ctx)
lock ctx {
ctx.ok_server_accepts++
}
elog('server: new tcp connection con.sock.handle: ${tcp_con.sock.handle}')
continue
}
}
fn start_client(i int, shared ctx Context) {
elog('client [${i}]: start')
mut tcp_con := net.dial_tcp('127.0.0.1:${xport}') or {
elog('client [${i}]: net.dial_tcp err ${err}')
lock ctx {
ctx.fail_client_dials++
}
return
}
lock ctx {
ctx.ok_client_dials++
}
elog('client [${i}]: conn is connected, con.sock.handle: ${tcp_con.sock.handle}')
tcp_con.write([u8(i)]) or { elog('client [${i}]: write failed, err: ${err}') }
time.sleep(1 * time.second)
elog('client [${i}]: closing connection...')
tcp_con.close() or {
elog('client [${i}]: close failed, err: ${err}')
lock ctx {
ctx.fail_client_close++
}
return
}
lock ctx {
ctx.ok_client_close++
}
}
fn test_tcp_self_dialing() {
elog('>>> start')
start_time := time.now()
shared ctx := &Context{}
mut server_channel := chan int{cap: 1}
spawn start_server(server_channel, shared ctx)
svalue := <-server_channel
elog('>>> server was started: ${svalue}. Starting clients:')
for i := int(0); i < 20; i++ {
spawn start_client(i, shared ctx)
elog('>>> started client ${i}')
// time.sleep(2 * time.millisecond)
}
max_dt := 5 * time.second
for {
t := time.now()
dt := t - start_time
if dt > max_dt {
elog('>>> exiting after ${dt.milliseconds()} ms ...')
lock ctx {
// TODO: fix `dump(ctx)`, when `shared ctx := Type{}`
final_value_for_ctx := ctx // make a value copy as a temporary workaround. TODO: remove when dump(ctx) works.
dump(final_value_for_ctx)
assert ctx.fail_client_dials < 2, 'allowed failed client dials, from ${ctx.ok_server_accepts} connections'
assert ctx.received.len > ctx.ok_server_accepts / 2, 'at least half the clients sent some data, that was later received by the server'
}
elog('>>> goodbye')
exit(0)
}
time.sleep(10 * time.millisecond)
}
}