zig/test/run_tests.cpp

1560 lines
39 KiB
C++
Raw Normal View History

2015-11-26 00:29:52 -08:00
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of zig, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#include "list.hpp"
#include "buffer.hpp"
#include "os.hpp"
#include <stdio.h>
2015-11-27 17:55:06 -08:00
#include <stdarg.h>
2015-11-26 00:29:52 -08:00
struct TestSourceFile {
const char *relative_path;
2015-12-01 01:08:58 -08:00
const char *source_code;
2015-11-26 00:29:52 -08:00
};
struct TestCase {
const char *case_name;
const char *output;
2015-12-01 01:08:58 -08:00
ZigList<TestSourceFile> source_files;
2015-11-26 00:29:52 -08:00
ZigList<const char *> compile_errors;
ZigList<const char *> compiler_args;
ZigList<const char *> program_args;
};
2015-11-27 17:55:06 -08:00
static ZigList<TestCase*> test_cases = {0};
static const char *tmp_source_path = ".tmp_source.zig";
static const char *tmp_exe_path = "./.tmp_exe";
static const char *zig_exe = "./zig";
2015-11-26 00:29:52 -08:00
2015-12-01 01:08:58 -08:00
static void add_source_file(TestCase *test_case, const char *path, const char *source) {
test_case->source_files.add_one();
test_case->source_files.last().relative_path = path;
test_case->source_files.last().source_code = source;
}
static TestCase *add_simple_case(const char *case_name, const char *source, const char *output) {
2015-11-26 00:29:52 -08:00
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = case_name;
test_case->output = output;
2015-12-01 01:08:58 -08:00
test_case->source_files.resize(1);
test_case->source_files.at(0).relative_path = tmp_source_path;
test_case->source_files.at(0).source_code = source;
2015-11-26 00:29:52 -08:00
test_case->compiler_args.append("build");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--export");
test_case->compiler_args.append("exe");
test_case->compiler_args.append("--name");
test_case->compiler_args.append("test");
2015-11-26 00:29:52 -08:00
test_case->compiler_args.append("--output");
test_case->compiler_args.append(tmp_exe_path);
test_case->compiler_args.append("--release");
test_case->compiler_args.append("--strip");
test_case->compiler_args.append("--color");
test_case->compiler_args.append("on");
2015-11-26 00:29:52 -08:00
test_cases.append(test_case);
2015-12-01 01:08:58 -08:00
return test_case;
2015-11-26 00:29:52 -08:00
}
2015-12-01 01:08:58 -08:00
static TestCase *add_compile_fail_case(const char *case_name, const char *source, int count, ...) {
2015-11-27 17:55:06 -08:00
va_list ap;
va_start(ap, count);
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = case_name;
2015-12-01 01:08:58 -08:00
test_case->source_files.resize(1);
test_case->source_files.at(0).relative_path = tmp_source_path;
test_case->source_files.at(0).source_code = source;
2015-11-27 17:55:06 -08:00
for (int i = 0; i < count; i += 1) {
const char *arg = va_arg(ap, const char *);
test_case->compile_errors.append(arg);
}
test_case->compiler_args.append("build");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--output");
test_case->compiler_args.append(tmp_exe_path);
test_case->compiler_args.append("--release");
test_case->compiler_args.append("--strip");
2015-12-15 16:11:44 -08:00
//test_case->compiler_args.append("--verbose");
2015-11-27 17:55:06 -08:00
test_cases.append(test_case);
va_end(ap);
2015-12-01 01:08:58 -08:00
return test_case;
2015-11-27 17:55:06 -08:00
}
static void add_compiling_test_cases(void) {
2015-11-26 00:29:52 -08:00
add_simple_case("hello world with libc", R"SOURCE(
2016-01-13 17:15:51 -08:00
#link("c")
extern {
fn puts(s: &const u8) i32;
}
2015-11-26 00:29:52 -08:00
2016-01-13 17:15:51 -08:00
export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {
puts(c"Hello, world!");
return 0;
}
2015-11-26 00:29:52 -08:00
)SOURCE", "Hello, world!\n");
add_simple_case("function call", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
import "syscall.zig";
2015-11-26 00:29:52 -08:00
2016-01-13 17:15:51 -08:00
fn empty_function_1() => {}
fn empty_function_2() => { return; }
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
empty_function_1();
empty_function_2();
this_is_a_function();
}
2015-11-26 00:29:52 -08:00
2016-01-13 17:15:51 -08:00
fn this_is_a_function() unreachable => {
print_str("OK\n");
exit(0);
}
2015-11-26 00:29:52 -08:00
)SOURCE", "OK\n");
2015-11-26 23:40:26 -08:00
add_simple_case("comments", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
/**
* multi line doc comment
*/
fn another_function() => {}
/// this is a documentation comment
/// doc comment line 2
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
print_str(/* mid-line comment /* nested */ */ "OK\n");
return 0;
}
2015-11-26 23:40:26 -08:00
)SOURCE", "OK\n");
2015-12-01 01:08:58 -08:00
{
TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
import "foo.zig";
2015-12-01 01:08:58 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
private_function();
print_str("OK 2\n");
return 0;
}
2015-12-01 01:08:58 -08:00
2016-01-13 17:15:51 -08:00
fn private_function() => {
print_text();
}
)SOURCE", "OK 1\nOK 2\n");
2015-12-01 01:08:58 -08:00
add_source_file(tc, "foo.zig", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-01 01:08:58 -08:00
// purposefully conflicting function with main.zig
// but it's private so it should be OK
2016-01-13 17:15:51 -08:00
fn private_function() => {
print_str("OK 1\n");
}
2015-12-01 01:08:58 -08:00
2016-01-13 17:15:51 -08:00
pub fn print_text() => {
private_function();
}
2015-12-01 01:08:58 -08:00
)SOURCE");
}
2016-01-04 02:31:57 -08:00
{
TestCase *tc = add_simple_case("import segregation", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "foo.zig";
import "bar.zig";
2016-01-04 02:31:57 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-04 02:31:57 -08:00
foo_function();
bar_function();
return 0;
}
)SOURCE", "OK\nOK\n");
add_source_file(tc, "foo.zig", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn foo_function() => {
2016-01-04 02:31:57 -08:00
print_str("OK\n");
}
)SOURCE");
add_source_file(tc, "bar.zig", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "other.zig";
import "std.zig";
2016-01-04 02:31:57 -08:00
2016-01-13 17:15:51 -08:00
pub fn bar_function() => {
2016-01-04 02:31:57 -08:00
if (foo_function()) {
print_str("OK\n");
}
}
)SOURCE");
add_source_file(tc, "other.zig", R"SOURCE(
2016-01-13 17:15:51 -08:00
pub fn foo_function() bool => {
2016-01-04 02:31:57 -08:00
// this one conflicts with the one from foo
return true;
}
)SOURCE");
}
2015-12-01 20:19:38 -08:00
add_simple_case("if statements", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
if (1 != 0) {
print_str("1 is true\n");
} else {
print_str("1 is false\n");
}
if (0 != 0) {
print_str("0 is true\n");
} else if (1 - 1 != 0) {
print_str("1 - 1 is true\n");
}
if (!(0 != 0)) {
print_str("!0 is true\n");
}
return 0;
}
2015-12-01 20:19:38 -08:00
)SOURCE", "1 is true\n!0 is true\n");
add_simple_case("params", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
fn add(a: i32, b: i32) i32 => {
a + b
}
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
if (add(22, 11) == 33) {
print_str("pass\n");
}
return 0;
}
)SOURCE", "pass\n");
2015-12-02 23:47:35 -08:00
add_simple_case("goto", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-02 23:47:35 -08:00
2016-01-13 17:15:51 -08:00
fn loop(a : i32) => {
if (a == 0) {
goto done;
}
print_str("loop\n");
loop(a - 1);
2015-12-02 23:47:35 -08:00
2016-01-13 17:15:51 -08:00
done:
return;
}
2015-12-02 23:47:35 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
loop(3);
return 0;
}
2015-12-02 23:47:35 -08:00
)SOURCE", "loop\nloop\nloop\n");
2015-12-03 10:06:05 -08:00
add_simple_case("local variables", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-03 10:06:05 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
const a : i32 = 1;
const b = i32(2);
2015-12-03 10:06:05 -08:00
if (a + b == 3) {
print_str("OK\n");
2015-12-03 10:06:05 -08:00
}
return 0;
2015-12-03 10:06:05 -08:00
}
)SOURCE", "OK\n");
2015-12-03 11:19:28 -08:00
add_simple_case("bool literals", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-03 11:19:28 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
if (true) { print_str("OK 1\n"); }
if (false) { print_str("BAD 1\n"); }
if (!true) { print_str("BAD 2\n"); }
if (!false) { print_str("OK 2\n"); }
return 0;
2015-12-03 12:26:49 -08:00
}
)SOURCE", "OK 1\nOK 2\n");
add_simple_case("separate block scopes", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-03 12:26:49 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2015-12-03 12:26:49 -08:00
if (true) {
const no_conflict : i32 = 5;
if (no_conflict == 5) { print_str("OK 1\n"); }
2015-12-03 12:26:49 -08:00
}
const c = {
const no_conflict = i32(10);
2015-12-03 12:26:49 -08:00
no_conflict
};
if (c == 10) { print_str("OK 2\n"); }
return 0;
2015-12-03 11:19:28 -08:00
}
)SOURCE", "OK 1\nOK 2\n");
2015-12-03 13:33:13 -08:00
add_simple_case("void parameters", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-03 13:33:13 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
void_fun(1, void{}, 2);
return 0;
2015-12-03 13:33:13 -08:00
}
2016-01-13 17:15:51 -08:00
fn void_fun(a : i32, b : void, c : i32) => {
const v = b;
const vv : void = if (a == 1) {v} else {};
if (a + c == 3) { print_str("OK\n"); }
2015-12-03 13:33:13 -08:00
return vv;
}
)SOURCE", "OK\n");
2015-12-06 22:09:46 -08:00
2016-01-10 17:56:50 -08:00
add_simple_case("void struct fields", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-10 17:56:50 -08:00
struct Foo {
a : void,
b : i32,
c : void,
}
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-10 17:56:50 -08:00
const foo = Foo {
2016-01-13 17:15:51 -08:00
.a = void{},
2016-01-10 17:56:50 -08:00
.b = 1,
2016-01-13 17:15:51 -08:00
.c = void{},
2016-01-10 17:56:50 -08:00
};
if (foo.b != 1) {
print_str("BAD\n");
}
2016-01-13 17:15:51 -08:00
if (@sizeof(Foo) != 4) {
2016-01-10 17:56:50 -08:00
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
2016-01-15 17:41:19 -08:00
add_simple_case("void arrays", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-15 17:41:19 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var array: [4]void;
array[0] = void{};
array[1] = array[2];
if (@sizeof(@typeof(array)) != 0) {
print_str("BAD\n");
}
if (array.len != 4) {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
2015-12-06 22:33:10 -08:00
add_simple_case("mutable local variables", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-06 22:09:46 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-11 19:33:06 -08:00
var zero : i32 = 0;
if (zero == 0) { print_str("zero\n"); }
2015-12-06 22:33:10 -08:00
var i = i32(0);
2015-12-06 22:09:46 -08:00
loop_start:
if (i == 3) {
2015-12-06 22:09:46 -08:00
goto done;
}
print_str("loop\n");
2015-12-06 22:09:46 -08:00
i = i + 1;
goto loop_start;
done:
return 0;
2015-12-06 22:09:46 -08:00
}
2015-12-06 22:33:10 -08:00
)SOURCE", "zero\nloop\nloop\nloop\n");
2015-12-08 14:46:36 -08:00
add_simple_case("arrays", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-08 14:46:36 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var array : [5]u32;
2015-12-08 14:46:36 -08:00
var i : u32 = 0;
while (i < 5) {
array[i] = i + 1;
i = array[i];
2015-12-08 14:46:36 -08:00
}
i = 0;
var accumulator = u32(0);
while (i < 5) {
accumulator += array[i];
2015-12-08 14:46:36 -08:00
i += 1;
}
2015-12-08 14:46:36 -08:00
if (accumulator == 15) {
print_str("OK\n");
2015-12-08 14:46:36 -08:00
}
2016-01-06 00:30:11 -08:00
if (get_array_len(array) != 5) {
print_str("BAD\n");
}
return 0;
2016-01-06 00:30:11 -08:00
}
2016-01-13 17:15:51 -08:00
fn get_array_len(a: []u32) usize => {
2016-01-06 00:30:11 -08:00
a.len
2015-12-08 14:46:36 -08:00
}
)SOURCE", "OK\n");
2015-12-10 14:34:38 -08:00
2015-12-11 02:55:26 -08:00
add_simple_case("hello world without libc", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-11 02:55:26 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
print_str("Hello, world!\n");
2015-12-11 02:55:26 -08:00
return 0;
}
)SOURCE", "Hello, world!\n");
add_simple_case("a + b + c", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
if (false || false || false) { print_str("BAD 1\n"); }
if (true && true && false) { print_str("BAD 2\n"); }
if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }
if (3 ^ 6 ^ 8 != 13) { print_str("BAD 4\n"); }
if (7 & 14 & 28 != 4) { print_str("BAD 5\n"); }
if (9 << 1 << 2 != 9 << 3) { print_str("BAD 6\n"); }
if (90 >> 1 >> 2 != 90 >> 3) { print_str("BAD 7\n"); }
if (100 - 1 + 1000 != 1099) { print_str("BAD 8\n"); }
if (5 * 4 / 2 % 3 != 1) { print_str("BAD 9\n"); }
if (i32(i32(5)) != 5) { print_str("BAD 10\n"); }
if (!!false) { print_str("BAD 11\n"); }
if (i32(7) != --(i32(7))) { print_str("BAD 12\n"); }
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
2015-12-11 02:55:26 -08:00
2015-12-12 16:33:45 -08:00
add_simple_case("short circuit", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-12 16:33:45 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
if (true || { print_str("BAD 1\n"); false }) {
print_str("OK 1\n");
2015-12-12 16:33:45 -08:00
}
if (false || { print_str("OK 2\n"); false }) {
print_str("BAD 2\n");
2015-12-12 16:33:45 -08:00
}
if (true && { print_str("OK 3\n"); false }) {
print_str("BAD 3\n");
2015-12-12 16:33:45 -08:00
}
if (false && { print_str("BAD 4\n"); false }) {
2015-12-12 16:33:45 -08:00
} else {
print_str("OK 4\n");
2015-12-12 16:33:45 -08:00
}
return 0;
}
)SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");
add_simple_case("modify operators", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
var i : i32 = 0;
i += 5; if (i != 5) { print_str("BAD +=\n"); }
i -= 2; if (i != 3) { print_str("BAD -=\n"); }
i *= 20; if (i != 60) { print_str("BAD *=\n"); }
i /= 3; if (i != 20) { print_str("BAD /=\n"); }
i %= 11; if (i != 9) { print_str("BAD %=\n"); }
i <<= 1; if (i != 18) { print_str("BAD <<=\n"); }
i >>= 2; if (i != 4) { print_str("BAD >>=\n"); }
i = 6;
i &= 5; if (i != 4) { print_str("BAD &=\n"); }
i ^= 6; if (i != 2) { print_str("BAD ^=\n"); }
i = 6;
i |= 3; if (i != 7) { print_str("BAD |=\n"); }
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
add_simple_case("number literals", R"SOURCE(
#link("c")
extern {
2016-01-13 17:15:51 -08:00
fn printf(__format: &const u8, ...) i32;
}
2016-01-13 17:15:51 -08:00
export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
2015-12-15 12:15:07 -08:00
printf(c"\n");
2015-12-15 13:12:33 -08:00
printf(c"0: %llu\n",
u64(0));
2015-12-15 13:12:33 -08:00
printf(c"320402575052271: %llu\n",
u64(320402575052271));
2015-12-15 13:12:33 -08:00
printf(c"0x01236789abcdef: %llu\n",
u64(0x01236789abcdef));
2015-12-15 13:12:33 -08:00
printf(c"0xffffffffffffffff: %llu\n",
u64(0xffffffffffffffff));
2015-12-15 13:12:33 -08:00
printf(c"0x000000ffffffffffffffff: %llu\n",
u64(0x000000ffffffffffffffff));
2015-12-15 13:12:33 -08:00
printf(c"0o1777777777777777777777: %llu\n",
u64(0o1777777777777777777777));
2015-12-15 13:12:33 -08:00
printf(c"0o0000001777777777777777777777: %llu\n",
u64(0o0000001777777777777777777777));
2015-12-15 13:12:33 -08:00
printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
u64(0b1111111111111111111111111111111111111111111111111111111111111111));
2015-12-15 13:12:33 -08:00
printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
u64(0b0000001111111111111111111111111111111111111111111111111111111111111111));
2015-12-15 13:12:33 -08:00
printf(c"\n");
2015-12-15 12:15:07 -08:00
printf(c"0.0: %a\n",
f64(0.0));
2015-12-15 12:15:07 -08:00
printf(c"0e0: %a\n",
f64(0e0));
2015-12-15 12:15:07 -08:00
printf(c"0.0e0: %a\n",
f64(0.0e0));
2015-12-15 12:15:07 -08:00
printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
f64(000000000000000000000000000000000000000000000000000000000.0e0));
2015-12-15 12:15:07 -08:00
printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
f64(0.000000000000000000000000000000000000000000000000000000000e0));
2015-12-15 12:15:07 -08:00
printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
f64(0.0e000000000000000000000000000000000000000000000000000000000));
2015-12-15 13:54:16 -08:00
printf(c"1.0: %a\n",
f64(1.0));
2015-12-15 13:54:16 -08:00
printf(c"10.0: %a\n",
f64(10.0));
2015-12-15 13:54:16 -08:00
printf(c"10.5: %a\n",
f64(10.5));
2015-12-15 13:54:16 -08:00
printf(c"10.5e5: %a\n",
f64(10.5e5));
2015-12-15 13:54:16 -08:00
printf(c"10.5e+5: %a\n",
f64(10.5e+5));
2015-12-15 13:54:16 -08:00
printf(c"50.0e-2: %a\n",
f64(50.0e-2));
2015-12-15 13:54:16 -08:00
printf(c"50e-2: %a\n",
f64(50e-2));
2015-12-15 12:15:07 -08:00
printf(c"\n");
printf(c"0x1.0: %a\n",
f64(0x1.0));
2015-12-15 12:15:07 -08:00
printf(c"0x10.0: %a\n",
f64(0x10.0));
2015-12-15 12:15:07 -08:00
printf(c"0x100.0: %a\n",
f64(0x100.0));
2015-12-15 12:15:07 -08:00
printf(c"0x103.0: %a\n",
f64(0x103.0));
2015-12-15 12:15:07 -08:00
printf(c"0x103.7: %a\n",
f64(0x103.7));
2015-12-15 12:15:07 -08:00
printf(c"0x103.70: %a\n",
f64(0x103.70));
2015-12-15 12:15:07 -08:00
printf(c"0x103.70p4: %a\n",
f64(0x103.70p4));
2015-12-15 12:15:07 -08:00
printf(c"0x103.70p5: %a\n",
f64(0x103.70p5));
2015-12-15 12:15:07 -08:00
printf(c"0x103.70p+5: %a\n",
f64(0x103.70p+5));
2015-12-15 12:15:07 -08:00
printf(c"0x103.70p-5: %a\n",
f64(0x103.70p-5));
2015-12-15 12:15:07 -08:00
printf(c"\n");
printf(c"0b10100.00010e0: %a\n",
f64(0b10100.00010e0));
2015-12-15 12:15:07 -08:00
printf(c"0o10700.00010e0: %a\n",
f64(0o10700.00010e0));
2015-12-15 12:15:07 -08:00
return 0;
}
2015-12-15 12:15:07 -08:00
)SOURCE", R"OUTPUT(
2015-12-15 13:12:33 -08:00
0: 0
320402575052271: 320402575052271
0x01236789abcdef: 320402575052271
0xffffffffffffffff: 18446744073709551615
0x000000ffffffffffffffff: 18446744073709551615
0o1777777777777777777777: 18446744073709551615
0o0000001777777777777777777777: 18446744073709551615
0b1111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615
0b0000001111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615
2015-12-15 12:15:07 -08:00
0.0: 0x0p+0
0e0: 0x0p+0
0.0e0: 0x0p+0
000000000000000000000000000000000000000000000000000000000.0e0: 0x0p+0
0.000000000000000000000000000000000000000000000000000000000e0: 0x0p+0
0.0e000000000000000000000000000000000000000000000000000000000: 0x0p+0
2015-12-15 13:54:16 -08:00
1.0: 0x1p+0
10.0: 0x1.4p+3
10.5: 0x1.5p+3
10.5e5: 0x1.0059p+20
10.5e+5: 0x1.0059p+20
50.0e-2: 0x1p-1
50e-2: 0x1p-1
2015-12-15 12:15:07 -08:00
0x1.0: 0x1p+0
0x10.0: 0x1p+4
0x100.0: 0x1p+8
0x103.0: 0x1.03p+8
0x103.7: 0x1.037p+8
0x103.70: 0x1.037p+8
0x103.70p4: 0x1.037p+12
0x103.70p5: 0x1.037p+13
0x103.70p+5: 0x1.037p+13
0x103.70p-5: 0x1.037p+3
0b10100.00010e0: 0x1.41p+4
0o10700.00010e0: 0x1.1c0001p+12
)OUTPUT");
2015-12-12 21:55:29 -08:00
add_simple_case("structs", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2015-12-12 21:55:29 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
var foo : Foo;
2016-01-13 17:15:51 -08:00
@memset(&foo, 0, @sizeof(Foo));
foo.a += 1;
2015-12-12 21:55:29 -08:00
foo.b = foo.a == 1;
test_foo(foo);
test_mutation(&foo);
if (foo.c != 100) {
print_str("BAD\n");
}
test_point_to_self();
test_byval_assign();
2015-12-23 23:00:23 -08:00
test_initializer();
print_str("OK\n");
2015-12-12 21:55:29 -08:00
return 0;
}
struct Foo {
a : i32,
b : bool,
c : f32,
}
2016-01-13 17:15:51 -08:00
fn test_foo(foo : Foo) => {
if (!foo.b) {
print_str("BAD\n");
2015-12-12 21:55:29 -08:00
}
}
2016-01-13 17:15:51 -08:00
fn test_mutation(foo : &Foo) => {
foo.c = 100;
}
struct Node {
val: Val,
next: &Node,
}
struct Val {
x: i32,
}
2016-01-13 17:15:51 -08:00
fn test_point_to_self() => {
var root : Node;
root.val.x = 1;
var node : Node;
node.next = &root;
node.val.x = 2;
root.next = &node;
if (node.next.next.next.val.x != 1) {
print_str("BAD\n");
}
}
2016-01-13 17:15:51 -08:00
fn test_byval_assign() => {
var foo1 : Foo;
var foo2 : Foo;
foo1.a = 1234;
if (foo2.a != 0) { print_str("BAD\n"); }
foo2 = foo1;
if (foo2.a != 1234) { print_str("BAD - byval assignment failed\n"); }
2015-12-23 23:00:23 -08:00
}
2016-01-13 17:15:51 -08:00
fn test_initializer() => {
2015-12-23 23:00:23 -08:00
const val = Val { .x = 42 };
if (val.x != 42) { print_str("BAD\n"); }
}
)SOURCE", "OK\n");
add_simple_case("global variables", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
const g1 : i32 = 1233 + 1;
2016-01-11 19:33:06 -08:00
var g2 : i32 = 0;
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
if (g2 != 0) { print_str("BAD\n"); }
g2 = g1;
if (g2 != 1234) { print_str("BAD\n"); }
print_str("OK\n");
return 0;
2015-12-12 21:55:29 -08:00
}
)SOURCE", "OK\n");
2015-12-24 13:41:00 -08:00
add_simple_case("while loop", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
2015-12-24 13:41:00 -08:00
var i : i32 = 0;
while (i < 4) {
2015-12-24 13:41:00 -08:00
print_str("loop\n");
i += 1;
}
return f();
}
2016-01-13 17:15:51 -08:00
fn f() i32 => {
while (true) {
return 0;
}
2015-12-24 14:09:35 -08:00
}
)SOURCE", "loop\nloop\nloop\nloop\n");
add_simple_case("continue and break", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
2015-12-24 14:09:35 -08:00
var i : i32 = 0;
while (true) {
print_str("loop\n");
i += 1;
if (i < 4) {
continue;
2015-12-24 14:09:35 -08:00
}
break;
2015-12-24 14:09:35 -08:00
}
return 0;
2015-12-24 13:41:00 -08:00
}
)SOURCE", "loop\nloop\nloop\nloop\n");
2016-01-01 23:06:06 -08:00
add_simple_case("maybe type", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-01 23:06:06 -08:00
const x : ?bool = true;
if (const y ?= x) {
if (y) {
print_str("x is true\n");
} else {
print_str("x is false\n");
}
} else {
print_str("x is none\n");
}
const next_x : ?i32 = null;
const z = next_x ?? 1234;
if (z != 1234) {
print_str("BAD\n");
}
const final_x : ?i32 = 13;
2016-01-13 17:15:51 -08:00
const num = final_x ?? unreachable{};
if (num != 13) {
print_str("BAD\n");
}
2016-01-01 23:06:06 -08:00
return 0;
}
)SOURCE", "x is true\n");
add_simple_case("implicit cast after unreachable", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
const x = outer();
if (x == 1234) {
print_str("OK\n");
}
return 0;
}
2016-01-13 17:15:51 -08:00
fn inner() i32 => { 1234 }
fn outer() isize => {
return inner();
2016-01-03 17:17:50 -08:00
}
)SOURCE", "OK\n");
2016-01-13 17:15:51 -08:00
add_simple_case("@sizeof() and @typeof()", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-03 17:17:50 -08:00
const x: u16 = 13;
2016-01-13 17:15:51 -08:00
const z: @typeof(x) = 19;
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
const y: @typeof(x) = 120;
print_u64(@sizeof(@typeof(y)));
2016-01-03 18:38:36 -08:00
print_str("\n");
2016-01-03 17:17:50 -08:00
return 0;
}
2016-01-03 18:38:36 -08:00
)SOURCE", "2\n");
2016-01-04 15:57:22 -08:00
add_simple_case("member functions", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-04 15:57:22 -08:00
struct Rand {
seed: u32,
2016-01-13 17:15:51 -08:00
pub fn get_seed(r: Rand) u32 => {
2016-01-04 15:57:22 -08:00
r.seed
}
}
2016-01-13 17:15:51 -08:00
pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
2016-01-04 15:57:22 -08:00
const r = Rand {.seed = 1234};
if (r.get_seed() != 1234) {
print_str("BAD seed\n");
}
print_str("OK\n");
return 0;
2016-01-04 18:10:52 -08:00
}
)SOURCE", "OK\n");
add_simple_case("pointer dereferencing", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-04 18:10:52 -08:00
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var x = i32(3);
2016-01-04 18:10:52 -08:00
const y = &x;
*y += 1;
if (x != 4) {
print_str("BAD\n");
}
if (*y != 4) {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
2016-01-04 15:57:22 -08:00
}
)SOURCE", "OK\n");
add_simple_case("constant expressions", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
const ARRAY_SIZE : u8 = 20;
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var array : [ARRAY_SIZE]u8;
2016-01-13 17:15:51 -08:00
print_u64(@sizeof(@typeof(array)));
print_str("\n");
return 0;
}
)SOURCE", "20\n");
2016-01-05 05:30:49 -08:00
add_simple_case("#min_value() and #max_value()", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-05 05:30:49 -08:00
print_str("max u8: ");
2016-01-13 17:15:51 -08:00
print_u64(@max_value(u8));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max u16: ");
2016-01-13 17:15:51 -08:00
print_u64(@max_value(u16));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max u32: ");
2016-01-13 17:15:51 -08:00
print_u64(@max_value(u32));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max u64: ");
2016-01-13 17:15:51 -08:00
print_u64(@max_value(u64));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max i8: ");
2016-01-13 17:15:51 -08:00
print_i64(@max_value(i8));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max i16: ");
2016-01-13 17:15:51 -08:00
print_i64(@max_value(i16));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max i32: ");
2016-01-13 17:15:51 -08:00
print_i64(@max_value(i32));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("max i64: ");
2016-01-13 17:15:51 -08:00
print_i64(@max_value(i64));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min u8: ");
2016-01-13 17:15:51 -08:00
print_u64(@min_value(u8));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min u16: ");
2016-01-13 17:15:51 -08:00
print_u64(@min_value(u16));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min u32: ");
2016-01-13 17:15:51 -08:00
print_u64(@min_value(u32));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min u64: ");
2016-01-13 17:15:51 -08:00
print_u64(@min_value(u64));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min i8: ");
2016-01-13 17:15:51 -08:00
print_i64(@min_value(i8));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min i16: ");
2016-01-13 17:15:51 -08:00
print_i64(@min_value(i16));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min i32: ");
2016-01-13 17:15:51 -08:00
print_i64(@min_value(i32));
2016-01-05 05:30:49 -08:00
print_str("\n");
print_str("min i64: ");
2016-01-13 17:15:51 -08:00
print_i64(@min_value(i64));
2016-01-05 05:30:49 -08:00
print_str("\n");
return 0;
}
)SOURCE",
"max u8: 255\n"
"max u16: 65535\n"
"max u32: 4294967295\n"
"max u64: 18446744073709551615\n"
"max i8: 127\n"
"max i16: 32767\n"
"max i32: 2147483647\n"
"max i64: 9223372036854775807\n"
"min u8: 0\n"
"min u16: 0\n"
"min u32: 0\n"
"min u64: 0\n"
"min i8: -128\n"
"min i16: -32768\n"
"min i32: -2147483648\n"
"min i64: -9223372036854775808\n");
add_simple_case("slicing", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var array : [20]i32;
array[5] = 1234;
var slice = array[5...10];
if (slice.len != 5) {
print_str("BAD\n");
}
if (slice.ptr[0] != 1234) {
print_str("BAD\n");
}
var slice_rest = array[10...];
if (slice_rest.len != 10) {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
add_simple_case("else if expression", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
if (f(1) == 1) {
print_str("OK\n");
}
return 0;
2015-11-26 00:29:52 -08:00
}
2016-01-13 17:15:51 -08:00
fn f(c: u8) u8 => {
if (c == 0) {
0
} else if (c == 1) {
1
} else {
2
}
}
)SOURCE", "OK\n");
add_simple_case("overflow intrinsics", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
var result: u8;
if (!@add_with_overflow(u8, 250, 100, &result)) {
print_str("BAD\n");
}
if (@add_with_overflow(u8, 100, 150, &result)) {
print_str("BAD\n");
}
if (result != 250) {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
2016-01-09 01:16:54 -08:00
add_simple_case("memcpy and memset intrinsics", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-09 01:16:54 -08:00
var foo : [20]u8;
var bar : [20]u8;
@memset(foo.ptr, 'A', foo.len);
@memcpy(bar.ptr, foo.ptr, bar.len);
if (bar[11] != 'A') {
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
add_simple_case("order-independent declarations", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-13 17:15:51 -08:00
const z : @typeof(stdin_fileno) = 0;
const x : @typeof(y) = 1234;
const y : u16 = 5678;
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
print_ok(x)
}
2016-01-13 17:15:51 -08:00
fn print_ok(val: @typeof(x)) @typeof(foo) => {
print_str("OK\n");
return 0;
}
const foo : i32 = 0;
)SOURCE", "OK\n");
2016-01-11 00:15:17 -08:00
2016-01-11 19:33:06 -08:00
add_simple_case("enum type", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "std.zig";
2016-01-11 19:33:06 -08:00
struct Point {
x: u64,
y: u64,
}
enum Foo {
One: i32,
Two: Point,
Three: void,
}
enum Bar {
A,
B,
C,
D,
}
2016-01-13 17:15:51 -08:00
pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
2016-01-11 19:33:06 -08:00
const foo1 = Foo.One(13);
const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
2016-01-11 19:43:48 -08:00
const bar = Bar.B;
if (bar != Bar.B) {
print_str("BAD\n");
}
2016-01-11 19:33:06 -08:00
2016-01-13 17:15:51 -08:00
if (@value_count(Foo) != 3) {
2016-01-11 19:33:06 -08:00
print_str("BAD\n");
}
2016-01-13 17:15:51 -08:00
if (@value_count(Bar) != 4) {
2016-01-11 19:33:06 -08:00
print_str("BAD\n");
}
2016-01-13 17:15:51 -08:00
if (@sizeof(Foo) != 17) {
2016-01-11 19:33:06 -08:00
print_str("BAD\n");
}
2016-01-13 17:15:51 -08:00
if (@sizeof(Bar) != 1) {
2016-01-11 19:33:06 -08:00
print_str("BAD\n");
}
print_str("OK\n");
return 0;
}
)SOURCE", "OK\n");
}
2015-11-26 00:29:52 -08:00
////////////////////////////////////////////////////////////////////////////////////
2015-11-27 17:55:06 -08:00
static void add_compile_failure_test_cases(void) {
add_compile_fail_case("multiple function definitions", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {}
fn a() => {}
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("bad directive", R"SOURCE(
#bogus1("")
extern {
fn b();
}
#bogus2("")
2016-01-13 17:15:51 -08:00
fn a() => {}
)SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("unreachable with return", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() unreachable => {return;}
)SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("control reaches end of non-void function", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() i32 => {}
)SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got 'void'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("undefined function call", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {
2015-11-27 17:55:06 -08:00
b();
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("wrong number of arguments", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {
2015-11-27 17:55:06 -08:00
b(1);
}
2016-01-13 17:15:51 -08:00
fn b(a: i32, b: i32, c: i32) => { }
)SOURCE", 1, ".tmp_source.zig:3:6: error: expected 3 arguments, got 1");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("invalid type", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() bogus => {}
)SOURCE", 1, ".tmp_source.zig:2:8: error: use of undeclared identifier 'bogus'");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("pointer to unreachable", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() &unreachable => {}
)SOURCE", 1, ".tmp_source.zig:2:8: error: pointer to unreachable not allowed");
2015-11-27 17:55:06 -08:00
add_compile_fail_case("unreachable code", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {
2015-11-27 17:55:06 -08:00
return;
b();
}
2016-01-13 17:15:51 -08:00
fn b() => {}
)SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
2015-11-30 01:14:54 -08:00
add_compile_fail_case("bad version string", R"SOURCE(
#version("aoeu")
export executable "test";
)SOURCE", 1, ".tmp_source.zig:2:1: error: invalid version string");
2015-12-01 01:29:21 -08:00
add_compile_fail_case("bad import", R"SOURCE(
2016-01-15 17:45:52 -08:00
import "bogus-does-not-exist.zig";
)SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");
add_compile_fail_case("undeclared identifier", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {
b +
c
}
)SOURCE", 2,
".tmp_source.zig:3:5: error: use of undeclared identifier 'b'",
".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");
2015-12-02 23:47:35 -08:00
add_compile_fail_case("goto cause unreachable code", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn a() => {
2015-12-02 23:47:35 -08:00
goto done;
b();
done:
return;
}
2016-01-13 17:15:51 -08:00
fn b() => {}
2015-12-02 23:47:35 -08:00
)SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
2015-12-03 10:06:05 -08:00
add_compile_fail_case("parameter redeclaration", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f(a : i32, a : i32) => {
2015-12-03 10:06:05 -08:00
}
)SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'");
2015-12-03 10:06:05 -08:00
add_compile_fail_case("local variable redeclaration", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
const a : i32 = 0;
const a = 0;
2015-12-03 10:06:05 -08:00
}
)SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'");
2015-12-03 10:06:05 -08:00
add_compile_fail_case("local variable redeclares parameter", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f(a : i32) => {
const a = 0;
2015-12-03 10:06:05 -08:00
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");
2015-12-03 10:06:05 -08:00
add_compile_fail_case("variable has wrong type", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() i32 => {
const a = c"a";
2015-12-03 10:06:05 -08:00
a
}
)SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got '&const u8'");
2015-12-03 10:06:05 -08:00
2015-12-03 11:19:28 -08:00
add_compile_fail_case("if condition is bool, not int", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
2015-12-03 11:19:28 -08:00
if (0) {}
}
)SOURCE", 1, ".tmp_source.zig:3:9: error: expected type 'bool', got '(u8 literal)'");
2015-12-03 11:19:28 -08:00
2015-12-03 11:38:28 -08:00
add_compile_fail_case("assign unreachable", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
const a = return;
2015-12-03 11:38:28 -08:00
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable");
2015-12-03 11:38:28 -08:00
add_compile_fail_case("unreachable variable", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
const a : unreachable = return;
2015-12-03 11:38:28 -08:00
}
)SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
2015-12-03 11:38:28 -08:00
add_compile_fail_case("unreachable parameter", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f(a : unreachable) => {}
)SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
add_compile_fail_case("exporting a void parameter", R"SOURCE(
2016-01-13 17:15:51 -08:00
export fn f(a : void) => {}
)SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions");
2015-12-03 11:38:28 -08:00
2015-12-05 20:04:57 -08:00
add_compile_fail_case("unused label", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
2015-12-05 20:04:57 -08:00
a_label:
}
)SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");
2015-12-06 22:09:46 -08:00
add_compile_fail_case("bad assignment target", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
2015-12-06 22:09:46 -08:00
3 = 3;
}
2016-01-04 18:10:52 -08:00
)SOURCE", 1, ".tmp_source.zig:3:5: error: invalid assignment target");
2015-12-06 22:09:46 -08:00
add_compile_fail_case("assign to constant variable", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
const a = 3;
2015-12-06 22:09:46 -08:00
a = 4;
}
)SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
2015-12-06 22:09:46 -08:00
add_compile_fail_case("use of undeclared identifier", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
2015-12-06 22:09:46 -08:00
b = 3;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
(const a = 0);
}
)SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");
2015-12-08 14:31:43 -08:00
add_compile_fail_case("array access errors", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
var bad : bool;
2015-12-08 14:31:43 -08:00
i[i] = i[i];
bad[bad] = bad[bad];
}
)SOURCE", 8, ".tmp_source.zig:4:5: error: use of undeclared identifier 'i'",
".tmp_source.zig:4:7: error: use of undeclared identifier 'i'",
".tmp_source.zig:4:12: error: use of undeclared identifier 'i'",
".tmp_source.zig:4:14: error: use of undeclared identifier 'i'",
".tmp_source.zig:5:8: error: array access of non-array",
".tmp_source.zig:5:9: error: expected type 'usize', got 'bool'",
2015-12-08 14:31:43 -08:00
".tmp_source.zig:5:19: error: array access of non-array",
".tmp_source.zig:5:20: error: expected type 'usize', got 'bool'");
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f(...) => {}
)SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
add_compile_fail_case("write to const global variable", R"SOURCE(
const x : i32 = 99;
2016-01-13 17:15:51 -08:00
fn f() => {
x = 1;
}
)SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
2015-12-15 16:11:44 -08:00
add_compile_fail_case("missing else clause", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
const x : i32 = if (true) { 1 };
const y = if (true) { i32(1) };
2015-12-15 16:11:44 -08:00
}
)SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",
2015-12-15 17:21:59 -08:00
".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");
add_compile_fail_case("direct struct loop", R"SOURCE(
struct A { a : A, }
)SOURCE", 1, ".tmp_source.zig:2:1: error: struct has infinite size");
add_compile_fail_case("indirect struct loop", R"SOURCE(
struct A { b : B, }
struct B { c : C, }
struct C { a : A, }
)SOURCE", 1, ".tmp_source.zig:4:1: error: struct has infinite size");
add_compile_fail_case("invalid struct field", R"SOURCE(
struct A { x : i32, }
2016-01-13 17:15:51 -08:00
fn f() => {
var a : A;
a.foo = 1;
const y = a.bar;
}
)SOURCE", 2,
".tmp_source.zig:5:6: error: no member named 'foo' in 'A'",
".tmp_source.zig:6:16: error: no member named 'bar' in 'A'");
add_compile_fail_case("redefinition of struct", R"SOURCE(
struct A { x : i32, }
struct A { y : i32, }
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");
add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
struct A { x : i32, }
2016-01-13 17:15:51 -08:00
export fn f(a : A) => {}
)SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");
add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
struct A {
x : i32,
y : i32,
z : i32,
}
2016-01-13 17:15:51 -08:00
fn f() => {
const a = A {
.z = 1,
.y = 2,
.x = 3,
.z = 4,
};
}
)SOURCE", 1, ".tmp_source.zig:12:9: error: duplicate field");
add_compile_fail_case("missing field in struct value expression", R"SOURCE(
struct A {
x : i32,
y : i32,
z : i32,
}
2016-01-13 17:15:51 -08:00
fn f() => {
const a = A {
.z = 4,
.y = 2,
};
}
2016-01-13 17:15:51 -08:00
)SOURCE", 1, ".tmp_source.zig:8:17: error: missing field: 'x'");
add_compile_fail_case("invalid field in struct value expression", R"SOURCE(
struct A {
x : i32,
y : i32,
z : i32,
}
2016-01-13 17:15:51 -08:00
fn f() => {
const a = A {
.z = 4,
.y = 2,
.foo = 42,
};
}
)SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");
add_compile_fail_case("invalid break expression", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
break;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop");
add_compile_fail_case("invalid continue expression", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
continue;
}
)SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop");
add_compile_fail_case("invalid maybe type", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() => {
if (const x ?= true) { }
}
)SOURCE", 1, ".tmp_source.zig:3:20: error: expected maybe type");
add_compile_fail_case("cast unreachable", R"SOURCE(
2016-01-13 17:15:51 -08:00
fn f() i32 => {
i32(return 1)
}
)SOURCE", 1, ".tmp_source.zig:3:8: error: invalid cast from type 'unreachable' to 'i32'");
2016-01-03 17:17:50 -08:00
2016-01-13 17:15:51 -08:00
add_compile_fail_case("invalid builtin fn", R"SOURCE(
fn f() @bogus(foo) => {
2016-01-03 17:17:50 -08:00
}
2016-01-13 17:15:51 -08:00
)SOURCE", 1, ".tmp_source.zig:2:8: error: invalid builtin function: 'bogus'");
add_compile_fail_case("top level decl dependency loop", R"SOURCE(
2016-01-13 17:15:51 -08:00
const a : @typeof(b) = 0;
const b : @typeof(a) = 0;
)SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");
add_compile_fail_case("noalias on non pointer param", R"SOURCE(
fn f(noalias x: i32) => {}
)SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter");
add_compile_fail_case("struct init syntax for array", R"SOURCE(
const foo = []u16{.x = 1024,};
)SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax");
2015-11-27 17:55:06 -08:00
}
static void print_compiler_invocation(TestCase *test_case) {
2015-11-27 17:55:06 -08:00
printf("%s", zig_exe);
for (int i = 0; i < test_case->compiler_args.length; i += 1) {
printf(" %s", test_case->compiler_args.at(i));
}
printf("\n");
}
2015-11-26 00:29:52 -08:00
static void run_test(TestCase *test_case) {
2015-12-01 01:08:58 -08:00
for (int i = 0; i < test_case->source_files.length; i += 1) {
TestSourceFile *test_source = &test_case->source_files.at(i);
os_write_file(
buf_create_from_str(test_source->relative_path),
buf_create_from_str(test_source->source_code));
}
2015-11-26 00:29:52 -08:00
Buf zig_stderr = BUF_INIT;
Buf zig_stdout = BUF_INIT;
int return_code;
2015-11-26 23:40:26 -08:00
os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout);
2015-11-26 00:29:52 -08:00
2015-11-27 17:55:06 -08:00
if (test_case->compile_errors.length) {
if (return_code) {
for (int i = 0; i < test_case->compile_errors.length; i += 1) {
const char *err_text = test_case->compile_errors.at(i);
if (!strstr(buf_ptr(&zig_stderr), err_text)) {
printf("\n");
printf("========= Expected this compile error: =========\n");
printf("%s\n", err_text);
printf("================================================\n");
print_compiler_invocation(test_case);
printf("%s\n", buf_ptr(&zig_stderr));
2015-11-27 17:55:06 -08:00
exit(1);
}
}
return; // success
} else {
printf("\nCompile failed with return code 0 (Expected failure):\n");
print_compiler_invocation(test_case);
printf("%s\n", buf_ptr(&zig_stderr));
2015-11-27 17:55:06 -08:00
exit(1);
}
}
2015-11-26 00:29:52 -08:00
if (return_code != 0) {
printf("\nCompile failed with return code %d:\n", return_code);
print_compiler_invocation(test_case);
printf("%s\n", buf_ptr(&zig_stderr));
2015-11-26 00:29:52 -08:00
exit(1);
}
Buf program_stderr = BUF_INIT;
Buf program_stdout = BUF_INIT;
os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout);
if (return_code != 0) {
printf("\nProgram exited with return code %d:\n", return_code);
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
2015-11-26 00:29:52 -08:00
}
printf("\n");
printf("%s\n", buf_ptr(&program_stderr));
exit(1);
}
if (!buf_eql_str(&program_stdout, test_case->output)) {
printf("\n");
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
}
2015-11-26 00:29:52 -08:00
printf("\n");
printf("==== Test failed. Expected output: ====\n");
printf("%s\n", test_case->output);
printf("========= Actual output: ==============\n");
printf("%s\n", buf_ptr(&program_stdout));
printf("=======================================\n");
exit(1);
}
2015-12-01 01:08:58 -08:00
for (int i = 0; i < test_case->source_files.length; i += 1) {
TestSourceFile *test_source = &test_case->source_files.at(i);
remove(test_source->relative_path);
}
2015-11-26 00:29:52 -08:00
}
2015-12-04 22:04:49 -08:00
static void run_all_tests(bool reverse) {
if (reverse) {
for (int i = test_cases.length - 1; i >= 0; i -= 1) {
TestCase *test_case = test_cases.at(i);
printf("Test %d/%d %s...", i + 1, test_cases.length, test_case->case_name);
run_test(test_case);
printf("OK\n");
}
} else {
for (int i = 0; i < test_cases.length; i += 1) {
TestCase *test_case = test_cases.at(i);
printf("Test %d/%d %s...", i + 1, test_cases.length, test_case->case_name);
run_test(test_case);
printf("OK\n");
}
2015-11-26 00:29:52 -08:00
}
printf("%d tests passed.\n", test_cases.length);
}
static void cleanup(void) {
remove(tmp_source_path);
remove(tmp_exe_path);
}
2015-12-04 22:04:49 -08:00
static int usage(const char *arg0) {
fprintf(stderr, "Usage: %s [--reverse]\n", arg0);
return 1;
}
2015-11-26 00:29:52 -08:00
int main(int argc, char **argv) {
2015-12-04 22:04:49 -08:00
bool reverse = false;
for (int i = 1; i < argc; i += 1) {
if (strcmp(argv[i], "--reverse") == 0) {
reverse = true;
} else {
return usage(argv[0]);
}
}
2015-11-27 17:55:06 -08:00
add_compiling_test_cases();
add_compile_failure_test_cases();
2015-12-04 22:04:49 -08:00
run_all_tests(reverse);
2015-11-26 00:29:52 -08:00
cleanup();
}