mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Create a unit7 for all unit tests.
This commit is contained in:
@@ -28,16 +28,6 @@ fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic
|
||||
return n;
|
||||
}
|
||||
|
||||
fn String EnumMap.to_string(&self, Allocator allocator) @dynamic
|
||||
{
|
||||
return string::format("%s", *self, allocator: allocator);
|
||||
}
|
||||
|
||||
fn String EnumMap.to_tstring(&self) @dynamic
|
||||
{
|
||||
return string::tformat("%s", *self);
|
||||
}
|
||||
|
||||
<*
|
||||
@return "The total size of this map, which is the same as the number of enum values"
|
||||
@pure
|
||||
|
||||
@@ -156,7 +156,7 @@ fn void Object.init_map_if_needed(&self) @private
|
||||
if (self.is_empty())
|
||||
{
|
||||
self.type = ObjectInternalMap.typeid;
|
||||
self.map.tinit();
|
||||
self.map.init(self.allocator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
@require Type.kindof == ARRAY : "Required an array type"
|
||||
*>
|
||||
module std::collections::ringbuffer(<Type>);
|
||||
import std::io;
|
||||
|
||||
def Element = $typeof((Type){}[0]);
|
||||
|
||||
struct RingBuffer
|
||||
struct RingBuffer (Printable)
|
||||
{
|
||||
Type buf;
|
||||
usz written;
|
||||
@@ -19,7 +20,7 @@ fn void RingBuffer.init(&self) @inline
|
||||
|
||||
fn void RingBuffer.push(&self, Element c)
|
||||
{
|
||||
if (self.written < buf.len)
|
||||
if (self.written < self.buf.len)
|
||||
{
|
||||
self.buf[self.written] = c;
|
||||
self.written++;
|
||||
@@ -27,14 +28,14 @@ fn void RingBuffer.push(&self, Element c)
|
||||
else
|
||||
{
|
||||
self.buf[self.head] = c;
|
||||
self.head = (self.head + 1) % buf.len;
|
||||
self.head = (self.head + 1) % self.buf.len;
|
||||
}
|
||||
}
|
||||
|
||||
fn Element RingBuffer.get(&self, usz index) @operator([])
|
||||
{
|
||||
index %= buf.len;
|
||||
usz avail = buf.len - self.head;
|
||||
index %= self.buf.len;
|
||||
usz avail = self.buf.len - self.head;
|
||||
if (index < avail)
|
||||
{
|
||||
return self.buf[self.head + index];
|
||||
@@ -48,25 +49,25 @@ fn Element! RingBuffer.pop(&self)
|
||||
{
|
||||
case self.written == 0:
|
||||
return SearchResult.MISSING?;
|
||||
case self.written < buf.len:
|
||||
case self.written < self.buf.len:
|
||||
self.written--;
|
||||
return self.buf[self.written];
|
||||
default:
|
||||
self.head = (self.head - 1) % buf.len;
|
||||
self.head = (self.head - 1) % self.buf.len;
|
||||
return self.buf[self.head];
|
||||
}
|
||||
}
|
||||
|
||||
fn usz! RingBuffer.to_format(&self, Formatter* format)
|
||||
fn usz! RingBuffer.to_format(&self, Formatter* format) @dynamic
|
||||
{
|
||||
// Improve this?
|
||||
return format.printnf("%s", self.buf);
|
||||
return format.printf("%s", self.buf);
|
||||
}
|
||||
|
||||
fn usz RingBuffer.read(&self, usz index, Element[] buffer)
|
||||
{
|
||||
index %= buf.len;
|
||||
if (self.written < buf.len)
|
||||
index %= self.buf.len;
|
||||
if (self.written < self.buf.len)
|
||||
{
|
||||
if (index >= self.written) return 0;
|
||||
usz end = self.written - index;
|
||||
@@ -74,7 +75,7 @@ fn usz RingBuffer.read(&self, usz index, Element[] buffer)
|
||||
buffer[:n] = self.buf[index:n];
|
||||
return n;
|
||||
}
|
||||
usz end = buf.len - self.head;
|
||||
usz end = self.buf.len - self.head;
|
||||
if (index >= end)
|
||||
{
|
||||
index -= end;
|
||||
@@ -83,13 +84,13 @@ fn usz RingBuffer.read(&self, usz index, Element[] buffer)
|
||||
buffer[:n] = self.buf[index:n];
|
||||
return n;
|
||||
}
|
||||
if (buffer.len <= buf.len - index)
|
||||
if (buffer.len <= self.buf.len - index)
|
||||
{
|
||||
usz n = buffer.len;
|
||||
buffer[:n] = self.buf[self.head + index:n];
|
||||
return n;
|
||||
}
|
||||
usz n1 = buf.len - index;
|
||||
usz n1 = self.buf.len - index;
|
||||
buffer[:n1] = self.buf[self.head + index:n1];
|
||||
buffer = buffer[n1..];
|
||||
index -= n1;
|
||||
@@ -101,7 +102,7 @@ fn usz RingBuffer.read(&self, usz index, Element[] buffer)
|
||||
fn void RingBuffer.write(&self, Element[] buffer)
|
||||
{
|
||||
usz i;
|
||||
while (self.written < buf.len && i < buffer.len)
|
||||
while (self.written < self.buf.len && i < buffer.len)
|
||||
{
|
||||
self.buf[self.written] = buffer[i++];
|
||||
self.written++;
|
||||
@@ -109,6 +110,6 @@ fn void RingBuffer.write(&self, Element[] buffer)
|
||||
foreach (c : buffer[i..])
|
||||
{
|
||||
self.buf[self.head] = c;
|
||||
self.head = (self.head + 1) % buf.len;
|
||||
self.head = (self.head + 1) % self.buf.len;
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ macro @check(#condition, String format = "", args...)
|
||||
@stack_mem(512; Allocator allocator)
|
||||
{
|
||||
DString s;
|
||||
s.new_init(allocator: allocator);
|
||||
s.init(allocator);
|
||||
s.appendf("check `%s` failed. ", $stringify(#condition));
|
||||
s.appendf(format, ...args);
|
||||
print_panicf(s.str_view());
|
||||
|
||||
@@ -77,13 +77,13 @@ macro void! CsvReader.@each_row(self, int rows = int.max; @body(String[] row)) @
|
||||
{
|
||||
@stack_mem(512; Allocator mem)
|
||||
{
|
||||
String! s = io::readline(stream, mem);
|
||||
String! s = io::readline(mem, stream);
|
||||
if (catch err = s)
|
||||
{
|
||||
if (err == IoError.EOF) return;
|
||||
return err?;
|
||||
}
|
||||
@body(s.split(sep, allocator: mem));
|
||||
@body(s.split(mem, sep));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,9 @@ fn Object*! tparse_string(String s)
|
||||
|
||||
fn Object*! parse(Allocator allocator, InStream s)
|
||||
{
|
||||
@stack_mem(512; Allocator mem)
|
||||
@stack_mem(512; Allocator smem)
|
||||
{
|
||||
JsonContext context = { .last_string = dstring::new_with_capacity(mem, 64), .stream = s, .allocator = allocator };
|
||||
JsonContext context = { .last_string = dstring::new_with_capacity(smem, 64), .stream = s, .allocator = allocator };
|
||||
@pool(allocator)
|
||||
{
|
||||
return parse_any(&context);
|
||||
|
||||
@@ -170,81 +170,81 @@ fn Url! parse(Allocator allocator, String url_string)
|
||||
return url;
|
||||
}
|
||||
|
||||
<*
|
||||
Stringify a Url struct.
|
||||
|
||||
@param [in] self
|
||||
@param [inout] allocator
|
||||
@return "Url as a string"
|
||||
*>
|
||||
fn String Url.to_string(&self, Allocator allocator = allocator::heap()) @dynamic => @pool(allocator)
|
||||
fn usz! Url.to_format(&self, Formatter* f) @dynamic
|
||||
{
|
||||
DString builder = dstring::tnew();
|
||||
|
||||
usz len;
|
||||
// Add scheme if it exists
|
||||
if (self.scheme != "")
|
||||
{
|
||||
builder.append_chars(self.scheme);
|
||||
builder.append_char(':');
|
||||
if (self.host.len > 0) builder.append_chars("//");
|
||||
len += f.print(self.scheme)!;
|
||||
len += f.print(":")!;
|
||||
if (self.host.len > 0) len += f.print("//")!;
|
||||
}
|
||||
|
||||
// Add username and password if they exist
|
||||
if (self.username != "")
|
||||
if (self.username)
|
||||
{
|
||||
String username = tencode(self.username, USERPASS);
|
||||
builder.append_chars(username);
|
||||
|
||||
if (self.password != "")
|
||||
@stack_mem(64; Allocator smem)
|
||||
{
|
||||
builder.append_char(':');
|
||||
|
||||
String password = tencode(self.password, USERPASS);
|
||||
builder.append_chars(password);
|
||||
len += f.print(encode(smem, self.username, USERPASS))!;
|
||||
};
|
||||
if (self.password)
|
||||
{
|
||||
len += f.print(":")!;
|
||||
@stack_mem(64; Allocator smem)
|
||||
{
|
||||
len += f.print(encode(smem, self.password, USERPASS))!;
|
||||
};
|
||||
}
|
||||
builder.append_char('@');
|
||||
len += f.print("@")!;
|
||||
}
|
||||
|
||||
// Add host
|
||||
String host = tencode(self.host, HOST);
|
||||
builder.append_chars(host);
|
||||
@stack_mem(128; Allocator smem)
|
||||
{
|
||||
len += f.print(encode(smem, self.host, HOST))!;
|
||||
};
|
||||
|
||||
// Add port
|
||||
if (self.port != 0)
|
||||
{
|
||||
builder.append_char(':');
|
||||
builder.appendf("%d", self.port);
|
||||
}
|
||||
if (self.port) len += f.printf(":%d", self.port)!;
|
||||
|
||||
// Add path
|
||||
String path = tencode(self.path, PATH);
|
||||
builder.append_chars(path);
|
||||
@stack_mem(256; Allocator smem)
|
||||
{
|
||||
len += f.print(encode(smem, self.path, PATH))!;
|
||||
};
|
||||
|
||||
// Add query if it exists (note that `query` is expected to
|
||||
// be already properly encoded).
|
||||
if (self.query != "")
|
||||
if (self.query)
|
||||
{
|
||||
builder.append_char('?');
|
||||
builder.append_chars(self.query);
|
||||
len += f.print("?")!;
|
||||
len += f.print(self.query)!;
|
||||
}
|
||||
|
||||
// Add fragment if it exists
|
||||
if (self.fragment != "")
|
||||
if (self.fragment)
|
||||
{
|
||||
builder.append_char('#');
|
||||
|
||||
String fragment = tencode(self.fragment, FRAGMENT);
|
||||
builder.append_chars(fragment);
|
||||
@stack_mem(256; Allocator smem)
|
||||
{
|
||||
len += f.print("#")!;
|
||||
len += f.print(encode(smem, self.fragment, FRAGMENT))!;
|
||||
};
|
||||
}
|
||||
|
||||
return builder.copy_str(allocator);
|
||||
return len;
|
||||
}
|
||||
|
||||
def UrlQueryValueList = List(<String>);
|
||||
fn String Url.to_string(&self, Allocator allocator)
|
||||
{
|
||||
return string::format(allocator, "%s", *self);
|
||||
}
|
||||
|
||||
|
||||
def UrlQueryValueList = List{String};
|
||||
|
||||
struct UrlQueryValues
|
||||
{
|
||||
inline HashMap(<String, UrlQueryValueList>) map;
|
||||
inline HashMap{String, UrlQueryValueList} map;
|
||||
UrlQueryValueList key_order;
|
||||
}
|
||||
|
||||
@@ -317,41 +317,35 @@ fn UrlQueryValues* UrlQueryValues.add(&self, String key, String value)
|
||||
}
|
||||
|
||||
|
||||
<*
|
||||
Stringify UrlQueryValues into an encoded query string.
|
||||
|
||||
@param [in] self
|
||||
@param [inout] allocator
|
||||
@return "a percent-encoded query string"
|
||||
*>
|
||||
fn String UrlQueryValues.to_string(&self, Allocator allocator = allocator::heap()) @dynamic => @pool(allocator)
|
||||
fn usz! UrlQueryValues.to_format(&self, Formatter* f) @dynamic
|
||||
{
|
||||
DString builder = dstring::tnew();
|
||||
|
||||
usz len;
|
||||
usz i;
|
||||
foreach (key: self.key_order)
|
||||
{
|
||||
String encoded_key = tencode(key, QUERY);
|
||||
|
||||
UrlQueryValueList! values = self.map.get(key);
|
||||
if (catch values) continue;
|
||||
|
||||
foreach (value: values)
|
||||
@stack_mem(128; Allocator mem)
|
||||
{
|
||||
if (i > 0) builder.append_char('&');
|
||||
|
||||
builder.append_chars(encoded_key);
|
||||
builder.append_char('=');
|
||||
|
||||
String encoded_value = tencode(value, QUERY);
|
||||
builder.append_chars(encoded_value);
|
||||
i++;
|
||||
}
|
||||
};
|
||||
|
||||
return builder.copy_str(allocator);
|
||||
String encoded_key = encode(mem, key, QUERY);
|
||||
UrlQueryValueList! values = self.map.get(key);
|
||||
if (catch values) continue;
|
||||
foreach (value : values)
|
||||
{
|
||||
if (i > 0) len += f.print("&")!;
|
||||
len += f.print(encoded_key)!;
|
||||
len += f.print("=")!;
|
||||
@stack_mem(256; Allocator smem)
|
||||
{
|
||||
len += f.print(encode(smem, value, QUERY))!;
|
||||
};
|
||||
i++;
|
||||
}
|
||||
};
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
fn void UrlQueryValues.free(&self)
|
||||
{
|
||||
self.map.@each(;String key, UrlQueryValueList values)
|
||||
|
||||
25
test/unit7/regression/any.c3
Normal file
25
test/unit7/regression/any.c3
Normal file
@@ -0,0 +1,25 @@
|
||||
module any_tests @test;
|
||||
|
||||
fn void any_compare()
|
||||
{
|
||||
int x;
|
||||
any a = &x;
|
||||
any b = &x;
|
||||
assert(a == b);
|
||||
assert(a == a);
|
||||
}
|
||||
|
||||
def AnyAlias = any;
|
||||
|
||||
fn void test_aliasing()
|
||||
{
|
||||
int x;
|
||||
AnyAlias z = &x;
|
||||
switch (z)
|
||||
{
|
||||
case int:
|
||||
assert(true);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
44
test/unit7/regression/bitstruct_ops.c3
Normal file
44
test/unit7/regression/bitstruct_ops.c3
Normal file
@@ -0,0 +1,44 @@
|
||||
module bitstruct_ops;
|
||||
import std::io;
|
||||
|
||||
bitstruct Foo : int
|
||||
{
|
||||
bool a : 0;
|
||||
bool b : 1;
|
||||
}
|
||||
|
||||
bitstruct Bar : char[13]
|
||||
{
|
||||
bool z : 0;
|
||||
bool w : 1;
|
||||
bool gh : 25;
|
||||
}
|
||||
|
||||
fn void test_bitops() @test
|
||||
{
|
||||
Foo f1 = { true, true };
|
||||
Foo f2 = { true, false };
|
||||
|
||||
Foo f3 = f1 & f2;
|
||||
assert(f3.a == true);
|
||||
assert(f3.b == false);
|
||||
|
||||
Foo f4 = (f1 | ~f2) ^ f3;
|
||||
assert(f4.a == false && f4.b == true);
|
||||
Foo f5 = (Foo) { true, false } | (Foo) { false, true };
|
||||
assert(f5.a == true && f5.b == true);
|
||||
|
||||
f5 &= f2;
|
||||
assert(f5.a == true && f5.b == false);
|
||||
|
||||
Bar b1 = { true, true, true };
|
||||
Bar b2 = { true, false, false };
|
||||
|
||||
Bar b3 = b1 & b2;
|
||||
assert(b3.z == true && b3.w == false && b3.gh == false);
|
||||
b3 = ~b3;
|
||||
assert(b3.z == false && b3.w == true && b3.gh == true);
|
||||
b3 ^= (Bar) { true, true, false };
|
||||
assert(b3.z == true && b3.w == false && b3.gh == true);
|
||||
}
|
||||
|
||||
65
test/unit7/regression/bitstruct_ops2.c3
Normal file
65
test/unit7/regression/bitstruct_ops2.c3
Normal file
@@ -0,0 +1,65 @@
|
||||
module bitstruct_ops_bool;
|
||||
import std::io;
|
||||
|
||||
bitstruct Foo : int
|
||||
{
|
||||
bool a;
|
||||
bool b;
|
||||
}
|
||||
|
||||
bitstruct Bar : char[13]
|
||||
{
|
||||
bool z;
|
||||
bool w;
|
||||
bool gh;
|
||||
}
|
||||
|
||||
fn void test_bitops() @test
|
||||
{
|
||||
Foo f1 = { true, true };
|
||||
Foo f2 = { true, false };
|
||||
|
||||
Foo f3 = f1 & f2;
|
||||
assert(f3.a == true);
|
||||
assert(f3.b == false);
|
||||
|
||||
Foo f4 = (f1 | ~f2) ^ f3;
|
||||
assert(f4.a == false && f4.b == true);
|
||||
Foo f5 = (Foo) { true, false } | (Foo) { false, true };
|
||||
assert(f5.a == true && f5.b == true);
|
||||
|
||||
f5 &= f2;
|
||||
assert(f5.a == true && f5.b == false);
|
||||
|
||||
Bar b1 = { true, true, true };
|
||||
Bar b2 = { true, false, false };
|
||||
|
||||
Bar b3 = b1 & b2;
|
||||
assert(b3.z == true && b3.w == false && b3.gh == false);
|
||||
b3 = ~b3;
|
||||
assert(b3.z == false && b3.w == true && b3.gh == true);
|
||||
b3 ^= (Bar) { true, true, false };
|
||||
assert(b3.z == true && b3.w == false && b3.gh == true);
|
||||
}
|
||||
|
||||
fn void test_bitops_const() @test
|
||||
{
|
||||
const Foo F1 = { true, true };
|
||||
const Foo F2 = { true, false };
|
||||
|
||||
const Foo F3 = F1 & F2;
|
||||
assert(F3.a == true);
|
||||
assert(F3.b == false);
|
||||
|
||||
const Foo F4 = (F1 | ~F2) ^ F3;
|
||||
assert(F4.a == false && F4.b == true);
|
||||
const Foo F5 = (Foo) { true, false } | (Foo) { false, true };
|
||||
assert(F5.a == true && F5.b == true);
|
||||
|
||||
const Bar B1 = { true, true, true };
|
||||
const Bar B2 = { true, false, false };
|
||||
|
||||
const Bar B3 = B1 & B2;
|
||||
assert(B3.z == true && B3.w == false && B3.gh == false);
|
||||
}
|
||||
|
||||
90
test/unit7/regression/bitstruct_ops3.c3
Normal file
90
test/unit7/regression/bitstruct_ops3.c3
Normal file
@@ -0,0 +1,90 @@
|
||||
module bitstruct_ops_inc @test;
|
||||
import std::io;
|
||||
|
||||
struct Data {
|
||||
bitstruct : ushort @overlap {
|
||||
char a : 0..7;
|
||||
}
|
||||
bitstruct : ushort @overlap {
|
||||
ushort ab : 0..15;
|
||||
}
|
||||
}
|
||||
|
||||
bitstruct Foo : char[10]
|
||||
{
|
||||
int a : 10..15;
|
||||
}
|
||||
|
||||
struct NewData {
|
||||
char a;
|
||||
ushort ab;
|
||||
}
|
||||
|
||||
fn void test_inc()
|
||||
{
|
||||
NewData newdata;
|
||||
newdata.a = 0x55;
|
||||
newdata.ab = 0xAABB;
|
||||
NewData newdata2 = newdata;
|
||||
|
||||
newdata.a += 1;
|
||||
newdata.ab += 1;
|
||||
newdata2.a++;
|
||||
newdata2.ab++;
|
||||
assert(newdata.a == newdata2.a, "Structs: Expected %x, found %x", newdata.a, newdata2.a);
|
||||
assert(newdata.ab == newdata2.ab, "Structs: Expected %x, found %x", newdata.ab, newdata2.ab);
|
||||
|
||||
Data data;
|
||||
data.a = 0x55;
|
||||
data.ab = 0xAABB;
|
||||
Data data2 = data;
|
||||
|
||||
data.a += 1;
|
||||
data.ab += 1;
|
||||
data2.a++;
|
||||
data2.ab++;
|
||||
assert(data.a == data2.a, "BitStructs: Expected %x, found %x", data.a, data2.a);
|
||||
assert(data.ab == data2.ab, "BitStructs: Expected %x, found %x", data.ab, data2.ab);
|
||||
|
||||
data.a -= 1;
|
||||
data.ab -= 1;
|
||||
data2.a--;
|
||||
data2.ab--;
|
||||
assert(data.a == data2.a, "BitStructs: Expected %x, found %x", data.a, data2.a);
|
||||
assert(data.ab == data2.ab, "BitStructs: Expected %x, found %x", data.ab, data2.ab);
|
||||
|
||||
char a = data.a;
|
||||
assert(a == data.a++);
|
||||
assert(a != data.a);
|
||||
assert(a == --data.a);
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn void test_inc_array()
|
||||
{
|
||||
Foo x;
|
||||
x.a = 10;
|
||||
assert(x.a == 10);
|
||||
assert(x.a++ == 10);
|
||||
assert(x.a == 11, "Value was %d", x.a);
|
||||
assert(--x.a == 10);
|
||||
}
|
||||
|
||||
bitstruct Flags : int
|
||||
{
|
||||
bool flag1;
|
||||
bool flag2;
|
||||
}
|
||||
|
||||
fn void negate()
|
||||
{
|
||||
Flags flags;
|
||||
flags = ~flags;
|
||||
assert(~0 == (int)flags);
|
||||
flags = ~(Flags){};
|
||||
assert(3 == (int)flags);
|
||||
const Flags FLAGS = {.flag1 };
|
||||
flags = ~FLAGS;
|
||||
assert(2 == (int)flags);
|
||||
}
|
||||
17
test/unit7/regression/cast_slice_to_arr.c3
Normal file
17
test/unit7/regression/cast_slice_to_arr.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
module slice_to_arr @test;
|
||||
|
||||
fn void to_arr()
|
||||
{
|
||||
int[] x = { 1, 2, 3, 4, 5 };
|
||||
int z = 2;
|
||||
int[2] y = x[z:2];
|
||||
assert(y == {3, 4});
|
||||
}
|
||||
|
||||
fn void to_vec()
|
||||
{
|
||||
int[] x = { 1, 2, 3, 4, 5 };
|
||||
int z = 2;
|
||||
int[<2>] y = x[z:2];
|
||||
assert(y == { 3, 4 });
|
||||
}
|
||||
24
test/unit7/regression/castable_assignable.c3
Normal file
24
test/unit7/regression/castable_assignable.c3
Normal file
@@ -0,0 +1,24 @@
|
||||
module castable @test;
|
||||
|
||||
fn void assignable()
|
||||
{
|
||||
assert($assignable(12.0, int) == false);
|
||||
assert($assignable(12, int));
|
||||
assert(!$assignable("12", int));
|
||||
assert($assignable("12", String));
|
||||
assert($assignable("12", char*));
|
||||
assert($assignable("12", char[?]));
|
||||
assert($assignable("12", char[2]));
|
||||
assert($assignable("12", char[3]));
|
||||
}
|
||||
|
||||
fn void castable()
|
||||
{
|
||||
assert($defined((int)12.0));
|
||||
assert($defined((int)12));
|
||||
assert(!$defined((int)"12"));
|
||||
assert($defined((String)"12"));
|
||||
assert($defined((char*)"12"));
|
||||
assert($defined((char[2])"12"));
|
||||
assert($defined((char[3])"12"));
|
||||
}
|
||||
21
test/unit7/regression/catch_err.c3
Normal file
21
test/unit7/regression/catch_err.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module catch_err @test;
|
||||
|
||||
fn void test()
|
||||
{
|
||||
anyfault a;
|
||||
int! z = fn int!(anyfault* a) {
|
||||
const ABC = 4;
|
||||
int! x = SearchResult.MISSING?;
|
||||
defer (catch err) *a = err;
|
||||
return x;
|
||||
}(&a);
|
||||
assert(a == SearchResult.MISSING);
|
||||
anyfault y;
|
||||
z = fn int!(anyfault* y) {
|
||||
const ABC = 4;
|
||||
int! x = 1;
|
||||
defer (catch err) *y = err;
|
||||
return x;
|
||||
}(&y);
|
||||
assert(!y);
|
||||
}
|
||||
15
test/unit7/regression/copysign.c3
Normal file
15
test/unit7/regression/copysign.c3
Normal file
@@ -0,0 +1,15 @@
|
||||
module copysign @test;
|
||||
import std::math;
|
||||
fn void copysign_float()
|
||||
{
|
||||
float a = 3;
|
||||
float b = -4;
|
||||
float c = math::copysign(a, b);
|
||||
assert(c == -3);
|
||||
float d = math::copysign(a, 3);
|
||||
assert(d == 3);
|
||||
assert(math::copysign(a, -3) == -3);
|
||||
float e = math::copysign(3, a);
|
||||
assert(e == 3);
|
||||
assert(math::copysign(3, b) == -3);
|
||||
}
|
||||
38
test/unit7/regression/ct_slice.c3
Normal file
38
test/unit7/regression/ct_slice.c3
Normal file
@@ -0,0 +1,38 @@
|
||||
module ct_slice @test;
|
||||
|
||||
fn void slice_bytes()
|
||||
{
|
||||
char[4] $a = x'aabbccdd';
|
||||
var $b = $a[1..2];
|
||||
char[2] y = $b;
|
||||
assert($b == (char[]){187, 204});
|
||||
assert(y == {187, 204 });
|
||||
}
|
||||
|
||||
fn void slice_string()
|
||||
{
|
||||
String $a = "abcd";
|
||||
test::eq($a, "abcd");
|
||||
var $c = $a[1:0];
|
||||
String c = $c;
|
||||
assert($c == "");
|
||||
assert(c == "");
|
||||
var $d = $a[1:2];
|
||||
String d = $d;
|
||||
assert($d == "bc");
|
||||
assert(d == "bc");
|
||||
assert($a[..] == "abcd");
|
||||
}
|
||||
|
||||
fn void slice_untyped()
|
||||
{
|
||||
var $v = { 1, "hello", 3 };
|
||||
int[1] v = $v[0:1];
|
||||
assert(v == { 1 });
|
||||
int[1] v2 = $v[2:1];
|
||||
assert(v2 == { 3 });
|
||||
String[1] v3 = $v[1:1];
|
||||
assert(v3 == { "hello" });
|
||||
int[] v4 = $v[0:1];
|
||||
assert(v4 == { 1 });
|
||||
}
|
||||
49
test/unit7/regression/distinct_inline.c3
Normal file
49
test/unit7/regression/distinct_inline.c3
Normal file
@@ -0,0 +1,49 @@
|
||||
module distinct_inline @test;
|
||||
|
||||
distinct Foo = inline int;
|
||||
distinct Bar = inline Foo;
|
||||
distinct Baz = inline Foo;
|
||||
distinct Abc = inline Baz;
|
||||
distinct Def = inline Abc;
|
||||
distinct Other = inline int;
|
||||
distinct Other2 = inline Other;
|
||||
fn void test_binary()
|
||||
{
|
||||
assert($typeof((Foo)1 + 1).typeid == Foo.typeid);
|
||||
assert($typeof((Foo)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Baz)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Def)1 + (Bar)1).typeid == Foo.typeid);
|
||||
assert($typeof((Other2)1 + (Def)1).typeid == int.typeid);
|
||||
}
|
||||
|
||||
distinct DistinctInt = inline int;
|
||||
distinct DistinctUInt = inline uint;
|
||||
|
||||
fn void test_comparison()
|
||||
{
|
||||
char v_char;
|
||||
ichar v_ichar;
|
||||
short v_short;
|
||||
short v_ushort;
|
||||
int v_int;
|
||||
uint v_uint;
|
||||
long v_long;
|
||||
ulong v_ulong;
|
||||
assert((DistinctInt)0 == v_ichar);
|
||||
assert((DistinctInt)0 == v_char);
|
||||
assert((DistinctInt)0 == v_short);
|
||||
assert((DistinctInt)0 == v_ushort);
|
||||
assert((DistinctInt)0 == v_int);
|
||||
assert((DistinctInt)0 == v_uint);
|
||||
assert((DistinctInt)0 == v_long);
|
||||
assert((DistinctInt)0 == v_ulong);
|
||||
|
||||
assert((DistinctUInt)0 == v_ichar);
|
||||
assert((DistinctUInt)0 == v_char);
|
||||
assert((DistinctUInt)0 == v_short);
|
||||
assert((DistinctUInt)0 == v_ushort);
|
||||
assert((DistinctUInt)0 == v_int);
|
||||
assert((DistinctUInt)0 == v_uint);
|
||||
assert((DistinctUInt)0 == v_long);
|
||||
assert((DistinctUInt)0 == v_ulong);
|
||||
}
|
||||
21
test/unit7/regression/faults.c3
Normal file
21
test/unit7/regression/faults.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module faults @test;
|
||||
|
||||
fault Foo
|
||||
{
|
||||
ABC,
|
||||
CDE
|
||||
}
|
||||
|
||||
fn void ordinals()
|
||||
{
|
||||
Foo z = {};
|
||||
assert(z.ordinal == 0);
|
||||
$assert Foo.ABC.ordinal == 1;
|
||||
$assert Foo.CDE.ordinal == 2;
|
||||
$assert (Foo){}.ordinal == 0;
|
||||
Foo x = Foo.CDE;
|
||||
assert(x.ordinal == 2);
|
||||
x = Foo.ABC;
|
||||
assert(x.ordinal == 1);
|
||||
}
|
||||
|
||||
22
test/unit7/regression/file_line_func_module_builtins.c3
Normal file
22
test/unit7/regression/file_line_func_module_builtins.c3
Normal file
@@ -0,0 +1,22 @@
|
||||
module test::module_a;
|
||||
import std::io;
|
||||
|
||||
macro line() => $$LINE;
|
||||
macro func() => $$FUNC;
|
||||
macro mod() => $$MODULE;
|
||||
|
||||
macro line_indirect() => line();
|
||||
macro func_indirect() => func();
|
||||
macro mod_indirect() => mod();
|
||||
|
||||
module test @test;
|
||||
|
||||
fn void test_builtins()
|
||||
{
|
||||
assert(module_a::line() == module_a::line_indirect());
|
||||
assert(module_a::line() == $$LINE);
|
||||
assert(module_a::func() == module_a::func_indirect());
|
||||
assert(module_a::func() == $$FUNC);
|
||||
assert(module_a::mod() == module_a::mod_indirect());
|
||||
assert(module_a::mod() == $$MODULE);
|
||||
}
|
||||
16
test/unit7/regression/gather_scatter.c3
Normal file
16
test/unit7/regression/gather_scatter.c3
Normal file
@@ -0,0 +1,16 @@
|
||||
module gather_scatter;
|
||||
|
||||
fn void test_simple() @test
|
||||
{
|
||||
int[5] a = { 1, 2, 3, 4, 5 };
|
||||
void*[<2>] x = { &a[0], &a[4] };
|
||||
int*[<2>] y = x;
|
||||
int[<2>] result = mem::@gather_aligned(y, (bool[<2>]) { true, false }, (int[<2>]){ 10, 20 }, 4);
|
||||
assert(result == { 1, 20});
|
||||
result = mem::gather(y, (bool[<2>]) { true, false }, (int[<2>]){ 10, 20 });
|
||||
assert(result == { 1, 20});
|
||||
mem::@scatter_aligned(y, (int[<2>]){ 66, 77 }, (bool[<2>]) { false, true } , 4);
|
||||
assert(a == (int[5]){ 1, 2, 3, 4, 77});
|
||||
mem::scatter(y, (int[<2>]){ 88, 99 }, (bool[<2>]) { true, false });
|
||||
assert(a == (int[5]){ 88, 2, 3, 4, 77});
|
||||
}
|
||||
34
test/unit7/regression/inc_dec.c3
Normal file
34
test/unit7/regression/inc_dec.c3
Normal file
@@ -0,0 +1,34 @@
|
||||
fn void vector_inc_dec() @test
|
||||
{
|
||||
int[<3>] x;
|
||||
int[<3>] y;
|
||||
int z = ++x[0];
|
||||
int zz = y[0]++;
|
||||
x[1]++;
|
||||
++y[2];
|
||||
int[<3>] g = x--;
|
||||
assert(x == { 0, 0, -1 });
|
||||
assert(y == { 1, 0, 1 });
|
||||
assert(z == 0 && zz == 1);
|
||||
assert(g == { 1, 1, 0 });
|
||||
}
|
||||
|
||||
fn void int_inc_dec() @test
|
||||
{
|
||||
int x;
|
||||
assert(x++ == 0);
|
||||
assert(x == 1);
|
||||
assert(++x == 2);
|
||||
assert(x-- == 2);
|
||||
assert(--x == 0);
|
||||
}
|
||||
|
||||
fn void float_inc_dec() @test
|
||||
{
|
||||
double x;
|
||||
assert(x++ == 0);
|
||||
assert(x == 1.0);
|
||||
assert(++x == 2.0);
|
||||
assert(x-- == 2.0);
|
||||
assert(--x == 0);
|
||||
}
|
||||
21
test/unit7/regression/int128.c3
Normal file
21
test/unit7/regression/int128.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module int128_test;
|
||||
|
||||
fn void check(uint128 a, uint128 b)
|
||||
{
|
||||
uint128 div = a / b;
|
||||
uint128 mod = a % b;
|
||||
assert(div * b + mod == a);
|
||||
}
|
||||
|
||||
fn void test_big() @test
|
||||
{
|
||||
uint128 a = 12345678901234567890012u128;
|
||||
uint128 b = 1234567890123456789001u128;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
check(a + i, b + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
test/unit7/regression/int_min.c3
Normal file
9
test/unit7/regression/int_min.c3
Normal file
@@ -0,0 +1,9 @@
|
||||
fn void int_min() @test
|
||||
{
|
||||
assert(int.min == -2147483648);
|
||||
assert((float)int.min == -2147483648.0f);
|
||||
assert(short.min == -32768);
|
||||
assert((float)short.min == -32768.0f);
|
||||
assert(ichar.min == -128);
|
||||
assert((float)ichar.min == -128.0f);
|
||||
}
|
||||
22
test/unit7/regression/liveness_any.c3
Normal file
22
test/unit7/regression/liveness_any.c3
Normal file
@@ -0,0 +1,22 @@
|
||||
module liveness;
|
||||
|
||||
interface TestProto
|
||||
{
|
||||
fn void tesT();
|
||||
}
|
||||
|
||||
fn void Test.tesT(&self) @dynamic
|
||||
{}
|
||||
|
||||
struct Test (TestProto)
|
||||
{
|
||||
void* abc;
|
||||
}
|
||||
|
||||
fn void reflect_test() @test
|
||||
{
|
||||
TestProto b = mem::alloc(Test);
|
||||
b.tesT();
|
||||
defer free(b);
|
||||
|
||||
}
|
||||
21
test/unit7/regression/lvalue_handling.c3
Normal file
21
test/unit7/regression/lvalue_handling.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module lvalue_handling;
|
||||
import std;
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
}
|
||||
def IntList = List{Foo};
|
||||
fn void subscript_overload() @test
|
||||
{
|
||||
IntList x;
|
||||
defer x.free();
|
||||
|
||||
x.push({ 3 });
|
||||
int* a = &x[0].a;
|
||||
assert(*a == 3);
|
||||
assert(x[0].a == 3);
|
||||
*a = 4;
|
||||
assert(x[0].a == 4);
|
||||
x[0].a = 5;
|
||||
assert(x[0].a == 5);
|
||||
}
|
||||
28
test/unit7/regression/masked_load_store.c3
Normal file
28
test/unit7/regression/masked_load_store.c3
Normal file
@@ -0,0 +1,28 @@
|
||||
import std;
|
||||
fn void masked_load() @test
|
||||
{
|
||||
long[<4>] val = { 1, 3, 5, 8 };
|
||||
long[<4>] res = mem::masked_load(&val, { true, false, true, false }, (long[<4>]){ 100, 200, 300, 400 });
|
||||
assert(res == { 1, 200, 5, 400 });
|
||||
}
|
||||
|
||||
fn void masked_load_aligned() @test
|
||||
{
|
||||
long[<4>] val = { 1, 3, 5, 8 };
|
||||
long[<4>] res = mem::@masked_load_aligned(&val, { true, false, true, false }, (long[<4>]) { 100, 200, 300, 400 }, 8);
|
||||
assert(res == { 1, 200, 5, 400 });
|
||||
}
|
||||
|
||||
fn void masked_store() @test
|
||||
{
|
||||
long[<4>] val = { 1, 3, 5, 8 };
|
||||
mem::masked_store(&val, (long[<4>]){11, 22, 33, 44}, { true, false, false, true });
|
||||
assert(val == { 11, 3, 5, 44 });
|
||||
}
|
||||
|
||||
fn void masked_store_aligned() @test
|
||||
{
|
||||
long[<4>] val = { 1, 3, 5, 8 };
|
||||
mem::@masked_store_aligned(&val, (long[<4>]){11, 22, 33, 44}, { true, false, false, true }, 8);
|
||||
assert(val == { 11, 3, 5, 44 });
|
||||
}
|
||||
80
test/unit7/regression/methodsof.c3
Normal file
80
test/unit7/regression/methodsof.c3
Normal file
@@ -0,0 +1,80 @@
|
||||
module methodsof;
|
||||
|
||||
interface IBar
|
||||
{
|
||||
fn void fnA();
|
||||
fn void fnB();
|
||||
}
|
||||
struct Bar (IBar)
|
||||
{
|
||||
int a;
|
||||
}
|
||||
fn void Bar.fnB(&self) @dynamic {}
|
||||
fn void Bar.fnA(&self) @dynamic {}
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int i;
|
||||
bool b;
|
||||
}
|
||||
|
||||
fn void Foo.foo(&self) {}
|
||||
fn int Foo.bar(&self, int x) { return x * self.i; }
|
||||
fn bool Foo.xyz(&self) { return self.b; }
|
||||
|
||||
struct NoMethods
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
bitstruct BazBits : char
|
||||
{
|
||||
int a : 0..2;
|
||||
int b : 4..6;
|
||||
bool c : 7;
|
||||
}
|
||||
|
||||
fn void BazBits.fn1(&self) {}
|
||||
fn void BazBits.fn2(&self) {}
|
||||
|
||||
union AUnion {
|
||||
int y;
|
||||
double z;
|
||||
}
|
||||
|
||||
fn void AUnion.a(&self) {}
|
||||
fn void AUnion.b(&self) {}
|
||||
|
||||
|
||||
module methodsof @test;
|
||||
|
||||
import std::io;
|
||||
|
||||
fn void methodsof()
|
||||
{
|
||||
assert(Foo.methodsof.len == 3);
|
||||
assert(Bar.methodsof.len == 2);
|
||||
assert(NoMethods.methodsof.len == 0);
|
||||
|
||||
assert(Foo.methodsof[0] == "foo");
|
||||
assert(Foo.methodsof[1] == "bar");
|
||||
assert(Foo.methodsof[2] == "xyz");
|
||||
assert(Bar.methodsof[0] == "fnB");
|
||||
assert(Bar.methodsof[1] == "fnA");
|
||||
|
||||
assert(BazBits.methodsof[0] == "fn1");
|
||||
assert(BazBits.methodsof[1] == "fn2");
|
||||
|
||||
assert(AUnion.methodsof[0] == "a");
|
||||
assert(AUnion.methodsof[1] == "b");
|
||||
|
||||
Foo foo = { .i = 4, .b = true };
|
||||
assert(Foo.$eval(Foo.methodsof[2])(&foo) == true); // Foo.xyz
|
||||
assert(Foo.$eval(Foo.methodsof[1])(&foo, 2) == 8); // Foo.bar
|
||||
assert(Foo.$eval(Foo.methodsof[2])(&foo) == true); // Foo.xyz
|
||||
assert(Foo.$eval(Foo.methodsof[1])(&foo, 2) == 8); // Foo.bar
|
||||
|
||||
Foo foo2 = { .i = 2, .b = false };
|
||||
assert(foo2.$eval(Foo.methodsof[2])() == false); // Foo.xyz
|
||||
assert(foo2.$eval(Foo.methodsof[1])(10) == 20); // Foo.bar
|
||||
}
|
||||
20
test/unit7/regression/pointer_diff.c3
Normal file
20
test/unit7/regression/pointer_diff.c3
Normal file
@@ -0,0 +1,20 @@
|
||||
import std;
|
||||
struct Foo
|
||||
{
|
||||
int a,b,c,d;
|
||||
}
|
||||
|
||||
fn void pointer_diff() @test
|
||||
{
|
||||
Foo* foo;
|
||||
isz offset = &foo[1] - &foo[0];
|
||||
assert(offset == 1);
|
||||
}
|
||||
|
||||
fn void pointer_add() @test
|
||||
{
|
||||
Foo* foo;
|
||||
Foo* bar = foo + 2;
|
||||
isz offset = bar - foo;
|
||||
assert(offset == 2);
|
||||
}
|
||||
19
test/unit7/regression/pointer_non_decay.c3
Normal file
19
test/unit7/regression/pointer_non_decay.c3
Normal file
@@ -0,0 +1,19 @@
|
||||
module test @test;
|
||||
|
||||
fn void pointer_non_decay()
|
||||
{
|
||||
int[6] x;
|
||||
int[3]* y = (int[3]*)&x;
|
||||
int* z = y;
|
||||
int[] sub = y;
|
||||
int[3] y1 = y[1];
|
||||
int z1 = z[1];
|
||||
int* xx = y + 1;
|
||||
int[3]* yy = (int[3]*)(xx);
|
||||
int* zz = yy - 1;
|
||||
assert(y == z);
|
||||
assert(z == zz);
|
||||
assert(&(*y)[1] == &xx[-2]);
|
||||
x[1] = 123;
|
||||
assert(x[1] == z[1]);
|
||||
}
|
||||
10
test/unit7/regression/select.c3
Normal file
10
test/unit7/regression/select.c3
Normal file
@@ -0,0 +1,10 @@
|
||||
import std;
|
||||
fn long[<4>] process(long[<4>] a, long[<4>] b) @noinline
|
||||
{
|
||||
return math::select({ true, true, false, true }, a, b);
|
||||
}
|
||||
fn void test_select() @test
|
||||
{
|
||||
long[<4>] res = process({ 4, 5, 6, 7 }, { 100, 200, 300, 400 });
|
||||
assert(res == { 4, 5, 300, 7});
|
||||
}
|
||||
157
test/unit7/regression/signed_unsigned_compare.c3
Normal file
157
test/unit7/regression/signed_unsigned_compare.c3
Normal file
@@ -0,0 +1,157 @@
|
||||
module signed_unsigned_comparisons @test;
|
||||
|
||||
fn void test_signed()
|
||||
{
|
||||
int a = 0;
|
||||
int b = 1;
|
||||
|
||||
bool ab_gt = a > b;
|
||||
bool ab_ge = a >= b;
|
||||
bool ab_le = a <= b;
|
||||
bool ab_lt = a < b;
|
||||
bool ab_ne = a != b;
|
||||
bool ab_eq = a == b;
|
||||
|
||||
}
|
||||
|
||||
fn void test_unsigned()
|
||||
{
|
||||
uint a = 0;
|
||||
uint b = 1;
|
||||
|
||||
bool ab_gt = a > b;
|
||||
bool ab_ge = a >= b;
|
||||
bool ab_le = a <= b;
|
||||
bool ab_lt = a < b;
|
||||
bool ab_ne = a != b;
|
||||
bool ab_eq = a == b;
|
||||
|
||||
}
|
||||
|
||||
fn void test_signedunsigned()
|
||||
{
|
||||
ichar a = 0 - 1;
|
||||
char b = (char)(a);
|
||||
|
||||
assert(!(a > b));
|
||||
assert(!(a >= b));
|
||||
assert(a < b);
|
||||
assert(a <= b);
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 1;
|
||||
b = 1;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(a <= b);
|
||||
assert(!(a != b));
|
||||
assert(a == b);
|
||||
|
||||
a = 1;
|
||||
b = 4;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(!(a >= b));
|
||||
assert(a < b);
|
||||
assert(a <= b);
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 4;
|
||||
b = 1;
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(!(a <= b));
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 4;
|
||||
b = 129;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(!(a >= b));
|
||||
assert(a < b);
|
||||
assert(a <= b);
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 0 - 4;
|
||||
b = 129;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(!(a >= b));
|
||||
assert(a < b);
|
||||
assert(a <= b);
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
}
|
||||
|
||||
fn void test_unsignedsigned()
|
||||
{
|
||||
int b = -1;
|
||||
uint a = (uint)(b);
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(!(a <= b));
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 1;
|
||||
b = 1;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(a <= b);
|
||||
assert(!(a != b));
|
||||
assert(a == b);
|
||||
|
||||
a = 4;
|
||||
b = 1;
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(!(a <= b));
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 1;
|
||||
b = 4;
|
||||
|
||||
assert(!(a > b));
|
||||
assert(!(a >= b));
|
||||
assert(a < b);
|
||||
assert(a <= b);
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
a = 0x8000_0001;
|
||||
b = 4;
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(!(a <= b));
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
b = 0 - 4;
|
||||
a = 0x8000_0001;
|
||||
|
||||
assert(a > b);
|
||||
assert(a >= b);
|
||||
assert(!(a < b));
|
||||
assert(!(a <= b));
|
||||
assert(a != b);
|
||||
assert(!(a == b));
|
||||
|
||||
}
|
||||
9
test/unit7/regression/slice_assign.c3
Normal file
9
test/unit7/regression/slice_assign.c3
Normal file
@@ -0,0 +1,9 @@
|
||||
module slice_assign @test;
|
||||
|
||||
fn void assign_slice()
|
||||
{
|
||||
int[8] a;
|
||||
a[2..3] = { 1, 2 };
|
||||
a[5..7] = 5;
|
||||
assert(a == (int[8]){ 0, 0, 1, 2, 0, 5, 5, 5});
|
||||
}
|
||||
18
test/unit7/regression/struct_alignment.c3
Normal file
18
test/unit7/regression/struct_alignment.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
module struct_alignment @test;
|
||||
|
||||
struct Test @align(16) { void* foo; }
|
||||
|
||||
struct Test2
|
||||
{
|
||||
Test test;
|
||||
uint a;
|
||||
}
|
||||
|
||||
fn void nested_struct()
|
||||
{
|
||||
Test2* array;
|
||||
assert((uptr)&array[1] - (uptr)array == 32);
|
||||
assert((uptr)&array[1] - (uptr)array == Test2.sizeof);
|
||||
assert(Test2.sizeof == 32);
|
||||
assert(Test.sizeof == 16);
|
||||
}
|
||||
15
test/unit7/regression/subscripting.c3
Normal file
15
test/unit7/regression/subscripting.c3
Normal file
@@ -0,0 +1,15 @@
|
||||
module subscripting_tests @test;
|
||||
|
||||
fn void subscript_ct()
|
||||
{
|
||||
$if int.nameof[0] == 'i':
|
||||
assert(true);
|
||||
$else
|
||||
assert(false);
|
||||
$endif
|
||||
$if int.nameof[^1] == 't':
|
||||
assert(true);
|
||||
$else
|
||||
assert(false);
|
||||
$endif
|
||||
}
|
||||
91
test/unit7/regression/subtype.c3
Normal file
91
test/unit7/regression/subtype.c3
Normal file
@@ -0,0 +1,91 @@
|
||||
module switch_subtype @test;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
inline Baz g;
|
||||
int a;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
inline Foo f;
|
||||
}
|
||||
struct Baz
|
||||
{
|
||||
int z;
|
||||
}
|
||||
fn void switch_subtyping()
|
||||
{
|
||||
Foo f = {};
|
||||
f.z = 123;
|
||||
any x = &f;
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Baz:
|
||||
assert(true);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Foo:
|
||||
assert(true);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (x)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(true);
|
||||
}
|
||||
switch (Bar.typeid)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Baz:
|
||||
assert(true);
|
||||
case Foo:
|
||||
assert(false);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (Bar.typeid)
|
||||
{
|
||||
case int:
|
||||
assert(false);
|
||||
case Foo:
|
||||
assert(true);
|
||||
case Bar:
|
||||
assert(false);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
$switch (Bar.typeid)
|
||||
$case Foo:
|
||||
assert(true);
|
||||
$case Bar:
|
||||
assert(false);
|
||||
$default:
|
||||
assert(false);
|
||||
$endswitch
|
||||
}
|
||||
|
||||
fn void is_subtype()
|
||||
{
|
||||
$assert(types::is_subtype_of(Bar, Baz));
|
||||
$assert(!types::is_subtype_of(Baz, Bar));
|
||||
typeid baz = Baz.typeid;
|
||||
typeid bar = Bar.typeid;
|
||||
assert(bar.is_subtype_of(baz));
|
||||
assert(!bar.is_subtype_of(double.typeid));
|
||||
assert(!baz.is_subtype_of(bar));
|
||||
}
|
||||
18
test/unit7/regression/swizzle.c3
Normal file
18
test/unit7/regression/swizzle.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
module swizzletest @test;
|
||||
|
||||
fn void test_swizzle()
|
||||
{
|
||||
int[<4>] a = { 1, 2, 3, 4 };
|
||||
int[<4>] b = { 100, 1000, 10000, 100000 };
|
||||
assert($$swizzle(a, 0, 1, 1, 3) == (int[<4>]) { 1, 2, 2, 4 });
|
||||
assert($$swizzle2(a, b, 0, 1, 4, 6, 2) == (int[<5>]) { 1, 2, 100, 10000, 3 });
|
||||
}
|
||||
|
||||
fn void swizzle_builtin()
|
||||
{
|
||||
int[<4>] abc = { 1, 2, 3, 4 };
|
||||
assert(abc.rb == { 1, 3 });
|
||||
assert(abc.xxww == { 1, 1, 4, 4 });
|
||||
abc = abc.abgr;
|
||||
assert(abc == { 4, 3, 2, 1 });
|
||||
}
|
||||
11
test/unit7/regression/ternary.c3
Normal file
11
test/unit7/regression/ternary.c3
Normal file
@@ -0,0 +1,11 @@
|
||||
module test @test;
|
||||
|
||||
fn void const_ternary()
|
||||
{
|
||||
int foo = 1;
|
||||
const int FOO = 1;
|
||||
assert((foo ?: 2) == 1);
|
||||
assert((FOO ?: 2) == 1);
|
||||
int bar = 2;
|
||||
assert((FOO ?: bar) == 1);
|
||||
}
|
||||
19
test/unit7/regression/unwrapping.c3
Normal file
19
test/unit7/regression/unwrapping.c3
Normal file
@@ -0,0 +1,19 @@
|
||||
module unwrapping;
|
||||
|
||||
fn bool! get_bool()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
fn void bool_chain_unwrap() @test
|
||||
{
|
||||
bool b;
|
||||
if (try v = get_bool() && b)
|
||||
{
|
||||
assert(v == true);
|
||||
}
|
||||
if (try v = get_bool() && v)
|
||||
{
|
||||
assert(v == true);
|
||||
}
|
||||
}
|
||||
35
test/unit7/regression/vecpointer.c3
Normal file
35
test/unit7/regression/vecpointer.c3
Normal file
@@ -0,0 +1,35 @@
|
||||
module vecpointer @test;
|
||||
|
||||
fn void pointer_npot2_size()
|
||||
{
|
||||
int[<9>][3] a;
|
||||
assert((usz)&a[1] - (usz)&a[0] == 64);
|
||||
}
|
||||
|
||||
fn void pointer_add_sub_diff()
|
||||
{
|
||||
int[5] a;
|
||||
void*[<2>] x = { &a[0], &a[4] };
|
||||
int*[<2>] y = x;
|
||||
assert(x[0] == y[0] && x[1] == y[1]);
|
||||
int*[2] y2;
|
||||
y2 = y;
|
||||
assert(y2[0] == x[0] && y2[1] == x[1]);
|
||||
y = { null, null };
|
||||
assert(y[0] == null && y[0] == null);
|
||||
y = y2;
|
||||
assert(x[0] == y[0] && x[1] == y[1]);
|
||||
int[<2>] z = { 1, -1 };
|
||||
y = y + z;
|
||||
assert(y[0] == &a[1] && y[1] == &a[3]);
|
||||
y = y - z;
|
||||
assert(y[0] == &a[0] && y[1] == &a[4]);
|
||||
int*[<2>] yy = { &a[1], &a[2] };
|
||||
isz[<2>] w;
|
||||
w = y - yy;
|
||||
assert(w == { -1, 2 });
|
||||
int*[<2>] zz = y - (y - yy);
|
||||
assert(zz[0] == &a[1] && zz[1] == &a[2]);
|
||||
int[?]*[<2>] g = (int[2]*[<2>]) { null, null };
|
||||
int[?]*[<?>] g2 = (int[2]*[<2>]) { null, null };
|
||||
}
|
||||
31
test/unit7/regression/vector_conversion.c3
Normal file
31
test/unit7/regression/vector_conversion.c3
Normal file
@@ -0,0 +1,31 @@
|
||||
module test @test;
|
||||
|
||||
fn void vector_array_inferred()
|
||||
{
|
||||
int[<2>] x = { 4, 7 };
|
||||
int[2] y = x;
|
||||
int[?] y1 = y;
|
||||
int[?] y2 = x;
|
||||
int[<?>] z = x;
|
||||
int[<?>] w = y;
|
||||
double[<2>] ww = x;
|
||||
assert((int[<2>])y == { 4, 7});
|
||||
assert((int[<2>])y1 == { 4, 7 });
|
||||
assert((int[<2>])y2 == { 4, 7 });
|
||||
assert(z == { 4, 7 });
|
||||
assert(w == { 4, 7 });
|
||||
}
|
||||
|
||||
fn void vector_convert_slice()
|
||||
{
|
||||
int[<2>] x = { 1, 2 };
|
||||
int[2] y = { 4, 4 };
|
||||
x *= y[:2];
|
||||
assert(x == { 4, 8 });
|
||||
}
|
||||
fn void vector_convert_bool()
|
||||
{
|
||||
bool[<2>] a = { true, false };
|
||||
assert({ -1, 0 } == (int[<2>])a);
|
||||
assert({ 1.0, 0 } == (float[<2>])a);
|
||||
}
|
||||
18
test/unit7/regression/vector_method_reduce.c3
Normal file
18
test/unit7/regression/vector_method_reduce.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
import std::math;
|
||||
|
||||
fn void vector_method_reduce() @test
|
||||
{
|
||||
float[<3>] x = { 1, 2.0, 4.0 };
|
||||
int[<?>] y = { -23, 1, 4 };
|
||||
assert(y.sum() == -18);
|
||||
assert(y.product() == -92);
|
||||
assert(y.max() == 4);
|
||||
assert(y.and() == 0);
|
||||
assert(y.xor() == -20);
|
||||
assert(y.min() == -23);
|
||||
assert(y.or() == -19);
|
||||
assert(x.sum(1.2) - 8.2 < 0.000001);
|
||||
assert(x.product(1.2) - 9.6 < 0.000001);
|
||||
assert(x.min() == 1.0);
|
||||
assert(x.max() == 4.0);
|
||||
}
|
||||
114
test/unit7/regression/vector_ops.c3
Normal file
114
test/unit7/regression/vector_ops.c3
Normal file
@@ -0,0 +1,114 @@
|
||||
import std::io;
|
||||
|
||||
fn void test_int_mod() @test
|
||||
{
|
||||
int[<2>] y = { 10, 99 };
|
||||
int[<2>] z = { 3, 5 };
|
||||
assert(y % z == { 1, 4 });
|
||||
assert(y / z == { 3, 19 });
|
||||
assert((int[<2>]){ 10, 99 } % { 3, 5 } == { 1, 4 });
|
||||
assert((int[<2>]){ 10, 99 } / { 3, 5 } == { 3, 19 });
|
||||
}
|
||||
|
||||
fn void test_conv() @test
|
||||
{
|
||||
float[<4>] y = { 1, 2, 3, 4 };
|
||||
float[<4>] z = { 0, 2, 2, -100 };
|
||||
int[<4>] w = { -1, 2, 3, 4 };
|
||||
float[<4>] yy = w;
|
||||
assert(yy == { -1.0, 2.0, 3.0, 4.0 });
|
||||
ulong[<4>] ww = w;
|
||||
assert(ww == { (ulong)-1, 2, 3, 4 });
|
||||
int[<4>] g = (int[<4>])ww;
|
||||
assert(g == w);
|
||||
ww = (long[<4>])y;
|
||||
assert(ww == { 1, 2, 3, 4 });
|
||||
bool[<2>] b = { true, false };
|
||||
int[<2>] gh = b;
|
||||
assert(gh == { -1, 0 });
|
||||
var $k = (bool[<2>]){ true, false };
|
||||
var $gh = (int[<2>])$k;
|
||||
$assert $gh[0] == -1;
|
||||
var $gh2 = (char[<2>])$gh;
|
||||
$assert $gh2[0] == 255;
|
||||
b = (bool[<2>])gh;
|
||||
assert(b == { true, false });
|
||||
}
|
||||
|
||||
fn void testf() @test
|
||||
{
|
||||
float[<4>] x = { 4, 0, -1, 33 };
|
||||
assert({ true, false, true, true} == (bool[<4>])x);
|
||||
float[<4>] y = { 1, 2, 3, 4 };
|
||||
float[<4>] z = { 2, 2, 2, -100 };
|
||||
float[<4>] w = y + z;
|
||||
assert(w == { 3, 4, 5, -96 });
|
||||
w = y * z;
|
||||
assert(w == { 2, 4, 6, -400 });
|
||||
w = y / z;
|
||||
assert(w == { 0.5, 1.0, 1.5, -0.04 });
|
||||
w = y - z;
|
||||
assert(w == { -1, 0, 1, 104 });
|
||||
int[<4>] ww = $$veccomplt(y, z);
|
||||
assert(ww == { -1, 0, 0, 0 });
|
||||
ww = $$veccomple(y, z);
|
||||
assert(ww == { -1, -1, 0, 0 });
|
||||
ww = $$veccompgt(y, z);
|
||||
assert(ww == { 0, 0, -1, -1 });
|
||||
ww = $$veccompge(y, z);
|
||||
assert(ww == { 0, -1, -1, -1 });
|
||||
ww = $$veccompeq(y, z);
|
||||
assert(ww == { 0, -1, 0, 0 });
|
||||
ww = $$veccompne(y, z);
|
||||
assert(ww == { -1, 0, -1, -1 });
|
||||
}
|
||||
|
||||
fn void testb() @test
|
||||
{
|
||||
bool[<4>] y = { true, false, true, true };
|
||||
bool[<4>] z = { false, false, true, true };
|
||||
ichar[<4>] ww = $$veccomplt(y, z);
|
||||
assert(ww == { 0, 0, 0, 0 });
|
||||
ww = $$veccomple(y, z);
|
||||
assert(ww == { 0, -1, -1, -1 });
|
||||
ww = $$veccompgt(y, z);
|
||||
assert(ww == { -1, 0, 0, 0 });
|
||||
ww = $$veccompge(y, z);
|
||||
assert(ww == { -1, -1, -1, -1 });
|
||||
ww = $$veccompeq(y, z);
|
||||
assert(ww == { 0, -1, -1, -1 });
|
||||
ww = $$veccompne(y, z);
|
||||
assert(ww == { -1, 0, 0, 0 });
|
||||
}
|
||||
|
||||
fn void testi() @test
|
||||
{
|
||||
int[<4>] x = { 4, 0, -1, 33 };
|
||||
assert({ true, false, true, true} == (bool[<4>])x);
|
||||
int[<4>] y = { 1, 2, 3, 4 };
|
||||
int[<4>] z = { 2, 2, 2, -100 };
|
||||
int[<4>] w = y + z;
|
||||
assert(w == { 3, 4, 5, -96 });
|
||||
w = y * z;
|
||||
assert(w == { 2, 4, 6, -400 });
|
||||
w = y / z;
|
||||
assert(w == { 0, 1, 1, 0 });
|
||||
w = y - z;
|
||||
assert(w == { -1, 0, 1, 104 });
|
||||
w = z >> y;
|
||||
assert(w == { 1, 0, 0, -7});
|
||||
w = z << y;
|
||||
assert(w == { 4, 8, 16, -1600 });
|
||||
w = $$veccompgt(z, y);
|
||||
assert(w == { -1, 0, 0, 0});
|
||||
w = $$veccompge(z, y);
|
||||
assert(w == { -1, -1, 0, 0 });
|
||||
w = $$veccomplt(z, y);
|
||||
assert(w == { 0, 0, -1, -1 });
|
||||
w = $$veccomple(z, y);
|
||||
assert(w == { 0, -1, -1, -1 });
|
||||
w = $$veccompeq(z, y);
|
||||
assert(w == { 0, -1, 0, 0 });
|
||||
w = $$veccompne(z, y);
|
||||
assert(w == { -1, 0, -1, -1 });
|
||||
}
|
||||
245
test/unit7/stdlib/atomic.c3
Normal file
245
test/unit7/stdlib/atomic.c3
Normal file
@@ -0,0 +1,245 @@
|
||||
import std::thread;
|
||||
import std::io;
|
||||
import std::atomic;
|
||||
|
||||
uint a;
|
||||
float fa;
|
||||
|
||||
fn void add() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a = 0;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&a, 5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a == ts.len * 10 * 5, "Threads returned %d, expected %d", a, ts.len * 10 * 5);
|
||||
}
|
||||
|
||||
fn void sub() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a = ts.len * 10 * 5;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&a, 5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a == 0, "Threads returned %d, expected %d", a, 0);
|
||||
}
|
||||
|
||||
fn void div() @test
|
||||
{
|
||||
Thread[8] ts;
|
||||
a = 8 * 8 * 8 * 8 * 8 * 8 * 8 * 8 * 8;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_div(&a, 8);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a == 8, "Threads returned %d, expected %d", a, 8);
|
||||
}
|
||||
|
||||
fn void max() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a = 0;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
uint la = 0;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_max(&a, la);
|
||||
la++;
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a == 5, "Threads returned %d, expected %d", a, 5);
|
||||
}
|
||||
|
||||
fn void min() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a = 10;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
uint la = 5;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_min(&a, la);
|
||||
la--;
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a == 0, "Threads returned %d, expected %d", a, 0);
|
||||
}
|
||||
|
||||
fn void fadd() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
fa = 0;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_add(&fa, 0.5f);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(fa == ts.len * 10 * 0.5, "Threads returned %f, expected %f", fa, ts.len * 10 * 0.5);
|
||||
}
|
||||
|
||||
fn void fsub() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
fa = ts.len * 10 * 0.5;
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
thread::sleep_ms(5);
|
||||
atomic::fetch_sub(&fa, 0.5f);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(fa == 0, "Threads returned %f, expected %f", fa, 0);
|
||||
}
|
||||
156
test/unit7/stdlib/atomic_types.c3
Normal file
156
test/unit7/stdlib/atomic_types.c3
Normal file
@@ -0,0 +1,156 @@
|
||||
import std::thread;
|
||||
import std::io;
|
||||
import std::atomic::types;
|
||||
|
||||
def AtomicUint = Atomic{uint};
|
||||
def AtomicFloat = Atomic{float};
|
||||
AtomicUint a;
|
||||
AtomicFloat fa;
|
||||
|
||||
fn void add() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a.store(0);
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
thread::sleep_ms(5);
|
||||
a.add(5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a.load() == ts.len * 10 * 5, "Threads returned %d, expected %d", a.load(), ts.len * 10 * 5);
|
||||
}
|
||||
|
||||
fn void sub() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
a.store(ts.len * 10 * 5);
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
thread::sleep_ms(5);
|
||||
a.sub(5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(a.load() == 0, "Threads returned %d, expected %d", a.load(), 0);
|
||||
}
|
||||
|
||||
fn void fadd() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
fa.store(0);
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.add(0.5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(fa.load() == ts.len * 10 * 0.5, "Threads returned %f, expected %f", fa.load(), ts.len * 10 * 0.5);
|
||||
}
|
||||
|
||||
fn void fsub() @test
|
||||
{
|
||||
Thread[100] ts;
|
||||
fa.store(ts.len * 10 * 0.5);
|
||||
foreach (&t : ts)
|
||||
{
|
||||
t.create(fn int(void* arg) {
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
thread::sleep_ms(5);
|
||||
fa.sub(0.5);
|
||||
return 0;
|
||||
}, null)!!;
|
||||
}
|
||||
foreach (&t : ts)
|
||||
{
|
||||
assert(t.join()!! == 0);
|
||||
}
|
||||
assert(fa.load() == 0, "Threads returned %f, expected %f", fa.load(), 0);
|
||||
}
|
||||
89
test/unit7/stdlib/collections/bitset.c3
Normal file
89
test/unit7/stdlib/collections/bitset.c3
Normal file
@@ -0,0 +1,89 @@
|
||||
module bitset_test @test;
|
||||
import std::collections::bitset;
|
||||
import std::collections::growablebitset;
|
||||
import std::collections::list;
|
||||
import std::io;
|
||||
|
||||
def List = List{usz};
|
||||
|
||||
def BitSet = BitSet{2048};
|
||||
|
||||
fn void set_get()
|
||||
{
|
||||
BitSet bs;
|
||||
assert(bs.cardinality() == 0);
|
||||
|
||||
assert(!bs.get(0));
|
||||
bs.set(0);
|
||||
assert(bs.get(0));
|
||||
assert(bs.cardinality() == 1);
|
||||
|
||||
assert(!bs.get(2000));
|
||||
bs[2000] = true;
|
||||
assert(bs.get(2000));
|
||||
assert(bs.cardinality() == 2);
|
||||
|
||||
List found;
|
||||
foreach (i, x : bs)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 2000:
|
||||
assert(x);
|
||||
found.push(i);
|
||||
default:
|
||||
assert(!x);
|
||||
}
|
||||
}
|
||||
assert(found.array_view() == (usz[]){0, 2000});
|
||||
|
||||
bs.unset(0);
|
||||
assert(!bs.get(0));
|
||||
bs[2000] = false;
|
||||
assert(!bs.get(2000));
|
||||
assert(bs.cardinality() == 0);
|
||||
}
|
||||
|
||||
def GrowableBitSet = GrowableBitSet{char};
|
||||
fn void growable_set_get()
|
||||
{
|
||||
GrowableBitSet bs;
|
||||
bs.tinit();
|
||||
assert(bs.cardinality() == 0, "Invalid cardinality");
|
||||
|
||||
assert(!bs.get(0), "Get was true");
|
||||
bs.set(0);
|
||||
assert(bs.get(0), "Get should be true");
|
||||
assert(bs.cardinality() == 1, "Cardinality should be 1");
|
||||
assert(bs.len() == 1, "Len should be 1");
|
||||
|
||||
assert(!bs.get(2000), "Get 2000 should be false");
|
||||
bs[2000] = true;
|
||||
assert(bs.get(2000), "Get 2000 should be true");
|
||||
assert(bs.cardinality() == 2, "Cardinality should be 2");
|
||||
|
||||
assert(bs.data.len() == 251, "Len should be 251");
|
||||
assert(bs.len() == 2001, "Len should be 2001");
|
||||
|
||||
List found;
|
||||
foreach (i, x : bs)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 2000:
|
||||
assert(x);
|
||||
found.push(i);
|
||||
default:
|
||||
assert(!x, "Should not get here");
|
||||
}
|
||||
}
|
||||
assert(found.array_view() == (usz[]){0, 2000}, "Array view should hold 2");
|
||||
|
||||
bs.unset(0);
|
||||
assert(!bs.get(0), "Get should be false");
|
||||
bs[2000] = false;
|
||||
assert(!bs.get(2000), "Get should be false");
|
||||
assert(bs.cardinality() == 0, "Cardinality should be 0");
|
||||
}
|
||||
53
test/unit7/stdlib/collections/copy_map.c3
Normal file
53
test/unit7/stdlib/collections/copy_map.c3
Normal file
@@ -0,0 +1,53 @@
|
||||
module test;
|
||||
import std::io;
|
||||
import std::collections::map;
|
||||
|
||||
def IntMap = HashMap{String, int};
|
||||
fn void copy_map() @test
|
||||
{
|
||||
TrackingAllocator alloc;
|
||||
alloc.init(allocator::heap());
|
||||
defer alloc.free();
|
||||
assert(alloc.allocated() == 0);
|
||||
mem::@scoped(&alloc)
|
||||
{
|
||||
IntMap x;
|
||||
x.init(mem);
|
||||
DString y;
|
||||
y.append("hello");
|
||||
x.set(y.str_view(), 123);
|
||||
y.append("bye");
|
||||
x.set(y.str_view(), 333);
|
||||
y.clear();
|
||||
y.append("bye");
|
||||
x.set(y.str_view(), 444);
|
||||
assert(x.get("hello")!! == 123);
|
||||
assert(x.get("hellobye")!! == 333);
|
||||
assert(x.get("bye")!! == 444);
|
||||
assert(alloc.allocated() > 0);
|
||||
x.free();
|
||||
y.free();
|
||||
assert(alloc.allocated() == 0);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Some Keys (including Strings) are deep_copied into the hashmap on insertion.
|
||||
When copying keys out, the keys themselves must also be deep-copied out.
|
||||
Otherwise when the map is freed, the copied-in keys will also be freed,
|
||||
resulting in use-after-free.
|
||||
*/
|
||||
fn void copy_keys() @test
|
||||
{
|
||||
String[] y;
|
||||
@pool()
|
||||
{
|
||||
IntMap x;
|
||||
x.set("hello", 0); // keys copied into temp hashmap
|
||||
y = x.keys(mem); // keys copied out
|
||||
// end of pool: hashmap and its copied-in keys dropped
|
||||
};
|
||||
assert(y == {"hello"});
|
||||
foreach(key : y) free(key);
|
||||
free(y);
|
||||
}
|
||||
143
test/unit7/stdlib/collections/elastic_array.c3
Normal file
143
test/unit7/stdlib/collections/elastic_array.c3
Normal file
@@ -0,0 +1,143 @@
|
||||
module elastic_array_test @test;
|
||||
import std::collections::elastic_array;
|
||||
|
||||
def IntList = ElasticArray{int, 10};
|
||||
def PtrList = ElasticArray{void*, 10};
|
||||
|
||||
fn void delete_contains_index()
|
||||
{
|
||||
IntList test;
|
||||
test.add_array({ 1, 2 });
|
||||
assert(test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(!test.contains(0));
|
||||
assert(!test.contains(3));
|
||||
assert(test.array_view() == (int[]){ 1, 2 });
|
||||
test.push(3);
|
||||
assert(test.array_view() == (int[]){ 1, 2, 3 });
|
||||
assert(test.contains(3));
|
||||
test[0] = 10;
|
||||
assert(test.contains(10));
|
||||
test.remove_item(10);
|
||||
assert(test.array_view() == (int[]){ 2, 3 });
|
||||
assert(!test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(test.len() == 2);
|
||||
test.push(0);
|
||||
test.insert_at(0, 0);
|
||||
assert(test.array_view() == (int[]){ 0, 2, 3, 0 });
|
||||
assert(test.index_of(0)!! == 0);
|
||||
assert(test.rindex_of(0)!! == 3);
|
||||
test.remove_item(0);
|
||||
assert(test.len() == 2);
|
||||
assert(test.array_view() == (int[]){ 2, 3 });
|
||||
}
|
||||
|
||||
fn void compact()
|
||||
{
|
||||
PtrList test;
|
||||
test.add_array({ null, &test });
|
||||
assert(test.compact_count() == 1);
|
||||
test.push(null);
|
||||
assert(test.compact_count() == 1);
|
||||
assert(test.len() == 3);
|
||||
assert(test.compact() == 2);
|
||||
assert(test.len() == 1);
|
||||
assert(test.compact() == 0);
|
||||
}
|
||||
|
||||
fn void reverse()
|
||||
{
|
||||
IntList test;
|
||||
test.reverse();
|
||||
test.add_array({ 1, 2 });
|
||||
test.push(3);
|
||||
assert(test.array_view() == (int[]) { 1, 2, 3});
|
||||
test.reverse();
|
||||
assert(test.array_view() == (int[]) { 3, 2, 1 });
|
||||
test.push(10);
|
||||
assert(test.array_view() == (int[]) { 3, 2, 1, 10 });
|
||||
test.reverse();
|
||||
assert(test.array_view() == (int[]) { 10, 1, 2, 3 });
|
||||
}
|
||||
|
||||
fn void remove_if()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_if(&filter);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == (int[]){1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_if(&select);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == (int[]){11, 10, 20});
|
||||
}
|
||||
|
||||
|
||||
fn void remove_using_test()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i >= *(int*)ctx, &&10);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == (int[]){1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i < *(int*)ctx, &&10);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == (int[]){11, 10, 20});
|
||||
}
|
||||
|
||||
fn void retain_if()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.retain_if(&select);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == (int[]){1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.retain_if(&filter);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == (int[]){11, 10, 20});
|
||||
}
|
||||
|
||||
fn void retain_using_test()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i >= *(int*)ctx, &&10);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == (int[]){1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i < *(int*)ctx, &&10);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == (int[]){11, 10, 20});
|
||||
}
|
||||
|
||||
module elastic_array_test;
|
||||
|
||||
fn bool filter(int* i)
|
||||
{
|
||||
return *i >= 10;
|
||||
}
|
||||
|
||||
fn bool select(int* i)
|
||||
{
|
||||
return *i < 10;
|
||||
}
|
||||
29
test/unit7/stdlib/collections/enummap.c3
Normal file
29
test/unit7/stdlib/collections/enummap.c3
Normal file
@@ -0,0 +1,29 @@
|
||||
module enummap_test @test;
|
||||
import std::collections::enummap;
|
||||
|
||||
enum FooEnum
|
||||
{
|
||||
ONE,
|
||||
TWO,
|
||||
THREE,
|
||||
}
|
||||
|
||||
def FooEnumMap = EnumMap{FooEnum, uint};
|
||||
|
||||
fn void enums()
|
||||
{
|
||||
FooEnumMap nm;
|
||||
nm.set(ONE, 1);
|
||||
nm.set(TWO, 2);
|
||||
nm.set(THREE, 3);
|
||||
|
||||
assert(nm[FooEnum.ONE] == 1);
|
||||
assert(nm[FooEnum.TWO] == 2);
|
||||
assert(nm[FooEnum.THREE] == 3);
|
||||
|
||||
nm.init(0);
|
||||
|
||||
assert(nm[FooEnum.ONE] == 0);
|
||||
assert(nm[FooEnum.TWO] == 0);
|
||||
assert(nm[FooEnum.THREE] == 0);
|
||||
}
|
||||
15
test/unit7/stdlib/collections/generic_list.c3
Normal file
15
test/unit7/stdlib/collections/generic_list.c3
Normal file
@@ -0,0 +1,15 @@
|
||||
module glist @test;
|
||||
import std::collections;
|
||||
|
||||
fn void simple_use()
|
||||
{
|
||||
AnyList l;
|
||||
l.push(1);
|
||||
l.push("Hello");
|
||||
assert(l.get(1, String)!! == "Hello");
|
||||
assert(l.get(0, int)!! == 1);
|
||||
assert(l.pop(String)!! == "Hello");
|
||||
assert(l.pop(int)!! == 1);
|
||||
assert(l.len() == 0);
|
||||
l.free();
|
||||
}
|
||||
237
test/unit7/stdlib/collections/linkedlist.c3
Normal file
237
test/unit7/stdlib/collections/linkedlist.c3
Normal file
@@ -0,0 +1,237 @@
|
||||
module linkedlist_test @test;
|
||||
import std::collections::linkedlist;
|
||||
|
||||
def IntList = LinkedList{int};
|
||||
|
||||
fn void test_push_front()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push_front(23);
|
||||
assert(list.len() == 1);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 23);
|
||||
list.push_front(55);
|
||||
assert(list.len() == 2);
|
||||
assert(list.last()!! == 23);
|
||||
assert(list.first()!! == 55);
|
||||
|
||||
}
|
||||
|
||||
fn void test_push()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
assert(list.len() == 1);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 23);
|
||||
list.push(55);
|
||||
assert(list.len() == 2);
|
||||
assert(list.last()!! == 55);
|
||||
assert(list.first()!! == 23);
|
||||
}
|
||||
|
||||
fn void test_get()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.get(2) == -3);
|
||||
assert(list.get(1) == 55);
|
||||
assert(list.get(0) == 23);
|
||||
}
|
||||
|
||||
fn void test_insert()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(-3);
|
||||
list.push(55);
|
||||
list.push(23);
|
||||
list.insert_at(0, 1);
|
||||
list.insert_at(2, 11);
|
||||
list.insert_at(4, 111);
|
||||
list.insert_at(6, 1111);
|
||||
assert(list.get(0) == 1);
|
||||
assert(list.get(1) == -3);
|
||||
assert(list.get(2) == 11);
|
||||
assert(list.get(3) == 55);
|
||||
assert(list.get(4) == 111);
|
||||
assert(list.get(5) == 23);
|
||||
assert(list.get(6) == 1111);
|
||||
}
|
||||
|
||||
fn void test_set()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(-3);
|
||||
list.push(55);
|
||||
list.push(23);
|
||||
for (int i = 0; i < 3; i++) list.set(i, list.get(i) + 1);
|
||||
assert(list.get(0) == -2);
|
||||
assert(list.get(1) == 56);
|
||||
assert(list.get(2) == 24);
|
||||
}
|
||||
|
||||
fn void test_remove_at()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
for (int i = 0; i < 10; i++) list.push(i);
|
||||
list.remove_at(0);
|
||||
list.remove_at(1);
|
||||
list.remove_at(7);
|
||||
list.remove_at(5);
|
||||
assert(list.get(0) == 1);
|
||||
assert(list.get(1) == 3);
|
||||
assert(list.get(5) == 8);
|
||||
assert(list.get(4) == 6);
|
||||
}
|
||||
|
||||
fn void test_remove()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(2);
|
||||
for (int i = 0; i < 10; i++) list.push(5);
|
||||
list.push(2);
|
||||
list.remove(5);
|
||||
assert(list.len() == 2);
|
||||
}
|
||||
|
||||
fn void test_remove_first_match()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_first_match(23));
|
||||
assert(list.pop()!! == -3);
|
||||
assert(list.pop()!! == 55);
|
||||
assert(!list.len());
|
||||
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_first_match(55));
|
||||
assert(list.pop()!! == -3);
|
||||
assert(list.pop()!! == 23);
|
||||
assert(!list.len());
|
||||
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_first_match(-3));
|
||||
assert(list.pop()!! == 55);
|
||||
assert(list.pop()!! == 23);
|
||||
assert(!list.len());
|
||||
}
|
||||
|
||||
fn void test_remove_last_match()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_last_match(23));
|
||||
assert(list.pop()!! == -3);
|
||||
assert(list.pop()!! == 55);
|
||||
assert(!list.len());
|
||||
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_last_match(55));
|
||||
assert(list.pop()!! == -3);
|
||||
assert(list.pop()!! == 23);
|
||||
assert(!list.len());
|
||||
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.remove_last_match(-3));
|
||||
assert(list.pop()!! == 55);
|
||||
assert(list.pop()!! == 23);
|
||||
assert(!list.len());
|
||||
}
|
||||
|
||||
fn void test_pop()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.len() == 3);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == -3);
|
||||
assert(list.pop()!! == -3);
|
||||
assert(list.len() == 2);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 55);
|
||||
assert(list.pop()!! == 55);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 23);
|
||||
assert(list.pop()!! == 23);
|
||||
assert(list.len() == 0);
|
||||
assert(@catch(list.pop()));
|
||||
assert(list.len() == 0);
|
||||
list.push(55);
|
||||
assert(list.len() == 1);
|
||||
}
|
||||
|
||||
fn void test_remove_last()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.len() == 3);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == -3);
|
||||
assert(@ok(list.remove_last()));
|
||||
assert(list.len() == 2);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 55);
|
||||
assert(@ok(list.remove_last()));
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == 23);
|
||||
assert(@ok(list.remove_last()));
|
||||
assert(list.len() == 0);
|
||||
assert(@catch(list.pop()));
|
||||
assert(list.len() == 0);
|
||||
list.push(55);
|
||||
assert(list.len() == 1);
|
||||
}
|
||||
|
||||
fn void test_remove_first()
|
||||
{
|
||||
IntList list;
|
||||
defer list.free();
|
||||
list.push(23);
|
||||
list.push(55);
|
||||
list.push(-3);
|
||||
assert(list.len() == 3);
|
||||
assert(list.first()!! == 23);
|
||||
assert(list.last()!! == -3);
|
||||
assert(@ok(list.remove_first()));
|
||||
assert(list.len() == 2);
|
||||
assert(list.last()!! == -3);
|
||||
assert(list.first()!! == 55);
|
||||
assert(@ok(list.remove_first()));
|
||||
assert(list.last()!! == -3);
|
||||
assert(list.first()!! == -3);
|
||||
assert(@ok(list.remove_first()));
|
||||
assert(list.len() == 0);
|
||||
assert(@catch(list.remove_first()));
|
||||
assert(list.len() == 0);
|
||||
list.push(55);
|
||||
assert(list.len() == 1);
|
||||
}
|
||||
178
test/unit7/stdlib/collections/list.c3
Normal file
178
test/unit7/stdlib/collections/list.c3
Normal file
@@ -0,0 +1,178 @@
|
||||
module list_test @test;
|
||||
import std::collections::list;
|
||||
|
||||
def IntList = List{int};
|
||||
def PtrList = List{void*};
|
||||
|
||||
struct Overalign
|
||||
{
|
||||
float[<4>] x @align(128);
|
||||
}
|
||||
|
||||
def OveralignList = List{Overalign};
|
||||
fn void overaligned_type()
|
||||
{
|
||||
OveralignList l;
|
||||
defer l.free();
|
||||
|
||||
Overalign y;
|
||||
for (int i = 0; i < 1000; i++) l.push(y);
|
||||
assert((usz)l.get_ref(2) - (usz)l.get_ref(1) == Overalign.sizeof);
|
||||
}
|
||||
|
||||
|
||||
fn void delete_contains_index()
|
||||
{
|
||||
IntList test;
|
||||
|
||||
test.add_array({ 1, 2 });
|
||||
assert(test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(!test.contains(0));
|
||||
assert(!test.contains(3));
|
||||
assert(test.array_view() == { 1, 2 });
|
||||
test.push(3);
|
||||
assert(test.array_view() == { 1, 2, 3 });
|
||||
assert(test.contains(3));
|
||||
test[0] = 10;
|
||||
assert(test.contains(10));
|
||||
test.remove_item(10);
|
||||
assert(test.array_view() == { 2, 3 });
|
||||
assert(!test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(test.len() == 2);
|
||||
test.push(0);
|
||||
test.insert_at(0, 0);
|
||||
assert(test.array_view() == { 0, 2, 3, 0 });
|
||||
assert(test.index_of(0)!! == 0);
|
||||
assert(test.rindex_of(0)!! == 3);
|
||||
test.remove_item(0);
|
||||
assert(test.len() == 2);
|
||||
assert(test.array_view() == { 2, 3 });
|
||||
}
|
||||
|
||||
fn void compact()
|
||||
{
|
||||
PtrList test;
|
||||
test.add_array({ null, &test });
|
||||
assert(test.compact_count() == 1);
|
||||
test.push(null);
|
||||
assert(test.compact_count() == 1);
|
||||
assert(test.len() == 3);
|
||||
assert(test.compact() == 2);
|
||||
assert(test.len() == 1);
|
||||
assert(test.compact() == 0);
|
||||
}
|
||||
|
||||
fn void reverse()
|
||||
{
|
||||
IntList test;
|
||||
|
||||
test.reverse();
|
||||
test.add_array({ 1, 2 });
|
||||
test.push(3);
|
||||
assert(test.array_view() == { 1, 2, 3});
|
||||
test.reverse();
|
||||
assert(test.array_view() == { 3, 2, 1 });
|
||||
test.push(10);
|
||||
assert(test.array_view() == { 3, 2, 1, 10 });
|
||||
test.reverse();
|
||||
assert(test.array_view() == { 10, 1, 2, 3 });
|
||||
}
|
||||
|
||||
fn void remove_if()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_if(&filter);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == {1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_if(&select);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == {11, 10, 20});
|
||||
}
|
||||
|
||||
fn void init_with_array()
|
||||
{
|
||||
IntList foo;
|
||||
foo.init_with_array(mem, { 1, 2, 3});
|
||||
defer foo.free();
|
||||
assert(foo.len() == 3);
|
||||
assert(foo[2] == 3);
|
||||
}
|
||||
|
||||
fn void init_with_temp_array()
|
||||
{
|
||||
IntList foo;
|
||||
foo.tinit_with_array({ 1, 2, 3});
|
||||
assert(foo.len() == 3);
|
||||
assert(foo[2] == 3);
|
||||
}
|
||||
|
||||
fn void remove_using_test()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i >= *(int*)ctx, &&10);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == {1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i < *(int*)ctx, &&10);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == {11, 10, 20});
|
||||
}
|
||||
|
||||
fn void retain_if()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.retain_if(&select);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == {1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.retain_if(&filter);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == {11, 10, 20});
|
||||
}
|
||||
|
||||
fn void retain_using_test()
|
||||
{
|
||||
IntList test;
|
||||
usz removed;
|
||||
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i >= *(int*)ctx, &&10);
|
||||
assert(removed == 3);
|
||||
assert(test.array_view() == {1, 2});
|
||||
|
||||
test.clear();
|
||||
test.add_array({ 1, 11, 2, 10, 20 });
|
||||
removed = test.remove_using_test(fn bool(i, ctx) => *i < *(int*)ctx, &&10);
|
||||
assert(removed == 2);
|
||||
assert(test.array_view() == {11, 10, 20});
|
||||
}
|
||||
|
||||
module list_test;
|
||||
|
||||
fn bool filter(int* i)
|
||||
{
|
||||
return *i >= 10;
|
||||
}
|
||||
|
||||
fn bool select(int* i)
|
||||
{
|
||||
return *i < 10;
|
||||
}
|
||||
105
test/unit7/stdlib/collections/map.c3
Normal file
105
test/unit7/stdlib/collections/map.c3
Normal file
@@ -0,0 +1,105 @@
|
||||
module map_test @test;
|
||||
import std::collections::list;
|
||||
import std::collections::map;
|
||||
import std::sort;
|
||||
import std::io;
|
||||
|
||||
def TestHashMap = HashMap{String, usz};
|
||||
|
||||
struct MapTest
|
||||
{
|
||||
String key;
|
||||
usz value;
|
||||
}
|
||||
def List = List{MapTest};
|
||||
|
||||
fn void map()
|
||||
{
|
||||
TestHashMap m;
|
||||
assert(!m.is_initialized());
|
||||
m.tinit();
|
||||
assert(m.is_initialized());
|
||||
assert(m.is_empty());
|
||||
assert(m.len() == 0);
|
||||
|
||||
m.set("a", 1);
|
||||
assert(!m.is_empty());
|
||||
assert(m.len() == 1);
|
||||
m.remove("a");
|
||||
assert(m.is_empty());
|
||||
|
||||
MapTest[] tcases = { {"key1", 0}, {"key2", 1}, {"key3", 2} };
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
m.set(tc.key, tc.value);
|
||||
}
|
||||
assert(m.len() == tcases.len);
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
usz v = m.get(tc.key)!!;
|
||||
assert(tc.value == v);
|
||||
}
|
||||
|
||||
List list;
|
||||
list.tinit();
|
||||
m.@each(;String key, usz value)
|
||||
{
|
||||
list.push({key, value});
|
||||
};
|
||||
assert(list.len() == tcases.len);
|
||||
quicksort(list, fn int (MapTest a, MapTest b) => (int)(a.value - b.value));
|
||||
foreach (i, tc : tcases)
|
||||
{
|
||||
assert(tc.key == list[i].key);
|
||||
assert(tc.value == list[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
def FooMap = HashMap{char, Foobar};
|
||||
enum Foobar : inline char
|
||||
{
|
||||
FOO,
|
||||
BAR,
|
||||
BAZ
|
||||
}
|
||||
|
||||
enum Foobar2 : int (inline char y)
|
||||
{
|
||||
ABC = 3,
|
||||
DEF = 5,
|
||||
}
|
||||
|
||||
fn void map_inline_enum()
|
||||
{
|
||||
FooMap x;
|
||||
x[Foobar.BAZ] = FOO;
|
||||
x[Foobar2.ABC] = BAR;
|
||||
test::eq(string::tformat("%s", x), "{ 2: FOO, 3: BAR }");
|
||||
x.free();
|
||||
}
|
||||
|
||||
fn void map_remove()
|
||||
{
|
||||
TestHashMap m;
|
||||
assert(!@ok(m.remove("A")));
|
||||
m.tinit();
|
||||
assert(!@ok(m.remove("A")));
|
||||
m.set("A", 0);
|
||||
assert(@ok(m.remove("A")));
|
||||
}
|
||||
|
||||
fn void map_copy()
|
||||
{
|
||||
TestHashMap hash_map;
|
||||
hash_map.tinit();
|
||||
|
||||
hash_map.set("aa", 1);
|
||||
hash_map.set("b", 2);
|
||||
hash_map.set("bb", 1);
|
||||
|
||||
TestHashMap hash_map_copy;
|
||||
hash_map_copy.tinit_from_map(&hash_map);
|
||||
|
||||
assert(hash_map_copy.len() == hash_map.len());
|
||||
|
||||
}
|
||||
43
test/unit7/stdlib/collections/object.c3
Normal file
43
test/unit7/stdlib/collections/object.c3
Normal file
@@ -0,0 +1,43 @@
|
||||
module object_test @test;
|
||||
import std::collections::object;
|
||||
|
||||
fn void test_general()
|
||||
{
|
||||
Object* root = object::new_obj(allocator::heap());
|
||||
defer root.free();
|
||||
|
||||
root.set("foo", 1);
|
||||
root.set("bar", "baz");
|
||||
assert(root.get_int("foo")!! == 1);
|
||||
assert(root.get_string("bar")!! == "baz");
|
||||
Object* goo = root.set("goo", object::new_obj(allocator::heap()));
|
||||
goo.push("hello");
|
||||
goo.push(132);
|
||||
assert(root.get("goo").get_int_at(1)!! == 132);
|
||||
assert(root.get("goo").get_string_at(0)!! == "hello");
|
||||
Object* abc = root.get_or_create_obj("abc80");
|
||||
abc.set("cool", 1.3);
|
||||
assert(root.get("abc80").get_int("cool")!! == 1);
|
||||
assert(root.get("abc80").get_float("cool")!! == 1.3);
|
||||
assert((root.get_int("yyy") ?? -1) == -1);
|
||||
root.set("yyy", true);
|
||||
assert(root.get_bool("yyy") ?? false);
|
||||
}
|
||||
|
||||
fn void test_to_format_int()
|
||||
{
|
||||
{
|
||||
Object* int_object = object::new_int(16, allocator::heap());
|
||||
defer int_object.free();
|
||||
String s = string::format(mem, "%s", int_object);
|
||||
defer free(s);
|
||||
assert(s == "16");
|
||||
}
|
||||
{
|
||||
Object* int_object = object::new_int(-16, allocator::heap());
|
||||
defer int_object.free();
|
||||
String s = string::format(mem, "%s", int_object);
|
||||
defer free(s);
|
||||
assert(s == "-16");
|
||||
}
|
||||
}
|
||||
62
test/unit7/stdlib/collections/priorityqueue.c3
Normal file
62
test/unit7/stdlib/collections/priorityqueue.c3
Normal file
@@ -0,0 +1,62 @@
|
||||
module priorityqueue_test @test;
|
||||
import std::collections;
|
||||
import std::collections::priorityqueue;
|
||||
|
||||
def Queue = PriorityQueue{int};
|
||||
|
||||
fn void priorityqueue()
|
||||
{
|
||||
Queue q;
|
||||
defer q.free();
|
||||
|
||||
assert(q.is_empty());
|
||||
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
assert(q.len() == 2);
|
||||
|
||||
int x;
|
||||
x = q.pop()!!;
|
||||
assert(x == 1, "got %d; want %d", x, 1);
|
||||
x = q.pop()!!;
|
||||
assert(x == 2, "got %d; want %d", x, 2);
|
||||
|
||||
q.push(3);
|
||||
q.push(2);
|
||||
q.push(1);
|
||||
x = q.pop()!!;
|
||||
assert(x == 1, "got %d; want %d", x, 1);
|
||||
x = q.pop()!!;
|
||||
assert(x == 2, "got %d; want %d", x, 2);
|
||||
x = q.pop()!!;
|
||||
assert(x == 3, "got %d; want %d", x, 3);
|
||||
}
|
||||
|
||||
def QueueMax = PriorityQueueMax{int};
|
||||
|
||||
fn void priorityqueue_max()
|
||||
{
|
||||
QueueMax q;
|
||||
defer q.free();
|
||||
assert(q.is_empty());
|
||||
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
assert(q.len() == 2);
|
||||
|
||||
int x;
|
||||
x = q.pop()!!;
|
||||
assert(x == 2, "got %d; want %d", x, 2);
|
||||
x = q.pop()!!;
|
||||
assert(x == 1, "got %d; want %d", x, 1);
|
||||
|
||||
q.push(3);
|
||||
q.push(2);
|
||||
q.push(1);
|
||||
x = q.pop()!!;
|
||||
assert(x == 3, "got %d; want %d", x, 3);
|
||||
x = q.pop()!!;
|
||||
assert(x == 2, "got %d; want %d", x, 2);
|
||||
x = q.pop()!!;
|
||||
assert(x == 1, "got %d; want %d", x, 1);
|
||||
}
|
||||
36
test/unit7/stdlib/collections/range.c3
Normal file
36
test/unit7/stdlib/collections/range.c3
Normal file
@@ -0,0 +1,36 @@
|
||||
module range_test @test;
|
||||
import std::collections::range;
|
||||
|
||||
def IntRange = Range{int};
|
||||
def IntExRange = ExclusiveRange{int};
|
||||
|
||||
fn void test_range()
|
||||
{
|
||||
IntRange range = { -4, 2 };
|
||||
int sum = 0;
|
||||
foreach (int z : range)
|
||||
{
|
||||
assert(z >= -4 && z < 3);
|
||||
sum += z * z;
|
||||
}
|
||||
assert(sum == 35);
|
||||
assert(range.contains(-4));
|
||||
assert(range.contains(2));
|
||||
assert(!range.contains(3));
|
||||
}
|
||||
|
||||
fn void test_exrange()
|
||||
{
|
||||
IntExRange range = { -4, 2 };
|
||||
int sum = 0;
|
||||
foreach (int z : range)
|
||||
{
|
||||
assert(z >= -4 && z < 2);
|
||||
sum += z * z;
|
||||
}
|
||||
assert(sum == 31);
|
||||
assert(range.contains(-4));
|
||||
assert(range.contains(1));
|
||||
assert(!range.contains(2));
|
||||
}
|
||||
|
||||
29
test/unit7/stdlib/collections/ringbuffer.c3
Normal file
29
test/unit7/stdlib/collections/ringbuffer.c3
Normal file
@@ -0,0 +1,29 @@
|
||||
module ringbuffer_test @test;
|
||||
import std::collections::ringbuffer;
|
||||
import std::io;
|
||||
|
||||
def Buffer = RingBuffer{char[4]};
|
||||
|
||||
fn void push_get()
|
||||
{
|
||||
Buffer rb;
|
||||
rb.init();
|
||||
rb.push(1);
|
||||
rb.push(2);
|
||||
rb.push(3);
|
||||
rb.push(4);
|
||||
|
||||
assert(rb.get(0) == 1);
|
||||
assert(rb.get(1) == 2);
|
||||
assert(rb.get(2) == 3);
|
||||
assert(rb.get(3) == 4);
|
||||
|
||||
rb.push(5);
|
||||
assert(rb.get(0) == 2);
|
||||
assert(rb.get(1) == 3);
|
||||
assert(rb.get(2) == 4);
|
||||
assert(rb.get(3) == 5);
|
||||
|
||||
char c = rb.pop()!!;
|
||||
assert(c == 5);
|
||||
}
|
||||
38
test/unit7/stdlib/compression/qoi.c3
Normal file
38
test/unit7/stdlib/compression/qoi.c3
Normal file
File diff suppressed because one or more lines are too long
79
test/unit7/stdlib/conv_tests.c3
Normal file
79
test/unit7/stdlib/conv_tests.c3
Normal file
@@ -0,0 +1,79 @@
|
||||
module conv_tests;
|
||||
import std::io;
|
||||
|
||||
fn void! comparison_helper_32_to_8(Char32 c32, String expected_output)
|
||||
{
|
||||
char[8] out;
|
||||
usz len = conv::char32_to_utf8(c32, &out)!;
|
||||
assert(len == expected_output.len, "Len should be 1");
|
||||
foreach (i, c : expected_output)
|
||||
{
|
||||
assert(out[i] == c, "Expected other value");
|
||||
}
|
||||
}
|
||||
|
||||
fn void! comparison_helper_8_to_32(String in, Char32 c32)
|
||||
{
|
||||
usz len = in.len;
|
||||
Char32 res = conv::utf8_to_char32(in.ptr, &len)!;
|
||||
assert(len == in.len, "All len should be used.");
|
||||
assert(res == c32, "Expected character match.");
|
||||
}
|
||||
|
||||
fn void assert_utf8_is_error(String in)
|
||||
{
|
||||
usz len = in.len;
|
||||
assert(@catch(conv::utf8_to_char32(in.ptr, &len)), "Expected error");
|
||||
}
|
||||
|
||||
fn void test_char32_ut8_boundary() @test
|
||||
{
|
||||
// First sequence per len
|
||||
comparison_helper_32_to_8(0x00000000, { 0 })!!;
|
||||
comparison_helper_32_to_8(0x00000080, { 0xc2, 0x80 })!!;
|
||||
comparison_helper_32_to_8(0x00000800, { 0xe0, 0xa0, 0x80 })!!;
|
||||
comparison_helper_32_to_8(0x00010000, { 0xf0, 0x90, 0x80, 0x80 })!!;
|
||||
assert(@catch(comparison_helper_32_to_8(0x10ffff + 1, { 0 })), "Expected error");
|
||||
// Last seq per len
|
||||
comparison_helper_32_to_8(0x0000007f, { 0x7f })!!;
|
||||
comparison_helper_32_to_8(0x000007ff, { 0xdf, 0xbf })!!;
|
||||
comparison_helper_32_to_8(0x0000ffff, { 0xef, 0xbf, 0xbf })!!;
|
||||
comparison_helper_32_to_8(0x0010ffff, { 0xf4, 0x8f, 0xbf, 0xbf })!!;
|
||||
// Other boundaries
|
||||
comparison_helper_32_to_8(0x0000d7ff, { 0xed, 0x9f, 0xbf})!!;
|
||||
comparison_helper_32_to_8(0x0000e000, { 0xee, 0x80, 0x80 })!!;
|
||||
comparison_helper_32_to_8(0x0000fffd, { 0xef, 0xbf, 0xbd })!!;
|
||||
|
||||
}
|
||||
|
||||
fn void test_utf8_to_char32_boundary() @test
|
||||
{
|
||||
// First sequence per len
|
||||
comparison_helper_8_to_32("\0", 0x0 )!!;
|
||||
comparison_helper_8_to_32({ 0xc2, 0x80 }, 0x80)!!;
|
||||
comparison_helper_8_to_32({ 0xe0, 0xa0, 0x80 }, 0x800 )!!;
|
||||
comparison_helper_8_to_32({ 0xf0, 0x90, 0x80, 0x80 }, 0x10000)!!;
|
||||
// Last seq per len
|
||||
comparison_helper_8_to_32({ 0x7f }, 0x7f)!!;
|
||||
comparison_helper_8_to_32({ 0xdf, 0xbf }, 0x7ff )!!;
|
||||
comparison_helper_8_to_32({ 0xef, 0xbf, 0xbf }, 0xffff)!!;
|
||||
comparison_helper_8_to_32({ 0xf4, 0x8f, 0xbf, 0xbf }, 0x10ffff)!!;
|
||||
// Other boundaries
|
||||
comparison_helper_8_to_32({ 0xed, 0x9f, 0xbf }, 0xd7ff)!!;
|
||||
comparison_helper_8_to_32({ 0xee, 0x80, 0x80 }, 0xe000)!!;
|
||||
comparison_helper_8_to_32({ 0xef, 0xbf, 0xbd }, 0xfffd)!!;
|
||||
|
||||
assert_utf8_is_error({ 0x80 });
|
||||
assert_utf8_is_error({ 0xbf });
|
||||
assert_utf8_is_error({ 0xfe });
|
||||
assert_utf8_is_error({ 0xff });
|
||||
assert_utf8_is_error({ 0xfe, 0xfe, 0xff, 0xff });
|
||||
|
||||
// Overlong
|
||||
assert_utf8_is_error({ 0xc0, 0xaf });
|
||||
assert_utf8_is_error({ 0xe0, 0x80, 0xaf });
|
||||
assert_utf8_is_error({ 0xf0, 0x80, 0x80, 0xaf });
|
||||
assert_utf8_is_error({ 0xf8, 0x80, 0x80, 0xaf });
|
||||
assert_utf8_is_error({ 0xfc, 0x80, 0x80, 0x80, 0xaf });
|
||||
}
|
||||
|
||||
32
test/unit7/stdlib/core/array.c3
Normal file
32
test/unit7/stdlib/core/array.c3
Normal file
@@ -0,0 +1,32 @@
|
||||
module arraytests @test;
|
||||
|
||||
fn void find()
|
||||
{
|
||||
int[3] a = { 1, 2, 3 };
|
||||
assert(array::index_of(a, 2)!! == 1);
|
||||
assert(array::index_of(a, 1)!! == 0);
|
||||
assert(array::index_of(a, 3)!! == 2);
|
||||
assert(@catch(array::index_of(a, 4)) == SearchResult.MISSING);
|
||||
}
|
||||
|
||||
fn void find_subarray()
|
||||
{
|
||||
int[] a = { 1, 2, 3 };
|
||||
assert(array::index_of(a, 2)!! == 1);
|
||||
assert(array::index_of(a, 1)!! == 0);
|
||||
assert(array::index_of(a, 3)!! == 2);
|
||||
assert(@catch(array::index_of(a, 4)) == SearchResult.MISSING);
|
||||
}
|
||||
|
||||
fn void concat()
|
||||
{
|
||||
int[3] a = { 1, 2, 3 };
|
||||
free(array::concat_new(a, a));
|
||||
free(array::concat_new(a[..], a[..]));
|
||||
free(array::concat_new(a[:0], a[:0]));
|
||||
free(array::concat_new((int[2]) { 1, 2 }, a[:0]));
|
||||
free(array::concat_new(a[:0], (int[2]) { 1, 2 }));
|
||||
int[] c = array::concat_new(a[1..2], a);
|
||||
defer free(c);
|
||||
assert (c == (int[]){ 2, 3, 1, 2, 3 });
|
||||
}
|
||||
45
test/unit7/stdlib/core/bitorder.c3
Normal file
45
test/unit7/stdlib/core/bitorder.c3
Normal file
@@ -0,0 +1,45 @@
|
||||
module std::core::bitorder @test;
|
||||
|
||||
fn void test_read()
|
||||
{
|
||||
char[?] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
||||
|
||||
assert(bitorder::read(bytes, UShortBE) == 0x0102);
|
||||
assert(bitorder::read(bytes, UShortLE) == 0x0201);
|
||||
assert(bitorder::read(bytes, UIntBE) == 0x01020304);
|
||||
assert(bitorder::read(bytes, UIntLE) == 0x04030201);
|
||||
assert(bitorder::read(bytes, ULongBE) == 0x0102030405060708);
|
||||
assert(bitorder::read(bytes, ULongLE) == 0x0807060504030201);
|
||||
|
||||
assert(bitorder::read(&bytes, UShortBE) == 0x0102);
|
||||
assert(bitorder::read(&bytes, UShortLE) == 0x0201);
|
||||
assert(bitorder::read(&bytes, UIntBE) == 0x01020304);
|
||||
assert(bitorder::read(&bytes, UIntLE) == 0x04030201);
|
||||
assert(bitorder::read(&bytes, ULongBE) == 0x0102030405060708);
|
||||
assert(bitorder::read(&bytes, ULongLE) == 0x0807060504030201);
|
||||
|
||||
assert(bitorder::read(bytes[..], UShortBE) == 0x0102);
|
||||
assert(bitorder::read(bytes[..], UShortLE) == 0x0201);
|
||||
assert(bitorder::read(bytes[..], UIntBE) == 0x01020304);
|
||||
assert(bitorder::read(bytes[..], UIntLE) == 0x04030201);
|
||||
assert(bitorder::read(bytes[..], ULongBE) == 0x0102030405060708);
|
||||
assert(bitorder::read(bytes[..], ULongLE) == 0x0807060504030201);
|
||||
}
|
||||
|
||||
fn void test_write()
|
||||
{
|
||||
char[?] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
||||
char[8] buf;
|
||||
|
||||
ushort x1 = bitorder::read(bytes, UShortBE);
|
||||
bitorder::write(x1, &buf, UShortBE);
|
||||
assert(bitorder::read(buf, UShortBE) == x1);
|
||||
|
||||
uint x2 = bitorder::read(bytes, UIntBE);
|
||||
bitorder::write(x2, buf[..], UIntBE);
|
||||
assert(bitorder::read(buf, UIntBE) == x2);
|
||||
|
||||
ulong x3 = bitorder::read(bytes, ULongBE);
|
||||
bitorder::write(x3, buf[..], ULongBE);
|
||||
assert(bitorder::read(buf, ULongBE) == x3);
|
||||
}
|
||||
79
test/unit7/stdlib/core/builtintests.c3
Normal file
79
test/unit7/stdlib/core/builtintests.c3
Normal file
@@ -0,0 +1,79 @@
|
||||
module std::core::builtins @test;
|
||||
|
||||
fn void test_anycast()
|
||||
{
|
||||
int a;
|
||||
any b = &a;
|
||||
assert(anycast(b, int)!! == &a);
|
||||
assert(@catch(anycast(b, double)) == CastResult.TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
fn void test_bitcast()
|
||||
{
|
||||
int a = 123;
|
||||
float z = bitcast(a, float);
|
||||
assert(bitcast(z, int) == a);
|
||||
}
|
||||
|
||||
enum Tester
|
||||
{
|
||||
ABC,
|
||||
DEF,
|
||||
}
|
||||
|
||||
fn void test_enum_by_name()
|
||||
{
|
||||
assert(enum_by_name(Tester, "ABC")!! == Tester.ABC);
|
||||
assert(enum_by_name(Tester, "DEF")!! == Tester.DEF);
|
||||
assert(@catch(enum_by_name(Tester, "GHI")) == SearchResult.MISSING);
|
||||
}
|
||||
|
||||
fn void test_likely()
|
||||
{
|
||||
int a = 2;
|
||||
int b = 43;
|
||||
if (@likely(a > b, 0.5)) a++;
|
||||
if (@likely(a < b)) b++;
|
||||
}
|
||||
|
||||
fn void test_unlikely()
|
||||
{
|
||||
int a = 2;
|
||||
int b = 43;
|
||||
if (@unlikely(a > b, 0.5)) a++;
|
||||
if (@unlikely(a < b)) b++;
|
||||
}
|
||||
|
||||
fn void test_expect()
|
||||
{
|
||||
int a = 2;
|
||||
int b = 43;
|
||||
int c = @expect(a, 2, 0.5);
|
||||
int d = @expect(b, 2u8);
|
||||
}
|
||||
|
||||
|
||||
int abc;
|
||||
|
||||
fn void test_prefetch()
|
||||
{
|
||||
@prefetch(&abc);
|
||||
}
|
||||
|
||||
fn void test_hash()
|
||||
{
|
||||
(char){}.hash();
|
||||
(ichar){}.hash();
|
||||
(short){}.hash();
|
||||
(ushort){}.hash();
|
||||
(int){}.hash();
|
||||
(uint){}.hash();
|
||||
(long){}.hash();
|
||||
(ulong){}.hash();
|
||||
(int128){}.hash();
|
||||
(uint128){}.hash();
|
||||
String x = "abc";
|
||||
char[] y = "abc";
|
||||
assert(x.hash() == y.hash());
|
||||
assert(int.typeid.hash());
|
||||
}
|
||||
22
test/unit7/stdlib/core/comparison.c3
Normal file
22
test/unit7/stdlib/core/comparison.c3
Normal file
@@ -0,0 +1,22 @@
|
||||
module comparison @test;
|
||||
|
||||
fn void compare_long()
|
||||
{
|
||||
assert(compare_to(long.max, long.min) == 1);
|
||||
assert(compare_to(long.min, long.max) == -1);
|
||||
assert(compare_to(long.min, long.min) == 0);
|
||||
}
|
||||
|
||||
fn void compare_ulong()
|
||||
{
|
||||
assert(compare_to(ulong.max, ulong.min) == 1);
|
||||
assert(compare_to(ulong.min, ulong.max) == -1);
|
||||
assert(compare_to(ulong.min, ulong.min) == 0);
|
||||
}
|
||||
|
||||
fn void compare_int128()
|
||||
{
|
||||
assert(compare_to(int128.max, int128.min) == 1);
|
||||
assert(compare_to(int128.min, int128.max) == -1);
|
||||
assert(compare_to(int128.min, int128.min) == 0);
|
||||
}
|
||||
277
test/unit7/stdlib/core/dstring.c3
Normal file
277
test/unit7/stdlib/core/dstring.c3
Normal file
@@ -0,0 +1,277 @@
|
||||
module std::core::dstring2 @test;
|
||||
|
||||
const TEST_STRING = "hello world";
|
||||
|
||||
fn void test_replace()
|
||||
{
|
||||
DString hello = dstring::new(mem, "Hello world where are you? Are you here too?");
|
||||
defer hello.free();
|
||||
hello.replace("u", "ooo");
|
||||
assert(hello.str_view() == "Hello world where are yoooo? Are yoooo here too?");
|
||||
}
|
||||
|
||||
fn void test_reverse()
|
||||
{
|
||||
DString a;
|
||||
a.append("abcd");
|
||||
a.reverse();
|
||||
assert(a.str_view() == "dcba");
|
||||
a.reverse();
|
||||
assert(a.str_view() == "abcd");
|
||||
a.append("e");
|
||||
assert(a.str_view() == "abcde");
|
||||
a.reverse();
|
||||
assert(a.str_view() == "edcba");
|
||||
a.free();
|
||||
}
|
||||
|
||||
fn void test_delete()
|
||||
{
|
||||
{
|
||||
DString d;
|
||||
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.");
|
||||
d.delete(0, 2);
|
||||
assert(d.str_view() == "llo cruel world.");
|
||||
d.delete(14, 2);
|
||||
assert(d.str_view() == "llo cruel worl");
|
||||
d.delete(7);
|
||||
assert(d.str_view() == "llo crul worl");
|
||||
d.delete(2, 0);
|
||||
assert(d.str_view() == "llo crul worl");
|
||||
d.delete(0, 1);
|
||||
assert(d.str_view() == "lo crul worl");
|
||||
d.free();
|
||||
}
|
||||
|
||||
fn void test_append()
|
||||
{
|
||||
DString str = dstring::new(mem, TEST_STRING);
|
||||
defer str.free();
|
||||
String s;
|
||||
|
||||
assert(str.len() == TEST_STRING.len);
|
||||
assert(str.capacity() == 16);
|
||||
|
||||
s = str.str_view();
|
||||
assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING);
|
||||
ZString zs;
|
||||
zs = str.zstr_view();
|
||||
assert(s.ptr[s.len] == 0, "got '%c'; want 0", s.ptr[s.len]);
|
||||
|
||||
str.chop(5);
|
||||
s = str.str_view();
|
||||
assert(s == TEST_STRING[:5], "got '%s'; want '%s'", s, TEST_STRING[:5]);
|
||||
|
||||
str.append(TEST_STRING[5..]);
|
||||
s = str.str_view();
|
||||
assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING);
|
||||
|
||||
str.append_char('x');
|
||||
s = str.str_view();
|
||||
assert(s[^1] == 'x', "got '%c'; want 'x'", s[^1]);
|
||||
|
||||
str.append('y');
|
||||
s = str.str_view();
|
||||
assert(s[^1] == 'y', "got '%c'; want 'y'", s[^1]);
|
||||
|
||||
str.set(0, 'z');
|
||||
s = str.str_view();
|
||||
assert(s[0] == 'z', "got '%c'; want 'z'", s[0]);
|
||||
|
||||
str.clear();
|
||||
assert(str.len() == 0);
|
||||
|
||||
str.append_char32('é');
|
||||
s = str.str_view();
|
||||
assert(s == "é", "got '%s'; want 'é'", s);
|
||||
|
||||
str.append_utf32({ 'è', 'à' });
|
||||
s = str.str_view();
|
||||
assert(s == "éèà", "got '%s'; want 'éèà'", s);
|
||||
str.clear();
|
||||
|
||||
str.append_chars("foo");
|
||||
s = str.str_view();
|
||||
assert(s == "foo", "got '%s'; want 'foo'", s);
|
||||
str.clear();
|
||||
|
||||
str.append_repeat('x', 3);
|
||||
s = str.str_view();
|
||||
assert(s == "xxx", "got '%s'; want 'xxx'", s);
|
||||
|
||||
DString str2 = dstring::new(mem, "yyy");
|
||||
defer str2.free();
|
||||
DString str3 = str.concat(mem, str2);
|
||||
defer str3.free();
|
||||
s = str3.str_view();
|
||||
assert(s == "xxxyyy", "got '%s'; want 'xxxyyy'", s);
|
||||
|
||||
str3.clear();
|
||||
str3.append_string(str2);
|
||||
s = str3.str_view();
|
||||
assert(s == "yyy", "got '%s'; want 'yyy'", s);
|
||||
}
|
||||
|
||||
fn void test_print()
|
||||
{
|
||||
DString str = dstring::new(mem, "");
|
||||
defer str.free();
|
||||
String s;
|
||||
|
||||
str.appendf("_%s_", "foo");
|
||||
s = str.str_view();
|
||||
assert(s == "_foo_", "got '%s'; want '_foo_'", s);
|
||||
|
||||
str.clear();
|
||||
str.appendfn("_%s_", "foo");
|
||||
s = str.str_view();
|
||||
assert(s == "_foo_\n", "got '%s'; want '_foo_\n'", s);
|
||||
}
|
||||
|
||||
fn void test_copy()
|
||||
{
|
||||
DString str = dstring::new(mem, TEST_STRING);
|
||||
defer str.free();
|
||||
String s;
|
||||
|
||||
DString str2 = str.copy(mem);
|
||||
defer str2.free();
|
||||
s = str2.str_view();
|
||||
assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING);
|
||||
}
|
||||
|
||||
fn void test_cmp()
|
||||
{
|
||||
DString str = dstring::new(mem, TEST_STRING);
|
||||
defer str.free();
|
||||
|
||||
DString str2 = dstring::new(mem, TEST_STRING);
|
||||
defer str2.free();
|
||||
|
||||
assert(str.equals(str2));
|
||||
|
||||
str2.clear();
|
||||
str2.append("hello you..");
|
||||
assert(str.len() == str2.len());
|
||||
assert(!str.less(str2));
|
||||
}
|
||||
|
||||
fn void test_join()
|
||||
{
|
||||
DString str = dstring::join(mem, {"hello", "world"}, " ");
|
||||
defer str.free();
|
||||
|
||||
String s = str.str_view();
|
||||
assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING);
|
||||
}
|
||||
|
||||
fn void test_insert_at()
|
||||
{
|
||||
DString str = dstring::tnew(" world");
|
||||
String s;
|
||||
|
||||
str.insert_at(0, "");
|
||||
s = str.str_view();
|
||||
assert(s == " world", "got '%s'; want ' world'", s);
|
||||
|
||||
str.insert_at(0, "hello");
|
||||
s = str.str_view();
|
||||
assert(s == "hello world", "got '%s'; want 'hello world'", s);
|
||||
|
||||
str.insert_at(5, " shiny");
|
||||
s = str.str_view();
|
||||
assert(s == "hello shiny world", "got '%s'; want 'hello shiny world'", s);
|
||||
|
||||
str.insert_at(0, '[');
|
||||
s = str.str_view();
|
||||
assert(s == "[hello shiny world", "got '%s'; want '[hello shiny world'", s);
|
||||
|
||||
str.insert_at(18, ']');
|
||||
s = str.str_view();
|
||||
assert(s == "[hello shiny world]", "got '%s'; want 'hello shiny world]'", s);
|
||||
|
||||
str.insert_at(0, 'ꫩ');
|
||||
s = str.str_view();
|
||||
assert(s == "ꫩ[hello shiny world]", "got '%s'; want 'ꫩ[hello shiny world]'", s);
|
||||
|
||||
// ꫩ is 3 bytes long
|
||||
str.insert_utf32_at(4, {'寃', 't', 'e', 'x', 't', '¥'});
|
||||
s = str.str_view();
|
||||
assert(s == "ꫩ[寃text¥hello shiny world]", "got '%s'; want 'ꫩ[寃text¥hello shiny world]'", s);
|
||||
}
|
||||
|
||||
fn void test_insert_at_overlaps()
|
||||
{
|
||||
DString str = dstring::tnew("abc");
|
||||
String s;
|
||||
String v;
|
||||
|
||||
str.insert_at(0, "bc");
|
||||
s = str.str_view();
|
||||
assert(s == "bcabc", "got '%s'; want 'bcabc'", s);
|
||||
|
||||
// Inserted string is unchanged.
|
||||
str.chop(0);
|
||||
str.append("abc");
|
||||
v = str.str_view();
|
||||
str.insert_at(0, v);
|
||||
s = str.str_view();
|
||||
assert(s == "abc", "got '%s'; want 'abc'", s);
|
||||
|
||||
// Inserted string is part of the tail.
|
||||
str.chop(0);
|
||||
str.append("abc");
|
||||
v = str.str_view()[1..];
|
||||
assert(v == "bc");
|
||||
str.insert_at(0, v);
|
||||
s = str.str_view();
|
||||
assert(s == "bcabc", "got '%s'; want 'bcabc'", s);
|
||||
|
||||
// Inserted string is part of the head.
|
||||
str.chop(0);
|
||||
str.append("abc");
|
||||
v = str.str_view()[1..];
|
||||
str.insert_at(2, v);
|
||||
s = str.str_view();
|
||||
assert(s == "abbcc", "got '%s'; want 'abbcc'", s);
|
||||
|
||||
str.chop(0);
|
||||
str.append("abcdef");
|
||||
v = str.str_view()[3..];
|
||||
assert(v == "def");
|
||||
str.insert_at(0, v);
|
||||
str.chop(3);
|
||||
s = str.str_view();
|
||||
assert(s == "def", "got '%s'; want 'def'", s);
|
||||
}
|
||||
|
||||
fn void test_char_at()
|
||||
{
|
||||
DString str = dstring::new(mem, "hello");
|
||||
defer str.free();
|
||||
|
||||
char c = str.char_at(1);
|
||||
assert(c == 'e');
|
||||
|
||||
char c_with_operator = str[4];
|
||||
assert(c_with_operator == 'o');
|
||||
}
|
||||
|
||||
fn void test_operators()
|
||||
{
|
||||
DString str = dstring::new(mem, "hello");
|
||||
defer str.free();
|
||||
|
||||
str[0] = 'p';
|
||||
assert(str.str_view() == "pello");
|
||||
|
||||
char* c = &str[1];
|
||||
assert(*c == 'e');
|
||||
}
|
||||
|
||||
20
test/unit7/stdlib/core/formatter.c3
Normal file
20
test/unit7/stdlib/core/formatter.c3
Normal file
@@ -0,0 +1,20 @@
|
||||
module std::core::formatter_test;
|
||||
|
||||
import std;
|
||||
|
||||
struct Foo (Printable) { int a; }
|
||||
fn usz! Foo.to_format(&self, Formatter *f) @dynamic
|
||||
{
|
||||
return f.printf("Foo[%d]", self.a);
|
||||
}
|
||||
|
||||
fn void test_ref() @test
|
||||
{
|
||||
Foo* f = &&(Foo){ 8 };
|
||||
Foo* f0 = null;
|
||||
int* a = (void*)(uptr)0x40;
|
||||
int* b = null;
|
||||
String s = string::format(mem, "%s %s %s %s %s", a, b, f0, f, *f);
|
||||
defer free(s);
|
||||
assert(s == "0x40 0x0 (null) Foo[8] Foo[8]");
|
||||
}
|
||||
25
test/unit7/stdlib/core/mem_allocator.c3
Normal file
25
test/unit7/stdlib/core/mem_allocator.c3
Normal file
@@ -0,0 +1,25 @@
|
||||
module std::core::allocator_test;
|
||||
|
||||
import std;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
struct Bar
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
List{Foo} foos;
|
||||
}
|
||||
|
||||
fn void test_new_aligned_compiles() @test
|
||||
{
|
||||
Bar* bar2 = allocator::new_aligned(allocator::heap(), Bar)!!;
|
||||
allocator::free_aligned(allocator::heap(), bar2);
|
||||
|
||||
Bar* bar = allocator::new_aligned(allocator::heap(), Bar, {.x = 1, .y = 2, .foos = {}})!!;
|
||||
allocator::free_aligned(allocator::heap(), bar);
|
||||
}
|
||||
37
test/unit7/stdlib/core/runtime.c3
Normal file
37
test/unit7/stdlib/core/runtime.c3
Normal file
@@ -0,0 +1,37 @@
|
||||
module std::core::runtime_test;
|
||||
import std::sort;
|
||||
|
||||
fn void cmp_unit() @test
|
||||
{
|
||||
TestUnit[] list = {
|
||||
{ .name = "http::url_test::url_query" },
|
||||
{ .name = "http::url_test::url_init" },
|
||||
{ .name = "http::url_test::url_decode" },
|
||||
{ .name = "text_test::test_render_notag" },
|
||||
{ .name = "text_test::test_render_tag1" },
|
||||
{ .name = "text_test::test_render_template_iter" },
|
||||
{ .name = "http::header_test::header_scan" },
|
||||
{ .name = "http::header_test::header" },
|
||||
{ .name = "stringmap_test::test_map" },
|
||||
{ .name = "text_test::test_render_template" },
|
||||
};
|
||||
quicksort(list, &runtime::cmp_test_unit);
|
||||
|
||||
String[] want = {
|
||||
"http::header_test::header",
|
||||
"http::header_test::header_scan",
|
||||
"http::url_test::url_decode",
|
||||
"http::url_test::url_init",
|
||||
"http::url_test::url_query",
|
||||
"stringmap_test::test_map",
|
||||
"text_test::test_render_notag",
|
||||
"text_test::test_render_tag1",
|
||||
"text_test::test_render_template",
|
||||
"text_test::test_render_template_iter",
|
||||
};
|
||||
assert(list.len == want.len);
|
||||
foreach (i, l : list)
|
||||
{
|
||||
assert(l.name == want[i], "got %s; want %s", l.name, want[i]);
|
||||
}
|
||||
}
|
||||
208
test/unit7/stdlib/core/string.c3
Normal file
208
test/unit7/stdlib/core/string.c3
Normal file
@@ -0,0 +1,208 @@
|
||||
module std::core::string::tests @test;
|
||||
|
||||
fn void test_starts_with()
|
||||
{
|
||||
String s = "ofke";
|
||||
assert(s.starts_with("of"));
|
||||
assert(s.starts_with("ofke"));
|
||||
assert(!s.starts_with("ofkes"));
|
||||
assert(!s.starts_with("ofkf"));
|
||||
s = "";
|
||||
assert(s.starts_with(""));
|
||||
assert(!s.starts_with("o"));
|
||||
}
|
||||
|
||||
fn void test_print_null()
|
||||
{
|
||||
ZString z;
|
||||
int* y;
|
||||
ZString w = "hello";
|
||||
String s = string::format(mem, "%s %s %s", z, w, y);
|
||||
defer free(s);
|
||||
assert(s == "(null) hello 0x0");
|
||||
}
|
||||
|
||||
fn void test_strip()
|
||||
{
|
||||
String s = "ofke";
|
||||
assert(s.strip("of") == "ke");
|
||||
assert(s.strip("ofke") == "");
|
||||
assert(s.strip("ofkes") == "ofke");
|
||||
assert(s.strip("ofkf") == "ofke");
|
||||
assert(s.strip("") == "ofke");
|
||||
s = "";
|
||||
assert(s.strip("") == "");
|
||||
assert(s.strip("o") == "");
|
||||
}
|
||||
|
||||
fn void test_strip_end()
|
||||
{
|
||||
String s = "ofke";
|
||||
assert(s.strip_end("ke") == "of");
|
||||
assert(s.strip_end("ofke") == "");
|
||||
assert(s.strip_end("ofkes") == "ofke");
|
||||
assert(s.strip_end("ofkf") == "ofke");
|
||||
assert(s.strip_end("") == "ofke");
|
||||
s = "";
|
||||
assert(s.strip_end("") == "");
|
||||
assert(s.strip_end("o") == "");
|
||||
}
|
||||
|
||||
fn void test_ends_with()
|
||||
{
|
||||
String s = "ofke";
|
||||
assert(s.ends_with("ke"));
|
||||
assert(s.ends_with("ofke"));
|
||||
assert(!s.ends_with("ofkes"));
|
||||
assert(!s.ends_with("ofkf"));
|
||||
s = "";
|
||||
assert(s.ends_with(""));
|
||||
assert(!s.ends_with("e"));
|
||||
}
|
||||
|
||||
fn void test_trim()
|
||||
{
|
||||
String s = " \t\nabc ";
|
||||
assert(s.trim() == "abc");
|
||||
assert("\n\t".trim() == "");
|
||||
assert(" \n\tok".trim() == "ok");
|
||||
assert("!! \n\t ".trim() == "!!");
|
||||
assert(s.trim("c \t") == "\nab");
|
||||
assert("".trim() == "");
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn void test_trim_left()
|
||||
{
|
||||
String s = " \t\nabc ";
|
||||
assert(s.trim_left() == "abc ");
|
||||
assert("\n\t".trim_left() == "");
|
||||
assert(" \n\tok".trim_left() == "ok");
|
||||
assert("!! \n\t ".trim_left() == "!! \n\t ");
|
||||
assert("".trim_left() == "");
|
||||
}
|
||||
|
||||
fn void test_trim_right()
|
||||
{
|
||||
String s = " \t\nabc ";
|
||||
assert(s.trim_right() == " \t\nabc");
|
||||
assert("\n\t".trim_right() == "");
|
||||
assert(" \n\tok".trim_right() == " \n\tok");
|
||||
assert("!! \n\t ".trim_right() == "!!");
|
||||
assert("".trim_right() == "");
|
||||
}
|
||||
|
||||
fn void test_split()
|
||||
{
|
||||
String test = "abc|b||c|";
|
||||
String[] strings = test.split(mem, "|");
|
||||
assert(strings.len == 5);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b");
|
||||
assert(strings[2] == "");
|
||||
assert(strings[3] == "c");
|
||||
assert(strings[4] == "");
|
||||
free(strings);
|
||||
strings = test.split(mem, "|", 2);
|
||||
assert(strings.len == 2);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b||c|");
|
||||
free(strings);
|
||||
}
|
||||
|
||||
fn void test_split_skip_empty()
|
||||
{
|
||||
String test = "abc|b||c|";
|
||||
String[] strings = test.split(mem, "|", skip_empty: true);
|
||||
assert(strings.len == 3);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b");
|
||||
assert(strings[2] == "c");
|
||||
free(strings);
|
||||
strings = test.split(mem, "|", 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()
|
||||
{
|
||||
String[10] buffer;
|
||||
String test = "abc|b||c|";
|
||||
String[] strings = test.split_to_buffer("|", &buffer, skip_empty: true)!!;
|
||||
assert(strings.len == 3);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b");
|
||||
assert(strings[2] == "c");
|
||||
strings = test.split(mem, "|", 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()
|
||||
{
|
||||
String[5] b;
|
||||
String test = "abc|b||c|";
|
||||
String[] strings = test.split_to_buffer("|", &b)!!;
|
||||
assert(strings.len == 5);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b");
|
||||
assert(strings[2] == "");
|
||||
assert(strings[3] == "c");
|
||||
assert(strings[4] == "");
|
||||
String[4] c;
|
||||
assert(@catch(test.split_to_buffer("|", &c)) == SplitResult.BUFFER_EXCEEDED);
|
||||
strings = test.split(mem, "|", 2);
|
||||
assert(strings.len == 2);
|
||||
assert(strings[0] == "abc");
|
||||
assert(strings[1] == "b||c|");
|
||||
free(strings);
|
||||
}
|
||||
|
||||
fn void test_index_of()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.index_of("o")!! == 4);
|
||||
assert(test.index_of("ll")!! == 2);
|
||||
assert(test.index_of(" hello")!! == 11);
|
||||
assert(@catch(test.index_of("wi")));
|
||||
}
|
||||
|
||||
fn void test_rindex_of()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.rindex_of("o")!! == 16);
|
||||
assert(test.rindex_of("ll")!! == 14);
|
||||
assert(test.rindex_of("he")!! == 12);
|
||||
assert(test.rindex_of("world")!! == 6);
|
||||
assert(test.rindex_of("hello ")!! == 0);
|
||||
assert(@catch(test.rindex_of("wi")));
|
||||
}
|
||||
|
||||
fn void test_index_of_char()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.index_of_char('o')!! == 4);
|
||||
assert(test.index_of_char('l')!! == 2);
|
||||
assert(test.index_of_char('h')!! == 0);
|
||||
assert(@catch(test.index_of_char('x')));
|
||||
}
|
||||
|
||||
fn void test_rindex_of_char()
|
||||
{
|
||||
String test = "hello world hello";
|
||||
assert(test.rindex_of_char('o')!! == 16);
|
||||
assert(test.rindex_of_char('l')!! == 15);
|
||||
assert(test.rindex_of_char('h')!! == 12);
|
||||
assert(@catch(test.index_of_char('x')));
|
||||
}
|
||||
|
||||
fn void test_hex_conversion()
|
||||
{
|
||||
assert("0x123aCd".to_long()!! == 0x123acd);
|
||||
assert("123acD".to_long(16)!! == 0x123acd);
|
||||
}
|
||||
35
test/unit7/stdlib/core/string_iterator.c3
Normal file
35
test/unit7/stdlib/core/string_iterator.c3
Normal file
@@ -0,0 +1,35 @@
|
||||
module std::core::test::string_iterator::tests @test;
|
||||
|
||||
fn void test_at_start()
|
||||
{
|
||||
String test = "abcd";
|
||||
StringIterator iterator = test.iterator();
|
||||
assert(iterator.get()!! == 'a');
|
||||
assert(iterator.peek()!! == 'a');
|
||||
iterator.next()!!;
|
||||
assert(iterator.next()!! == 'b');
|
||||
assert(iterator.has_next());
|
||||
}
|
||||
|
||||
|
||||
fn void test_general()
|
||||
{
|
||||
String test = "åƦs1";
|
||||
StringIterator iterator = test.iterator();
|
||||
assert(iterator.get()!! == 'å');
|
||||
iterator.next()!!;
|
||||
assert(iterator.peek()!! == 'Ʀ');
|
||||
assert(iterator.next()!! == 'Ʀ');
|
||||
iterator.reset();
|
||||
assert(iterator.current == 0);
|
||||
}
|
||||
|
||||
fn void test_end()
|
||||
{
|
||||
String test = "åƦ";
|
||||
StringIterator iterator = test.iterator();
|
||||
assert(@ok(iterator.next()));
|
||||
assert(iterator.peek()!! == 'Ʀ');
|
||||
assert(@ok(iterator.next()));
|
||||
assert(@catch(iterator.next()));
|
||||
}
|
||||
332
test/unit7/stdlib/core/test_test.c3
Normal file
332
test/unit7/stdlib/core/test_test.c3
Normal file
@@ -0,0 +1,332 @@
|
||||
module test::std::core::test @test;
|
||||
import std::core::runtime @public;
|
||||
import std::core::builtin;
|
||||
import std::io;
|
||||
|
||||
struct TestState
|
||||
{
|
||||
int n_runs;
|
||||
int n_fails;
|
||||
bool expected_fail;
|
||||
|
||||
// NOTE: we must wrap setup/teardown functions to hide them from module @test runner
|
||||
TestFn setup_fn;
|
||||
TestFn teardown_fn;
|
||||
PanicFn old_panic; // original test panic, use it when it's really fails
|
||||
PanicFn panic_mock_fn; // mock panic, for testing the test:: failed
|
||||
void* buf;
|
||||
}
|
||||
|
||||
TestState state =
|
||||
{
|
||||
.setup_fn = fn void()
|
||||
{
|
||||
state.n_runs++;
|
||||
state.n_fails = 0;
|
||||
|
||||
assert (runtime::test_context.assert_print_backtrace);
|
||||
assert (builtin::panic != state.panic_mock_fn, "missing finalization of panic");
|
||||
state.buf = mem::alloc(int);
|
||||
|
||||
state.old_panic = builtin::panic;
|
||||
builtin::panic = state.panic_mock_fn;
|
||||
},
|
||||
.teardown_fn = fn void()
|
||||
{
|
||||
builtin::panic = state.old_panic;
|
||||
|
||||
assert(state.n_runs > 0);
|
||||
|
||||
if (state.expected_fail)
|
||||
{
|
||||
assert(state.n_fails > 0, "test case expected to fail, but it's not");
|
||||
}
|
||||
state.n_fails = 0;
|
||||
state.expected_fail = false;
|
||||
state.n_runs = 0;
|
||||
mem::free(state.buf);
|
||||
},
|
||||
.panic_mock_fn = fn void (String message, String file, String function, uint line)
|
||||
{
|
||||
if (runtime::test_context.is_in_panic) return;
|
||||
if (runtime::test_context.assert_print_backtrace)
|
||||
{
|
||||
$if env::NATIVE_STACKTRACE:
|
||||
builtin::print_backtrace(message, 0);
|
||||
$else
|
||||
io::printfn("No print_backtrace() supported by this platform");
|
||||
$endif
|
||||
}
|
||||
runtime::test_context.assert_print_backtrace = true;
|
||||
if (state.expected_fail)
|
||||
{
|
||||
state.n_fails++;
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin::panic = state.old_panic;
|
||||
state.old_panic(message, file, function, line);
|
||||
}
|
||||
runtime::test_context.is_in_panic = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
fn void test_eq()
|
||||
{
|
||||
test::eq(1, 1);
|
||||
test::eq(true, true);
|
||||
test::eq(1.31, 1.31);
|
||||
test::eq("foo", "foo");
|
||||
}
|
||||
|
||||
fn void test_almost_equal()
|
||||
{
|
||||
test::eq_approx(1, 1);
|
||||
test::eq_approx(1.31, 1.31);
|
||||
test::eq_approx(1.31f, 1.31f);
|
||||
test::eq_approx(double.nan, double.nan);
|
||||
test::eq_approx(float.nan, float.nan);
|
||||
test::eq_approx(1.31, 1.31, delta: 0.01);
|
||||
test::eq_approx(1.311, 1.312, delta: 0.01);
|
||||
test::eq_approx(1.311, 1.312, places: 2);
|
||||
// 7 decimal places are default
|
||||
test::eq_approx(1.00000001, 1.00000000);
|
||||
}
|
||||
|
||||
|
||||
fn void test_almost_equal_fails()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
// 7 decimal places are default
|
||||
test::eq_approx(1.0000001, 1.00000000);
|
||||
}
|
||||
|
||||
fn void test_almost_equal_fails_nan()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::eq_approx(1.0000001, double.nan);
|
||||
}
|
||||
|
||||
fn void test_almost_equal_fails_nan2()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::eq_approx(double.nan, 1);
|
||||
}
|
||||
|
||||
fn void test_almost_equal_fails_equal_nan_false()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::eq_approx(double.nan, double.nan, equal_nan: false);
|
||||
}
|
||||
|
||||
fn void setup_teardown()
|
||||
{
|
||||
state.n_runs = 0; // just in case of previous test failed
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
|
||||
test::eq(state.n_runs, 1);
|
||||
test::eq(state.n_fails, 0);
|
||||
test::eq(state.expected_fail, false);
|
||||
}
|
||||
|
||||
fn void setup_no_teardown()
|
||||
{
|
||||
test::@setup(state.setup_fn);
|
||||
|
||||
test::eq(state.n_runs, 1);
|
||||
test::eq(state.n_fails, 0);
|
||||
test::eq(state.expected_fail, false);
|
||||
|
||||
mem::free(state.buf);
|
||||
|
||||
// WARNING: reverting back original panic func
|
||||
builtin::panic = state.old_panic;
|
||||
}
|
||||
|
||||
fn void expected_fail()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::eq(state.n_fails, 0);
|
||||
test::eq(2, 1); // this fails, and we test it
|
||||
test::eq(state.n_fails, 1);
|
||||
}
|
||||
|
||||
fn void test_neq()
|
||||
{
|
||||
test::ne(2, 1);
|
||||
test::ne(false, true);
|
||||
test::ne(1.32, 1.31);
|
||||
test::ne("foo", "bar");
|
||||
}
|
||||
|
||||
fn void test_neq_fails()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::ne(1, 1);
|
||||
}
|
||||
|
||||
fn void test_gt()
|
||||
{
|
||||
test::gt(2, 1);
|
||||
test::gt(true, false);
|
||||
test::gt(1.32, 1.31);
|
||||
}
|
||||
|
||||
fn void test_gt_fails_when_equal()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::gt(2, 2);
|
||||
}
|
||||
|
||||
fn void test_gt_fails_when_less()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::gt(1, 2);
|
||||
}
|
||||
|
||||
|
||||
fn void test_gte()
|
||||
{
|
||||
test::ge(2, 1);
|
||||
test::ge(true, false);
|
||||
test::ge(1.32, 1.31);
|
||||
test::ge(2, 2);
|
||||
test::ge(true, true);
|
||||
test::ge(1.32, 1.32);
|
||||
}
|
||||
|
||||
fn void test_gte_fails_when_less()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::ge(1, 2);
|
||||
}
|
||||
|
||||
fn void test_lt()
|
||||
{
|
||||
test::lt(1, 2);
|
||||
test::lt(false, true);
|
||||
test::lt(1.31, 1.32);
|
||||
}
|
||||
|
||||
fn void test_lt_fails_when_equal()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::lt(2, 2);
|
||||
}
|
||||
|
||||
fn void test_lt_fails_when_greater()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::lt(2, 1);
|
||||
}
|
||||
|
||||
fn void test_lte()
|
||||
{
|
||||
test::le(1, 2);
|
||||
test::le(false, true);
|
||||
test::le(1.31, 1.32);
|
||||
test::le(2, 2);
|
||||
test::le(true, true);
|
||||
test::le(1.32, 1.32);
|
||||
}
|
||||
|
||||
fn void test_lte_fails_when_greater()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::le(2, 1);
|
||||
}
|
||||
|
||||
fn void test_check(){
|
||||
test::@check(1 == 1);
|
||||
test::@check(1.2 == 1.2, "1 == 1");
|
||||
test::@check(true == true, "1 == 1");
|
||||
test::@check("foo" == "foo", "2 == %d", 1 );
|
||||
}
|
||||
|
||||
fn void test_check_fails()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::@check(2 == 1, "2 == %d", 1 );
|
||||
}
|
||||
|
||||
fn void test_check_fails_no_info()
|
||||
{
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::@check(2 == 1);
|
||||
}
|
||||
|
||||
def TestIntFn = fn int! (int a, int b);
|
||||
def TestFailFn = fn void! (bool to_fail);
|
||||
|
||||
fault MyFault
|
||||
{
|
||||
FOO,
|
||||
}
|
||||
|
||||
fn void test_error()
|
||||
{
|
||||
TestFailFn ffail_void = fn void!(bool to_fail)
|
||||
{
|
||||
if (to_fail) return IoError.FILE_NOT_FOUND?;
|
||||
};
|
||||
TestIntFn ffail_int = fn int! (int a, int b)
|
||||
{
|
||||
if (b == 0) return IoError.FILE_NOT_FOUND?;
|
||||
return a / b;
|
||||
};
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
|
||||
test::@error(ffail_void(true), IoError.FILE_NOT_FOUND);
|
||||
test::@error(ffail_int(1, 0), IoError.FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
fn void test_error_not_raised()
|
||||
{
|
||||
TestIntFn ffail_int = fn int! (int a, int b) {
|
||||
if (b == 0) return IoError.FILE_NOT_FOUND?;
|
||||
return a / b;
|
||||
};
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
test::@error(ffail_int(1, 1), IoError.FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
fn void test_error_wrong_error_expected()
|
||||
{
|
||||
TestIntFn ffail_int = fn int! (int a, int b) {
|
||||
if (b == 0) return IoError.BUSY?;
|
||||
return a / b;
|
||||
};
|
||||
test::@setup(state.setup_fn, state.teardown_fn);
|
||||
state.expected_fail = true;
|
||||
|
||||
test::@error(ffail_int(1, 0), IoError.FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
fn void test_std_out_hijack()
|
||||
{
|
||||
io::print("print: aldsjalsdjlasjdlja\n");
|
||||
io::printf("printf: aldsjalsdjlasjdlja\n");
|
||||
io::eprint("eprint: aldsjalsdjlasjdlja\n");
|
||||
io::eprintfn("eprintfn: aldsjalsdjlasjdlja\n");
|
||||
io::fprint(io::stdout(), "fprint: stdout aldsjalsdjlasjdlja\n")!!;
|
||||
io::fprint(io::stderr(), "fprint: stderr aldsjalsdjlasjdlja\n")!!;
|
||||
io::fprintf(io::stderr(), "fprintf: stderr aldsjalsdjlasjdlja\n")!!;
|
||||
io::fprintf(io::stderr(), "fprintfn: stderr aldsjalsdjlasjdlja\n")!!;
|
||||
test::eq(true, true);
|
||||
}
|
||||
9
test/unit7/stdlib/core/values.c3
Normal file
9
test/unit7/stdlib/core/values.c3
Normal file
@@ -0,0 +1,9 @@
|
||||
module std::core::values @test;
|
||||
|
||||
fn void test_select()
|
||||
{
|
||||
const int X = @select(true, 1, "Hello");
|
||||
const String Y = @select(false, 1, "Hello");
|
||||
test::eq(X, 1);
|
||||
test::eq(Y, "Hello");
|
||||
}
|
||||
16
test/unit7/stdlib/crypto/rc4.c3
Normal file
16
test/unit7/stdlib/crypto/rc4.c3
Normal file
@@ -0,0 +1,16 @@
|
||||
import std::crypto;
|
||||
import std::io;
|
||||
|
||||
fn void rc_crypt() @test
|
||||
{
|
||||
Rc4 rc;
|
||||
rc.init(&&x"63727970746969");
|
||||
char[200] x;
|
||||
String text = "The quick brown fox jumps over the lazy dog.";
|
||||
rc.crypt(text, &x);
|
||||
char[?] res = x'2ac2fecdd8fbb84638e3a4
|
||||
820eb205cc8e29c28b9d5d
|
||||
6b2ef974f311964971c90e
|
||||
8b9ca16467ef2dc6fc3520';
|
||||
assert(res[:text.len] == x[:text.len]);
|
||||
}
|
||||
108
test/unit7/stdlib/encoding/base32.c3
Normal file
108
test/unit7/stdlib/encoding/base32.c3
Normal file
@@ -0,0 +1,108 @@
|
||||
module encoding::base32 @test;
|
||||
import std::encoding::base32;
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc4648#section-10
|
||||
|
||||
struct TestCase
|
||||
{
|
||||
char[] dec;
|
||||
char[] enc;
|
||||
}
|
||||
|
||||
TestCase[?] std_tests = {
|
||||
{ "", "" },
|
||||
{ "f", "MY======" },
|
||||
{ "fo", "MZXQ====" },
|
||||
{ "foo", "MZXW6===" },
|
||||
{ "foob", "MZXW6YQ=" },
|
||||
{ "fooba", "MZXW6YTB" },
|
||||
{ "foobar", "MZXW6YTBOI======" },
|
||||
};
|
||||
|
||||
TestCase[?] hex_tests = {
|
||||
{ "", "" },
|
||||
{ "f", "CO======" },
|
||||
{ "fo", "CPNG====" },
|
||||
{ "foo", "CPNMU===" },
|
||||
{ "foob", "CPNMUOG=" },
|
||||
{ "fooba", "CPNMUOJ1" },
|
||||
{ "foobar", "CPNMUOJ1E8======" },
|
||||
};
|
||||
|
||||
macro encode_tests(tests, alphabet, padding)
|
||||
{
|
||||
foreach (t : tests)
|
||||
{
|
||||
char[64] buf;
|
||||
usz n = base32::encode_len(t.dec.len, padding);
|
||||
base32::encode_buffer(t.dec, buf[:n], padding, alphabet);
|
||||
|
||||
char[] want = t.enc;
|
||||
usz! pad_idx = array::index_of(want, '=');
|
||||
if (try pad_idx && !padding)
|
||||
{
|
||||
want = want[:pad_idx];
|
||||
}
|
||||
|
||||
assert(buf[:n] == want, "got: %s, want: %s",
|
||||
(String)buf[:n], (String)want);
|
||||
}
|
||||
}
|
||||
|
||||
fn void encode()
|
||||
{
|
||||
encode_tests(std_tests, &base32::STANDARD, '=');
|
||||
encode_tests(hex_tests, &base32::HEX, '=');
|
||||
}
|
||||
|
||||
fn void encode_nopadding()
|
||||
{
|
||||
encode_tests(std_tests, &base32::STANDARD, base32::NO_PAD);
|
||||
encode_tests(hex_tests, &base32::HEX, base32::NO_PAD);
|
||||
}
|
||||
|
||||
macro decode_tests(tests, alphabet, padding)
|
||||
{
|
||||
foreach (t : tests)
|
||||
{
|
||||
char[] input = t.enc[..];
|
||||
usz! pad_idx = array::index_of(input, '=');
|
||||
if (try pad_idx && !padding)
|
||||
{
|
||||
input = input[:pad_idx];
|
||||
}
|
||||
|
||||
char[64] buf;
|
||||
usz n = base32::decode_len(input.len, padding);
|
||||
char[] buf2 = base32::decode_buffer(input, buf[:n], padding, alphabet)!!;
|
||||
|
||||
assert(buf2 == t.dec, "got: %s, want: %s", buf2, (String)t.dec);
|
||||
}
|
||||
}
|
||||
|
||||
fn void decode()
|
||||
{
|
||||
decode_tests(std_tests, &base32::STANDARD, '=');
|
||||
decode_tests(hex_tests, &base32::HEX, '=');
|
||||
}
|
||||
|
||||
fn void decode_nopadding()
|
||||
{
|
||||
decode_tests(std_tests, &base32::STANDARD, base32::NO_PAD);
|
||||
decode_tests(hex_tests, &base32::HEX, base32::NO_PAD);
|
||||
}
|
||||
|
||||
fn void base32_api()
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
foreach (t : std_tests)
|
||||
{
|
||||
String got = base32::encode_temp(t.dec)!!;
|
||||
assert(got == t.enc, "got: %s, want: %s", got, t.enc);
|
||||
|
||||
char[] got_chars = base32::decode_temp(t.enc)!!;
|
||||
assert(got_chars == t.dec, "got: %s, want: %s", got_chars, t.dec);
|
||||
}
|
||||
};
|
||||
}
|
||||
122
test/unit7/stdlib/encoding/base64.c3
Normal file
122
test/unit7/stdlib/encoding/base64.c3
Normal file
@@ -0,0 +1,122 @@
|
||||
module encoding::base64_test @test;
|
||||
import std::encoding::base64;
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc4648#section-10
|
||||
|
||||
struct TestCase
|
||||
{
|
||||
char[] in;
|
||||
char[] out;
|
||||
}
|
||||
import std;
|
||||
|
||||
fn void encode()
|
||||
{
|
||||
TestCase[] tcases = {
|
||||
{ "", "" },
|
||||
{ "f", "Zg==" },
|
||||
{ "fo", "Zm8=" },
|
||||
{ "foo", "Zm9v" },
|
||||
{ "foob", "Zm9vYg==" },
|
||||
{ "fooba", "Zm9vYmE=" },
|
||||
{ "foobar", "Zm9vYmFy" },
|
||||
{ "test", "dGVzdA==" },
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
|
||||
usz n = base64::encode_len(tc.in.len, base64::DEFAULT_PAD);
|
||||
char[64] buf;
|
||||
char[] res = base64::encode_buffer(tc.in, buf[:n]);
|
||||
assert(res == tc.out);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn void encode_nopadding()
|
||||
{
|
||||
TestCase[] tcases = {
|
||||
{ "", "" },
|
||||
{ "f", "Zg" },
|
||||
{ "fo", "Zm8" },
|
||||
{ "foo", "Zm9v" },
|
||||
{ "foob", "Zm9vYg" },
|
||||
{ "fooba", "Zm9vYmE" },
|
||||
{ "foobar", "Zm9vYmFy" },
|
||||
{ "test", "dGVzdA" },
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
usz n = base64::encode_len(tc.in.len, base64::NO_PAD);
|
||||
char[64] buf;
|
||||
base64::encode_buffer(tc.in, buf[:n], padding: base64::NO_PAD);
|
||||
assert(buf[:n] == tc.out);
|
||||
}
|
||||
}
|
||||
|
||||
fn void decode()
|
||||
{
|
||||
TestCase[] tcases = {
|
||||
{ "", "" },
|
||||
{ "Zg==", "f" },
|
||||
{ "Zm8=", "fo" },
|
||||
{ "Zm9v", "foo" },
|
||||
{ "Zm9vYg==", "foob" },
|
||||
{ "Zm9vYmE=", "fooba" },
|
||||
{ "Zm9vYmFy", "foobar" },
|
||||
{ "Zm9vYmFy", "foobar" },
|
||||
{ "dGVzdA==", "test" },
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
usz n = base64::decode_len(tc.in.len, base64::DEFAULT_PAD)!!;
|
||||
char[64] buf;
|
||||
char[] res = base64::decode_buffer(tc.in, buf[:n])!!;
|
||||
assert(res == tc.out);
|
||||
}
|
||||
}
|
||||
|
||||
fn void decode_nopadding()
|
||||
{
|
||||
TestCase[] tcases = {
|
||||
{ "", "" },
|
||||
{ "Zg", "f" },
|
||||
{ "Zm8", "fo" },
|
||||
{ "Zm9v", "foo" },
|
||||
{ "Zm9vYg", "foob" },
|
||||
{ "Zm9vYmE", "fooba" },
|
||||
{ "Zm9vYmFy", "foobar" },
|
||||
{ "dGVzdA", "test" },
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
usz n = base64::decode_len(tc.in.len, base64::NO_PAD)!!;
|
||||
char[64] buf;
|
||||
char[] res = base64::decode_buffer(tc.in, buf[:n], base64::NO_PAD)!!;
|
||||
assert(res == tc.out);
|
||||
}
|
||||
}
|
||||
|
||||
fn void urlencode() {
|
||||
TestCase[] tcases = {
|
||||
{ x"14fb9c03d97e", "FPucA9l-"},
|
||||
};
|
||||
|
||||
@pool()
|
||||
{
|
||||
usz n;
|
||||
char[] got;
|
||||
char[64] buf;
|
||||
foreach (t : tcases)
|
||||
{
|
||||
char[] res = base64::encode_buffer(t.in, buf[..], alphabet: &base64::URL);
|
||||
assert (res == t.out, "got: %s, want: %s", (String)res, (String)t.out);
|
||||
|
||||
res = base64::decode_buffer(t.out, buf[..], alphabet: &base64::URL)!!;
|
||||
assert (res == t.in, "got: %s, want: %s", (String)res, (String)t.in);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
68
test/unit7/stdlib/encoding/csv.c3
Normal file
68
test/unit7/stdlib/encoding/csv.c3
Normal file
@@ -0,0 +1,68 @@
|
||||
module csv_test @test;
|
||||
import std::encoding::csv;
|
||||
import std::io;
|
||||
|
||||
struct TestCase {
|
||||
String input;
|
||||
String[] want;
|
||||
String sep;
|
||||
}
|
||||
|
||||
fn void csv_each_row()
|
||||
{
|
||||
TestCase[] tests = {
|
||||
{
|
||||
"aaa,bbb,ccc",
|
||||
{"aaa","bbb","ccc"},
|
||||
","
|
||||
},
|
||||
{
|
||||
"aaa;bbb;ccc",
|
||||
{"aaa", "bbb", "ccc"},
|
||||
";"
|
||||
},
|
||||
{
|
||||
"aaa,bbb,ccc\n111,222,333",
|
||||
{"aaa", "bbb", "ccc", "111", "222", "333"},
|
||||
","
|
||||
},
|
||||
{
|
||||
"aaa , bbb\t ,ccc\r\n 111,222,333\r\n",
|
||||
{"aaa ", " bbb\t ", "ccc", " 111", "222", "333"},
|
||||
","
|
||||
},
|
||||
};
|
||||
foreach (t : tests) {
|
||||
String[] want = t.want;
|
||||
|
||||
CsvReader r;
|
||||
r.init((ByteReader){}.init(t.input), t.sep);
|
||||
r.@each_row(; String[] row) {
|
||||
foreach (i, s : row) {
|
||||
assert(want.len > 0,
|
||||
"more records than we want");
|
||||
assert(s == want[0], "columns do not match; "
|
||||
"got: '%s', want: '%s'", s, want[0]);
|
||||
want = want[1..];
|
||||
}
|
||||
};
|
||||
assert(want.len == 0, "not enough records found");
|
||||
}
|
||||
}
|
||||
|
||||
fn void csv_row()
|
||||
{
|
||||
TestCase t = {
|
||||
"aaa,bbb,ccc",
|
||||
{"aaa", "bbb", "ccc"},
|
||||
","
|
||||
};
|
||||
CsvReader r;
|
||||
r.init((ByteReader){}.init(t.input), t.sep);
|
||||
CsvRow row = r.tread_row()!!;
|
||||
assert(row.list.len == t.want.len, "not enough records found");
|
||||
for (int i = 0; i < row.list.len; i++) {
|
||||
assert(row.list[i] == t.want[i],"columns do not match; "
|
||||
"got: '%s', want: '%s'", row.list[i], t.want[i]);
|
||||
}
|
||||
}
|
||||
49
test/unit7/stdlib/encoding/hex.c3
Normal file
49
test/unit7/stdlib/encoding/hex.c3
Normal file
@@ -0,0 +1,49 @@
|
||||
module encoding::hex @test;
|
||||
import std::encoding::hex;
|
||||
|
||||
struct TestCase
|
||||
{
|
||||
char[] dec;
|
||||
char[] enc;
|
||||
}
|
||||
|
||||
TestCase[] tests = {
|
||||
{"", ""},
|
||||
{{'g'}, "67"},
|
||||
{{0,1,2,3,4,5,6,7}, "0001020304050607"},
|
||||
{{8,9,10,11,12,13,14,15}, "08090a0b0c0d0e0f"},
|
||||
{{0xf0, 0xf1, 0xf2, 0xf3}, "f0f1f2f3"},
|
||||
{{0xe3, 0xa1}, "e3a1"},
|
||||
{{0xe3, 0xa1}, "E3A1"},
|
||||
};
|
||||
|
||||
fn void encode()
|
||||
{
|
||||
usz n;
|
||||
char[64] buf;
|
||||
foreach (t : tests)
|
||||
{
|
||||
n = hex::encode_bytes(t.dec, buf[..]);
|
||||
String want = ((String)t.enc).to_lower_tcopy();
|
||||
assert(want == buf[:n], "encode failed: got: %s, want: %s", buf[:n], want);
|
||||
@pool()
|
||||
{
|
||||
assert(want == hex::tencode(t.dec));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn void decode()
|
||||
{
|
||||
usz n;
|
||||
char[64] buf;
|
||||
foreach (t : tests)
|
||||
{
|
||||
n = hex::decode_bytes(t.enc, buf[..])!!;
|
||||
assert(t.dec == buf[:n], "decode failed: got: %s, want: %s", buf[:n], t.dec);
|
||||
@pool()
|
||||
{
|
||||
assert(t.dec == hex::tdecode(t.enc)!!);
|
||||
};
|
||||
}
|
||||
}
|
||||
53
test/unit7/stdlib/encoding/json.c3
Normal file
53
test/unit7/stdlib/encoding/json.c3
Normal file
@@ -0,0 +1,53 @@
|
||||
module json_test @test;
|
||||
import std::collections::object;
|
||||
import std::io;
|
||||
import std::encoding::json;
|
||||
|
||||
fn void simple_test()
|
||||
{
|
||||
ByteReader reader;
|
||||
reader.init(`{ "b": 123, "c": [ { "d": 66 }, null, "hello\tworld", false, { "id": "xyz" } ] }`);
|
||||
Object* o = json::parse(mem, &reader)!!;
|
||||
defer o.free();
|
||||
assert(o.get_int("b")!! == 123);
|
||||
assert(o.get("c").get_len()!! == 5);
|
||||
assert(o.get("c").get_at(0).get_int("d")!! == 66);
|
||||
assert(o.get("c").get_at(1).is_null()!!);
|
||||
assert(o.get("c").get_string_at(2)!! == "hello\tworld");
|
||||
assert(o.get("c").get_bool_at(3)!! == false);
|
||||
assert(o.get("c").get_at(4).get_string("id")!! == "xyz");
|
||||
}
|
||||
|
||||
fn void simple_test2()
|
||||
{
|
||||
ByteReader reader;
|
||||
reader.init(`{"jsonrpc":"2.0","id":null,"method":"initialize"}`);
|
||||
Object* o = json::parse(mem, &reader)!!;
|
||||
defer o.free();
|
||||
}
|
||||
|
||||
|
||||
fn void test_string()
|
||||
{
|
||||
Object* o = json::parse_string(mem, `{"jsonrpc":"2","id":null,"method":"initialize"}`)!!;
|
||||
defer o.free();
|
||||
String s = string::tformat("%s", *o);
|
||||
Object* o2 = json::parse_string(mem, s)!!;
|
||||
defer o2.free();
|
||||
String s2 = string::tformat("%s", *o2);
|
||||
assert(s2 == s, "Unexpectedly got %s and not %s", s2, s);
|
||||
}
|
||||
|
||||
fn void test_temp_string()
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
Object* o = json::tparse_string(`{"jsonrpc":"2","id":null,"method":"initialize"}`)!!;
|
||||
defer o.free();
|
||||
String s = string::tformat("%s", *o);
|
||||
Object* o2 = json::tparse_string(s)!!;
|
||||
defer o2.free();
|
||||
String s2 = string::tformat("%s", *o2);
|
||||
assert(s2 == s, "Unexpectedly got %s and not %s", s2, s);
|
||||
};
|
||||
}
|
||||
24
test/unit7/stdlib/hash/fnv32a.c3
Normal file
24
test/unit7/stdlib/hash/fnv32a.c3
Normal file
@@ -0,0 +1,24 @@
|
||||
module std::hash::fnv32a_test @test;
|
||||
import std::hash::fnv32a;
|
||||
|
||||
fn void test_fnv32a()
|
||||
{
|
||||
Fnv32a hash;
|
||||
|
||||
char[] input = "Hello world";
|
||||
uint want = 0x594d29c7;
|
||||
|
||||
// update
|
||||
hash.init();
|
||||
hash.update(input);
|
||||
assert ((uint)hash == want, "got: %d, want: %d", hash, want);
|
||||
|
||||
// update_char
|
||||
hash.init();
|
||||
foreach (c : input) hash.update_char(c);
|
||||
assert ((uint)hash == want, "got: %d, want: %d", hash, want);
|
||||
|
||||
// encode
|
||||
uint encoded = fnv32a::encode(input);
|
||||
assert (encoded == want, "got: %d, want: %d", encoded, want);
|
||||
}
|
||||
24
test/unit7/stdlib/hash/fnv64a.c3
Normal file
24
test/unit7/stdlib/hash/fnv64a.c3
Normal file
@@ -0,0 +1,24 @@
|
||||
module std::hash::fnv64a_test @test;
|
||||
import std::hash::fnv64a;
|
||||
|
||||
fn void test_fnv64a()
|
||||
{
|
||||
Fnv64a hash;
|
||||
|
||||
char[] input = "Hello world";
|
||||
ulong want = 0x2713f785a33764c7;
|
||||
|
||||
// update
|
||||
hash.init();
|
||||
hash.update(input);
|
||||
assert ((ulong)hash == want, "got: %d, want: %d", hash, want);
|
||||
|
||||
// update_char
|
||||
hash.init();
|
||||
foreach (c : input) hash.update_char(c);
|
||||
assert ((ulong)hash == want, "got: %d, want: %d", hash, want);
|
||||
|
||||
// encode
|
||||
ulong encoded = fnv64a::encode(input);
|
||||
assert (encoded == want, "got: %d, want: %d", encoded, want);
|
||||
}
|
||||
41
test/unit7/stdlib/hash/md5.c3
Normal file
41
test/unit7/stdlib/hash/md5.c3
Normal file
@@ -0,0 +1,41 @@
|
||||
module std::hash::md5_test @test;
|
||||
import std::hash::md5;
|
||||
|
||||
|
||||
fn void test_md5_rfc()
|
||||
{
|
||||
Md5 md5;
|
||||
md5.init();
|
||||
assert (md5.final() == x'd41d8cd98f00b204e9800998ecf8427e');
|
||||
|
||||
md5.init();
|
||||
md5.update("a");
|
||||
assert (md5.final() == x'0cc175b9c0f1b6a831c399e269772661');
|
||||
|
||||
md5.init();
|
||||
md5.update("abc");
|
||||
assert (md5.final() == x'900150983cd24fb0d6963f7d28e17f72');
|
||||
|
||||
md5.init();
|
||||
md5.update("message ");
|
||||
md5.update("digest");
|
||||
assert(md5.final() == x'f96b697d7cb7938d525a2f31aaf161d0');
|
||||
|
||||
md5.init();
|
||||
md5.update("abcdefghijklmnopqrstuvwxyz");
|
||||
assert(md5.final() == x'c3fcd3d76192e4007dfb496cca67e13b');
|
||||
|
||||
md5.init();
|
||||
md5.update("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||
assert(md5.final() == x'd174ab98d277d9f5a5611c2c9f419d9f');
|
||||
|
||||
md5.init();
|
||||
md5.update("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
|
||||
assert(md5.final() == x'57edf4a22be3c955ac49da2e2107b67a');
|
||||
|
||||
}
|
||||
|
||||
fn void test_md5_hash()
|
||||
{
|
||||
assert(md5::hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890") == x'57edf4a22be3c955ac49da2e2107b67a');
|
||||
}
|
||||
70
test/unit7/stdlib/hash/sha1.c3
Normal file
70
test/unit7/stdlib/hash/sha1.c3
Normal file
@@ -0,0 +1,70 @@
|
||||
module std::hash::sha1_test @test;
|
||||
import std::hash::sha1;
|
||||
|
||||
fn void test_sha1_abc()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
sha.update("abc");
|
||||
assert(sha.final() == x"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
|
||||
}
|
||||
|
||||
fn void test_sha1_even_longer()
|
||||
{
|
||||
char[] content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce viverra nulla nec neque convallis feugiat. Vestibulum sodales at.";
|
||||
Sha1 sha1;
|
||||
sha1.init();
|
||||
sha1.update(content);
|
||||
assert(sha1.final() == x"7ba51bc42c21e6159556537c2134d1c2028799ef");
|
||||
}
|
||||
|
||||
fn void test_sha1_longer()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
sha.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
|
||||
assert(sha.final() == x"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
|
||||
}
|
||||
|
||||
fn void test_pbkdf2()
|
||||
{
|
||||
char[] pw = "password";
|
||||
char[] s = "salt";
|
||||
char[20] out;
|
||||
sha1::pbkdf2(pw, s, 1, &out);
|
||||
assert(out == x'0c60c80f961f0e71f3a9b524af6012062fe037a6');
|
||||
sha1::pbkdf2(pw, s, 2, &out);
|
||||
assert(out == x'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957');
|
||||
sha1::pbkdf2(pw, s, 4096, &out);
|
||||
assert(out == x'4b007901b765489abead49d926f721d065a429c1');
|
||||
}
|
||||
|
||||
fn void test_pbkdf2_2()
|
||||
{
|
||||
char[] pw = "passwordPASSWORDpassword";
|
||||
char[] s = "saltSALTsaltSALTsaltSALTsaltSALTsalt";
|
||||
char[25] out;
|
||||
sha1::pbkdf2(pw, s, 4096, &out);
|
||||
assert(out == x'3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038');
|
||||
}
|
||||
|
||||
fn void test_pbkdf2_3()
|
||||
{
|
||||
char[] pw = "pass\0word";
|
||||
char[] salt = "sa\0lt";
|
||||
char[16] out;
|
||||
sha1::pbkdf2(pw, salt, 4096, &out);
|
||||
assert(out == x'56fa6aa75548099dcc37d7f03425e0c3');
|
||||
}
|
||||
|
||||
fn void test_sha1_million_a()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
const int COUNT = 1_000_000;
|
||||
for (int i = 0; i < COUNT / 10; i++)
|
||||
{
|
||||
sha.update("aaaaaaaaaa");
|
||||
}
|
||||
assert(sha.final() == x"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
|
||||
}
|
||||
74
test/unit7/stdlib/hash/sha256.c3
Normal file
74
test/unit7/stdlib/hash/sha256.c3
Normal file
@@ -0,0 +1,74 @@
|
||||
module std::hash::sha256_test @test;
|
||||
import std::hash::sha256;
|
||||
|
||||
fn void test_sha256_empty()
|
||||
{
|
||||
Sha256 sha;
|
||||
sha.init();
|
||||
sha.update("");
|
||||
|
||||
assert(sha.final() == x"E3B0C442 98FC1C14 9AFBF4C8 996FB924 27AE41E4 649B934C A495991B 7852B855");
|
||||
}
|
||||
|
||||
fn void test_sha256_abc()
|
||||
{
|
||||
Sha256 sha;
|
||||
sha.init();
|
||||
sha.update("abc");
|
||||
|
||||
assert(sha.final() == x"BA7816BF 8F01CFEA 414140DE 5DAE2223 B00361A3 96177A9C B410FF61 F20015AD");
|
||||
}
|
||||
|
||||
fn void test_sha256_longer()
|
||||
{
|
||||
Sha256 sha;
|
||||
sha.init();
|
||||
sha.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
|
||||
assert(sha.final() == x"59F109D9 533B2B70 E7C3B814 A2BD218F 78EA5D37 14455BC6 7987CF0D 664399CF");
|
||||
}
|
||||
|
||||
fn void test_pbkdf2()
|
||||
{
|
||||
char[] pw = "password";
|
||||
char[] s = "salt";
|
||||
char[32] out;
|
||||
sha256::pbkdf2(pw, s, 1, &out);
|
||||
assert(out == x'120FB6CF FCF8B32C 43E72252 56C4F837 A86548C9 2CCC3548 0805987C B70BE17B');
|
||||
sha256::pbkdf2(pw, s, 2, &out);
|
||||
assert(out == x'AE4D0C95 AF6B46D3 2D0ADFF9 28F06DD0 2A303F8E F3C251DF D6E2D85A 95474C43');
|
||||
sha256::pbkdf2(pw, s, 4096, &out);
|
||||
assert(out == x'C5E478D5 9288C841 AA530DB6 845C4C8D 962893A0 01CE4E11 A4963873 AA98134A');
|
||||
}
|
||||
|
||||
fn void test_pbkdf2_2()
|
||||
{
|
||||
char[] pw = "passwordPASSWORDpassword";
|
||||
char[] s = "saltSALTsaltSALTsaltSALTsaltSALTsalt";
|
||||
char[32] out;
|
||||
sha256::pbkdf2(pw, s, 4096, &out);
|
||||
assert(out == x'348C89DB CBD32B2F 32D814B8 116E84CF 2B17347E BC180018 1C4E2A1F B8DD53E1');
|
||||
}
|
||||
|
||||
|
||||
fn void test_pbkdf2_3()
|
||||
{
|
||||
char[] pw = "pass\0word";
|
||||
char[] salt = "sa\0lt";
|
||||
char[32] out;
|
||||
sha256::pbkdf2(pw, salt, 4096, &out);
|
||||
|
||||
assert(out == x'89B69D05 16F82989 3C696226 650A8687 8C029AC1 3EE27650 9D5AE58B 6466A724');
|
||||
}
|
||||
|
||||
fn void test_sha256_million_a()
|
||||
{
|
||||
Sha256 sha;
|
||||
sha.init();
|
||||
const int COUNT = 1_000_000;
|
||||
for (int i = 0; i < COUNT / 10; i++)
|
||||
{
|
||||
sha.update("aaaaaaaaaa");
|
||||
}
|
||||
|
||||
assert(sha.final() == x"CDC76E5C 9914FB92 81A1C7E2 84D73E67 F1809A48 A497200E 046D39CC C7112CD0");
|
||||
}
|
||||
249
test/unit7/stdlib/io/bits.c3
Normal file
249
test/unit7/stdlib/io/bits.c3
Normal file
@@ -0,0 +1,249 @@
|
||||
module std::io::bits @test;
|
||||
import std::io;
|
||||
|
||||
fn void test_write_0b1() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b11111111, 1)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"80"); // 0b1000 0000
|
||||
}
|
||||
|
||||
fn void test_write_0b1111() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b11111111, 4)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"f0"); // 0b1111 0000
|
||||
}
|
||||
|
||||
fn void test_write_0b1111_1111() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b11111111, 8)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"ff");
|
||||
}
|
||||
|
||||
fn void test_write_0b1000() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b0001000, 4)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"80"); // 0b1000 0000
|
||||
}
|
||||
|
||||
fn void test_write_0b01000() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b0001000, 5)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"40"); // 0b0100 0000
|
||||
}
|
||||
|
||||
fn void test_write_0b0001() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b0000001, 4)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"10"); // 0b0001 0000
|
||||
}
|
||||
|
||||
|
||||
fn void test_write_0b0000_0001() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b0000001, 8)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"01"); // 0b0000 0001
|
||||
}
|
||||
|
||||
fn void test_write_10_bits() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0x789, 10)!!; // 01|11 1000 1001
|
||||
bw.flush()!!;
|
||||
|
||||
// e 2 4 0
|
||||
assert(w.str_view() == x"e2 40"); // 0b1110 0010 0100 0000
|
||||
}
|
||||
|
||||
fn void test_write_16_bits() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xfafb, 16)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"fa fb");
|
||||
}
|
||||
|
||||
fn void test_write_24_bits() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xfafbfc, 24)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"fa fb fc");
|
||||
}
|
||||
|
||||
fn void test_write_30_bits() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xf0f1f2f3, 30)!!; // 11 | 110000111100011111001011110011
|
||||
bw.flush()!!;
|
||||
// c 3 c 7 c b c c
|
||||
assert(w.str_view() == x"c3 c7 cb cc"); // 1100 0011 1100 0111 1100 1011 1100 1100
|
||||
}
|
||||
|
||||
fn void test_write_32_bits() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xfafbfcfd, 32)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"fa fb fc fd");
|
||||
}
|
||||
|
||||
fn void test_write_2_bits_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0b11111111, 2)!!;
|
||||
bw.write_bits(0b00000001, 2)!!;
|
||||
bw.write_bits(0b11111111, 2)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"dc"); // 0b1101 1100
|
||||
}
|
||||
|
||||
fn void test_write_10_bits_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0x789, 10)!!; // 01 | 11 1000 1001
|
||||
bw.write_bits(0xabc, 10)!!; // 10 | 10 1011 1100
|
||||
bw.write_bits(0xdef, 10)!!; // 11 | 01 1110 1111
|
||||
bw.flush()!!;
|
||||
|
||||
// e 2 6 b c 7 b c
|
||||
assert(w.str_view() == x"e2 6b c7 bc"); // 0b1110 0010 0110 1011 1100 0111 1011 1100
|
||||
}
|
||||
|
||||
fn void test_write_24_bits_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xfafbfc, 24)!!;
|
||||
bw.write_bits(0xfdfeff, 24)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"fa fb fc fd fe ff");
|
||||
}
|
||||
|
||||
fn void test_write_30_bits_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xf0f1f2f3, 30)!!; // 11 | 110000111100011111001011110011
|
||||
bw.write_bits(0xfafbfcfd, 30)!!; // 11 | 111010111110111111110011111101
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"c3 c7 cb cf af bf cf d0");
|
||||
}
|
||||
|
||||
fn void test_write_32_bits_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xf0f1f2f3, 32)!!;
|
||||
bw.write_bits(0xfafbfcfd, 32)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"f0 f1 f2 f3 fa fb fc fd");
|
||||
}
|
||||
|
||||
fn void test_write_mixed_multiple() {
|
||||
ByteWriter w;
|
||||
w.temp_init();
|
||||
|
||||
BitWriter bw;
|
||||
bw.init(&w);
|
||||
|
||||
bw.write_bits(0xf0f1f2f3, 8)!!;
|
||||
bw.write_bits(0xf0f1f2f3, 32)!!;
|
||||
bw.write_bits(0xfafbfcfd, 30)!!;
|
||||
bw.write_bits(0xf4f5f6f7, 10)!!;
|
||||
bw.flush()!!;
|
||||
|
||||
assert(w.str_view() == x"f3 f0 f1 f2 f3 eb ef f3 f6 f7");
|
||||
}
|
||||
94
test/unit7/stdlib/io/bufferstream.c3
Normal file
94
test/unit7/stdlib/io/bufferstream.c3
Normal file
@@ -0,0 +1,94 @@
|
||||
module std::io @test;
|
||||
|
||||
const DATA = "Lorem ipsum blandit.";
|
||||
|
||||
fn void readbuffer_large()
|
||||
{
|
||||
ByteReader src;
|
||||
src.init(DATA);
|
||||
char[DATA.len] buf;
|
||||
ReadBuffer reader_buf;
|
||||
reader_buf.init(&src, buf[..]);
|
||||
|
||||
char[DATA.len] bytes;
|
||||
usz n = reader_buf.read(bytes[..])!!;
|
||||
|
||||
assert(n == DATA.len, "large read failed: got %d; want %d", n, DATA.len);
|
||||
String got = (String)bytes[..];
|
||||
assert(got == DATA, "large read failed: got %s; want %s", got, DATA);
|
||||
}
|
||||
|
||||
fn void readbuffer()
|
||||
{
|
||||
ByteReader src;
|
||||
src.init(DATA);
|
||||
char[3] buf;
|
||||
ReadBuffer reader_buf;
|
||||
reader_buf.init(&src, buf[..]);
|
||||
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
|
||||
usz n = io::copy_to(&reader_buf, &bw)!!;
|
||||
|
||||
assert(n == DATA.len, "got %d; want %d", n, DATA.len);
|
||||
String got = bw.str_view();
|
||||
assert(got == DATA, "got %s; want %s", got, DATA);
|
||||
}
|
||||
|
||||
fn void writebuffer_large()
|
||||
{
|
||||
ByteWriter out;
|
||||
out.temp_init();
|
||||
char[16] buf;
|
||||
WriteBuffer write_buf;
|
||||
write_buf.init(&out, buf[..]);
|
||||
|
||||
usz n = write_buf.write(DATA)!!;
|
||||
|
||||
assert(n == DATA.len, "large write failed: got %d; want %d", n, DATA.len);
|
||||
String got = out.str_view();
|
||||
assert(got == DATA, "large write failed: got %s; want %s", got, DATA);
|
||||
}
|
||||
|
||||
fn void writebuffer()
|
||||
{
|
||||
ByteReader br;
|
||||
br.init(DATA);
|
||||
ByteWriter out;
|
||||
out.temp_init();
|
||||
char[3] buf;
|
||||
WriteBuffer write_buf;
|
||||
write_buf.init(&out, buf[..]);
|
||||
|
||||
usz n = io::copy_to(&br, &write_buf)!!;
|
||||
|
||||
assert(n == DATA.len, "got %d; want %d", n, DATA.len);
|
||||
String got = out.str_view();
|
||||
assert(got == DATA, "got %s; want %s", got, DATA);
|
||||
}
|
||||
|
||||
fn void writebuffer_write_byte()
|
||||
{
|
||||
ByteWriter out;
|
||||
out.temp_init();
|
||||
char[2] buf;
|
||||
WriteBuffer write_buf;
|
||||
write_buf.init(&out, buf[..]);
|
||||
|
||||
write_buf.write_byte('a')!!;
|
||||
assert(write_buf.str_view() == "a");
|
||||
assert(out.str_view() == "");
|
||||
|
||||
write_buf.write_byte('b')!!;
|
||||
assert(write_buf.str_view() == "ab");
|
||||
assert(out.str_view() == "");
|
||||
|
||||
write_buf.write_byte('c')!!;
|
||||
assert(write_buf.str_view() == "c");
|
||||
assert(out.str_view() == "ab");
|
||||
|
||||
write_buf.flush()!!;
|
||||
assert(write_buf.str_view() == "");
|
||||
assert(out.str_view() == "abc");
|
||||
}
|
||||
29
test/unit7/stdlib/io/bytebuffer.c3
Normal file
29
test/unit7/stdlib/io/bytebuffer.c3
Normal file
@@ -0,0 +1,29 @@
|
||||
module std::io::bytebuffer @test;
|
||||
import std::io;
|
||||
|
||||
fn void write_read()
|
||||
{
|
||||
ByteBuffer buffer;
|
||||
buffer.new_init(0);
|
||||
defer buffer.free();
|
||||
buffer.write("hello")!!;
|
||||
|
||||
char[8] bytes;
|
||||
usz n = buffer.read(bytes[..])!!;
|
||||
assert(n == 5);
|
||||
assert((String)bytes[:n] == "hello");
|
||||
|
||||
buffer.write("hello world")!!;
|
||||
n = buffer.read(bytes[..])!!;
|
||||
assert(n == bytes.len);
|
||||
assert((String)bytes[:n] == "hello wo");
|
||||
assert(buffer.read_idx == 1);
|
||||
|
||||
char c = buffer.read_byte()!!;
|
||||
assert(c == 'r');
|
||||
buffer.pushback_byte()!!;
|
||||
|
||||
n = buffer.read(bytes[..])!!;
|
||||
assert((String)bytes[:n] == "rld");
|
||||
assert(buffer.read_idx == 1);
|
||||
}
|
||||
72
test/unit7/stdlib/io/bytestream.c3
Normal file
72
test/unit7/stdlib/io/bytestream.c3
Normal file
@@ -0,0 +1,72 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void bytestream()
|
||||
{
|
||||
ByteReader r;
|
||||
r.init("abc");
|
||||
InStream s = &r;
|
||||
assert(s.len() == 3);
|
||||
char[5] buffer;
|
||||
assert('a' == s.read_byte()!!);
|
||||
s.pushback_byte()!!;
|
||||
usz len = s.read(&buffer)!!;
|
||||
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");
|
||||
s.seek(0, SET)!!;
|
||||
io::copy_to(s, ws)!!;
|
||||
s.seek(1, SET)!!;
|
||||
s.write_to(ws)!!;
|
||||
assert(w.str_view() == "helloworldabcbc");
|
||||
}
|
||||
|
||||
fn void bytewriter_buffer()
|
||||
{
|
||||
ByteWriter writer;
|
||||
char[8] z;
|
||||
writer.init_with_buffer(&z);
|
||||
OutStream s = &writer;
|
||||
s.write("hello")!!;
|
||||
s.write_byte(0)!!;
|
||||
String o = ((ZString)&z).str_view();
|
||||
assert(o == "hello");
|
||||
assert(@catch(s.write("xxxx")));
|
||||
}
|
||||
|
||||
fn void bytewriter_read_from()
|
||||
{
|
||||
char[] data = "Lorem ipsum dolor sit amet biam.";
|
||||
TestReader r = { .bytes = data };
|
||||
InStream s = &r;
|
||||
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
bw.read_from(s)!!;
|
||||
|
||||
assert(bw.str_view() == data);
|
||||
}
|
||||
|
||||
module std::io;
|
||||
// TestReader only has the read method to trigger the path
|
||||
// in ByteWriter.read_from that does not rely on the available method.
|
||||
struct TestReader (InStream)
|
||||
{
|
||||
char[] bytes;
|
||||
usz index;
|
||||
}
|
||||
|
||||
fn usz! TestReader.read(&self, char[] bytes) @dynamic
|
||||
{
|
||||
usz left = self.bytes.len - self.index;
|
||||
if (left == 0) return 0;
|
||||
usz n = min(left, bytes.len);
|
||||
mem::copy(bytes.ptr, &self.bytes[self.index], n);
|
||||
self.index += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
fn char! TestReader.read_byte(&self) @dynamic => io::read_byte_using_read(self);
|
||||
18
test/unit7/stdlib/io/dstringstream.c3
Normal file
18
test/unit7/stdlib/io/dstringstream.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void test_writing()
|
||||
{
|
||||
DString foo;
|
||||
foo.init(mem);
|
||||
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)!!;
|
||||
String o = foo.str_view();
|
||||
assert(o == "hello-what?-------------------------------------------------------2134");
|
||||
}
|
||||
94
test/unit7/stdlib/io/file_read_write_any.c3
Normal file
94
test/unit7/stdlib/io/file_read_write_any.c3
Normal file
@@ -0,0 +1,94 @@
|
||||
module std::io::file @test;
|
||||
|
||||
import std::io;
|
||||
|
||||
struct Data
|
||||
{
|
||||
bool boolean;
|
||||
char byte;
|
||||
ichar s_byte;
|
||||
ushort word;
|
||||
short s_word;
|
||||
uint dword;
|
||||
int s_dword;
|
||||
ulong qword;
|
||||
long s_qword;
|
||||
uint128 dqword;
|
||||
int128 s_dqword;
|
||||
char[128] data;
|
||||
bool[57] flags;
|
||||
bitstruct : ushort
|
||||
{
|
||||
char upper : 8..15;
|
||||
char lower : 0..7;
|
||||
}
|
||||
bitstruct : ushort @overlap
|
||||
{
|
||||
ushort total : 0..15;
|
||||
char t_lower : 0..7;
|
||||
char t_upper : 8..15;
|
||||
bool t_rand : 12;
|
||||
bool t_other : 4;
|
||||
}
|
||||
union
|
||||
{
|
||||
char hello;
|
||||
short hallo;
|
||||
uint byebye;
|
||||
}
|
||||
}
|
||||
|
||||
fn void read_write_any()
|
||||
{
|
||||
Data data;
|
||||
data.boolean = false;
|
||||
data.byte = 0xAF;
|
||||
data.s_byte = -56;
|
||||
data.word = 0xBEAF;
|
||||
data.s_word = -547;
|
||||
data.qword = 0xCAFEAFBC;
|
||||
data.s_qword = -2000000000;
|
||||
data.dqword = 0xCAFEADDEAFBEFF;
|
||||
data.s_dqword = -45600000000000000;
|
||||
for (int i = 0; i < 128; ++i) data.data[i] = (char)(255 - i);
|
||||
for (int i = 0; i < 57; ++i) data.flags[i] = (i % 4) == 0;
|
||||
data.upper = 0x56;
|
||||
data.lower = 0x44;
|
||||
data.total = 0xA55A;
|
||||
data.hello = 0xCC;
|
||||
|
||||
File file = file::open("tmp/__file_read_write_any_test_file", "wb")!!;
|
||||
|
||||
io::write_any(&file, &data)!!;
|
||||
file.flush()!!;
|
||||
file.close()!!;
|
||||
|
||||
file = file::open("tmp/__file_read_write_any_test_file", "rb")!!;
|
||||
Data rdata;
|
||||
io::read_any(&file, &rdata)!!;
|
||||
|
||||
file.close()!!;
|
||||
|
||||
assert(rdata.boolean == data.boolean);
|
||||
assert(rdata.byte == data.byte);
|
||||
assert(rdata.s_byte == data.s_byte);
|
||||
assert(rdata.word == data.word);
|
||||
assert(rdata.s_word == data.s_word);
|
||||
assert(rdata.dword == data.dword);
|
||||
assert(rdata.s_dword == data.s_dword);
|
||||
assert(rdata.qword == data.qword);
|
||||
assert(rdata.s_qword == data.s_qword);
|
||||
assert(rdata.dqword == data.dqword);
|
||||
assert(rdata.data == data.data);
|
||||
assert(rdata.flags == data.flags);
|
||||
assert(rdata.upper == data.upper);
|
||||
assert(rdata.lower == data.lower);
|
||||
assert(rdata.t_lower == data.t_lower);
|
||||
assert(rdata.t_upper == data.t_upper);
|
||||
assert(rdata.t_rand == data.t_rand);
|
||||
assert(rdata.t_other == data.t_other);
|
||||
assert(rdata.total == data.total);
|
||||
assert(rdata.hello == data.hello);
|
||||
assert(rdata.hallo == data.hallo);
|
||||
assert(rdata.byebye == data.byebye);
|
||||
}
|
||||
16
test/unit7/stdlib/io/fileinfo.c3
Normal file
16
test/unit7/stdlib/io/fileinfo.c3
Normal file
@@ -0,0 +1,16 @@
|
||||
module std::io::fileinfo @test;
|
||||
import std::io::os;
|
||||
|
||||
fn void test_native_is_file() @if(env::LINUX || env::DARWIN)
|
||||
{
|
||||
assert(!os::native_is_file("/dev/loop0"));
|
||||
assert(!os::native_is_file("/dev/null"));
|
||||
}
|
||||
|
||||
fn void test_native_is_dir() @if(env::LINUX || env::DARWIN)
|
||||
{
|
||||
assert(os::native_is_dir("/"));
|
||||
assert(!os::native_is_file("/"));
|
||||
assert(!os::native_is_dir("/dev/loop0"));
|
||||
assert(!os::native_is_dir("/dev/null"));
|
||||
}
|
||||
20
test/unit7/stdlib/io/limitreader.c3
Normal file
20
test/unit7/stdlib/io/limitreader.c3
Normal file
@@ -0,0 +1,20 @@
|
||||
module std::io @test;
|
||||
|
||||
|
||||
fn void limitreader()
|
||||
{
|
||||
const DATA = "Hello World!";
|
||||
ByteReader src;
|
||||
src.init(DATA);
|
||||
const LIMIT = 5;
|
||||
LimitReader lmr;
|
||||
lmr.init(&src, LIMIT);
|
||||
|
||||
char[DATA.len] bytes;
|
||||
usz n = lmr.read(bytes[..])!!;
|
||||
|
||||
assert(n == LIMIT, "got %d; want %d", n, LIMIT);
|
||||
String got = (String)bytes[:n];
|
||||
String want = DATA[:LIMIT];
|
||||
assert(got == want, "got %d; want %d", got, want);
|
||||
}
|
||||
21
test/unit7/stdlib/io/multireader.c3
Normal file
21
test/unit7/stdlib/io/multireader.c3
Normal file
@@ -0,0 +1,21 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void test_multireader()
|
||||
{
|
||||
MultiReader mr;
|
||||
mr.temp_init(
|
||||
&&wrap_bytes("foo"),
|
||||
&&wrap_bytes(" "),
|
||||
&&wrap_bytes("bar"),
|
||||
&&wrap_bytes("!"),
|
||||
);
|
||||
defer mr.free();
|
||||
|
||||
ByteWriter w;
|
||||
io::copy_to(&mr, w.temp_init())!!;
|
||||
|
||||
String want = "foo bar!";
|
||||
assert(w.str_view() == want,
|
||||
"invalid data read; got: %s, want: %s", w.str_view(), want);
|
||||
}
|
||||
|
||||
17
test/unit7/stdlib/io/multiwriter.c3
Normal file
17
test/unit7/stdlib/io/multiwriter.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void test_multiwriter()
|
||||
{
|
||||
ByteWriter w1, w2;
|
||||
MultiWriter mw;
|
||||
mw.temp_init(w1.temp_init(), w2.temp_init());
|
||||
defer mw.free();
|
||||
|
||||
String want = "foobar";
|
||||
io::copy_to((ByteReader){}.init(want), &mw)!!;
|
||||
|
||||
assert(w1.str_view() == want,
|
||||
"invalid write; got: %s, want: %s", w1.str_view(), want);
|
||||
assert(w2.str_view() == want,
|
||||
"invalid write; got: %s, want: %s", w2.str_view(), want);
|
||||
}
|
||||
378
test/unit7/stdlib/io/path.c3
Normal file
378
test/unit7/stdlib/io/path.c3
Normal file
@@ -0,0 +1,378 @@
|
||||
module std::io::path @test;
|
||||
|
||||
fn void test_dot()
|
||||
{
|
||||
Path p = path::new(mem, ".")!!;
|
||||
defer p.free();
|
||||
assert(@catch(p.parent()));
|
||||
// It must be possible to form the absolute version.
|
||||
Path p2 = p.absolute(mem)!!;
|
||||
p2.free();
|
||||
p2 = p.append(mem, "/hello/world")!!;
|
||||
if (p2.env == POSIX)
|
||||
{
|
||||
assert(p2.str_view() == "hello/world");
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(p2.str_view() == `hello\world`);
|
||||
}
|
||||
p2.free();
|
||||
}
|
||||
|
||||
fn void test_parent()
|
||||
{
|
||||
Path p = path::new(mem, "")!!;
|
||||
assert(@catch(p.parent()));
|
||||
p.free();
|
||||
p = path::new(mem, "/", path_env: PathEnv.POSIX)!!;
|
||||
assert(@catch(p.parent()));
|
||||
p.free();
|
||||
p = path::new(mem, "/a/b/c", path_env: PathEnv.POSIX)!!;
|
||||
assert(p.parent().str_view()!! == "/a/b");
|
||||
p.free();
|
||||
p = path::new(mem, "/a/b/c", path_env: PathEnv.WIN32)!!;
|
||||
assert(p.parent().str_view()!! == `\a\b`);
|
||||
p.free();
|
||||
}
|
||||
|
||||
fn void test_path_normalized() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(path::new(mem, "", path_env: PathEnv.WIN32).str_view()!! == "");
|
||||
assert(@catch(path::new(mem, "1:\\a\\b\\c.txt", path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, ":", path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, "1:", path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, "1:a", path_env: PathEnv.WIN32)));
|
||||
// assert(@catch(path::new(mem, `\\\a\b\c.txt`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `\\server\a\b\..\..\..\c`, path_env: PathEnv.WIN32)));
|
||||
|
||||
assert(@catch(path::new(mem, `\\a`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `/a/b/../../../c`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `/a/b/../../../c`, path_env: PathEnv.POSIX)));
|
||||
assert(@catch(path::new(mem, `/a/b/../../..`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `/a/b/../../..`, path_env: PathEnv.POSIX)));
|
||||
assert(@catch(path::new(mem, `/../a`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `/../a`, path_env: PathEnv.POSIX)));
|
||||
assert(@catch(path::new(mem, `/..`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `/..`, path_env: PathEnv.POSIX)));
|
||||
assert(@catch(path::new(mem, `C:/a/b/../../../c`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `C:/../a`, path_env: PathEnv.WIN32)));
|
||||
assert(@catch(path::new(mem, `C:/..`, path_env: PathEnv.WIN32)));
|
||||
|
||||
assert(path::new(mem, "/", path_env: PathEnv.POSIX).str_view()!! == "/");
|
||||
assert(path::new(mem, "/./", path_env: PathEnv.POSIX).str_view()!! == "/");
|
||||
assert(path::new(mem, "/foo/../", path_env: PathEnv.POSIX).str_view()!! == "/");
|
||||
assert(path::new(mem, "/foo/bar/../", path_env: PathEnv.POSIX).str_view()!! == "/foo");
|
||||
assert(path::new(mem, "/foo//bar", path_env: PathEnv.POSIX).str_view()!! == "/foo/bar");
|
||||
assert(path::new(mem, "/foo//bar/../", path_env: PathEnv.POSIX).str_view()!! == "/foo");
|
||||
assert(path::new(mem, "/foo/.bar", path_env: PathEnv.POSIX).str_view()!! == "/foo/.bar");
|
||||
assert(path::new(mem, `\foo\.bar`, path_env: PathEnv.WIN32).str_view()!! == `\foo\.bar`);
|
||||
assert(path::new(mem, "a\\b/c.txt", path_env: PathEnv.WIN32).str_view()!! == `a\b\c.txt`);
|
||||
assert(path::new(mem, "a\\b/c.txt", path_env: PathEnv.POSIX).str_view()!! == "a\\b/c.txt");
|
||||
assert(path::new(mem, "C:\\a\\b/c.txt", path_env: PathEnv.WIN32).str_view()!! == `C:\a\b\c.txt`);
|
||||
assert(path::new(mem, "C:\\a\\b/c.txt", path_env: PathEnv.POSIX).str_view()!! == "C:\\a\\b/c.txt");
|
||||
assert(path::new(mem, `\\server\a\b/c.txt`, path_env: PathEnv.WIN32).str_view()!! == `\\server\a\b\c.txt`);
|
||||
assert(path::new(mem, `\\server\a\b/c.txt`, path_env: PathEnv.POSIX).str_view()!! == `\\server\a\b/c.txt`);
|
||||
assert(path::new(mem, `c:\hello//bar\\\\foo.txt`, path_env: PathEnv.WIN32).str_view()!! == `c:\hello\bar\foo.txt`);
|
||||
|
||||
assert(path::new(mem, `~\a\b/c.txt`, path_env: PathEnv.WIN32).str_view()!! == `~\a\b\c.txt`);
|
||||
assert(path::new(mem, `~\a\b/c.txt`, path_env: PathEnv.POSIX).str_view()!! == `~\a\b/c.txt`);
|
||||
|
||||
|
||||
assert(path::new(mem, `a/b/../../../c`, path_env: PathEnv.WIN32).str_view()!! == `..\c`);
|
||||
assert(path::new(mem, `a/b/../../../c`, path_env: PathEnv.POSIX).str_view()!! == `../c`);
|
||||
assert(path::new(mem, `a/b/../../..`, path_env: PathEnv.WIN32).str_view()!! == `..`);
|
||||
assert(path::new(mem, `a/b/../../..`, path_env: PathEnv.POSIX).str_view()!! == `..`);
|
||||
assert(path::new(mem, `../a`, path_env: PathEnv.WIN32).str_view()!! == `..\a`);
|
||||
assert(path::new(mem, `../a`, path_env: PathEnv.POSIX).str_view()!! == `../a`);
|
||||
assert(path::new(mem, `..`, path_env: PathEnv.WIN32).str_view()!! == `..`);
|
||||
assert(path::new(mem, `..`, path_env: PathEnv.POSIX).str_view()!! == `..`);
|
||||
assert(path::new(mem, `a/b/../c`, path_env: PathEnv.WIN32).str_view()!! == `a\c`);
|
||||
assert(path::new(mem, `a/b/../c`, path_env: PathEnv.POSIX).str_view()!! == `a/c`);
|
||||
assert(path::new(mem, `a/b/../../c`, path_env: PathEnv.WIN32).str_view()!! == `c`);
|
||||
assert(path::new(mem, `a/b/../../c`, path_env: PathEnv.POSIX).str_view()!! == `c`);
|
||||
assert(path::new(mem, `a/b/..`, path_env: PathEnv.WIN32).str_view()!! == `a`);
|
||||
assert(path::new(mem, `a/b/..`, path_env: PathEnv.POSIX).str_view()!! == `a`);
|
||||
assert(path::new(mem, `a/b/../`, path_env: PathEnv.WIN32).str_view()!! == `a`);
|
||||
assert(path::new(mem, `a/b/../`, path_env: PathEnv.POSIX).str_view()!! == `a`);
|
||||
assert(path::new(mem, `a/b/../..`, path_env: PathEnv.WIN32).str_view()!! == ".");
|
||||
assert(path::new(mem, `a/b/../..`, path_env: PathEnv.POSIX).str_view()!! == ".");
|
||||
assert(path::new(mem, `a/b/../../`, path_env: PathEnv.WIN32).str_view()!! == ".");
|
||||
assert(path::new(mem, `a/b/../../`, path_env: PathEnv.POSIX).str_view()!! == ".");
|
||||
assert(path::new(mem, `a/b/../c/../d`, path_env: PathEnv.WIN32).str_view()!! == `a\d`);
|
||||
assert(path::new(mem, `a/b/../c/../d`, path_env: PathEnv.POSIX).str_view()!! == `a/d`);
|
||||
assert(path::new(mem, `a/b/../c/../d/`, path_env: PathEnv.WIN32).str_view()!! == `a\d`);
|
||||
assert(path::new(mem, `a/b/../c/../d/`, path_env: PathEnv.POSIX).str_view()!! == `a/d`);
|
||||
assert(path::new(mem, `a/b//d`, path_env: PathEnv.WIN32).str_view()!! == `a\b\d`);
|
||||
assert(path::new(mem, `a/b//d`, path_env: PathEnv.POSIX).str_view()!! == `a/b/d`);
|
||||
assert(path::new(mem, `a/b/././.`, path_env: PathEnv.WIN32).str_view()!! == `a\b`);
|
||||
assert(path::new(mem, `a/b/././.`, path_env: PathEnv.POSIX).str_view()!! == `a/b`);
|
||||
assert(path::new(mem, `a/b/./././`, path_env: PathEnv.WIN32).str_view()!! == `a\b`);
|
||||
assert(path::new(mem, `a/b/./././`, path_env: PathEnv.POSIX).str_view()!! == `a/b`);
|
||||
assert(path::new(mem, `./a/`, path_env: PathEnv.WIN32).str_view()!! == `a`);
|
||||
assert(path::new(mem, `./a/`, path_env: PathEnv.POSIX).str_view()!! == `a`);
|
||||
assert(path::new(mem, `./`, path_env: PathEnv.WIN32).str_view()!! == `.`);
|
||||
assert(path::new(mem, `./`, path_env: PathEnv.POSIX).str_view()!! == `.`);
|
||||
assert(path::new(mem, `.`, path_env: PathEnv.WIN32).str_view()!! == `.`);
|
||||
assert(path::new(mem, `.`, path_env: PathEnv.POSIX).str_view()!! == `.`);
|
||||
assert(path::new(mem, ``, path_env: PathEnv.WIN32).str_view()!! == ``);
|
||||
assert(path::new(mem, ``, path_env: PathEnv.POSIX).str_view()!! == ``);
|
||||
assert(path::new(mem, `/a`, path_env: PathEnv.WIN32).str_view()!! == `\a`);
|
||||
assert(path::new(mem, `/a`, path_env: PathEnv.POSIX).str_view()!! == `/a`);
|
||||
assert(path::new(mem, `/a/`, path_env: PathEnv.WIN32).str_view()!! == `\a`);
|
||||
assert(path::new(mem, `/a/`, path_env: PathEnv.POSIX).str_view()!! == `/a`);
|
||||
assert(path::new(mem, `/a/b/../c`, path_env: PathEnv.WIN32).str_view()!! == `\a\c`);
|
||||
assert(path::new(mem, `/a/b/../c`, path_env: PathEnv.POSIX).str_view()!! == `/a/c`);
|
||||
assert(path::new(mem, `/a/b/../../c`, path_env: PathEnv.WIN32).str_view()!! == `\c`);
|
||||
assert(path::new(mem, `/a/b/../../c`, path_env: PathEnv.POSIX).str_view()!! == `/c`);
|
||||
assert(path::new(mem, `/a/b/..`, path_env: PathEnv.WIN32).str_view()!! == `\a`);
|
||||
assert(path::new(mem, `/a/b/..`, path_env: PathEnv.POSIX).str_view()!! == `/a`);
|
||||
assert(path::new(mem, `/a/b/../..`, path_env: PathEnv.WIN32).str_view()!! == `\`);
|
||||
assert(path::new(mem, `/a/b/../..`, path_env: PathEnv.POSIX).str_view()!! == `/`);
|
||||
assert(path::new(mem, `/a/b/../c/../d`, path_env: PathEnv.WIN32).str_view()!! == `\a\d`);
|
||||
assert(path::new(mem, `/a/b/../c/../d`, path_env: PathEnv.POSIX).str_view()!! == `/a/d`);
|
||||
assert(path::new(mem, `/a/b//d`, path_env: PathEnv.WIN32).str_view()!! == `\a\b\d`);
|
||||
assert(path::new(mem, `/a/b//d`, path_env: PathEnv.POSIX).str_view()!! == `/a/b/d`);
|
||||
assert(path::new(mem, `/./a/`, path_env: PathEnv.WIN32).str_view()!! == `\a`);
|
||||
assert(path::new(mem, `/./a/`, path_env: PathEnv.POSIX).str_view()!! == `/a`);
|
||||
assert(path::new(mem, `/./`, path_env: PathEnv.WIN32).str_view()!! == `\`);
|
||||
assert(path::new(mem, `/./`, path_env: PathEnv.POSIX).str_view()!! == `/`);
|
||||
assert(path::new(mem, `/.`, path_env: PathEnv.WIN32).str_view()!! == `\`);
|
||||
assert(path::new(mem, `/.`, path_env: PathEnv.POSIX).str_view()!! == `/`);
|
||||
assert(path::new(mem, `/`, path_env: PathEnv.WIN32).str_view()!! == `\`);
|
||||
assert(path::new(mem, `/`, path_env: PathEnv.POSIX).str_view()!! == `/`);
|
||||
assert(path::new(mem, `C:/a`, path_env: PathEnv.WIN32).str_view()!! == `C:\a`);
|
||||
assert(path::new(mem, `C:/a`, path_env: PathEnv.POSIX).str_view()!! == `C:/a`);
|
||||
assert(path::new(mem, `C:/a/b/../c`, path_env: PathEnv.WIN32).str_view()!! == `C:\a\c`);
|
||||
assert(path::new(mem, `C:/a/b/../c`, path_env: PathEnv.POSIX).str_view()!! == `C:/a/c`);
|
||||
assert(path::new(mem, `C:/a/b/../../c`, path_env: PathEnv.WIN32).str_view()!! == `C:\c`);
|
||||
assert(path::new(mem, `C:/a/b/../../c`, path_env: PathEnv.POSIX).str_view()!! == `C:/c`);
|
||||
assert(path::new(mem, `C:/a/b/../../../c`, path_env: PathEnv.POSIX).str_view()!! == `c`);
|
||||
assert(path::new(mem, `C:/a/b/..`, path_env: PathEnv.WIN32).str_view()!! == `C:\a`);
|
||||
assert(path::new(mem, `C:/a/b/..`, path_env: PathEnv.POSIX).str_view()!! == `C:/a`);
|
||||
assert(path::new(mem, `C:/a/b/../..`, path_env: PathEnv.WIN32).str_view()!! == `C:\`);
|
||||
assert(path::new(mem, `C:/a/b/../..`, path_env: PathEnv.POSIX).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:/a/b/../c/../d`, path_env: PathEnv.WIN32).str_view()!! == `C:\a\d`);
|
||||
assert(path::new(mem, `C:/a/b/../c/../d`, path_env: PathEnv.POSIX).str_view()!! == `C:/a/d`);
|
||||
assert(path::new(mem, `C:/a/b//d`, path_env: PathEnv.WIN32).str_view()!! == `C:\a\b\d`);
|
||||
assert(path::new(mem, `C:/a/b//d`, path_env: PathEnv.POSIX).str_view()!! == `C:/a/b/d`);
|
||||
assert(path::new(mem, `C:/a/b/././.`, path_env: PathEnv.WIN32).str_view()!! == `C:\a\b`);
|
||||
assert(path::new(mem, `C:/a/b/././.`, path_env: PathEnv.POSIX).str_view()!! == `C:/a/b`);
|
||||
assert(path::new(mem, `C:/./a`, path_env: PathEnv.WIN32).str_view()!! == `C:\a`);
|
||||
assert(path::new(mem, `C:/./a`, path_env: PathEnv.POSIX).str_view()!! == `C:/a`);
|
||||
assert(path::new(mem, `C:/./`, path_env: PathEnv.WIN32).str_view()!! == `C:\`);
|
||||
assert(path::new(mem, `C:/./`, path_env: PathEnv.POSIX).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:/../a`, path_env: PathEnv.POSIX).str_view()!! == `a`);
|
||||
assert(path::new(mem, `C:/..`, path_env: PathEnv.POSIX).str_view()!! == `.`);
|
||||
assert(path::new(mem, `C:/`, path_env: PathEnv.WIN32).str_view()!! == `C:\`);
|
||||
assert(path::new(mem, `C:/`, path_env: PathEnv.POSIX).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:a`, path_env: PathEnv.WIN32).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:a`, path_env: PathEnv.POSIX).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:a/`, path_env: PathEnv.WIN32).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:a/`, path_env: PathEnv.POSIX).str_view()!! == `C:a`);
|
||||
|
||||
assert(path::new(mem, `C:a/b/../c`, path_env: PathEnv.WIN32).str_view()!! == `C:a\c`);
|
||||
assert(path::new(mem, `C:a/b/../c`, path_env: PathEnv.POSIX).str_view()!! == `C:a/c`);
|
||||
assert(path::new(mem, `C:a/b/../../c`, path_env: PathEnv.WIN32).str_view()!! == `C:c`);
|
||||
assert(path::new(mem, `C:a/b/../../c`, path_env: PathEnv.POSIX).str_view()!! == `c`);
|
||||
assert(path::new(mem, `C:a/b/..`, path_env: PathEnv.WIN32).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:a/b/..`, path_env: PathEnv.POSIX).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:a/b/../..`, path_env: PathEnv.WIN32).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:a/b/../..`, path_env: PathEnv.POSIX).str_view()!! == `.`);
|
||||
assert(path::new(mem, `C:a/b/../c/../d`, path_env: PathEnv.WIN32).str_view()!! == `C:a\d`);
|
||||
assert(path::new(mem, `C:a/b/../c/../d`, path_env: PathEnv.POSIX).str_view()!! == `C:a/d`);
|
||||
assert(path::new(mem, `C:a/b//d`, path_env: PathEnv.WIN32).str_view()!! == `C:a\b\d`);
|
||||
assert(path::new(mem, `C:a/b//d`, path_env: PathEnv.POSIX).str_view()!! == `C:a/b/d`);
|
||||
assert(path::new(mem, `C:a/b/././.`, path_env: PathEnv.WIN32).str_view()!! == `C:a\b`);
|
||||
assert(path::new(mem, `C:a/b/././.`, path_env: PathEnv.POSIX).str_view()!! == `C:a/b`);
|
||||
assert(path::new(mem, `C:a/b/../../../c`, path_env: PathEnv.WIN32).str_view()!! == `C:..\c`);
|
||||
assert(path::new(mem, `C:./a`, path_env: PathEnv.WIN32).str_view()!! == `C:a`);
|
||||
assert(path::new(mem, `C:./a`, path_env: PathEnv.POSIX).str_view()!! == `C:./a`);
|
||||
assert(path::new(mem, `C:./`, path_env: PathEnv.WIN32).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:./`, path_env: PathEnv.POSIX).str_view()!! == `C:.`);
|
||||
assert(path::new(mem, `C:../a`, path_env: PathEnv.POSIX).str_view()!! == `C:../a`);
|
||||
assert(path::new(mem, `C:../a`, path_env: PathEnv.WIN32).str_view()!! == `C:..\a`);
|
||||
assert(path::new(mem, `C:..`, path_env: PathEnv.POSIX).str_view()!! == `C:..`);
|
||||
assert(path::new(mem, `C:..`, path_env: PathEnv.WIN32).str_view()!! == `C:..`);
|
||||
assert(path::new(mem, `C:`, path_env: PathEnv.WIN32).str_view()!! == `C:`);
|
||||
assert(path::new(mem, `C:`, path_env: PathEnv.POSIX).str_view()!! == `C:`);
|
||||
|
||||
assert(path::new(mem, `\\server\foo/a`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a`);
|
||||
assert(path::new(mem, `\\server\foo/a`, path_env: PathEnv.POSIX).str_view()!! == `\\server\foo/a`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\..\c`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a\c`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\..\..\c`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\c`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\..`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a`);
|
||||
assert(path::new(mem, `\\server\foo\a\..`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\..\c\..\d`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a\d`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\\d`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a\b\d`);
|
||||
assert(path::new(mem, `\\server\foo\a\b\.\.\.`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a\b`);
|
||||
assert(path::new(mem, `\\server\foo\.\a`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\a`);
|
||||
assert(path::new(mem, `\\server\foo\.`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\`);
|
||||
assert(path::new(mem, `\\server\foo\`, path_env: PathEnv.WIN32).str_view()!! == `\\server\foo\`);
|
||||
|
||||
}
|
||||
|
||||
fn void test_extension() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(@catch(path::new(mem, `C:`, path_env: PathEnv.WIN32).extension()));
|
||||
assert(@catch(path::new(mem, `C:`, path_env: PathEnv.POSIX).extension()));
|
||||
assert(@catch(path::new(mem, `file`, path_env: PathEnv.WIN32).extension()));
|
||||
assert(@catch(path::new(mem, `file`, path_env: PathEnv.POSIX).extension()));
|
||||
assert(@catch(path::new(mem, `C:\temp\foo.bar\README`, path_env: PathEnv.WIN32).extension()));
|
||||
|
||||
assert(path::for_windows(mem, "file.txt").extension()!! == "txt");
|
||||
assert(path::for_posix(mem, "file.txt").extension()!! == "txt");
|
||||
|
||||
assert(path::for_windows(mem, "a/b/file.txt").extension()!! == "txt");
|
||||
assert(path::for_posix(mem, "a/b/file.txt").extension()!! == "txt");
|
||||
|
||||
assert(path::for_windows(mem, "a\\b\\file.txt").extension()!! == "txt");
|
||||
|
||||
assert(path::for_windows(mem, "a.b/file.txt").extension()!! == "txt");
|
||||
assert(path::for_posix(mem, "a.b/file.txt").extension()!! == "txt");
|
||||
assert(path::for_windows(mem, "a.b/file.txt").extension()!! == "txt");
|
||||
assert(path::for_posix(mem, "a.b/file.txt").extension()!! == "txt");
|
||||
|
||||
assert(path::for_windows(mem, "a.b\\file.txt").extension()!! == "txt");
|
||||
|
||||
assert(path::for_windows(mem, "domain.dot.com").extension()!! == "com");
|
||||
assert(path::for_posix(mem, "domain.dot.com").extension()!! == "com");
|
||||
|
||||
assert(path::for_windows(mem, "image.jpeg").extension()!! == "jpeg");
|
||||
assert(path::for_posix(mem, "image.jpeg").extension()!! == "jpeg");
|
||||
|
||||
assert(path::for_windows(mem, "../filename.ext").extension()!! == "ext");
|
||||
assert(path::for_posix(mem, "../filename.ext").extension()!! == "ext");
|
||||
|
||||
}
|
||||
|
||||
fn void test_has_extension() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(!path::new(mem, `C:\temp\foo.bar\README`, path_env: PathEnv.WIN32)!!.has_extension(`bar\README`));
|
||||
|
||||
assert(path::for_windows(mem, "file.txt")!!.has_extension("txt"));
|
||||
assert(path::for_posix(mem, "file.txt")!!.has_extension("txt"));
|
||||
|
||||
assert(path::for_windows(mem, "a/b/file.txt")!!.has_extension("txt"));
|
||||
assert(path::for_posix(mem, "a/b/file.txt")!!.has_extension("txt"));
|
||||
|
||||
assert(path::for_windows(mem, "a\\b\\file.txt")!!.has_extension("txt"));
|
||||
|
||||
assert(path::for_windows(mem, "a.b/file.txt")!!.has_extension("txt"));
|
||||
assert(path::for_posix(mem, "a.b/file.txt")!!.has_extension("txt"));
|
||||
assert(path::for_windows(mem, "a.b/file.txt")!!.has_extension("txt"));
|
||||
assert(path::for_posix(mem, "a.b/file.txt")!!.has_extension("txt"));
|
||||
|
||||
assert(path::for_windows(mem, "a.b\\file.txt")!!.has_extension("txt"));
|
||||
|
||||
assert(path::for_windows(mem, "domain.dot.com")!!.has_extension("com"));
|
||||
assert(path::for_posix(mem, "domain.dot.com")!!.has_extension("com"));
|
||||
|
||||
assert(path::for_windows(mem, "image.jpeg")!!.has_extension("jpeg"));
|
||||
assert(path::for_posix(mem, "image.jpeg")!!.has_extension("jpeg"));
|
||||
|
||||
assert(path::for_windows(mem, "../filename.ext")!!.has_extension("ext"));
|
||||
assert(path::for_posix(mem, "../filename.ext")!!.has_extension("ext"));
|
||||
|
||||
}
|
||||
|
||||
fn void test_basename() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(path::for_windows(mem, "file.txt").basename()!! == "file.txt");
|
||||
assert(path::for_posix(mem, "file.txt").basename()!! == "file.txt");
|
||||
|
||||
assert(path::for_windows(mem, "a/b/file.txt").basename()!! == "file.txt");
|
||||
assert(path::for_posix(mem, "a/b/file.txt").basename()!! == "file.txt");
|
||||
|
||||
assert(path::for_windows(mem, "a.b/file.txt").basename()!! == "file.txt");
|
||||
assert(path::for_posix(mem, "a.b/file.txt").basename()!! == "file.txt");
|
||||
|
||||
assert(path::for_windows(mem, "a.b/file.txt").basename()!! == "file.txt");
|
||||
assert(path::for_posix(mem, "a.b/file.txt").basename()!! == "file.txt");
|
||||
|
||||
assert(path::for_windows(mem, "../filename.ext").basename()!! == "filename.ext");
|
||||
assert(path::for_posix(mem, "../filename.ext").basename()!! == "filename.ext");
|
||||
|
||||
assert(path::for_windows(mem, "C:").basename()!! == "");
|
||||
assert(path::for_posix(mem, "C:").basename()!! == "C:");
|
||||
|
||||
assert(path::for_windows(mem, "../..").basename()!! == "..");
|
||||
assert(path::for_posix(mem, "../..").basename()!! == "..");
|
||||
|
||||
assert(path::for_windows(mem, `\\server\abc`).basename()!! == "");
|
||||
assert(path::for_posix(mem, `\\server\abc`).basename()!! == `\\server\abc`);
|
||||
}
|
||||
|
||||
fn void test_dirname() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(path::for_posix(mem, "").dirname()!! == ".");
|
||||
assert(path::for_posix(mem, "/file").dirname()!! == "/");
|
||||
assert(path::for_posix(mem, "///").dirname()!! == "/");
|
||||
assert(path::for_windows(mem, "d:").dirname()!! == "d:");
|
||||
assert(path::for_windows(mem, "d:file").dirname()!! == "d:");
|
||||
assert(path::for_windows(mem, `d:\file`).dirname()!! == `d:\`);
|
||||
|
||||
assert(path::for_windows(mem, "file.txt").dirname()!! == ".");
|
||||
assert(path::for_posix(mem, "file.txt").dirname()!! == ".");
|
||||
|
||||
assert(path::for_windows(mem, "a/b/file.txt").dirname()!! == `a\b`);
|
||||
assert(path::for_posix(mem, "a/b/file.txt").dirname()!! == "a/b");
|
||||
|
||||
assert(path::for_windows(mem, "a.b/file.txt").dirname()!! == "a.b");
|
||||
assert(path::for_posix(mem, "a.b/file.txt").dirname()!! == "a.b");
|
||||
|
||||
assert(path::for_windows(mem, "../filename.ext").dirname()!! == "..");
|
||||
assert(path::for_posix(mem, "../filename.ext").dirname()!! == "..");
|
||||
|
||||
assert(path::for_windows(mem, "C:").dirname()!! == "C:");
|
||||
assert(path::for_posix(mem, "C:").dirname()!! == ".");
|
||||
|
||||
assert(path::for_windows(mem, "C:/").dirname()!! == "C:\\");
|
||||
assert(path::for_posix(mem, "C:/").dirname()!! == ".");
|
||||
|
||||
assert(path::for_windows(mem, "C:/a").dirname()!! == "C:\\");
|
||||
assert(path::for_posix(mem, "C:/a").dirname()!! == "C:");
|
||||
|
||||
assert(path::for_windows(mem, "../..").dirname()!! == "..");
|
||||
assert(path::for_posix(mem, "../..").dirname()!! == "..");
|
||||
|
||||
assert(path::for_windows(mem, `\\server\share\dir\file`).dirname()!! == `\\server\share\dir`);
|
||||
assert(path::for_windows(mem, `\\server\share\file`).dirname()!! == `\\server\share`);
|
||||
assert(path::for_windows(mem, `\\server\share\`).dirname()!! == `\\server\share`);
|
||||
assert(path::for_windows(mem, `\\server\share`).dirname()!! == `\\server\share`);
|
||||
assert(path::for_posix(mem, `\\server\`).dirname()!! == `.`);
|
||||
}
|
||||
|
||||
fn void test_path_volume() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(path::for_windows(mem, `C:\abs`).volume_name()!! == `C:`);
|
||||
assert(path::for_windows(mem, `C:abs`).volume_name()!! == `C:`);
|
||||
assert(path::for_posix(mem, `C:/abs`).volume_name()!! == ``);
|
||||
assert(path::for_posix(mem, `C:abs`).volume_name()!! == ``);
|
||||
assert(path::for_windows(mem, `\\server\foo`).volume_name()!! == `\\server\foo`);
|
||||
assert(path::for_windows(mem, `\\server\foo\abc`).volume_name()!! == `\\server\foo`);
|
||||
}
|
||||
|
||||
fn void test_path_is_absolute() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
assert(!path::for_posix(mem, "").is_absolute()!!);
|
||||
assert(path::for_posix(mem, "/").is_absolute()!!);
|
||||
assert(path::for_posix(mem, "/a/b").is_absolute()!!);
|
||||
assert(!path::for_posix(mem, "a/b").is_absolute()!!);
|
||||
|
||||
assert(!path::for_windows(mem, `C:`).is_absolute()!!);
|
||||
assert(path::for_windows(mem, `C:\abs`).is_absolute()!!);
|
||||
assert(!path::for_windows(mem, `C:abs`).is_absolute()!!);
|
||||
assert(path::for_windows(mem, `\\server\foo`).is_absolute()!!);
|
||||
assert(path::for_windows(mem, `\\server\foo\abc`).is_absolute()!!);
|
||||
}
|
||||
|
||||
fn void test_path_absolute() => mem::@scoped(allocator::temp())
|
||||
{
|
||||
$if env::WIN32:
|
||||
assert(path::for_windows(mem, `C:\abs`).absolute(mem, )!!.str_view() == `C:\abs`);
|
||||
$else
|
||||
assert(path::for_posix(mem, "/").absolute(mem, )!!.str_view() == "/");
|
||||
assert(path::for_posix(mem, ".").absolute(mem, )!!.str_view() == path::tcwd()!!.str_view());
|
||||
$endif
|
||||
}
|
||||
116
test/unit7/stdlib/io/printf.c3
Normal file
116
test/unit7/stdlib/io/printf.c3
Normal file
@@ -0,0 +1,116 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void printf_int()
|
||||
{
|
||||
String s;
|
||||
s = string::format(mem, "[%-10d]", 78);
|
||||
assert(s == "[78 ]");
|
||||
free(s);
|
||||
s = string::format(mem, "[%10d]", 78);
|
||||
assert(s == "[ 78]");
|
||||
free(s);
|
||||
s = string::format(mem, "[%010d]", 78);
|
||||
assert(s == "[0000000078]");
|
||||
free(s);
|
||||
s = string::format(mem, "[%+10d]", 78);
|
||||
assert(s == "[ +78]");
|
||||
free(s);
|
||||
s = string::format(mem, "[%-+10d]", 78);
|
||||
assert(s == "[+78 ]");
|
||||
free(s);
|
||||
}
|
||||
|
||||
fn void printf_a()
|
||||
{
|
||||
String s;
|
||||
s = string::format(mem, "%08.2a", 234.125);
|
||||
assert(s == "0x1.d4p+7", "got '%s'; want '0x1.d4p+7'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%a", 234.125);
|
||||
assert(s == "0x1.d44p+7", "got '%s'; want '0x1.d44p+7'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%A", 234.125);
|
||||
assert(s == "0X1.D44P+7", "got '%s'; want '0X1.D44P+7'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20a", 234.125);
|
||||
assert(s == " 0x1.d44p+7", "got '%s'; want ' 0x1.d44p+7'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%-20a", 234.125);
|
||||
assert(s == "0x1.d44p+7 ", "got '%s'; want '0x1.d44p+7 '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%-20s", "hello world");
|
||||
assert(s == "hello world ", "got '%s'; want 'hello world '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20s", "hello world");
|
||||
assert(s == " hello world", "got '%s'; want ' hello world'", s);
|
||||
free(s);
|
||||
|
||||
String str = "hello!";
|
||||
s = string::format(mem, "%-20s", str);
|
||||
assert(s == "hello! ", "got '%s'; want 'hello! '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20s", str);
|
||||
assert(s == " hello!", "got '%s'; want ' hello!'", s);
|
||||
free(s);
|
||||
|
||||
int[2] a = { 12, 23 };
|
||||
s = string::format(mem, "%-20s", a);
|
||||
assert(s == "[12, 23] ", "got '%s'; want '[12, 23] '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20s", a);
|
||||
assert(s == " [12, 23]", "got '%s'; want ' [12, 23]'", s);
|
||||
free(s);
|
||||
|
||||
s = string::format(mem, "%-20s", a[..]);
|
||||
assert(s == "[12, 23] ", "got '%s'; want '[12, 23] '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20s", a[..]);
|
||||
assert(s == " [12, 23]", "got '%s'; want ' [12, 23]'", s);
|
||||
free(s);
|
||||
|
||||
float[2] f = { 12.0, 23.0 };
|
||||
s = string::format(mem, "%-24s", f);
|
||||
assert(s == "[12.000000, 23.000000] ", "got '%s'; want '[12.000000, 23.000000] '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%24s", f);
|
||||
assert(s == " [12.000000, 23.000000]", "got '%s'; want ' [12.000000, 23.000000]'", s);
|
||||
free(s);
|
||||
|
||||
int[<2>] vec = { 12, 23 };
|
||||
s = string::format(mem, "%-20s", vec);
|
||||
assert(s == "[<12, 23>] ", "got '%s'; want '[<12, 23>] '", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%20s", vec);
|
||||
assert(s == " [<12, 23>]", "got '%s'; want ' [<12, 23>]'", s);
|
||||
free(s);
|
||||
|
||||
String ss = "hello world";
|
||||
s = string::format(mem, "%.4s %.5s", ss, ss);
|
||||
assert(s == "hell hello", "got '%s'; want 'hell hello'", s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
enum PrintfTest : ushort
|
||||
{
|
||||
ENUMA,
|
||||
ENUMB,
|
||||
}
|
||||
|
||||
fn void printf_enum()
|
||||
{
|
||||
String s;
|
||||
|
||||
s = string::format(mem, "%s", PrintfTest.ENUMA);
|
||||
assert(s == "ENUMA", "got '%s'; want 'ENUMA'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%s", PrintfTest.ENUMB);
|
||||
assert(s == "ENUMB", "got '%s'; want 'ENUMB'", s);
|
||||
free(s);
|
||||
|
||||
s = string::format(mem, "%d", PrintfTest.ENUMA);
|
||||
assert(s == "0", "got '%s'; want '0'", s);
|
||||
free(s);
|
||||
s = string::format(mem, "%d", PrintfTest.ENUMB);
|
||||
assert(s == "1", "got '%s'; want '1'", s);
|
||||
free(s);
|
||||
}
|
||||
68
test/unit7/stdlib/io/scanner.c3
Normal file
68
test/unit7/stdlib/io/scanner.c3
Normal file
@@ -0,0 +1,68 @@
|
||||
module std::io @test;
|
||||
import std::collections::list;
|
||||
|
||||
def Results = List{String};
|
||||
|
||||
struct ScanTest
|
||||
{
|
||||
String in;
|
||||
String[] out;
|
||||
String left_over;
|
||||
}
|
||||
|
||||
fn void scanner()
|
||||
{
|
||||
ScanTest[] tcases = {
|
||||
{"aa,,bb", {"aa"}, "bb"},
|
||||
{"a,,b,,", {"a", "b"}, ""},
|
||||
{"ab,,c", {"ab"}, "c"},
|
||||
{"ab,,cd,,e", {"ab", "cd"}, "e"},
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
ByteReader br;
|
||||
br.init(tc.in);
|
||||
Scanner sc;
|
||||
char[4] buffer; // max match (2) + pattern length (2)
|
||||
sc.init(&br, buffer[..]);
|
||||
|
||||
Results results;
|
||||
defer results.free();
|
||||
while LOOP: (true)
|
||||
{
|
||||
char[]! res = sc.scan(",,");
|
||||
if (catch err = res)
|
||||
{
|
||||
case SearchResult.MISSING:
|
||||
break LOOP;
|
||||
default:
|
||||
return err?!!;
|
||||
}
|
||||
String str = (String)res;
|
||||
results.push(str.tconcat(""));
|
||||
}
|
||||
|
||||
String[] got = results.array_view();
|
||||
assert(got == tc.out, "got %s; want %s", got, tc.out);
|
||||
char[] fl = sc.flush();
|
||||
String left_over = (String)fl;
|
||||
assert(left_over == tc.left_over, "%s -> %s", tc.in, left_over);
|
||||
}
|
||||
}
|
||||
|
||||
fn void scanner_as_reader()
|
||||
{
|
||||
ByteReader br;
|
||||
br.init("Lorem ipsum sit.");
|
||||
Scanner sc;
|
||||
char[8] buffer;
|
||||
sc.init(&br, buffer[..]);
|
||||
|
||||
sc.scan(" ")!!;
|
||||
|
||||
char[16] res;
|
||||
usz n = sc.read(&res)!!;
|
||||
String str = (String)res[:n];
|
||||
|
||||
assert(str == "ipsum sit.", "got '%s'; want 'ipsum sit.'", str);
|
||||
}
|
||||
89
test/unit7/stdlib/io/stream.c3
Normal file
89
test/unit7/stdlib/io/stream.c3
Normal file
@@ -0,0 +1,89 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void read_ushort_test()
|
||||
{
|
||||
ByteReader reader = io::wrap_bytes({0x34, 0x8a});
|
||||
assert(io::read_be_ushort(&reader)!! == 0x348a);
|
||||
}
|
||||
|
||||
fn void read_uint_test()
|
||||
{
|
||||
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc});
|
||||
assert(io::read_be_uint(&reader)!! == 0x348aefcc);
|
||||
}
|
||||
|
||||
fn void read_ulong_test()
|
||||
{
|
||||
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc});
|
||||
assert(io::read_be_ulong(&reader)!! == 0x348aefcc348aefcc);
|
||||
}
|
||||
|
||||
fn void read_uint128_test()
|
||||
{
|
||||
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc});
|
||||
assert(io::read_be_uint128(&reader)!! == 0x348aefcc348aefcc348aefcc348aefcc);
|
||||
}
|
||||
|
||||
fn void write_ushort_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_be_short(&bw, 0x348a)!!;
|
||||
assert(bw.str_view() == &&x'348a');
|
||||
}
|
||||
|
||||
fn void write_uint_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_be_int(&bw, 0x3421348a)!!;
|
||||
assert(bw.str_view() == &&x'3421348a');
|
||||
}
|
||||
|
||||
fn void write_ulong_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_be_long(&bw, 0xaabbccdd3421348a)!!;
|
||||
assert(bw.str_view() == &&x'aabbccdd3421348a');
|
||||
}
|
||||
|
||||
fn void write_uint128_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_be_int128(&bw, 0xaabbccdd3421348aaabbccdd3421348a)!!;
|
||||
assert(bw.str_view() == &&x'aabbccdd3421348aaabbccdd3421348a');
|
||||
}
|
||||
|
||||
fn void write_tiny_bytearray_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_tiny_bytearray(&bw, &&x"aabbcc00112233")!!;
|
||||
assert(bw.str_view() == &&x'07aabbcc00112233');
|
||||
}
|
||||
|
||||
fn void write_short_bytearray_test()
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
io::write_short_bytearray(&bw, &&x"aabbcc00112233")!!;
|
||||
assert(bw.str_view() == &&x'0007aabbcc00112233');
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
ByteReader reader = io::wrap_bytes(&&x'0007aabbcc00112233');
|
||||
char[] read = io::read_short_bytearray(&reader, allocator: allocator::heap())!!;
|
||||
assert(read == &&x'aabbcc00112233');
|
||||
free(read);
|
||||
}
|
||||
17
test/unit7/stdlib/io/teereader.c3
Normal file
17
test/unit7/stdlib/io/teereader.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
module std::io @test;
|
||||
|
||||
fn void test_teereader()
|
||||
{
|
||||
String want = "foobar";
|
||||
|
||||
ByteWriter w;
|
||||
TeeReader r = tee_reader((ByteReader){}.init(want), w.temp_init());
|
||||
|
||||
char[16] buf;
|
||||
usz n = r.read(buf[..])!!;
|
||||
|
||||
String got = w.str_view();
|
||||
assert(n == want.len, "teereader: invalid length");
|
||||
assert(got == want, "teereader: got: %s, want: %s", got, want);
|
||||
assert(got == (String)buf[:n], "teereader: got: %s, want: %s", got, (String)buf[:n]);
|
||||
}
|
||||
54
test/unit7/stdlib/io/varint.c3
Normal file
54
test/unit7/stdlib/io/varint.c3
Normal file
@@ -0,0 +1,54 @@
|
||||
module std::io::varint @test;
|
||||
import std::io;
|
||||
|
||||
fn void write_read()
|
||||
{
|
||||
ByteBuffer buf;
|
||||
buf.temp_init(16);
|
||||
usz n;
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
n = io::write_varint(&buf, 123)!!;
|
||||
assert(n == 1, "got %d; want 1", n);
|
||||
io::read_varint(&buf, &y)!!;
|
||||
assert(y == 123, "got %d; want 123", y);
|
||||
|
||||
n = io::write_varint(&buf, 123456789)!!;
|
||||
assert(n == 4, "got %d; want 4", n);
|
||||
io::read_varint(&buf, &y)!!;
|
||||
assert(y == 123456789, "got %d; want 123456789", y);
|
||||
}
|
||||
|
||||
struct VarIntTest
|
||||
{
|
||||
uint in;
|
||||
char[] bytes;
|
||||
}
|
||||
|
||||
fn void samples()
|
||||
{
|
||||
VarIntTest[] tcases = {
|
||||
{ 0, { 0x00 } },
|
||||
{ 100, { 0x64 } },
|
||||
{ 127, { 0x7F } },
|
||||
{ 128, { 0x80, 0x01 } },
|
||||
{ 16271, { 0x8F, 0x7F } },
|
||||
{ 16383, { 0xFF, 0x7F } },
|
||||
{ 16384, { 0x80, 0x80, 0x01 } },
|
||||
{ 1048576, { 0x80, 0x80, 0x40 } },
|
||||
{ 2097151, { 0xFF, 0xFF, 0x7F } },
|
||||
{ 2097152, { 0x80, 0x80, 0x80, 0x01 } },
|
||||
{ 2147483648, { 0x80, 0x80, 0x80, 0x80, 0x08 } },
|
||||
{ 4294967295, { 0xFF, 0xFF, 0xFF, 0xFF, 0x0F } },
|
||||
};
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
ByteWriter bw;
|
||||
bw.temp_init();
|
||||
usz n = io::write_varint(&bw, tc.in)!!;
|
||||
assert(n == tc.bytes.len, "got %d; want %d", n, tc.bytes.len);
|
||||
char[] bytes = bw.bytes[:bw.index];
|
||||
assert(bytes == tc.bytes, "got %d; want %d", bytes, tc.bytes);
|
||||
}
|
||||
}
|
||||
23
test/unit7/stdlib/macros/core_builtins.c3
Normal file
23
test/unit7/stdlib/macros/core_builtins.c3
Normal file
@@ -0,0 +1,23 @@
|
||||
module core_builtin_tests;
|
||||
|
||||
fn void test_likely() @test
|
||||
{
|
||||
assert(@likely(2 > 1));
|
||||
assert(@likely(2 > 1, 0.5));
|
||||
}
|
||||
|
||||
fn void test_unlikely() @test
|
||||
{
|
||||
assert(!@unlikely(2 < 1));
|
||||
assert(!@unlikely(2 < 1, 0.5));
|
||||
}
|
||||
|
||||
fn void test_expect() @test
|
||||
{
|
||||
assert(@expect(2 > 1, true));
|
||||
assert(!@expect(2 < 1, false));
|
||||
|
||||
assert(@expect(2 > 1, true, 0.5));
|
||||
assert(!@expect(2 < 1, false, 0.5));
|
||||
}
|
||||
|
||||
75
test/unit7/stdlib/math/bigint.c3
Normal file
75
test/unit7/stdlib/math/bigint.c3
Normal file
@@ -0,0 +1,75 @@
|
||||
module std::math::bigint @test;
|
||||
|
||||
fn void test_parse16()
|
||||
{
|
||||
BigInt bi @noinit;
|
||||
assert(bi.init_string_radix("c", 16)!!.equals(bigint::from_int(12)));
|
||||
}
|
||||
|
||||
fn void test_zero()
|
||||
{
|
||||
assert(bigint::from_int(0).to_string(allocator::temp()) == "0");
|
||||
BigInt bi;
|
||||
bi.init_string_radix("00", 16)!!;
|
||||
assert(bi.to_string(allocator::temp()) == "0");
|
||||
}
|
||||
|
||||
fn void test_plus()
|
||||
{
|
||||
BigInt a = bigint::from_int(123);
|
||||
BigInt b = bigint::from_int(234);
|
||||
assert(a.add(b).equals(bigint::from_int(234 + 123)));
|
||||
|
||||
a = bigint::from_int(12323400012311213314141414i128);
|
||||
b = bigint::from_int(23400012311213314141414i128);
|
||||
assert(a.add(b).equals(bigint::from_int(12323400012311213314141414i128 + 23400012311213314141414i128)));
|
||||
}
|
||||
|
||||
fn void test_mult()
|
||||
{
|
||||
BigInt a = bigint::from_int(123);
|
||||
BigInt b = bigint::from_int(234);
|
||||
assert(a.mult(b).equals(bigint::from_int(234 * 123)));
|
||||
|
||||
a = bigint::from_int(1232311213314141414i128);
|
||||
b = bigint::from_int(234000123112414i128);
|
||||
assert(a.mult(b).equals(bigint::from_int(1232311213314141414i128 * 234000123112414i128)));
|
||||
}
|
||||
|
||||
fn void test_minus()
|
||||
{
|
||||
BigInt a = bigint::from_int(123);
|
||||
BigInt b = bigint::from_int(234);
|
||||
assert(a.sub(b).equals(bigint::from_int(123 - 234)));
|
||||
|
||||
a = bigint::from_int(12323400012311213314141414i128);
|
||||
b = bigint::from_int(23400012311213314141414i128);
|
||||
assert(a.sub(b).equals(bigint::from_int(12323400012311213314141414i128 - 23400012311213314141414i128)));
|
||||
}
|
||||
|
||||
fn void test_init_string_radix()
|
||||
{
|
||||
BigInt a;
|
||||
a.init_string_radix("123", 10)!!;
|
||||
assert(a.equals(bigint::from_int(123)));
|
||||
a.init_string_radix("123", 8)!!;
|
||||
assert(a.equals(bigint::from_int(0o123)));
|
||||
a.init_string_radix("123", 16)!!;
|
||||
assert(a.equals(bigint::from_int(0x123)));
|
||||
}
|
||||
|
||||
fn void test_gcd()
|
||||
{
|
||||
BigInt a = bigint::from_int(15);
|
||||
BigInt b = bigint::from_int(20);
|
||||
assert(a.gcd(b).equals(bigint::from_int(5)));
|
||||
assert(math::gcd(a,b).equals(bigint::from_int(5)));
|
||||
}
|
||||
|
||||
fn void test_lcm()
|
||||
{
|
||||
BigInt a = bigint::from_int(11);
|
||||
BigInt b = bigint::from_int(17);
|
||||
assert(a.lcm(b).equals(bigint::from_int(11*17)));
|
||||
assert(math::lcm(a,b).equals(bigint::from_int(11*17)));
|
||||
}
|
||||
18
test/unit7/stdlib/math/frexp_signbit.c3
Normal file
18
test/unit7/stdlib/math/frexp_signbit.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
module std::math @test;
|
||||
|
||||
fn void test_frexp()
|
||||
{
|
||||
int a;
|
||||
double z = math::frexp(231.23, &a);
|
||||
assert((z - 0.903242187) < 0.0000001 && a == 8);
|
||||
float z2 = math::frexp(231.23f, &a);
|
||||
assert((z2 - 0.903242187) < 0.0000001 && a == 8);
|
||||
}
|
||||
|
||||
fn void test_signbit()
|
||||
{
|
||||
assert(math::signbit(-231.3) == 1);
|
||||
assert(math::signbit(231.3) == 0);
|
||||
assert(math::signbit(float.inf) == 0);
|
||||
assert(math::signbit(-float.inf) == 1);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user