From 55e8faaedf64ec9e77581af873479891baf249d1 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 03:59:47 +0300 Subject: [PATCH] all: fix tests --- vlib/flag/flag_test.v | 24 +++++++++---------- vlib/rand/mt19937/mt19937.v | 4 ++-- vlib/rand/musl/musl_rng.v | 3 +-- vlib/rand/pcg32/pcg32.v | 3 +-- vlib/rand/splitmix64/splitmix64.v | 3 +-- vlib/rand/sys/system_rng.c.v | 3 +-- vlib/rand/wyrand/z_wyrand.c.v | 4 ++-- vlib/rand/xoroshiro128pp/xoros128pp.v | 3 +-- vlib/v/checker/fn.v | 11 +++++++++ vlib/v/checker/tests/method_op_alias_err.out | 14 ----------- .../autofree_method_chain.c.must_have | 5 ++-- .../c/testdata/compare_structs.c.must_have | 6 +++-- .../struct_field_result_init.c.must_have | 8 +++---- ..._c_alias_structural_compatibility_test.c.v | 1 + .../sumtypes/sumtype_cast_from_voidptr_test.v | 4 ++-- vlib/veb/context.v | 15 +++++++++++- 16 files changed, 60 insertions(+), 51 deletions(-) diff --git a/vlib/flag/flag_test.v b/vlib/flag/flag_test.v index f54e37d1f..f4641a689 100644 --- a/vlib/flag/flag_test.v +++ b/vlib/flag/flag_test.v @@ -10,18 +10,18 @@ fn test_if_flag_not_given_return_default_values() { fn test_if_flag_not_given_can_return_option_defaults() { mut fp := flag.new_flag_parser([]) - assert fp.bool('a_bool', 0, ?bool(none), '') == none - assert fp.int('an_int', 0, ?int(none), '') == none - assert fp.float('a_float', 0, ?f64(none), '') == none - assert fp.string('a_string', 0, ?string(none), '') == none + assert fp.bool_val('a_bool', 0, ?bool(none), '') == none + assert fp.int_val('an_int', 0, ?int(none), '') == none + assert fp.float_val('a_float', 0, ?f64(none), '') == none + assert fp.string_val('a_string', 0, ?string(none), '') == none } fn test_if_flag_not_given_preserves_typed_option_defaults() { mut fp := flag.new_flag_parser([]) - a_bool := fp.bool('a_bool', 0, ?bool(true), '') - an_int := fp.int('an_int', 0, ?int(42), '') - a_float := fp.float('a_float', 0, ?f64(1.5), '') - a_string := fp.string('a_string', 0, ?string('stuff'), '') + a_bool := fp.bool_val('a_bool', 0, ?bool(true), '') + an_int := fp.int_val('an_int', 0, ?int(42), '') + a_float := fp.float_val('a_float', 0, ?f64(1.5), '') + a_string := fp.string_val('a_string', 0, ?string('stuff'), '') if value := a_bool { assert value } else { @@ -68,10 +68,10 @@ fn test_flag_values_can_be_returned_as_options() { 'stuff', '--a_bool=false', ]) - a_bool := fp.bool('a_bool', 0, ?bool(none), '') - an_int := fp.int('an_int', 0, ?int(none), '') - a_float := fp.float('a_float', 0, ?f64(none), '') - a_string := fp.string('a_string', 0, ?string(none), '') + a_bool := fp.bool_val('a_bool', 0, ?bool(none), '') + an_int := fp.int_val('an_int', 0, ?int(none), '') + a_float := fp.float_val('a_float', 0, ?f64(none), '') + a_string := fp.string_val('a_string', 0, ?string(none), '') if value := a_bool { assert !value } else { diff --git a/vlib/rand/mt19937/mt19937.v b/vlib/rand/mt19937/mt19937.v index f2b853d01..7a6a9bf49 100644 --- a/vlib/rand/mt19937/mt19937.v +++ b/vlib/rand/mt19937/mt19937.v @@ -178,8 +178,8 @@ pub fn (mut rng MT19937RNG) block_size() int { return 64 } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng MT19937RNG) free() { - unsafe { free(rng) } + unsafe { rng.state.free() } } diff --git a/vlib/rand/musl/musl_rng.v b/vlib/rand/musl/musl_rng.v index 4c19f3529..02d894979 100644 --- a/vlib/rand/musl/musl_rng.v +++ b/vlib/rand/musl/musl_rng.v @@ -90,8 +90,7 @@ pub fn (mut rng MuslRNG) block_size() int { return 32 } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng MuslRNG) free() { - unsafe { free(rng) } } diff --git a/vlib/rand/pcg32/pcg32.v b/vlib/rand/pcg32/pcg32.v index 6cef5184d..1493337ae 100644 --- a/vlib/rand/pcg32/pcg32.v +++ b/vlib/rand/pcg32/pcg32.v @@ -91,8 +91,7 @@ pub fn (mut rng PCG32RNG) block_size() int { return 32 } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng PCG32RNG) free() { - unsafe { free(rng) } } diff --git a/vlib/rand/splitmix64/splitmix64.v b/vlib/rand/splitmix64/splitmix64.v index 540d35ba5..f77b81d7a 100644 --- a/vlib/rand/splitmix64/splitmix64.v +++ b/vlib/rand/splitmix64/splitmix64.v @@ -90,8 +90,7 @@ pub fn (mut rng SplitMix64RNG) block_size() int { return 64 } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng SplitMix64RNG) free() { - unsafe { free(rng) } } diff --git a/vlib/rand/sys/system_rng.c.v b/vlib/rand/sys/system_rng.c.v index 62c398b74..47f62c964 100644 --- a/vlib/rand/sys/system_rng.c.v +++ b/vlib/rand/sys/system_rng.c.v @@ -118,8 +118,7 @@ pub fn (r SysRNG) block_size() int { return rand_bitsize } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng SysRNG) free() { - unsafe { free(rng) } } diff --git a/vlib/rand/wyrand/z_wyrand.c.v b/vlib/rand/wyrand/z_wyrand.c.v index f95e87632..ca5720454 100644 --- a/vlib/rand/wyrand/z_wyrand.c.v +++ b/vlib/rand/wyrand/z_wyrand.c.v @@ -2,10 +2,10 @@ module wyrand fn C._wymix(u64, u64) u64 -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. +// WyRandRNG contains no heap-allocated fields, so this is a no-op. @[unsafe] pub fn (mut rng WyRandRNG) free() { - unsafe { free(rng) } } // u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`. diff --git a/vlib/rand/xoroshiro128pp/xoros128pp.v b/vlib/rand/xoroshiro128pp/xoros128pp.v index 51f04b93d..07177d216 100644 --- a/vlib/rand/xoroshiro128pp/xoros128pp.v +++ b/vlib/rand/xoroshiro128pp/xoros128pp.v @@ -99,8 +99,7 @@ pub fn (mut rng XOROS128PPRNG) block_size() int { return 64 } -// free should be called when the generator is no longer needed +// free should be called when the generator is no longer needed. @[unsafe] pub fn (mut rng XOROS128PPRNG) free() { - unsafe { free(rng) } } diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 9c82e134d..e891c4709 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1927,6 +1927,17 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. node.should_be_skipped = c.evaluate_once_comptime_if_attribute(mut func.attrs[func.ctdefine_idx]) } + if node.kind == .free && func.mod == 'builtin' && args_len == 1 + && c.table.cur_fn != unsafe { nil } && c.table.cur_fn.is_method && !c.is_builtin_mod + && !c.inside_recheck { + if node.args[0].expr is ast.Ident { + if node.args[0].expr.name == c.table.cur_fn.receiver.name { + c.warn('calling builtin `free()` on a method receiver will cause a' + + ' runtime crash when the receiver is stack-allocated; free individual fields instead', + node.pos) + } + } + } // dont check number of args for JS functions since arguments are not required if node.language != .js { diff --git a/vlib/v/checker/tests/method_op_alias_err.out b/vlib/v/checker/tests/method_op_alias_err.out index e9dc3d70e..a50202398 100644 --- a/vlib/v/checker/tests/method_op_alias_err.out +++ b/vlib/v/checker/tests/method_op_alias_err.out @@ -5,13 +5,6 @@ vlib/v/checker/tests/method_op_alias_err.vv:4:18: error: expected `Foo` not `Foo | ~~~~ 5 | return Foo2(f + f1) 6 | } -vlib/v/checker/tests/method_op_alias_err.vv:5:14: error: infix expr: cannot use `Foo2` (right expression) as `Foo` - 3 | - 4 | fn (f Foo) + (f1 Foo2) Foo2 { - 5 | return Foo2(f + f1) - | ~~~~~~ - 6 | } - 7 | vlib/v/checker/tests/method_op_alias_err.vv:14:4: error: operator `+` must return `Foo` to be used as an assignment operator 12 | fn main() { 13 | mut f := Foo('fg') @@ -19,10 +12,3 @@ vlib/v/checker/tests/method_op_alias_err.vv:14:4: error: operator `+` must retur | ~~ 15 | f *= Foo2('2') 16 | f -= Foo('fo') -vlib/v/checker/tests/method_op_alias_err.vv:15:7: error: cannot assign to `f`: expected `Foo`, not `Foo2` - 13 | mut f := Foo('fg') - 14 | f += 'fg' - 15 | f *= Foo2('2') - | ~~~~~~~~~ - 16 | f -= Foo('fo') - 17 | println(f) diff --git a/vlib/v/gen/c/testdata/autofree_method_chain.c.must_have b/vlib/v/gen/c/testdata/autofree_method_chain.c.must_have index 6e23e33f0..d3a8e7532 100644 --- a/vlib/v/gen/c/testdata/autofree_method_chain.c.must_have +++ b/vlib/v/gen/c/testdata/autofree_method_chain.c.must_have @@ -4,8 +4,9 @@ string _arg_expr_split_0_169 = builtin__string_trim_space(builtin__string_replac builtin__string_free(&_arg_expr_split_0_169); // autofreed var main false } VV_LOC void main__main(void) { - main__Test test = ((main__Test){.tags = builtin____new_array(0, 0, sizeof(string)),}); + main__Test _t1 = ((main__Test){.tags = builtin____new_array(0, 0, sizeof(string)),}); + main__Test test = _t1; main__Test_set_tags(&test, _S("Hello, World")); - string _t1 = Array_string_str(test.tags); builtin__println(_t1); builtin__string_free(&_t1); + string _t2 = Array_string_str(test.tags); builtin__println(_t2); builtin__string_free(&_t2); ; } diff --git a/vlib/v/gen/c/testdata/compare_structs.c.must_have b/vlib/v/gen/c/testdata/compare_structs.c.must_have index 10632c0b3..8f8be46ea 100644 --- a/vlib/v/gen/c/testdata/compare_structs.c.must_have +++ b/vlib/v/gen/c/testdata/compare_structs.c.must_have @@ -1,4 +1,6 @@ -struct Something aaa = ((struct Something){.fint = 0,.ff32 = 0,.fchar = 0,}); -struct Something bbb = ((struct Something){.fint = 0,.ff32 = 0,.fchar = 0,}); +struct Something _t1 = ((struct Something){.fint = 0,.ff32 = 0,.fchar = 0,}); +struct Something aaa = _t1; +struct Something _t2 = ((struct Something){.fint = 0,.ff32 = 0,.fchar = 0,}); +struct Something bbb = _t2; if (Something_struct_eq(aaa, bbb)) { diff --git a/vlib/v/gen/c/testdata/struct_field_result_init.c.must_have b/vlib/v/gen/c/testdata/struct_field_result_init.c.must_have index a0460c32a..a56c6e192 100644 --- a/vlib/v/gen/c/testdata/struct_field_result_init.c.must_have +++ b/vlib/v/gen/c/testdata/struct_field_result_init.c.must_have @@ -1,5 +1,5 @@ -_result_math__big__Integer _t1 = math__big__integer_from_string(_S("115792089237316195423570985008687907853269984665640564039457584007913129639747")); -if (_t1.is_error) { -math__big__Integer _t2 = {0}; -return _t2; +_result_math__big__Integer _t2 = math__big__integer_from_string(_S("115792089237316195423570985008687907853269984665640564039457584007913129639747")); +if (_t2.is_error) { +math__big__Integer _t3 = {0}; +return _t3; } \ No newline at end of file diff --git a/vlib/v/tests/aliases/nested_c_alias_structural_compatibility_test.c.v b/vlib/v/tests/aliases/nested_c_alias_structural_compatibility_test.c.v index 4a758ec1f..fad21fd6b 100644 --- a/vlib/v/tests/aliases/nested_c_alias_structural_compatibility_test.c.v +++ b/vlib/v/tests/aliases/nested_c_alias_structural_compatibility_test.c.v @@ -1,3 +1,4 @@ +// vtest build: windows type C.WCHAR = u16 type C.PWSTR = &C.WCHAR type C.FILE_SHARE_MODE = u32 diff --git a/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v b/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v index 5f716d233..546e73ff4 100644 --- a/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v +++ b/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v @@ -14,9 +14,9 @@ fn test_main() { }) event := unsafe { &Event(some_ptr) } - d1 := &EventA(event) + d1 := unsafe { &EventA(event) } assert d1.a == 1234 - d2 := &EventB(event) + d2 := unsafe { &EventB(event) } assert d2.b == 1234 } diff --git a/vlib/veb/context.v b/vlib/veb/context.v index a489c3cc8..0ba198267 100644 --- a/vlib/veb/context.v +++ b/vlib/veb/context.v @@ -491,8 +491,8 @@ pub fn (mut ctx Context) set_content_type(mime string) { // send multiple responses. Like with the SSE. pub fn (mut ctx Context) takeover_conn() { ctx.takeover = true - // For the fasthttp backend: create a TcpConn from the raw fd on demand if ctx.conn == unsafe { nil } && ctx.client_fd >= 0 { + // For the fasthttp backend: create a TcpConn from the raw fd on demand. // Set the fd to blocking mode — fasthttp uses non-blocking sockets, // but TcpConn.write() expects blocking behavior for reliable writes. $if !windows { @@ -512,6 +512,19 @@ pub fn (mut ctx Context) takeover_conn() { read_timeout: 30 * time.second write_timeout: 30 * time.second } + } else if ctx.conn != unsafe { nil } { + // For the picoev backend: the connection exists but uses non-blocking I/O. + // Switch to blocking mode for reliable SSE writes. + fd := ctx.conn.handle + $if !windows { + flags := C.fcntl(fd, C.F_GETFL, 0) + if flags != -1 { + C.fcntl(fd, C.F_SETFL, flags & ~C.O_NONBLOCK) + } + } + ctx.conn.is_blocking = true + ctx.conn.set_read_timeout(30 * time.second) + ctx.conn.set_write_timeout(30 * time.second) } } -- 2.39.5