- Test runner will also check for leaks.

- `write` of qoi would leak memory.
- Issue when having an empty `Path` or just "."
- `set_env` would leak memory.
This commit is contained in:
Christoffer Lerno
2025-02-10 00:39:02 +01:00
parent 63f619e5b6
commit c4212c4649
20 changed files with 81 additions and 41 deletions

View File

@@ -7,6 +7,7 @@ fn void copy_map() @test
{
TrackingAllocator alloc;
alloc.init(allocator::heap());
defer alloc.free();
assert(alloc.allocated() == 0);
mem::@scoped(&alloc)
{
@@ -39,7 +40,8 @@ fn void copy_map() @test
fn void copy_keys() @test
{
String[] y;
@pool() {
@pool()
{
IntMap x;
x.temp_init();
x.set("hello", 0); // keys copied into temp hashmap
@@ -47,4 +49,6 @@ fn void copy_keys() @test
// end of pool: hashmap and its copied-in keys dropped
};
assert(y == {"hello"});
foreach(key : y) free(key);
free(y);
}

View File

@@ -9,18 +9,21 @@ const char[?] TEST_QOI_DATA = b64"cW9pZgAAAVQAAACpBABV/f39/f39/f39/f39/f39/f39/f
fn void test_qoi_all()
{
@pool() {
@pool()
{
// create a test descriptor
QOIDesc test_desc;
// decode the test data
char[] decoded = qoi::new_decode(TEST_QOI_DATA[..], &test_desc)!!;
defer free(decoded);
assert(test_desc.width == 340 && test_desc.height == 169, "Expected resolution of 340x169");
// encode the decoded data
char[] encoded = qoi::new_encode(decoded, &test_desc)!!;
assert(encoded == TEST_QOI_DATA[..], "Encoder output should match the test data");
defer free(encoded);
// encode and write the decoded data to a file
usz written = qoi::write("unittest.qoi", decoded, &test_desc)!!;
@@ -30,8 +33,6 @@ fn void test_qoi_all()
// cleanup
file::delete("unittest.qoi")!!;
free(encoded);
free(decoded);
free(read);
};
}

View File

@@ -22,6 +22,7 @@ fn void test_reverse()
assert(a.str_view() == "abcde");
a.reverse();
assert(a.str_view() == "edcba");
a.free();
}
fn void test_delete()
@@ -31,6 +32,7 @@ fn void test_delete()
d.append("Hello cruel world.");
d.delete_range(5, 10);
assert(d.str_view() == "Hello world.");
d.free();
}
DString d;
d.append("Hello cruel world.");
@@ -44,6 +46,7 @@ fn void test_delete()
assert(d.str_view() == "llo crul worl");
d.delete(0, 1);
assert(d.str_view() == "lo crul worl");
d.free();
}
fn void test_append()

View File

@@ -103,10 +103,12 @@ fn void test_split()
assert(strings[2] == "");
assert(strings[3] == "c");
assert(strings[4] == "");
free(strings);
strings = test.split("|", 2);
assert(strings.len == 2);
assert(strings[0] == "abc");
assert(strings[1] == "b||c|");
free(strings);
}
fn void test_split_skip_empty()
@@ -117,10 +119,12 @@ fn void test_split_skip_empty()
assert(strings[0] == "abc");
assert(strings[1] == "b");
assert(strings[2] == "c");
free(strings);
strings = test.split("|", 2, skip_empty: true);
assert(strings.len == 2);
assert(strings[0] == "abc");
assert(strings[1] == "b||c|");
free(strings);
}
fn void test_split_to_buffer_skip_empty()
@@ -136,6 +140,7 @@ fn void test_split_to_buffer_skip_empty()
assert(strings.len == 2);
assert(strings[0] == "abc");
assert(strings[1] == "b||c|");
free(strings);
}
fn void test_split_to_buffer()
@@ -155,6 +160,7 @@ fn void test_split_to_buffer()
assert(strings.len == 2);
assert(strings[0] == "abc");
assert(strings[1] == "b||c|");
free(strings);
}
fn void test_index_of()

View File

@@ -5,7 +5,7 @@ fn void write_read()
{
ByteBuffer buffer;
buffer.new_init(0)!!;
defer buffer.free();
buffer.write("hello")!!;
char[8] bytes;

View File

@@ -13,6 +13,7 @@ fn void bytestream()
assert((String)buffer[:len] == "abc");
ByteWriter w;
w.new_init();
defer (void)w.destroy();
OutStream ws = &w;
ws.write("helloworld")!!;
assert(w.str_view() == "helloworld");

View File

@@ -4,10 +4,12 @@ fn void test_writing()
{
DString foo;
foo.new_init();
defer foo.free();
OutStream s = &foo;
s.write("hello")!!;
s.write_byte('-')!!;
s.write("what?-------------------------------------------------------")!!;
ByteReader r;
String test_str = "2134";
io::copy_to(r.init(test_str), s)!!;

View File

@@ -3,9 +3,11 @@ module std::io::path @test;
fn void test_dot()
{
Path p = path::new(".")!!;
defer p.free();
assert(@catch(p.parent()));
// It must be possible to form the absolute version.
Path p2 = p.new_absolute()!!;
p2.free();
p2 = p.new_append("/hello/world")!!;
if (p2.env == POSIX)
{
@@ -15,21 +17,26 @@ fn void test_dot()
{
assert(p2.str_view() == `hello\world`);
}
p2.free();
}
fn void test_parent()
{
Path p = path::new("")!!;
assert(@catch(p.parent()));
p.free();
p = path::new("/", path_env: PathEnv.POSIX)!!;
assert(@catch(p.parent()));
p.free();
p = path::new("/a/b/c", path_env: PathEnv.POSIX)!!;
assert(p.parent().str_view()!! == "/a/b");
p.free();
p = path::new("/a/b/c", path_env: PathEnv.WIN32)!!;
assert(p.parent().str_view()!! == `\a\b`);
p.free();
}
fn void test_path_normalized()
fn void test_path_normalized() => mem::@scoped(allocator::temp())
{
assert(path::new("", path_env: PathEnv.WIN32).str_view()!! == "");
assert(@catch(path::new("1:\\a\\b\\c.txt", path_env: PathEnv.WIN32)));
@@ -205,7 +212,7 @@ fn void test_path_normalized()
}
fn void test_extension()
fn void test_extension() => mem::@scoped(allocator::temp())
{
assert(@catch(path::new(`C:`, path_env: PathEnv.WIN32).extension()));
assert(@catch(path::new(`C:`, path_env: PathEnv.POSIX).extension()));
@@ -239,7 +246,7 @@ fn void test_extension()
}
fn void test_has_extension()
fn void test_has_extension() => mem::@scoped(allocator::temp())
{
assert(!path::new(`C:\temp\foo.bar\README`, path_env: PathEnv.WIN32)!!.has_extension(`bar\README`));
@@ -269,7 +276,7 @@ fn void test_has_extension()
}
fn void test_basename()
fn void test_basename() => mem::@scoped(allocator::temp())
{
assert(path::new_windows("file.txt").basename()!! == "file.txt");
assert(path::new_posix("file.txt").basename()!! == "file.txt");
@@ -296,7 +303,7 @@ fn void test_basename()
assert(path::new_posix(`\\server\abc`).basename()!! == `\\server\abc`);
}
fn void test_dirname()
fn void test_dirname() => mem::@scoped(allocator::temp())
{
assert(path::new_posix("").dirname()!! == ".");
assert(path::new_posix("/file").dirname()!! == "/");
@@ -336,7 +343,7 @@ fn void test_dirname()
assert(path::new_posix(`\\server\`).dirname()!! == `.`);
}
fn void test_path_volume()
fn void test_path_volume() => mem::@scoped(allocator::temp())
{
assert(path::new_windows(`C:\abs`).volume_name()!! == `C:`);
assert(path::new_windows(`C:abs`).volume_name()!! == `C:`);
@@ -346,7 +353,7 @@ fn void test_path_volume()
assert(path::new_windows(`\\server\foo\abc`).volume_name()!! == `\\server\foo`);
}
fn void test_path_is_absolute()
fn void test_path_is_absolute() => mem::@scoped(allocator::temp())
{
assert(!path::new_posix("").is_absolute()!!);
assert(path::new_posix("/").is_absolute()!!);
@@ -360,7 +367,7 @@ fn void test_path_is_absolute()
assert(path::new_windows(`\\server\foo\abc`).is_absolute()!!);
}
fn void test_path_absolute()
fn void test_path_absolute() => mem::@scoped(allocator::temp())
{
$if env::WIN32:
assert(path::new_windows(`C:\abs`).new_absolute()!!.str_view() == `C:\abs`);

View File

@@ -27,6 +27,7 @@ fn void scanner()
sc.init(&br, buffer[..]);
Results results;
defer results.free();
while LOOP: (true)
{
char[]! res = sc.scan(",,");

View File

@@ -77,6 +77,7 @@ fn void read_tiny_bytearray_test()
ByteReader reader = io::wrap_bytes(&&x'07aabbcc00112233');
char[] read = io::read_tiny_bytearray(&reader, allocator: allocator::heap())!!;
assert(read == &&x'aabbcc00112233');
free(read);
}
fn void read_short_bytearray_test()
@@ -84,4 +85,5 @@ fn void read_short_bytearray_test()
ByteReader reader = io::wrap_bytes(&&x'0007aabbcc00112233');
char[] read = io::read_short_bytearray(&reader, allocator: allocator::heap())!!;
assert(read == &&x'aabbcc00112233');
free(read);
}

View File

@@ -95,4 +95,6 @@ module sort_test @test;
sort::countingsort(list, &sort::key_int_value);
assert(check::int_ascending_sort(list.array_view()));
list.free();
}

View File

@@ -3,6 +3,7 @@ module string_test;
fn void test_clear() @test
{
DString s = dstring::new_with_capacity(32);
defer s.free();
assert(s.len() == 0);
assert(s.capacity() == 32);
s.append_repeat('x', 63);

View File

@@ -77,7 +77,7 @@ fn void shared_mutex_decrement(ArgsWrapper1* args)
args.m.unlock()!!;
}
fn void shared_mutex() @test
fn void shared_mutex() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
Mutex m;
m.init()!!;
@@ -127,7 +127,7 @@ fn void acquire_recursively(RecursiveMutex* m)
}
}
fn void test_recursive_mutex() @test
fn void test_recursive_mutex() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
RecursiveMutex m;
m.init()!!;

View File

@@ -5,7 +5,7 @@ import std::thread::pool;
def Pool = ThreadPool(<4>);
fn void init_destroy() @test
fn void init_destroy() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
for (usz i = 0; i < 20; i++)
{
@@ -15,7 +15,7 @@ fn void init_destroy() @test
}
}
fn void push_destroy() @test
fn void push_destroy() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
for FOO: (usz i = 0; i < 20; i++)
{
@@ -42,7 +42,7 @@ fn void push_destroy() @test
}
}
fn void push_stop() @test
fn void push_stop() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
for (usz i = 0; i < 20; i++)
{

View File

@@ -3,7 +3,7 @@ import std::io;
int a;
fn void testrun() @test
fn void testrun() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
Thread t;
a = 0;
@@ -18,7 +18,7 @@ fn void testrun() @test
Mutex m_global;
fn void testrun_mutex() @test
fn void testrun_mutex() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
Thread[20] ts;
a = 0;
@@ -48,7 +48,7 @@ fn void testrun_mutex() @test
m_global.destroy()!!;
}
fn void testrun_mutex_try() @test
fn void testrun_mutex_try() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
Mutex m;
m.init()!!;
@@ -59,7 +59,7 @@ fn void testrun_mutex_try() @test
m.unlock()!!;
}
fn void testrun_mutex_timeout() @test
fn void testrun_mutex_timeout() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
TimedMutex m;
m.init()!!;
@@ -80,7 +80,7 @@ fn void call_once()
x_once += 100;
}
fn void testrun_once() @test
fn void testrun_once() @test => mem::@scoped(&allocator::LIBC_ALLOCATOR)
{
OnceFlag once;
once.call(&call_once);