v / vlib / net / tcp_last_write_sent_test.v
49 lines · 45 sloc · 1.38 KB · 75789c6f9989ff8de76988c5d312979ca5e27853
Raw
1import net
2import time
3
4// last_write_sent must reflect the bytes the most recent write managed to send,
5// both on success and (crucially) when the write fails, so a caller can tell a
6// zero-byte failure from a partial write. See vlang/v#27459.
7
8fn drain_one_conn(mut l net.TcpListener) {
9 mut c := l.accept() or { return }
10 for {
11 mut buf := []u8{len: 4096}
12 c.read(mut buf) or { break }
13 }
14 c.close() or {}
15}
16
17fn test_last_write_sent_on_success() {
18 mut l := net.listen_tcp(.ip, '127.0.0.1:0')!
19 addr := l.addr()!
20 th := spawn drain_one_conn(mut l)
21 mut c := net.dial_tcp(addr.str())!
22 payload := 'hello world'.bytes()
23 n := c.write(payload)!
24 assert n == payload.len
25 assert c.last_write_sent == payload.len
26 c.close() or {}
27 l.close() or {}
28 th.wait()
29}
30
31fn test_last_write_sent_is_zero_on_failed_write_to_closed_conn() {
32 mut l := net.listen_tcp(.ip, '127.0.0.1:0')!
33 addr := l.addr()!
34 th := spawn drain_one_conn(mut l)
35 mut c := net.dial_tcp(addr.str())!
36 // Close our side, then attempt a write: it must fail and report zero bytes
37 // sent, so a retry layer can treat it as safe to replay.
38 c.close() or {}
39 time.sleep(5 * time.millisecond)
40 c.write('data'.bytes()) or {
41 assert c.last_write_sent == 0, 'a failed write before any byte left must report 0'
42 l.close() or {}
43 th.wait()
44 return
45 }
46 assert false, 'write to a closed connection unexpectedly succeeded'
47 l.close() or {}
48 th.wait()
49}
50