mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -04:00
vlib: enable more satnitized memleak detection runs without false positives on the CI (#23200)
This commit is contained in:
parent
903e349a7c
commit
b0772193f8
13
.github/workflows/run_sanitizers_leak.suppressions
vendored
Normal file
13
.github/workflows/run_sanitizers_leak.suppressions
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# websocket tests
|
||||||
|
leak:mbedtls_ssl_setup
|
||||||
|
|
||||||
|
# sqlite tests
|
||||||
|
leak:*sqlite*
|
||||||
|
|
||||||
|
# v
|
||||||
|
leak:v__*
|
||||||
|
leak:os__*
|
||||||
|
leak:string__plus
|
||||||
|
leak:malloc_uncollectable
|
||||||
|
leak:new_array_from_c_array
|
||||||
|
leak:_vinit
|
22
.github/workflows/sanitized_ci.yml
vendored
22
.github/workflows/sanitized_ci.yml
vendored
@ -75,7 +75,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
tests-sanitize-undefined-clang:
|
tests-sanitize-undefined-clang:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
timeout-minutes: 240
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc clang
|
VFLAGS: -cc clang
|
||||||
VJOBS: 1
|
VJOBS: 1
|
||||||
@ -101,7 +101,7 @@ jobs:
|
|||||||
|
|
||||||
tests-sanitize-undefined-gcc:
|
tests-sanitize-undefined-gcc:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
timeout-minutes: 240
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc gcc
|
VFLAGS: -cc gcc
|
||||||
VJOBS: 1
|
VJOBS: 1
|
||||||
@ -126,7 +126,7 @@ jobs:
|
|||||||
|
|
||||||
tests-sanitize-address-clang:
|
tests-sanitize-address-clang:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
timeout-minutes: 240
|
timeout-minutes: 300
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc clang
|
VFLAGS: -cc clang
|
||||||
VJOBS: 1
|
VJOBS: 1
|
||||||
@ -146,16 +146,16 @@ jobs:
|
|||||||
- name: Recompile V with -cstrict
|
- name: Recompile V with -cstrict
|
||||||
run: ./v -cg -cstrict -o v cmd/v
|
run: ./v -cg -cstrict -o v cmd/v
|
||||||
- name: Self tests (-fsanitize=address)
|
- name: Self tests (-fsanitize=address)
|
||||||
run: ASAN_OPTIONS=detect_leaks=0 ./v -cflags "-fsanitize=address,pointer-compare,pointer-subtract" test-self vlib
|
run: ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v -cflags "-fsanitize=address,pointer-compare,pointer-subtract" test-self vlib
|
||||||
- name: Self tests (V compiled with -fsanitize=address)
|
- name: Self tests (V compiled with -fsanitize=address)
|
||||||
run: ./v -cflags -fsanitize=address -o v cmd/v &&
|
run: ./v -cflags -fsanitize=address -o v cmd/v &&
|
||||||
ASAN_OPTIONS=detect_leaks=0 ./v -cc tcc test-self -asan-compiler vlib
|
ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v -cc tcc test-self -asan-compiler vlib
|
||||||
- name: Build examples (V compiled with -fsanitize=address)
|
- name: Build examples (V compiled with -fsanitize=address)
|
||||||
run: ASAN_OPTIONS=detect_leaks=0 ./v build-examples
|
run: ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v build-examples
|
||||||
|
|
||||||
tests-sanitize-address-msvc:
|
tests-sanitize-address-msvc:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
timeout-minutes: 240
|
timeout-minutes: 30
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc msvc
|
VFLAGS: -cc msvc
|
||||||
VJOBS: 1
|
VJOBS: 1
|
||||||
@ -179,7 +179,7 @@ jobs:
|
|||||||
|
|
||||||
tests-sanitize-address-gcc:
|
tests-sanitize-address-gcc:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
timeout-minutes: 240
|
timeout-minutes: 300
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc gcc
|
VFLAGS: -cc gcc
|
||||||
VJOBS: 1
|
VJOBS: 1
|
||||||
@ -199,13 +199,13 @@ jobs:
|
|||||||
- name: Recompile V with -cstrict
|
- name: Recompile V with -cstrict
|
||||||
run: ./v -cg -cstrict -o v cmd/v
|
run: ./v -cg -cstrict -o v cmd/v
|
||||||
- name: Self tests (-fsanitize=address)
|
- name: Self tests (-fsanitize=address)
|
||||||
run: ASAN_OPTIONS=detect_leaks=0 ./v -cflags -fsanitize=address test-self vlib
|
run: ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v -cflags -fsanitize=address test-self vlib
|
||||||
- name: Self tests (V compiled with -fsanitize=address)
|
- name: Self tests (V compiled with -fsanitize=address)
|
||||||
run:
|
run:
|
||||||
./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -o v cmd/v &&
|
./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -o v cmd/v &&
|
||||||
ASAN_OPTIONS=detect_leaks=0 ./v -cc tcc test-self -asan-compiler vlib
|
ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v -cc tcc test-self -asan-compiler vlib
|
||||||
- name: Build examples (V compiled with -fsanitize=address)
|
- name: Build examples (V compiled with -fsanitize=address)
|
||||||
run: ASAN_OPTIONS=detect_leaks=0 ./v build-examples
|
run: ASAN_OPTIONS=detect_leaks=1:fast_unwind_on_malloc=0 LSAN_OPTIONS=max_leaks=1:print_suppressions=0:suppressions=.github/workflows/run_sanitizers_leak.suppressions ./v build-examples
|
||||||
|
|
||||||
tests-sanitize-memory-clang:
|
tests-sanitize-memory-clang:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
@ -106,6 +106,9 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
|
|||||||
output = output.replace(' (discriminator', ': (d.')
|
output = output.replace(' (discriminator', ': (d.')
|
||||||
eprintln('${output:-55s} | ${addr:14s} | ${beforeaddr}')
|
eprintln('${output:-55s} | ${addr:14s} | ${beforeaddr}')
|
||||||
}
|
}
|
||||||
|
if sframes.len > 0 {
|
||||||
|
unsafe { C.free(csymbols) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,11 @@ pub fn compress(data []u8, flags int) ![]u8 {
|
|||||||
if u64(out_len) > max_size {
|
if u64(out_len) > max_size {
|
||||||
return error('compressed data is too large (${out_len} > ${max_size})')
|
return error('compressed data is too large (${out_len} > ${max_size})')
|
||||||
}
|
}
|
||||||
return unsafe { address.vbytes(int(out_len)) }
|
unsafe {
|
||||||
|
ret := address.vbytes(int(out_len)).clone()
|
||||||
|
C.free(address)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// decompresses an array of bytes based on providing flags and returns the decompressed bytes in a new array
|
// decompresses an array of bytes based on providing flags and returns the decompressed bytes in a new array
|
||||||
@ -40,5 +44,10 @@ pub fn decompress(data []u8, flags int) ![]u8 {
|
|||||||
if u64(out_len) > max_size {
|
if u64(out_len) > max_size {
|
||||||
return error('decompressed data is too large (${out_len} > ${max_size})')
|
return error('decompressed data is too large (${out_len} > ${max_size})')
|
||||||
}
|
}
|
||||||
return unsafe { address.vbytes(int(out_len)) }
|
|
||||||
|
unsafe {
|
||||||
|
ret := address.vbytes(int(out_len)).clone()
|
||||||
|
C.free(address)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,3 +227,8 @@ pub fn (pub_key PublicKey) equal(other PublicKey) bool {
|
|||||||
res := C.EC_POINT_cmp(group, point1, point2, ctx)
|
res := C.EC_POINT_cmp(group, point1, point2, ctx)
|
||||||
return res == 0
|
return res == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear allocated memory for key
|
||||||
|
pub fn key_free(ec_key &C.EC_KEY) {
|
||||||
|
C.EC_KEY_free(ec_key)
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ fn test_ecdsa() {
|
|||||||
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
||||||
println('Signature valid: ${is_valid}')
|
println('Signature valid: ${is_valid}')
|
||||||
assert is_valid
|
assert is_valid
|
||||||
|
key_free(priv_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_generate_key() ! {
|
fn test_generate_key() ! {
|
||||||
@ -19,6 +20,7 @@ fn test_generate_key() ! {
|
|||||||
pub_key, priv_key := generate_key() or { panic(err) }
|
pub_key, priv_key := generate_key() or { panic(err) }
|
||||||
assert pub_key.key != unsafe { nil }
|
assert pub_key.key != unsafe { nil }
|
||||||
assert priv_key.key != unsafe { nil }
|
assert priv_key.key != unsafe { nil }
|
||||||
|
key_free(priv_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_new_key_from_seed() ! {
|
fn test_new_key_from_seed() ! {
|
||||||
@ -27,6 +29,7 @@ fn test_new_key_from_seed() ! {
|
|||||||
priv_key := new_key_from_seed(seed) or { panic(err) }
|
priv_key := new_key_from_seed(seed) or { panic(err) }
|
||||||
retrieved_seed := priv_key.seed() or { panic(err) }
|
retrieved_seed := priv_key.seed() or { panic(err) }
|
||||||
assert seed == retrieved_seed
|
assert seed == retrieved_seed
|
||||||
|
key_free(priv_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sign_and_verify() ! {
|
fn test_sign_and_verify() ! {
|
||||||
@ -36,6 +39,7 @@ fn test_sign_and_verify() ! {
|
|||||||
signature := priv_key.sign(message) or { panic(err) }
|
signature := priv_key.sign(message) or { panic(err) }
|
||||||
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
||||||
assert is_valid
|
assert is_valid
|
||||||
|
key_free(priv_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_seed() ! {
|
fn test_seed() ! {
|
||||||
@ -43,6 +47,7 @@ fn test_seed() ! {
|
|||||||
_, priv_key := generate_key() or { panic(err) }
|
_, priv_key := generate_key() or { panic(err) }
|
||||||
seed := priv_key.seed() or { panic(err) }
|
seed := priv_key.seed() or { panic(err) }
|
||||||
assert seed.len > 0
|
assert seed.len > 0
|
||||||
|
key_free(priv_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_public_key() ! {
|
fn test_public_key() ! {
|
||||||
@ -51,6 +56,9 @@ fn test_public_key() ! {
|
|||||||
pub_key1 := priv_key.public_key() or { panic(err) }
|
pub_key1 := priv_key.public_key() or { panic(err) }
|
||||||
pub_key2, _ := generate_key() or { panic(err) }
|
pub_key2, _ := generate_key() or { panic(err) }
|
||||||
assert !pub_key1.equal(pub_key2)
|
assert !pub_key1.equal(pub_key2)
|
||||||
|
key_free(priv_key.key)
|
||||||
|
key_free(pub_key1.key)
|
||||||
|
key_free(pub_key2.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_private_key_equal() ! {
|
fn test_private_key_equal() ! {
|
||||||
@ -59,6 +67,8 @@ fn test_private_key_equal() ! {
|
|||||||
seed := priv_key1.seed() or { panic(err) }
|
seed := priv_key1.seed() or { panic(err) }
|
||||||
priv_key2 := new_key_from_seed(seed) or { panic(err) }
|
priv_key2 := new_key_from_seed(seed) or { panic(err) }
|
||||||
assert priv_key1.equal(priv_key2)
|
assert priv_key1.equal(priv_key2)
|
||||||
|
key_free(priv_key1.key)
|
||||||
|
key_free(priv_key2.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_public_key_equal() ! {
|
fn test_public_key_equal() ! {
|
||||||
@ -67,6 +77,9 @@ fn test_public_key_equal() ! {
|
|||||||
pub_key1 := priv_key.public_key() or { panic(err) }
|
pub_key1 := priv_key.public_key() or { panic(err) }
|
||||||
pub_key2 := priv_key.public_key() or { panic(err) }
|
pub_key2 := priv_key.public_key() or { panic(err) }
|
||||||
assert pub_key1.equal(pub_key2)
|
assert pub_key1.equal(pub_key2)
|
||||||
|
key_free(priv_key.key)
|
||||||
|
key_free(pub_key1.key)
|
||||||
|
key_free(pub_key2.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sign_with_new_key_from_seed() ! {
|
fn test_sign_with_new_key_from_seed() ! {
|
||||||
@ -78,6 +91,8 @@ fn test_sign_with_new_key_from_seed() ! {
|
|||||||
pub_key := priv_key.public_key() or { panic(err) }
|
pub_key := priv_key.public_key() or { panic(err) }
|
||||||
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
is_valid := pub_key.verify(message, signature) or { panic(err) }
|
||||||
assert is_valid
|
assert is_valid
|
||||||
|
key_free(priv_key.key)
|
||||||
|
key_free(pub_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_invalid_signature() ! {
|
fn test_invalid_signature() ! {
|
||||||
@ -88,9 +103,11 @@ fn test_invalid_signature() ! {
|
|||||||
result := pub_key.verify(message, invalid_signature) or {
|
result := pub_key.verify(message, invalid_signature) or {
|
||||||
// Expecting verification to fail
|
// Expecting verification to fail
|
||||||
assert err.msg() == 'Failed to verify signature'
|
assert err.msg() == 'Failed to verify signature'
|
||||||
|
key_free(pub_key.key)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert !result
|
assert !result
|
||||||
|
key_free(pub_key.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_different_keys_not_equal() ! {
|
fn test_different_keys_not_equal() ! {
|
||||||
@ -98,4 +115,6 @@ fn test_different_keys_not_equal() ! {
|
|||||||
_, priv_key1 := generate_key() or { panic(err) }
|
_, priv_key1 := generate_key() or { panic(err) }
|
||||||
_, priv_key2 := generate_key() or { panic(err) }
|
_, priv_key2 := generate_key() or { panic(err) }
|
||||||
assert !priv_key1.equal(priv_key2)
|
assert !priv_key1.equal(priv_key2)
|
||||||
|
key_free(priv_key1.key)
|
||||||
|
key_free(priv_key2.key)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ struct Baby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_main() {
|
fn test_main() {
|
||||||
db := sqlite.connect(':memory:')!
|
mut db := sqlite.connect(':memory:')!
|
||||||
|
|
||||||
sql db {
|
sql db {
|
||||||
create table Parent
|
create table Parent
|
||||||
@ -80,4 +80,6 @@ fn test_main() {
|
|||||||
assert parent[0].children[0].id == 1
|
assert parent[0].children[0].id == 1
|
||||||
assert parent[0].children[1].id == 2
|
assert parent[0].children[1].id == 2
|
||||||
assert parent[0].children.len == 2
|
assert parent[0].children.len == 2
|
||||||
|
|
||||||
|
db.close()!
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ fn records_by_field[T](db sqlite.DB, fieldname string, value string) ![]T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_main() {
|
fn test_main() {
|
||||||
db := sqlite.connect(':memory:')!
|
mut db := sqlite.connect(':memory:')!
|
||||||
sql db {
|
sql db {
|
||||||
create table Blog
|
create table Blog
|
||||||
}!
|
}!
|
||||||
@ -40,4 +40,5 @@ fn test_main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert rows.len == 1
|
assert rows.len == 1
|
||||||
|
db.close()!
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ pub:
|
|||||||
type Content = []u8 | string
|
type Content = []u8 | string
|
||||||
|
|
||||||
struct Host {
|
struct Host {
|
||||||
pub:
|
pub mut:
|
||||||
db Connection
|
db Connection
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,8 @@ fn test_can_access_sqlite_result_consts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_alias_db() {
|
fn test_alias_db() {
|
||||||
create_host(sqlite.connect(':memory:')!)!
|
mut host := create_host(sqlite.connect(':memory:')!)!
|
||||||
|
host.db.close()!
|
||||||
assert true
|
assert true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +111,9 @@ fn test_exec_param_many() {
|
|||||||
'Sam',
|
'Sam',
|
||||||
]) or {
|
]) or {
|
||||||
assert err.code() == 19 // constraint failure
|
assert err.code() == 19 // constraint failure
|
||||||
|
db.close()!
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
db.close()!
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ fn test_object_with_null() {
|
|||||||
root.add_item_to_object('name', cjson.create_string('Andre'))
|
root.add_item_to_object('name', cjson.create_string('Andre'))
|
||||||
root.add_item_to_object('age', cjson.create_null())
|
root.add_item_to_object('age', cjson.create_null())
|
||||||
assert root.print_unformatted() == '{"name":"Andre","age":null}'
|
assert root.print_unformatted() == '{"name":"Andre","age":null}'
|
||||||
|
unsafe { cjson.delete(root) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_creating_complex_json() {
|
fn test_creating_complex_json() {
|
||||||
@ -18,4 +19,5 @@ fn test_creating_complex_json() {
|
|||||||
println(result)
|
println(result)
|
||||||
|
|
||||||
assert result == '["user",{"username":"foo","password":"bar"}]'
|
assert result == '["user",{"username":"foo","password":"bar"}]'
|
||||||
|
unsafe { cjson.delete(root) }
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,8 @@ fn C.cJSON_Print(object &C.cJSON) &char
|
|||||||
|
|
||||||
fn C.cJSON_PrintUnformatted(object &C.cJSON) &char
|
fn C.cJSON_PrintUnformatted(object &C.cJSON) &char
|
||||||
|
|
||||||
|
fn C.cJSON_free(voidptr)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
// version returns the version of cJSON as a string
|
// version returns the version of cJSON as a string
|
||||||
@ -168,7 +170,9 @@ pub fn (mut obj Node) print() string {
|
|||||||
// print serialises the node to a string, without formatting its structure, so the resulting string is shorter/cheaper to transmit.
|
// print serialises the node to a string, without formatting its structure, so the resulting string is shorter/cheaper to transmit.
|
||||||
pub fn (mut obj Node) print_unformatted() string {
|
pub fn (mut obj Node) print_unformatted() string {
|
||||||
mut s := C.cJSON_PrintUnformatted(obj)
|
mut s := C.cJSON_PrintUnformatted(obj)
|
||||||
return unsafe { tos3(s) }
|
ret := unsafe { tos_clone(&u8(s)) }
|
||||||
|
C.cJSON_free(s)
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// str returns the unformatted serialisation to string of the given Node.
|
// str returns the unformatted serialisation to string of the given Node.
|
||||||
|
@ -3,6 +3,7 @@ import net
|
|||||||
import net.websocket
|
import net.websocket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@[heap]
|
||||||
struct WebsocketTestResults {
|
struct WebsocketTestResults {
|
||||||
pub mut:
|
pub mut:
|
||||||
nr_messages int
|
nr_messages int
|
||||||
|
@ -10,7 +10,7 @@ const const_users_offset = 1
|
|||||||
const const_users_offset2 = 1
|
const const_users_offset2 = 1
|
||||||
|
|
||||||
fn test_orm() {
|
fn test_orm() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
|
|
||||||
upper_1 := User{
|
upper_1 := User{
|
||||||
name: 'Test'
|
name: 'Test'
|
||||||
@ -31,4 +31,5 @@ fn test_orm() {
|
|||||||
} or { panic(err) }
|
} or { panic(err) }
|
||||||
|
|
||||||
assert result[0].name == 'Test'
|
assert result[0].name == 'Test'
|
||||||
|
db.close()!
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ struct SubStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_orm_sub_structs() {
|
fn test_orm_sub_structs() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
sql db {
|
sql db {
|
||||||
create table Upper
|
create table Upper
|
||||||
}!
|
}!
|
||||||
@ -34,4 +34,5 @@ fn test_orm_sub_structs() {
|
|||||||
}!
|
}!
|
||||||
|
|
||||||
assert uppers.first().sub.name == upper_1.sub.name
|
assert uppers.first().sub.name == upper_1.sub.name
|
||||||
|
db.close()!
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,14 @@ struct ORMTableSpecificName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_orm_table_name() {
|
fn test_orm_table_name() {
|
||||||
db := sqlite.connect(':memory:') or { panic(err) }
|
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||||
r := sql db {
|
r := sql db {
|
||||||
select from ORMTableSpecificName
|
select from ORMTableSpecificName
|
||||||
} or {
|
} or {
|
||||||
|
db.close()!
|
||||||
assert true
|
assert true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
db.close()!
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ fn x(m Movie) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_sql_statement_inside_fn_call() {
|
fn test_sql_statement_inside_fn_call() {
|
||||||
db := sqlite.connect(':memory:') or { panic('failed') }
|
mut db := sqlite.connect(':memory:') or { panic('failed') }
|
||||||
sql db {
|
sql db {
|
||||||
create table Movie
|
create table Movie
|
||||||
}!
|
}!
|
||||||
@ -21,4 +21,5 @@ fn test_sql_statement_inside_fn_call() {
|
|||||||
dump(x(sql db {
|
dump(x(sql db {
|
||||||
select from Movie where id == 1
|
select from Movie where id == 1
|
||||||
}!.first()))
|
}!.first()))
|
||||||
|
db.close()!
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user