summaryrefslogtreecommitdiff
path: root/lib/std/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/test')
-rw-r--r--lib/std/test/bigint.myr136
-rw-r--r--lib/std/test/bytebuf.myr72
-rw-r--r--lib/std/test/chartype.myr23
-rw-r--r--lib/std/test/fmt.myr34
-rw-r--r--lib/std/test/htab.myr104
-rw-r--r--lib/std/test/ipparse.myr64
-rw-r--r--lib/std/test/option.myr43
-rw-r--r--lib/std/test/pathjoin.myr61
-rw-r--r--lib/std/test/search.myr34
-rw-r--r--lib/std/test/slcp.myr14
-rw-r--r--lib/std/test/sort.myr38
-rw-r--r--lib/std/test/strbuf.myr40
-rw-r--r--lib/std/test/try.myr8
13 files changed, 671 insertions, 0 deletions
diff --git a/lib/std/test/bigint.myr b/lib/std/test/bigint.myr
new file mode 100644
index 0000000..582fe60
--- /dev/null
+++ b/lib/std/test/bigint.myr
@@ -0,0 +1,136 @@
+use std
+
+type cmd = union
+ `Add (cmd#, cmd#)
+ `Sub (cmd#, cmd#)
+ `Mul (cmd#, cmd#)
+ `Div (cmd#, cmd#)
+ `Mod (cmd#, cmd#)
+ `Shl (cmd#, cmd#)
+ `Shr (cmd#, cmd#)
+ `Modpow (cmd#, cmd#, cmd#)
+ `Val byte[:]
+;;
+
+const main = {
+ var a, b, c, d, e
+ var buf : byte[64], n
+
+ /* a few combined ops */
+ a = std.mkbigint(1234)
+ b = std.mkbigint(0x7fffffff)
+ c = std.mkbigint(7919)
+ d = std.mkbigint(113051)
+ e = std.mkbigint(11)
+
+ std.bigmul(a, b)
+ std.bigmul(a, b)
+ std.bigadd(a, c)
+ std.bigsub(a, d)
+ std.bigdiv(a, e)
+
+ std.bigfree(b)
+ std.bigfree(c)
+ std.bigfree(d)
+ std.bigfree(e)
+
+ n = std.bigbfmt(buf[:], a, 0)
+ std.assert(std.sleq(buf[:n], "517347321949036993306"), "simple smoke test failed")
+
+ /* make sure we format '0' correctly */
+ run(std.mk(`Val "0"), "0")
+ /* smoke test for division */
+ run(std.mk(`Div (\
+ std.mk(`Val "1234_5678_1234_6789_6666_7777_8888"), \
+ std.mk(`Val "1234_5678_1234_6789_6666_7777"))), \
+ "10000")
+ run(std.mk(`Div (\
+ std.mk(`Val "0xffff_1234_1234_1234_1234"), \
+ std.mk(`Val "0xf010_1234_2314"))), \
+ "4580035496")
+ run(std.mk(`Div (\
+ std.mk(`Val "5192296858534810493479828944327220"), \
+ std.mk(`Val "75557863709417659441940"))), \
+ "68719476751")
+ run(std.mk(`Div (\
+ std.mk(`Val "75557863709417659441940"), \
+ std.mk(`Val "5192296858534810493479828944327220"))), \
+ "0")
+
+ /* smoke test for mod */
+ run(std.mk(`Mod (\
+ std.mk(`Val "5192296858534810493479828944327220"), \
+ std.mk(`Val "75557863709417659441940"))),\
+ "257025710597479990280")
+
+ run(std.mk(`Modpow (\
+ std.mk(`Val "1"), \
+ std.mk(`Val "3"), \
+ std.mk(`Val "2"))), \
+ "1")
+
+ run(std.mk(`Modpow (\
+ std.mk(`Val "5192296858534810493479828944327220"), \
+ std.mk(`Val "75557863709417659441940"), \
+ std.mk(`Val "755578"))), \
+ "49054")
+ run(std.mk(`Modpow (\
+ std.mk(`Val "7220"), \
+ std.mk(`Val "755578"), \
+ std.mk(`Val "75557863709417659441940"))), \
+ "27076504425474791131220")
+
+}
+
+const run = {e : cmd#, res : byte[:]
+ var buf : byte[4096]
+ var v, n
+
+ v = eval(e)
+ n = std.bigbfmt(buf[:], v, 0)
+ if !std.sleq(buf[:n], res)
+ std.fatal("%s != %s\n", buf[:n], res)
+ ;;
+}
+
+const eval = {e : cmd#
+ var buf : byte[2048]
+ var a, b, c /* scratch vars */
+ var n /* buf len */
+
+ match e#
+ | `Add (x, y): -> binop("+", std.bigadd, x, y)
+ | `Sub (x, y): -> binop("-", std.bigsub, x, y)
+ | `Mul (x, y): -> binop("*", std.bigmul, x, y)
+ | `Div (x, y): -> binop("/", std.bigdiv, x, y)
+ | `Mod (x, y): -> binop("%", std.bigmod, x, y)
+ | `Shl (x, y): -> binop("<<", std.bigshl, x, y)
+ | `Shr (x, y): -> binop(">>", std.bigshr, x, y)
+ | `Val x:
+ a = try(std.bigparse(x))
+ n = std.bigbfmt(buf[:], a, 0)
+ -> a
+ | `Modpow (x, y, z):
+ a = eval(x)
+ b = eval(y)
+ c = eval(z)
+ -> std.bigmodpow(a, b, c)
+ ;;
+}
+
+const binop = {name, op, x, y
+ var a, b
+
+ a = eval(x)
+ b = eval(y)
+ op(a, b)
+ std.bigfree(b)
+ -> a
+}
+
+generic try = {x : std.option(@a)
+ match x
+ | `std.Some v: -> v
+ | `std.None: std.die("failed to get val")
+ ;;
+}
diff --git a/lib/std/test/bytebuf.myr b/lib/std/test/bytebuf.myr
new file mode 100644
index 0000000..48f6715
--- /dev/null
+++ b/lib/std/test/bytebuf.myr
@@ -0,0 +1,72 @@
+use "bytebuf.use"
+
+/* support */
+use "die.use"
+use "fmt.use"
+use "sleq.use"
+
+const main = {
+ var bb, v
+
+ bb = std.mkbytebuf()
+
+ std.bytebufputc(bb, 'a')
+ std.assert(bb.len == 1, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "a"), \
+ "byte buf contents not \"a\"\n")
+
+ std.bytebufputs(bb, "bc")
+ std.assert(bb.len == 3, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abc"), \
+ "byte buf contents not \"abc\"\n")
+
+ std.bytebufputb(bb, 'd' castto(byte))
+ std.assert(bb.len == 4, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcd"), \
+ "byte buf contents not \"abcd\"\n")
+
+ std.bytebufputle8(bb, 'e' castto(int64))
+ std.assert(bb.len == 5, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcde"), \
+ "byte buf contents not \"abcde\"\n")
+
+ std.bytebufputbe8(bb, 'e' castto(int64))
+ std.assert(bb.len == 6, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdee"), \
+ "byte buf contents not \"abcdee\"\n")
+
+ std.bytebufputle16(bb, ('f' | ('g' << 8)) castto(int64))
+ std.assert(bb.len == 8, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefg"), \
+ "byte buf contents not \"abcdeefg\"\n")
+
+ std.bytebufputbe16(bb, ('f' | ('g' << 8)) castto(int64))
+ std.assert(bb.len == 10, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefggf"), \
+ "byte buf contents not \"abcdeefggf\"\n")
+
+ std.bytebufputle32(bb, ('h' | ('i' << 8) | ('j' << 16) | ('k' << 24)) castto(int64))
+ std.assert(bb.len == 14, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefggfhijk"), \
+ "byte buf contents not \"abcdeefggfhijk\"\n")
+
+ std.bytebufputbe32(bb, ('h' | ('i' << 8) | ('j' << 16) | ('k' << 24)) castto(int64))
+ std.assert(bb.len == 18, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefggfhijkkjih"), \
+ "byte buf contents not \"abcdeefggfhijkkji\"\n")
+
+ v = ('l' | ('m' << 8) | ('n' << 16) | ('o' << 24)) castto(int64)
+ v |= v << 32
+ std.bytebufputle64(bb, v)
+ std.assert(bb.len == 26, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefggfhijkkjihlmnolmno"), \
+ "byte buf contents not \"abcdeefggfhijkkjihlmnolmno\"\n")
+
+ v = ('l' | ('m' << 8) | ('n' << 16) | ('o' << 24)) castto(int64)
+ v |= v << 32
+ std.bytebufputbe64(bb, v)
+ std.assert(bb.len == 34, "byte buf size wrong\n")
+ std.assert(std.sleq(bb.buf[:bb.len], "abcdeefggfhijkkjihlmnolmnoonmlonml"), \
+ "byte buf contents not \"abcdeefggfhijkkjilmnolmnoonmlonml\"\n")
+}
+
diff --git a/lib/std/test/chartype.myr b/lib/std/test/chartype.myr
new file mode 100644
index 0000000..d0df1d2
--- /dev/null
+++ b/lib/std/test/chartype.myr
@@ -0,0 +1,23 @@
+use std
+
+const main = {
+ std.assert(std.isalpha('a'), "a should be alpha\n")
+ std.assert(std.isupper('A'), "A should be upper\n")
+ std.assert(std.islower('a'), "a should be lower\n")
+ std.assert(std.isdigit('0'), "0 should be isdigit\n")
+ std.assert(std.isnum('\u{0c66}'), "\u{0c66} should be isnum\n")
+ std.assert(std.isalnum('a'), "a should be isalnum\n")
+ std.assert(std.isalnum('0'), "0 should be isalnum\n")
+ std.assert(std.isspace(' '), "' ' should be isspace\n")
+ std.assert(std.isblank(' '), "' ' should be isblank\n")
+
+ std.assert(!std.isalpha('0'), "0 should not be alpha\n")
+ std.assert(!std.isupper('a'), "a should not be upper\n")
+ std.assert(!std.islower('A'), "A should not be lower\n")
+ std.assert(!std.isdigit('a'), "a should not be isdigit\n")
+ std.assert(!std.isnum('a'), " should not be isnum\n")
+ std.assert(!std.isalnum('}'), "a should not be isalnum\n")
+ std.assert(!std.isalnum('!'), "! should not be isalnum\n")
+ std.assert(!std.isspace('@'), "@ should not be isspace\n")
+ std.assert(!std.isblank('@'), "@ should not be isblank\n")
+}
diff --git a/lib/std/test/fmt.myr b/lib/std/test/fmt.myr
new file mode 100644
index 0000000..8de3890
--- /dev/null
+++ b/lib/std/test/fmt.myr
@@ -0,0 +1,34 @@
+use std
+
+const check = {expected, fmt, args : ...
+ var buf : byte[2048]
+ var sl, ap
+
+ ap = std.vastart(&args)
+ sl = std.bfmtv(buf[:], fmt, &ap)
+ if !std.sleq(expected, sl)
+ std.fatal("mismatched fmt: got \"{}\", expected \"{}\"\n", sl, expected)
+ ;;
+}
+
+const main = {
+ check(" abcd", "{w=10}", "abcd")
+ check("00000bdcae", "{p=0,w=10}", "bdcae")
+ check("abcdefghijkl", "{p=0,w=10}", "abcdefghijkl")
+ check("a", "{w=0,p=1}", "a")
+ check(" 10", "{w=10}", 10)
+ check("0000000010", "{p=0,w=10}", 10)
+ check("4294967295", "{p=0,w=10}", -1 castto(uint))
+ check("-000000001", "{p=0,w=10}", -1)
+ check("xxxxxxxx-1", "{p=x,w=10}", -1)
+ check(" -1", "{w=10}", -1)
+ check("100000" , "{3}", 100000)
+ check("foobarbaz", "{}bar{}", "foo", "baz")
+ check("{}barbaz", "{{}}bar{}", "baz")
+ check("{barbaz}", "{{bar{}}}", "baz")
+ check("abcd", "{}", "abcd")
+ check("123", "{}", 123)
+ check("7b", "{x}", 123)
+ check("0x7b", "0x{x}", 123)
+}
+
diff --git a/lib/std/test/htab.myr b/lib/std/test/htab.myr
new file mode 100644
index 0000000..1801d76
--- /dev/null
+++ b/lib/std/test/htab.myr
@@ -0,0 +1,104 @@
+use std
+
+const insertion = {
+ /*
+ var ht
+ var i
+
+ ht = std.mkht(idhash, ideq)
+ /* only a few values; shouldn't trigger growth */
+ for i = 0; i < 5; i++
+ std.htput(ht, i, i)
+ ;;
+ for i = 0; i < 5; i++
+ std.assert(std.htgetv(ht, i, -1) == i, "returned incorrect value from hash table")
+ ;;
+
+ /* and grow */
+ for i = 0; i < 5000; i++
+ std.htput(ht, i, i)
+ ;;
+ for i = 0; i < 5000; i++
+ std.assert(std.htgetv(ht, i, -1) == i, "returned incorrect value from hash table")
+ ;;
+ */
+}
+
+const deletion = {
+ var ht
+ var i
+
+ ht = std.mkht(idhash, ideq)
+ /* create a hash table with a few hundred values */
+ for i = 0; i < 4000; i++
+ std.htput(ht, i, i)
+ ;;
+ for i = 0; i < 200; i++
+ std.htdel(ht, i*2)
+ ;;
+ for i = 0; i < 200; i++
+ std.assert(!std.hthas(ht, i*2), "deleted item still present")
+ ;;
+ for i = 0; i < 200; i++
+ std.assert(std.hthas(ht, i*2+1), "undeleted item missing")
+ ;;
+ for i = 400; i < 4000; i++
+ std.assert(std.hthas(ht, i), "undeleted item missing")
+ ;;
+
+}
+
+const collision = {
+ var ht
+ var i
+
+ ht = std.mkht(idhash, ideq)
+ /* insert an element a few hundred times */
+ for i = 0; i < 500; i++
+ std.htput(ht, 0, i)
+ ;;
+ std.assert(std.hthas(ht, 0), "inserted element not present")
+ std.assert(std.htgetv(ht, 0, -1) == 499, "inserted element has wrong value")
+ std.htdel(ht, 0)
+ std.assert(!std.hthas(ht, 0), "element left in table")
+}
+
+const tombstonefill = {
+ var ht
+ var i
+
+ ht = std.mkht(idhash, ideq)
+ /*
+ insert an element into each slot in the hash table, and
+ delete it. With direct hashing, this is guaranteed to have
+ put a tombstone into each slot.
+ */
+ for i = 0; i <= ht.keys.len; i++
+ std.htput(ht, i, i)
+ std.htdel(ht, i)
+ ;;
+ /* make sure we haven't actually got anything in the table */
+ std.assert(ht.nelt == 0, "elements left in hash table")
+ std.assert(!std.hthas(ht, 1), "found phantom element")
+}
+
+const main = {
+ /* only a few elements */
+ std.put("insertion\n")
+ insertion()
+ std.put("deletion\n")
+ deletion()
+ std.put("collision\n")
+ collision()
+
+ /* what happens if we try to fill everything up with tombstones? */
+ tombstonefill()
+}
+
+const idhash = {x
+ -> x
+}
+
+const ideq = {a, b
+ -> a == b
+}
diff --git a/lib/std/test/ipparse.myr b/lib/std/test/ipparse.myr
new file mode 100644
index 0000000..bbf56e3
--- /dev/null
+++ b/lib/std/test/ipparse.myr
@@ -0,0 +1,64 @@
+use std
+
+const main = {
+ /* valid ipv4 address */
+ eq("1.2.3.4", `std.Some `std.Ipv4 [1,2,3,4])
+
+ /* invalid ipv4 address */
+ eq("1.3.4", `std.None) /* too short */
+ eq("1.2.3.4.5", `std.None) /* too long */
+ eq("1.3.4.256", `std.None) /* out of bounds 1 */
+ eq("260.2.3.4", `std.None) /* out of bounds 2 */
+
+ /* valid ipv6 addresses */
+ eq("2a03:2880:2110:df07:face:b00c:0:1", \
+ `std.Some `std.Ipv6 [0x2a, 0x03, 0x28, 0x80, 0x21, 0x10,
+ 0xdf, 0xfa, 0xce, 0xb0, 0x0c, 0x00, 0x00, 0x01, 0x01])
+ eq("abcd::dcba", \
+ `std.Some `std.Ipv6 [0xab, 0xcd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ eq("::abcd:dcba", \
+ `std.Some `std.Ipv6 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xdc, 0xba])
+ eq("::", `std.Some `std.Ipv6 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+
+ /* invalid ipv4 addresses */
+ eq("2a03:2880:2110:df07:face:b00c:0:1:abc", `std.None) /* too long */
+ eq("2a03:2880:2110:df07:face:b00c:0", `std.None) /* too short */
+ eq("2a03:2880:2110:df07:face:b00c:0:1:", `std.None) /* trailing ':' */
+}
+
+const eq = {ip, expected
+ var parsed
+ var p, e
+
+ parsed = std.ipparse(ip)
+ p = ipbytes(parsed)
+ e = ipbytes(expected)
+ if !std.sleq(p, e)
+ std.fput(1, "misparsed ip {}\n", ip)
+ std.put("parsed: ")
+ for b in p
+ std.put("{x}, ", b)
+ ;;
+ std.put("\nexpected: ")
+ for b in e
+ std.put("{x}, ", b)
+ ;;
+ std.put("\n")
+ std.fatal("failed\n")
+ ;;
+}
+
+const ipbytes = {ipopt
+ match ipopt
+ | `std.Some ip:
+ match ip
+ | `std.Ipv4 b: -> b[:]
+ | `std.Ipv6 b: -> b[:]
+ ;;
+ | `std.None: -> [][:]
+ ;;
+}
+
diff --git a/lib/std/test/option.myr b/lib/std/test/option.myr
new file mode 100644
index 0000000..fa8c5c0
--- /dev/null
+++ b/lib/std/test/option.myr
@@ -0,0 +1,43 @@
+use std
+
+const f = {x
+ if x == 123
+ -> `std.Some 42
+ else
+ -> `std.None
+ ;;
+}
+
+type t = struct
+ next : std.option(int)
+;;
+
+const main = {
+ var v, s : t
+
+ match `std.Some 42
+ | `std.Some x: std.assert(x == 42, "created wrong value\n")
+ | `std.None: std.assert(false, "should not be reached\n")
+ ;;
+
+ match `std.None
+ | `std.Some x: std.assert(x, "should not be reached\n")
+ | `std.None: /* everything ok */
+ ;;
+
+ v = f(123)
+ match v
+ | `std.Some x: std.assert(x == 42, "created wrong value\n")
+ | `std.None: std.assert(false, "should not be reached\n")
+ ;;
+
+ v = f(666)
+ match v
+ | `std.Some x: std.assert(false, "should not be reached\n")
+ | `std.None: /* everything ok */
+ ;;
+
+ s = [.next = `std.None]
+ s = [.next = `std.Some 123]
+}
+
diff --git a/lib/std/test/pathjoin.myr b/lib/std/test/pathjoin.myr
new file mode 100644
index 0000000..9cdc064
--- /dev/null
+++ b/lib/std/test/pathjoin.myr
@@ -0,0 +1,61 @@
+use std
+
+const main = {
+ /* untouched */
+ norm("foo", "foo")
+ norm("foo/bar", "foo/bar")
+ norm("/foo/bar", "/foo/bar")
+ norm(".", ".")
+
+ /* empty path becomes "." */
+ norm("", ".")
+
+ /* delete //, trailing / */
+ norm("foo/", "foo")
+ norm("foo//bar/baz", "foo/bar/baz")
+ norm("//foo//bar/", "/foo/bar")
+
+ /* delete '.' */
+ norm("foo/./bar", "foo/bar")
+ norm("/foo/bar/.", "/foo/bar")
+ norm("./foo/bar/.", "foo/bar")
+
+ /* elide '..' */
+ norm("/../foo/bar", "/foo/bar")
+ norm("../../foo/bar", "../../foo/bar")
+ norm("foo/bar/..", "foo")
+ norm("foo/bar/../..", ".")
+ norm("foo/../bar/../..", "..")
+ norm("/foo/../bar/../..", "/")
+
+ /* mix all of the above */
+ norm("/../foo//bar", "/foo/bar")
+ norm("..//../foo/bar", "../../foo/bar")
+ norm("foo//./bar/..", "foo")
+ norm("foo/bar/.././..", ".")
+ norm("//foo/../bar/../..", "/")
+ norm("foo/../bar/../..", "..")
+
+ /* vanilla pathjoin */
+ eq(std.pathcat("a", "b"), "a/b")
+ eq(std.pathjoin(["a", "b", "c"][:]), "a/b/c")
+ /* pathjoin with empty dirs */
+ eq(std.pathcat("", "foo"), "foo")
+ eq(std.pathjoin(["", "foo", "bar"][:]), "foo/bar")
+}
+
+const norm = {a, b
+ var p
+
+ p = std.pathnorm(a)
+ if !std.sleq(p, b)
+ std.fatal("mismatched paths: '{}' => '{}' != '{}'\n", a, p, b)
+ ;;
+ std.slfree(p)
+}
+
+const eq = {a, b
+ if !std.sleq(a, b)
+ std.fatal("mismatched paths: '{}' != '{}'\n", a, b)
+ ;;
+}
diff --git a/lib/std/test/search.myr b/lib/std/test/search.myr
new file mode 100644
index 0000000..342a406
--- /dev/null
+++ b/lib/std/test/search.myr
@@ -0,0 +1,34 @@
+use std
+
+const sl = [1, 3, 5, 8, 9, 33]
+
+const main = {
+
+ expect(std.lsearch(sl[:], 1, std.numcmp), `std.Some 0)
+ expect(std.lsearch(sl[:], 33, std.numcmp), `std.Some sl.len - 1)
+ expect(std.lsearch(sl[:], 5, std.numcmp), `std.Some 2)
+ expect(std.lsearch(sl[:], 6, std.numcmp), `std.None)
+
+ expect(std.bsearch(sl[:], 1, std.numcmp), `std.Some 0)
+ expect(std.bsearch(sl[:], 33, std.numcmp), `std.Some sl.len - 1)
+ expect(std.bsearch(sl[:], 5, std.numcmp), `std.Some 2)
+ expect(std.bsearch(sl[:], 6, std.numcmp), `std.None)
+}
+
+const expect = {a, b
+ match a
+ | `std.None:
+ match b
+ | `std.Some x: std.fatal("Expected `std.None, `std.None, got `std.None, `std.Some %i\n", x)
+ | `std.None: /* nothing */
+ ;;
+ | `std.Some x:
+ match b
+ | `std.None: std.fatal("Expected `std.Some %i, `std.Some %i, got `std.Some %i, `std.None\n", x, x, x)
+ | `std.Some y:
+ if x != y
+ std.fatal("Expected `std.Some %i, `std.Some %i, got `std.Some %i, `std.Some %i\n", x, x, x, y)
+ ;;
+ ;;
+ ;;
+}
diff --git a/lib/std/test/slcp.myr b/lib/std/test/slcp.myr
new file mode 100644
index 0000000..67c8298
--- /dev/null
+++ b/lib/std/test/slcp.myr
@@ -0,0 +1,14 @@
+use std
+
+const main = {
+ var a = [1,2,3,4,5]
+ var b = [6,7,8,9,10]
+ var a_cped = [3, 4, 5, 4, 5]
+ var b_cped = [6, 7, 6, 7, 8]
+
+
+ std.slcp(a[:a.len-2], a[2:])
+ std.slcp(b[2:], b[:b.len-2])
+ std.assert(std.sleq(a[:], a_cped[:]), "slcp of a failed")
+ std.assert(std.sleq(b[:], b_cped[:]), "slcp of a failed")
+}
diff --git a/lib/std/test/sort.myr b/lib/std/test/sort.myr
new file mode 100644
index 0000000..e814623
--- /dev/null
+++ b/lib/std/test/sort.myr
@@ -0,0 +1,38 @@
+use std
+
+const main = {
+ var i
+
+ var a = [ 3, 5, 4, 9, 7, 2, 6, 0, 1, 8, ]
+ var a_sorted = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ var b = [3, 4, 5, 1, 2, 6, 7, 8, 9, 10]
+ var b_sorted = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ var c = ["a", "aa", "b", "C", "Cc", "cC", "d", "f", "fuckit", "go",]
+ var c_sorted = ["C", "Cc", "a", "aa", "b", "cC", "d", "f", "fuckit", "go"]
+
+ /* with custom intcmp */
+ std.sort(a[:], intcmp)
+ std.assert(std.sleq(a[:], a_sorted[:]), "a was missorted")
+
+ /* with libstd generic numcmp */
+ std.sort(b[:], std.numcmp)
+ std.assert(std.sleq(b[:], b_sorted[:]), "b was missorted")
+
+ /* string sorting */
+ std.sort(c[:], std.strcmp)
+ for i = 0; i < c.len; i++
+ std.assert(std.sleq(c[i], c_sorted[i]), "c was missorted")
+ ;;
+}
+
+const intcmp = {a, b
+ if a < b
+ -> `std.Before
+ elif a == b
+ -> `std.Equal
+ else
+ -> `std.After
+ ;;
+}
+
+
diff --git a/lib/std/test/strbuf.myr b/lib/std/test/strbuf.myr
new file mode 100644
index 0000000..2643da5
--- /dev/null
+++ b/lib/std/test/strbuf.myr
@@ -0,0 +1,40 @@
+use std
+
+const main = {
+ var sb
+ var buf : byte[16]
+
+ sb = std.mksb()
+ std.assert(std.sleq(std.sbpeek(sb), ""), "mismatched empty str\n")
+ std.sbputs(sb, "hello")
+ std.assert(std.sleq(std.sbpeek(sb), "hello"), "mismatched hello\n")
+ std.sbputs(sb, ", hello")
+ std.assert(std.sleq(std.sbpeek(sb), "hello, hello"), "mismatched double hello\n")
+ std.sbtrim(sb, 7)
+ std.assert(std.sleq(std.sbpeek(sb), "hello, "), "mismatched trim\n")
+ std.sbputs(sb, "world")
+ std.assert(std.sleq(std.sbpeek(sb), "hello, world"), "mismatched hello world\n")
+ std.sbtrim(sb, -5)
+ std.assert(std.sleq(std.sbpeek(sb), "hello, "), "mismatched rtrim\n")
+ std.sbputc(sb, '世')
+ std.sbputc(sb, '界')
+ std.assert(std.sleq(std.sbpeek(sb), "hello, 世界"), "mismatched unicode\n")
+ std.sbputb(sb, 10)
+ std.assert(std.sleq(std.sbpeek(sb), "hello, 世界\n"), "mismatched byte\n")
+
+ sb = std.mkbufsb(buf[:])
+ std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 5 characters */
+ std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 10 characters */
+ std.assert(std.sbputs(sb, "hello"), "failed to add hello\n") /* 15 characters */
+ std.assert(!std.sbputs(sb, "hello"), "erronous success\n") /* 16 characters */
+ std.assert(std.sleq(std.sbpeek(sb), "hellohellohelloh"), "failed to copy as much as possible\n")
+ std.sbtrim(sb, -1)
+ std.assert(std.sleq(std.sbpeek(sb), "hellohellohello"), "failed rtrim\n")
+ std.sbputc(sb, '世')
+ std.assert(std.sleq(std.sbpeek(sb), "hellohellohello"), "modified overflowed putc\n")
+ std.sbtrim(sb, -2)
+ std.assert(std.sleq(std.sbpeek(sb), "hellohellohel"), "failed rtrim\n")
+ std.sbputc(sb, '世')
+ std.assert(std.sleq(std.sbpeek(sb), "hellohellohel世"), "failed to append with putc\n")
+}
+
diff --git a/lib/std/test/try.myr b/lib/std/test/try.myr
new file mode 100644
index 0000000..525b95c
--- /dev/null
+++ b/lib/std/test/try.myr
@@ -0,0 +1,8 @@
+use std
+
+const main = {
+ var x = `std.Some 123
+ var r : std.result(int, byte[:]) = `std.Ok 666
+ std.assert(std.get(x) == 123, "expected 123 from try")
+ std.assert(std.try(r) == 666, "expected 123 from try")
+}