hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 8b0405d1b5ad4b63d786de45b89a18a673ac306f
parent 4d7e408616beb70d105665703066d72ecc17f3ab
Author: Sebastian <sebastian@sebsite.pw>
Date:   Mon,  6 Nov 2023 23:27:55 -0500

all: fix test failure memory leaks

by using defer to free resources, so they free even if an assertion
fails

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mascii/string.ha | 37++++++++++++++++++++++---------------
Mcrypto/bigint/+test/arithm_test.ha | 37++++++++++++++++---------------------
Mcrypto/bigint/+test/monty_test.ha | 22++++++++++------------
Mcrypto/bigint/+test/utils.ha | 5++---
Mhare/unparse/ident.ha | 7++++---
Mstrings/concat.ha | 24++++++++++++------------
Mstrings/dup.ha | 10+++++-----
Mstrings/replace.ha | 50+++++++++++++++++++++++++++++++++++++-------------
Mstrings/runes.ha | 58+++++++++++++++++++++++-----------------------------------
9 files changed, 131 insertions(+), 119 deletions(-)

diff --git a/ascii/string.ha b/ascii/string.ha @@ -54,29 +54,36 @@ export fn strcasecmp(a: str, b: str) int = { @test fn strcasecmp() void = { let s = strupper("ABC"); + defer free(s); assert(s == "ABC"); - free(s); - s = strlower("ABC"); + + let s = strlower("ABC"); + defer free(s); assert(s == "abc"); - free(s); - s = strupper("abc"); + + let s = strupper("abc"); + defer free(s); assert(s == "ABC"); - free(s); - s = strlower("abc"); + + let s = strlower("abc"); + defer free(s); assert(s == "abc"); - free(s); - s = strupper("[[["); + + let s = strupper("[[["); + defer free(s); assert(s == "[[["); - free(s); - s = strlower("[[["); + + let s = strlower("[[["); + defer free(s); assert(s == "[[["); - free(s); - s = strupper("こ"); + + let s = strupper("こ"); + defer free(s); assert(s == "こ"); - free(s); - s = strlower("こ"); + + let s = strlower("こ"); + defer free(s); assert(s == "こ"); - free(s); assert(strcasecmp("ABC", "ABC") == 0); assert(strcasecmp("ABC", "abc") == 0); diff --git a/crypto/bigint/+test/arithm_test.ha b/crypto/bigint/+test/arithm_test.ha @@ -25,30 +25,27 @@ use bytes; @test fn muladd_small() void = { const mod = fromhex("0100"); + defer free(mod); let x = fromhex("0100"); + defer free(x); muladd_small(x, 3, mod); assert(equalshex(x, "03")); - free(mod); - free(x); - const mod = fromhex("1000000000"); + defer free(mod); let x = fromhexmod("0000000001", mod); + defer free(x); muladd_small(x, 27, mod); assert(equalshex(x, "8000001b")); - - free(mod); - free(x); }; @test fn mulacc() void = { let d = fromhex("0000000000000000"); - let a = fromhex("0010"); - let b = fromhex("0014"); - defer free(d); + let a = fromhex("0010"); defer free(a); + let b = fromhex("0014"); defer free(b); mulacc(d, a, b); @@ -60,39 +57,40 @@ use bytes; @test fn rshift() void = { let x = fromhex("1020304050"); + defer free(x); rshift(x, 1); assert(equalshex(x, "0810182028")); - free(x); let x = fromhex("00"); + defer free(x); rshift(x, 1); assert(equalshex(x, "")); - free(x); }; @test fn reduce() void = { let m = fromhex("87654321"); + defer free(m); let a = fromhex("1234"); + defer free(a); let x = fromhex("00000000"); + defer free(x); reduce(x, a, m); assert(equalshex(x, "1234")); - free(a); - free(x); let a = fromhex("0123456789abcdef"); + defer free(a); let x = fromhex("00000000"); + defer free(x); reduce(x, a, m); assert(equalshex(x, "14786ead")); - free(a); - free(x); - - free(m); }; @test fn modpow() void = { let m = fromhex("87654321"); + defer free(m); let x = fromhexmod("00f03202", m); + defer free(x); let e: [_]u8 = [0x00, 0x00, 0xc1, 0xf4]; const m0i = ninv31(m[1]); @@ -101,14 +99,11 @@ use bytes; modpow(x, e, m, m0i, tmp); assert(equalshex(x, "3de073fc")); - free(x); let x = fromhexmod("00f03202", m); + defer free(x); let tmp: [20]word = [0...]; modpow(x, e, m, m0i, tmp); assert(equalshex(x, "3de073fc")); - - free(m); - free(x); }; diff --git a/crypto/bigint/+test/monty_test.ha b/crypto/bigint/+test/monty_test.ha @@ -18,9 +18,13 @@ @test fn montymul() void = { let m = fromhex("10000061"); + defer free(m); let x = fromhexmod("00000123", m); + defer free(x); let y = fromhexmod("000003cf", m); + defer free(y); let d = fromhexmod("00000000", m); + defer free(d); const m0i = ninv31(m[1]); @@ -31,13 +35,12 @@ assert(equalshex(d, "04544d")); - free(d); - free(x); - free(y); - - d = fromhexmod("00000000", m); - x = fromhexmod("0f98b7cf", m); - y = fromhexmod("04216b9c", m); + let d = fromhexmod("00000000", m); + defer free(d); + let x = fromhexmod("0f98b7cf", m); + defer free(x); + let y = fromhexmod("04216b9c", m); + defer free(y); tomonty(x, m); tomonty(y, m); @@ -45,9 +48,4 @@ frommonty(d, m, m0i); assert(equalshex(d, "0d031f49")); - - free(x); - free(y); - free(m); - free(d); }; diff --git a/crypto/bigint/+test/utils.ha b/crypto/bigint/+test/utils.ha @@ -45,13 +45,12 @@ export fn equalshex(x: []word, h: str) bool = { @test fn iszero() void = { let x = fromhex("210032a0"); + defer free(x); let y = fromhex("00000000"); + defer free(y); assert(iszero(x) == 0); assert(iszero(y) == 1); - - free(x); - free(y); }; @test fn zero() void = { diff --git a/hare/unparse/ident.ha b/hare/unparse/ident.ha @@ -40,9 +40,10 @@ export fn identstr(id: ast::ident) str = { @test fn ident() void = { let s = identstr(["foo", "bar", "baz"]); + defer free(s); assert(s == "foo::bar::baz"); - free(s); - s = identstr(["foo"]); + + let s = identstr(["foo"]); + defer free(s); assert(s == "foo"); - free(s); }; diff --git a/strings/concat.ha b/strings/concat.ha @@ -16,24 +16,24 @@ export fn concat(strs: str...) str = { @test fn concat() void = { let s = concat("hello ", "world"); + defer free(s); assert(s == "hello world"); - free(s); - s = concat("hello", " ", "world"); + let s = concat("hello", " ", "world"); + defer free(s); assert(s == "hello world"); - free(s); - s = concat("hello", "", "world"); + let s = concat("hello", "", "world"); + defer free(s); assert(s == "helloworld"); - free(s); - s = concat("", ""); + let s = concat("", ""); + defer free(s); assert(s == ""); - free(s); - s = concat(); + let s = concat(); + defer free(s); assert(s == ""); - free(s); }; // Joins several strings together by placing a delimiter between them. The @@ -58,15 +58,15 @@ export fn join(delim: str, strs: str...) str = { @test fn join() void = { let s = join(".", "a", "b", "c"); + defer free(s); assert(s == "a.b.c"); - free(s); let s = join("", "a", "b", "c"); + defer free(s); assert(s == "abc"); - free(s); let s = join("."); + defer free(s); assert(s == ""); - free(s); }; diff --git a/strings/dup.ha b/strings/dup.ha @@ -41,30 +41,30 @@ export fn freeall(s: []str) void = { @test fn dup() void = { let s = dup(""); + defer free(s); assert(s == ""); - free(s); - s = dup("hello"); + let s = dup("hello"); + defer free(s); assert(s == "hello"); - free(s); }; @test fn dupall() void = { const payload: []str = []; let s = dupall(payload); + defer freeall(s); assert(len(s) == len(payload)); for (let i = 0z; i < len(s); i += 1) { assert(s[i] == payload[i]); }; - freeall(s); const payload: []str = ["a", "aaa"]; let s = dupall(payload); + defer freeall(s); assert(len(s) == len(payload)); for (let i = 0z; i < len(s); i += 1) { assert(s[i] == payload[i]); }; - freeall(s); }; diff --git a/strings/replace.ha b/strings/replace.ha @@ -41,23 +41,47 @@ export fn multireplace(s: str, repls: (str, str)...) str = { i += 1; }; append(res, b[prev..i]...); - return fromutf8(res)!; + return fromutf8_unsafe(res); }; @test fn replace() void = { - assert(replace("Hello world!", "world", "there") == "Hello there!"); - assert(replace("I like dogs, dogs, birds, dogs", "dogs", "cats") == - "I like cats, cats, birds, cats"); - assert(replace("aaaaaa", "aa", "a") == "aaa"); - assert(replace("aaa", "a", "aa") == "aaaaaa"); - assert(replace("こんにちは", "にち", "ばん") == "こんばんは"); + const s = replace("Hello world!", "world", "there"); + defer free(s); + assert(s == "Hello there!"); + + const s = replace("I like dogs, dogs, birds, dogs", "dogs", "cats"); + defer free(s); + assert(s == "I like cats, cats, birds, cats"); + + const s = replace("aaaaaa", "aa", "a"); + defer free(s); + assert(s == "aaa"); + + const s = replace("aaa", "a", "aa"); + defer free(s); + assert(s == "aaaaaa"); + + const s = replace("こんにちは", "にち", "ばん"); + defer free(s); + assert(s == "こんばんは"); }; @test fn multireplace() void = { - assert(multireplace("Hello world", ("Hello", "Greetings"), - ("world", "globe")) == "Greetings globe"); - assert(multireplace("ababa", ("a", "ba"), ("b", "a"), ("a", "c")) == - "baabaaba"); - assert(multireplace("hello there", ("e", "a"), ("a", "x"), ("ell", "eww")) == "hallo thara"); - assert(multireplace("hello there", ("ell", "eww"), ("e", "a")) == "hewwo thara"); + const s = multireplace("Hello world", + ("Hello", "Greetings"), ("world", "globe")); + defer free(s); + assert(s == "Greetings globe"); + + const s = multireplace("ababa", ("a", "ba"), ("b", "a"), ("a", "c")); + defer free(s); + assert(s == "baabaaba"); + + const s = multireplace("hello there", ("e", "a"), + ("a", "x"), ("ell", "eww")); + defer free(s); + assert(s == "hallo thara"); + + const s = multireplace("hello there", ("ell", "eww"), ("e", "a")); + defer free(s); + assert(s == "hewwo thara"); }; diff --git a/strings/runes.ha b/strings/runes.ha @@ -29,39 +29,27 @@ export fn fromrunes(rs: []rune) str = { }; @test fn fromrunes() void = { - const rs = ['H', 'a', 'r', 'r', 'i', 'e', 't']; - const s = fromrunes(rs); defer free(s); - assert(s == "Harriet", "strings::fromrunes() error (Harriet)"); - - const rs: []rune = []; - const s = fromrunes(rs); defer free(s); - assert(s == "", "strings::fromrunes() error (empty)"); - - const rs = ['.']; - const s = fromrunes(rs); defer free(s); - assert(s == ".", "strings::fromrunes() error (period)"); - - const rs = ['\a', '\b', '\f', '\n', '\r', '\t', '\v']; - const s = fromrunes(rs); defer free(s); - assert(s == "\a\b\f\n\r\t\v", "strings::fromrunes() error (control chars)"); - - const rs = ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!']; - const s = fromrunes(rs); defer free(s); - assert(s == "Hello, world!", "strings::fromrunes() error (English)"); - - const rs = ['¡', 'H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd', 'o', '!']; - const s = fromrunes(rs); defer free(s); - assert(s == "¡Hola Mundo!", "strings::fromrunes() error (Spanish)"); - - const rs = ['Γ', 'ε', 'ι', 'ά', ' ', 'σ', 'ο', 'υ', ' ', 'Κ', 'ό', 'σ', 'μ', 'ε', '!']; - const s = fromrunes(rs); defer free(s); - assert(s == "Γειά σου Κόσμε!", "strings::fromrunes() error (Greek)"); - - const rs = ['П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'м', 'и', 'р', '!']; - const s = fromrunes(rs); defer free(s); - assert(s == "Привет, мир!", "strings::fromrunes() error (Russian)"); - - const rs = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']; - const s = fromrunes(rs); defer free(s); - assert(s == "こんにちは世界!", "strings::fromrunes() error (Japanese)"); + const tests: [_](str, []rune) = [ + ("Harriet", ['H', 'a', 'r', 'r', 'i', 'e', 't']), + ("", []), + (".", ['.']), + ("\a\b\f\n\r\t\v", ['\a', '\b', '\f', '\n', '\r', '\t', '\v']), + ("Hello, world!", ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!']), + ("¡Hola Mundo!", ['¡', 'H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd', 'o', '!']), + ("Γειά σου Κόσμε!", ['Γ', 'ε', 'ι', 'ά', ' ', 'σ', 'ο', 'υ', ' ', 'Κ', 'ό', 'σ', 'μ', 'ε', '!']), + ("Привет, мир!", ['П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'м', 'и', 'р', '!']), + ("こんにちは世界!", ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']), + ]; + + for (let i = 0z; i < len(tests); i += 1) { + const s = fromrunes(tests[i].1); + defer free(s); + assert(s == tests[i].0); + const rs = torunes(s); + defer free(rs); + assert(len(rs) == len(tests[i].1)); + for (let j = 0z; j < len(rs); j += 1) { + assert(rs[j] == tests[i].1[j]); + }; + }; };