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);
|
2015-11-27 20:24:11 -08:00
|
|
|
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");
|
2015-12-15 16:11:44 -08:00
|
|
|
//test_case->compiler_args.append("--verbose");
|
2015-12-01 00:06:10 -08:00
|
|
|
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(
|
|
|
|
#link("c")
|
|
|
|
extern {
|
2015-12-14 17:10:25 -08:00
|
|
|
fn puts(s: &const u8) -> i32;
|
2015-11-26 00:29:52 -08:00
|
|
|
}
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-11 23:10:37 -08:00
|
|
|
puts(c"Hello, world!");
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-11-26 00:29:52 -08:00
|
|
|
}
|
|
|
|
)SOURCE", "Hello, world!\n");
|
|
|
|
|
|
|
|
add_simple_case("function call", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-11-26 00:29:52 -08:00
|
|
|
|
2015-11-27 09:52:31 -08:00
|
|
|
fn empty_function_1() {}
|
|
|
|
fn empty_function_2() { return; }
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-11-27 09:52:31 -08:00
|
|
|
empty_function_1();
|
|
|
|
empty_function_2();
|
2015-11-26 00:29:52 -08:00
|
|
|
this_is_a_function();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn this_is_a_function() -> unreachable {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("OK\n");
|
2015-11-26 00:29:52 -08:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
)SOURCE", "OK\n");
|
2015-11-26 23:40:26 -08:00
|
|
|
|
|
|
|
add_simple_case("comments", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-11-26 23:40:26 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* multi line doc comment
|
|
|
|
*/
|
2015-11-27 09:52:31 -08:00
|
|
|
fn another_function() {}
|
2015-11-26 23:40:26 -08:00
|
|
|
|
|
|
|
/// this is a documentation comment
|
|
|
|
/// doc comment line 2
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str(/* mid-line comment /* nested */ */ "OK\n");
|
2015-12-15 11:44:42 -08:00
|
|
|
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(
|
|
|
|
use "libc.zig";
|
|
|
|
use "foo.zig";
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-01 01:08:58 -08:00
|
|
|
private_function();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn private_function() -> unreachable {
|
|
|
|
print_text();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
)SOURCE", "OK\n");
|
|
|
|
|
|
|
|
add_source_file(tc, "libc.zig", R"SOURCE(
|
|
|
|
#link("c")
|
|
|
|
extern {
|
2015-12-14 17:10:25 -08:00
|
|
|
pub fn puts(s: &const u8) -> i32;
|
2015-12-01 01:08:58 -08:00
|
|
|
pub fn exit(code: i32) -> unreachable;
|
|
|
|
}
|
|
|
|
)SOURCE");
|
|
|
|
|
|
|
|
add_source_file(tc, "foo.zig", R"SOURCE(
|
|
|
|
use "libc.zig";
|
|
|
|
|
|
|
|
// purposefully conflicting function with main source file
|
|
|
|
// but it's private so it should be OK
|
|
|
|
fn private_function() {
|
2015-12-11 23:10:37 -08:00
|
|
|
puts(c"OK");
|
2015-12-01 01:08:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn print_text() {
|
|
|
|
private_function();
|
|
|
|
}
|
|
|
|
)SOURCE");
|
|
|
|
}
|
|
|
|
|
2015-12-01 20:19:38 -08:00
|
|
|
add_simple_case("if statements", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-01 20:19:38 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-01 20:19:38 -08:00
|
|
|
if 1 != 0 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("1 is true\n");
|
2015-12-01 20:19:38 -08:00
|
|
|
} else {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("1 is false\n");
|
2015-12-01 20:19:38 -08:00
|
|
|
}
|
|
|
|
if 0 != 0 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("0 is true\n");
|
2015-12-01 20:19:38 -08:00
|
|
|
} else if 1 - 1 != 0 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("1 - 1 is true\n");
|
2015-12-01 20:19:38 -08:00
|
|
|
}
|
|
|
|
if !(0 != 0) {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("!0 is true\n");
|
2015-12-01 20:19:38 -08:00
|
|
|
}
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-12-01 20:19:38 -08:00
|
|
|
}
|
|
|
|
)SOURCE", "1 is true\n!0 is true\n");
|
2015-12-01 23:53:57 -08:00
|
|
|
|
|
|
|
add_simple_case("params", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-01 23:53:57 -08:00
|
|
|
|
|
|
|
fn add(a: i32, b: i32) -> i32 {
|
|
|
|
a + b
|
|
|
|
}
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-01 23:53:57 -08:00
|
|
|
if add(22, 11) == 33 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("pass\n");
|
2015-12-01 23:53:57 -08:00
|
|
|
}
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-12-01 23:53:57 -08:00
|
|
|
}
|
|
|
|
)SOURCE", "pass\n");
|
2015-12-02 23:47:35 -08:00
|
|
|
|
|
|
|
add_simple_case("goto", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-02 23:47:35 -08:00
|
|
|
|
|
|
|
fn loop(a : i32) {
|
|
|
|
if a == 0 {
|
|
|
|
goto done;
|
|
|
|
}
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("loop\n");
|
2015-12-02 23:47:35 -08:00
|
|
|
loop(a - 1);
|
|
|
|
|
|
|
|
done:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-02 23:47:35 -08:00
|
|
|
loop(3);
|
2015-12-15 11:44:42 -08:00
|
|
|
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(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-03 10:06:05 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a : i32 = 1;
|
|
|
|
const b = 2 as i32;
|
2015-12-03 10:06:05 -08:00
|
|
|
if (a + b == 3) {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("OK\n");
|
2015-12-03 10:06:05 -08:00
|
|
|
}
|
2015-12-15 11:44:42 -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(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-03 11:19:28 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
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"); }
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-12-03 12:26:49 -08:00
|
|
|
}
|
|
|
|
)SOURCE", "OK 1\nOK 2\n");
|
|
|
|
|
|
|
|
add_simple_case("separate block scopes", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-03 12:26:49 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-03 12:26:49 -08:00
|
|
|
if (true) {
|
2015-12-14 17:51:07 -08:00
|
|
|
const no_conflict : i32 = 5;
|
2015-12-15 16:29:44 -08:00
|
|
|
if (no_conflict == 5) { print_str("OK 1\n"); }
|
2015-12-03 12:26:49 -08:00
|
|
|
}
|
|
|
|
|
2015-12-14 17:51:07 -08:00
|
|
|
const c = {
|
|
|
|
const no_conflict = 10 as i32;
|
2015-12-03 12:26:49 -08:00
|
|
|
no_conflict
|
|
|
|
};
|
2015-12-15 16:29:44 -08:00
|
|
|
if (c == 10) { print_str("OK 2\n"); }
|
2015-12-15 11:44:42 -08:00
|
|
|
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(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-03 13:33:13 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-03 13:33:13 -08:00
|
|
|
void_fun(1, void, 2);
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-12-03 13:33:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn void_fun(a : i32, b : void, c : i32) {
|
2015-12-14 17:51:07 -08:00
|
|
|
const v = b;
|
|
|
|
const vv : void = if (a == 1) {v} else {};
|
2015-12-15 16:29:44 -08:00
|
|
|
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
|
|
|
|
2015-12-06 22:33:10 -08:00
|
|
|
add_simple_case("mutable local variables", R"SOURCE(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-06 22:09:46 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
var zero : i32;
|
2015-12-15 16:29:44 -08:00
|
|
|
if (zero == 0) { print_str("zero\n"); }
|
2015-12-06 22:33:10 -08:00
|
|
|
|
2015-12-14 17:51:07 -08:00
|
|
|
var i = 0 as i32;
|
2015-12-06 22:09:46 -08:00
|
|
|
loop_start:
|
|
|
|
if i == 3 {
|
|
|
|
goto done;
|
|
|
|
}
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("loop\n");
|
2015-12-06 22:09:46 -08:00
|
|
|
i = i + 1;
|
|
|
|
goto loop_start;
|
|
|
|
done:
|
2015-12-15 11:44:42 -08:00
|
|
|
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(
|
2015-12-15 11:44:42 -08:00
|
|
|
use "std.zig";
|
2015-12-08 14:46:36 -08:00
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
var array : [i32; 5];
|
2015-12-08 14:46:36 -08:00
|
|
|
|
2015-12-14 17:51:07 -08:00
|
|
|
var i : i32 = 0;
|
2015-12-08 14:46:36 -08:00
|
|
|
loop_start:
|
|
|
|
if i == 5 {
|
|
|
|
goto loop_end;
|
|
|
|
}
|
|
|
|
array[i] = i + 1;
|
|
|
|
i = array[i];
|
|
|
|
goto loop_start;
|
|
|
|
|
|
|
|
loop_end:
|
|
|
|
|
|
|
|
i = 0;
|
2015-12-14 17:51:07 -08:00
|
|
|
var accumulator = 0 as i32;
|
2015-12-08 14:46:36 -08:00
|
|
|
loop_2_start:
|
|
|
|
if i == 5 {
|
|
|
|
goto loop_2_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
accumulator = accumulator + array[i];
|
|
|
|
|
|
|
|
i = i + 1;
|
|
|
|
goto loop_2_start;
|
|
|
|
loop_2_end:
|
|
|
|
|
|
|
|
if accumulator == 15 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("OK\n");
|
2015-12-08 14:46:36 -08:00
|
|
|
}
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
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(
|
|
|
|
use "std.zig";
|
|
|
|
|
2015-12-14 17:10:25 -08:00
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("Hello, world!\n");
|
2015-12-11 02:55:26 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
)SOURCE", "Hello, world!\n");
|
|
|
|
|
|
|
|
|
2015-12-12 16:03:44 -08:00
|
|
|
add_simple_case("a + b + c", R"SOURCE(
|
|
|
|
use "std.zig";
|
|
|
|
|
2015-12-14 17:10:25 -08:00
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
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 5 as i32 as i32 != 5 { print_str("BAD 10\n"); }
|
|
|
|
if !!false { print_str("BAD 11\n"); }
|
|
|
|
if 7 != --7 { print_str("BAD 12\n"); }
|
|
|
|
|
|
|
|
print_str("OK\n");
|
2015-12-12 16:03:44 -08:00
|
|
|
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(
|
|
|
|
use "std.zig";
|
|
|
|
|
2015-12-14 17:10:25 -08:00
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
if true || { print_str("BAD 1\n"); false } {
|
|
|
|
print_str("OK 1\n");
|
2015-12-12 16:33:45 -08:00
|
|
|
}
|
2015-12-15 16:29:44 -08:00
|
|
|
if false || { print_str("OK 2\n"); false } {
|
|
|
|
print_str("BAD 2\n");
|
2015-12-12 16:33:45 -08:00
|
|
|
}
|
|
|
|
|
2015-12-15 16:29:44 -08:00
|
|
|
if true && { print_str("OK 3\n"); false } {
|
|
|
|
print_str("BAD 3\n");
|
2015-12-12 16:33:45 -08:00
|
|
|
}
|
2015-12-15 16:29:44 -08:00
|
|
|
if false && { print_str("BAD 4\n"); false } {
|
2015-12-12 16:33:45 -08:00
|
|
|
} else {
|
2015-12-15 16:29:44 -08:00
|
|
|
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");
|
|
|
|
|
2015-12-12 18:47:37 -08:00
|
|
|
add_simple_case("modify operators", R"SOURCE(
|
|
|
|
use "std.zig";
|
|
|
|
|
2015-12-14 17:10:25 -08:00
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
var i : i32 = 0;
|
2015-12-15 16:29:44 -08:00
|
|
|
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"); }
|
2015-12-12 18:47:37 -08:00
|
|
|
i = 6;
|
2015-12-15 16:29:44 -08:00
|
|
|
i &= 5; if i != 4 { print_str("BAD &=\n"); }
|
|
|
|
i ^= 6; if i != 2 { print_str("BAD ^=\n"); }
|
2015-12-12 18:47:37 -08:00
|
|
|
i = 6;
|
2015-12-15 16:29:44 -08:00
|
|
|
i |= 3; if i != 7 { print_str("BAD |=\n"); }
|
2015-12-12 18:47:37 -08:00
|
|
|
|
2015-12-15 16:29:44 -08:00
|
|
|
print_str("OK\n");
|
2015-12-12 18:47:37 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
)SOURCE", "OK\n");
|
|
|
|
|
2015-12-15 03:05:43 -08:00
|
|
|
add_simple_case("number literals", R"SOURCE(
|
|
|
|
#link("c")
|
|
|
|
extern {
|
|
|
|
fn printf(__format: &const u8, ...) -> i32;
|
|
|
|
}
|
|
|
|
|
2015-12-15 11:44:42 -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",
|
|
|
|
0 as u64);
|
|
|
|
printf(c"320402575052271: %llu\n",
|
|
|
|
320402575052271 as u64);
|
|
|
|
printf(c"0x01236789abcdef: %llu\n",
|
|
|
|
0x01236789abcdef as u64);
|
|
|
|
printf(c"0xffffffffffffffff: %llu\n",
|
|
|
|
0xffffffffffffffff as u64);
|
|
|
|
printf(c"0x000000ffffffffffffffff: %llu\n",
|
|
|
|
0x000000ffffffffffffffff as u64);
|
|
|
|
printf(c"0o1777777777777777777777: %llu\n",
|
|
|
|
0o1777777777777777777777 as u64);
|
|
|
|
printf(c"0o0000001777777777777777777777: %llu\n",
|
|
|
|
0o0000001777777777777777777777 as u64);
|
|
|
|
printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
|
|
|
|
0b1111111111111111111111111111111111111111111111111111111111111111 as u64);
|
|
|
|
printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
|
|
|
|
0b0000001111111111111111111111111111111111111111111111111111111111111111 as u64);
|
|
|
|
|
|
|
|
printf(c"\n");
|
|
|
|
|
2015-12-15 12:15:07 -08:00
|
|
|
printf(c"0.0: %a\n",
|
|
|
|
0.0 as f64);
|
|
|
|
printf(c"0e0: %a\n",
|
|
|
|
0e0 as f64);
|
|
|
|
printf(c"0.0e0: %a\n",
|
|
|
|
0.0e0 as f64);
|
|
|
|
printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
|
|
|
|
000000000000000000000000000000000000000000000000000000000.0e0 as f64);
|
|
|
|
printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
|
|
|
|
0.000000000000000000000000000000000000000000000000000000000e0 as f64);
|
|
|
|
printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
|
|
|
|
0.0e000000000000000000000000000000000000000000000000000000000 as f64);
|
2015-12-15 13:54:16 -08:00
|
|
|
printf(c"1.0: %a\n",
|
|
|
|
1.0 as f64);
|
|
|
|
printf(c"10.0: %a\n",
|
|
|
|
10.0 as f64);
|
|
|
|
printf(c"10.5: %a\n",
|
|
|
|
10.5 as f64);
|
|
|
|
printf(c"10.5e5: %a\n",
|
|
|
|
10.5e5 as f64);
|
|
|
|
printf(c"10.5e+5: %a\n",
|
|
|
|
10.5e+5 as f64);
|
|
|
|
printf(c"50.0e-2: %a\n",
|
|
|
|
50.0e-2 as f64);
|
|
|
|
printf(c"50e-2: %a\n",
|
|
|
|
50e-2 as f64);
|
2015-12-15 12:15:07 -08:00
|
|
|
|
|
|
|
printf(c"\n");
|
|
|
|
|
|
|
|
printf(c"0x1.0: %a\n",
|
|
|
|
0x1.0 as f64);
|
|
|
|
printf(c"0x10.0: %a\n",
|
|
|
|
0x10.0 as f64);
|
|
|
|
printf(c"0x100.0: %a\n",
|
|
|
|
0x100.0 as f64);
|
|
|
|
printf(c"0x103.0: %a\n",
|
|
|
|
0x103.0 as f64);
|
|
|
|
printf(c"0x103.7: %a\n",
|
|
|
|
0x103.7 as f64);
|
|
|
|
printf(c"0x103.70: %a\n",
|
|
|
|
0x103.70 as f64);
|
|
|
|
printf(c"0x103.70p4: %a\n",
|
|
|
|
0x103.70p4 as f64);
|
|
|
|
printf(c"0x103.70p5: %a\n",
|
|
|
|
0x103.70p5 as f64);
|
|
|
|
printf(c"0x103.70p+5: %a\n",
|
|
|
|
0x103.70p+5 as f64);
|
|
|
|
printf(c"0x103.70p-5: %a\n",
|
|
|
|
0x103.70p-5 as f64);
|
|
|
|
|
|
|
|
printf(c"\n");
|
|
|
|
|
|
|
|
printf(c"0b10100.00010e0: %a\n",
|
|
|
|
0b10100.00010e0 as f64);
|
|
|
|
printf(c"0o10700.00010e0: %a\n",
|
|
|
|
0o10700.00010e0 as f64);
|
|
|
|
|
2015-12-15 11:44:42 -08:00
|
|
|
return 0;
|
2015-12-15 03:05:43 -08:00
|
|
|
}
|
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-15 03:05:43 -08:00
|
|
|
|
2015-12-12 21:55:29 -08:00
|
|
|
add_simple_case("structs", R"SOURCE(
|
|
|
|
use "std.zig";
|
|
|
|
|
2015-12-14 17:10:25 -08:00
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
var foo : Foo;
|
2015-12-15 18:17:39 -08:00
|
|
|
foo.a += 1;
|
2015-12-12 21:55:29 -08:00
|
|
|
foo.b = foo.a == 1;
|
|
|
|
test_foo(foo);
|
2015-12-15 19:08:53 -08:00
|
|
|
test_mutation(&foo);
|
|
|
|
if foo.c != 100 {
|
|
|
|
print_str("BAD\n");
|
|
|
|
}
|
2015-12-22 12:22:40 -08:00
|
|
|
test_point_to_self();
|
2015-12-23 02:19:22 -08:00
|
|
|
test_byval_assign();
|
2015-12-23 23:00:23 -08:00
|
|
|
test_initializer();
|
2015-12-15 19:08:53 -08:00
|
|
|
print_str("OK\n");
|
2015-12-12 21:55:29 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
struct Foo {
|
|
|
|
a : i32,
|
|
|
|
b : bool,
|
|
|
|
c : f32,
|
|
|
|
}
|
|
|
|
fn test_foo(foo : Foo) {
|
2015-12-15 19:08:53 -08:00
|
|
|
if !foo.b {
|
|
|
|
print_str("BAD\n");
|
2015-12-12 21:55:29 -08:00
|
|
|
}
|
2015-12-15 19:08:53 -08:00
|
|
|
}
|
|
|
|
fn test_mutation(foo : &Foo) {
|
|
|
|
foo.c = 100;
|
2015-12-22 12:22:40 -08:00
|
|
|
}
|
|
|
|
struct Node {
|
|
|
|
val: Val,
|
|
|
|
next: &Node,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Val {
|
|
|
|
x: i32,
|
|
|
|
}
|
|
|
|
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");
|
|
|
|
}
|
2015-12-23 02:19:22 -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
|
|
|
}
|
|
|
|
fn test_initializer() {
|
|
|
|
const val = Val { .x = 42 };
|
|
|
|
if val.x != 42 { print_str("BAD\n"); }
|
2015-12-14 22:49:56 -08:00
|
|
|
}
|
|
|
|
)SOURCE", "OK\n");
|
|
|
|
|
|
|
|
add_simple_case("global variables", R"SOURCE(
|
|
|
|
use "std.zig";
|
|
|
|
|
|
|
|
const g1 : i32 = 1233 + 1;
|
|
|
|
var g2 : i32;
|
|
|
|
|
|
|
|
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
2015-12-15 16:29:44 -08:00
|
|
|
if g2 != 0 { print_str("BAD\n"); }
|
2015-12-14 22:49:56 -08:00
|
|
|
g2 = g1;
|
2015-12-15 16:29:44 -08:00
|
|
|
if g2 != 1234 { print_str("BAD\n"); }
|
|
|
|
print_str("OK\n");
|
2015-12-14 22:49:56 -08:00
|
|
|
return 0;
|
2015-12-12 21:55:29 -08:00
|
|
|
}
|
|
|
|
)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(
|
|
|
|
fn a() {}
|
|
|
|
fn a() {}
|
2015-11-30 23:50:11 -08:00
|
|
|
)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("")
|
|
|
|
fn a() {}
|
2015-11-30 23:50:11 -08:00
|
|
|
)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(
|
|
|
|
fn a() -> unreachable {return;}
|
2015-12-11 23:10:37 -08:00
|
|
|
)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(
|
|
|
|
fn a() -> i32 {}
|
2015-12-11 23:10:37 -08:00
|
|
|
)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(
|
|
|
|
fn a() {
|
|
|
|
b();
|
|
|
|
}
|
2015-11-30 23:50:11 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'");
|
2015-11-27 17:55:06 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("wrong number of arguments", R"SOURCE(
|
|
|
|
fn a() {
|
|
|
|
b(1);
|
|
|
|
}
|
|
|
|
fn b(a: i32, b: i32, c: i32) { }
|
2015-12-08 13:15:34 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:3:6: error: wrong number of arguments. Expected 3, got 1.");
|
2015-11-27 17:55:06 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("invalid type", R"SOURCE(
|
|
|
|
fn a() -> bogus {}
|
2015-11-30 23:50:11 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:2:11: error: invalid type name: 'bogus'");
|
2015-11-27 17:55:06 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("pointer to unreachable", R"SOURCE(
|
2015-12-14 17:10:25 -08:00
|
|
|
fn a() -> &unreachable {}
|
2015-11-30 23:50:11 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:2:11: error: pointer to unreachable not allowed");
|
2015-11-27 17:55:06 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("unreachable code", R"SOURCE(
|
|
|
|
fn a() {
|
|
|
|
return;
|
|
|
|
b();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn b() {}
|
2015-11-30 23:50:11 -08:00
|
|
|
)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";
|
2015-11-30 23:50:11 -08:00
|
|
|
)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(
|
|
|
|
use "bogus-does-not-exist.zig";
|
2015-12-10 16:42:47 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");
|
2015-12-01 23:59:58 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("undeclared identifier", R"SOURCE(
|
|
|
|
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(
|
|
|
|
fn a() {
|
|
|
|
goto done;
|
|
|
|
b();
|
|
|
|
done:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fn b() {}
|
|
|
|
)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(
|
|
|
|
fn f(a : i32, a : i32) {
|
|
|
|
}
|
2015-12-04 13:33:57 -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(
|
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a : i32 = 0;
|
|
|
|
const a = 0;
|
2015-12-03 10:06:05 -08:00
|
|
|
}
|
2015-12-04 13:33:57 -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(
|
|
|
|
fn f(a : i32) {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a = 0;
|
2015-12-03 10:06:05 -08:00
|
|
|
}
|
2015-12-04 13:33:57 -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(
|
|
|
|
fn f() -> i32 {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a = c"a";
|
2015-12-03 10:06:05 -08:00
|
|
|
a
|
|
|
|
}
|
2015-12-14 17:10:25 -08:00
|
|
|
)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(
|
|
|
|
fn f() {
|
|
|
|
if (0) {}
|
|
|
|
}
|
2015-12-14 01:46:37 -08:00
|
|
|
)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(
|
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a = return;
|
2015-12-03 11:38:28 -08:00
|
|
|
}
|
2015-12-04 13:33:57 -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(
|
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a : unreachable = return;
|
2015-12-03 11:38:28 -08:00
|
|
|
}
|
2015-12-14 17:51:07 -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(
|
|
|
|
fn f(a : unreachable) {}
|
2015-12-04 13:33:57 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
|
|
|
|
|
|
|
|
add_compile_fail_case("exporting a void parameter", R"SOURCE(
|
|
|
|
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(
|
2015-12-06 22:09:46 -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
|
|
|
|
2015-12-11 23:10:37 -08:00
|
|
|
add_compile_fail_case("bad assignment target", R"SOURCE(
|
2015-12-06 22:09:46 -08:00
|
|
|
fn f() {
|
|
|
|
3 = 3;
|
|
|
|
}
|
2015-12-11 23:10:37 -08:00
|
|
|
)SOURCE", 1, ".tmp_source.zig:3:5: error: assignment target must be variable, field, or array element");
|
2015-12-06 22:09:46 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("assign to constant variable", R"SOURCE(
|
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
const a = 3;
|
2015-12-06 22:09:46 -08:00
|
|
|
a = 4;
|
|
|
|
}
|
2015-12-15 18:17:39 -08:00
|
|
|
)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(
|
|
|
|
fn f() {
|
|
|
|
b = 3;
|
|
|
|
}
|
|
|
|
)SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
|
2015-12-06 22:49:20 -08:00
|
|
|
|
2015-12-14 17:51:07 -08:00
|
|
|
add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
|
2015-12-06 22:49:20 -08:00
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
(const a = 0);
|
2015-12-06 22:49:20 -08:00
|
|
|
}
|
2015-12-14 17:51:07 -08:00
|
|
|
)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(
|
|
|
|
fn f() {
|
2015-12-14 17:51:07 -08:00
|
|
|
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:8: error: array subscripts must be integers",
|
|
|
|
".tmp_source.zig:5:19: error: array access of non-array",
|
|
|
|
".tmp_source.zig:5:19: error: array subscripts must be integers");
|
2015-12-09 00:03:04 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
|
|
|
|
fn f(...) {}
|
|
|
|
)SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
|
2015-12-14 22:49:56 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("write to const global variable", R"SOURCE(
|
|
|
|
const x : i32 = 99;
|
|
|
|
fn f() {
|
|
|
|
x = 1;
|
|
|
|
}
|
2015-12-15 18:17:39 -08:00
|
|
|
)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(
|
|
|
|
fn f() {
|
|
|
|
const x : i32 = if true { 1 };
|
|
|
|
const y = if true { 1 as i32 };
|
|
|
|
}
|
|
|
|
)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'");
|
2015-12-22 12:41:33 -08:00
|
|
|
|
|
|
|
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:2:1: error: struct has infinite size");
|
2015-12-22 12:45:13 -08:00
|
|
|
|
|
|
|
add_compile_fail_case("invalid struct field", R"SOURCE(
|
|
|
|
struct A { x : i32, }
|
|
|
|
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'");
|
2015-12-24 12:19:31 -08:00
|
|
|
|
|
|
|
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'");
|
2015-11-27 17:55:06 -08:00
|
|
|
}
|
|
|
|
|
2015-12-14 01:46:37 -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");
|
2015-12-14 01:46:37 -08:00
|
|
|
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");
|
2015-12-14 01:46:37 -08:00
|
|
|
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);
|
2015-12-14 01:46:37 -08:00
|
|
|
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);
|
2015-12-14 01:46:37 -08:00
|
|
|
print_compiler_invocation(test_case);
|
2015-11-26 22:38:26 -08:00
|
|
|
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)) {
|
2015-12-14 01:46:37 -08:00
|
|
|
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();
|
|
|
|
}
|