mirror of
https://github.com/open-goal/jak-project
synced 2026-08-06 09:54:10 -04:00
[Decompiler] Begin expression conversion, rearrange tests (#209)
* refactor tests and analysis passes * identity test working * combine test categories with only a few cases * more fixes
This commit is contained in:
+3
-1
@@ -18,8 +18,10 @@ add_executable(goalc-test
|
||||
test_pretty_print.cpp
|
||||
test_zydis.cpp
|
||||
goalc/test_goal_kernel.cpp
|
||||
decompiler/FormRegressionTest.cpp
|
||||
decompiler/test_AtomicOpBuilder.cpp
|
||||
decompiler/test_FormRegression.cpp
|
||||
decompiler/test_FormBeforeExpressions.cpp
|
||||
decompiler/test_FormExpressionBuild.cpp
|
||||
decompiler/test_InstructionParser.cpp
|
||||
${GOALC_TEST_FRAMEWORK_SOURCES}
|
||||
${GOALC_TEST_CASES})
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
#include "FormRegressionTest.h"
|
||||
|
||||
#include "decompiler/analysis/variable_naming.h"
|
||||
#include "decompiler/analysis/reg_usage.h"
|
||||
#include "decompiler/analysis/cfg_builder.h"
|
||||
#include "decompiler/analysis/expression_build.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
|
||||
using namespace decompiler;
|
||||
|
||||
void FormRegressionTest::SetUpTestCase() {
|
||||
parser = std::make_unique<InstructionParser>();
|
||||
dts = std::make_unique<DecompilerTypeSystem>();
|
||||
dts->parse_type_defs({"decompiler", "config", "all-types.gc"});
|
||||
}
|
||||
|
||||
void FormRegressionTest::TearDownTestCase() {
|
||||
parser.reset();
|
||||
dts.reset();
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
void FormRegressionTest::TestData::add_string_at_label(const std::string& label_name,
|
||||
const std::string& data) {
|
||||
// first, align segment 1:
|
||||
while (file.words_by_seg.at(1).size() % 4) {
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(0));
|
||||
}
|
||||
|
||||
// add string type tag:
|
||||
LinkedWord type_tag(0);
|
||||
type_tag.kind = LinkedWord::Kind::TYPE_PTR;
|
||||
type_tag.symbol_name = "string";
|
||||
file.words_by_seg.at(1).push_back(type_tag);
|
||||
int string_start = 4 * int(file.words_by_seg.at(1).size());
|
||||
|
||||
// add size
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(int(data.length())));
|
||||
|
||||
// add string:
|
||||
std::vector<char> bytes;
|
||||
bytes.resize(((data.size() + 1 + 3) / 4) * 4);
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
bytes[i] = data[i];
|
||||
}
|
||||
for (size_t i = 0; i < bytes.size() / 4; i++) {
|
||||
auto word = ((uint32_t*)bytes.data())[i];
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(word));
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(0));
|
||||
}
|
||||
// will be already null terminated.
|
||||
|
||||
for (auto& label : file.labels) {
|
||||
if (label.name == label_name) {
|
||||
label.target_segment = 1;
|
||||
label.offset = string_start;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
|
||||
std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
|
||||
const std::string& code,
|
||||
const TypeSpec& function_type,
|
||||
bool do_expressions,
|
||||
bool allow_pairs,
|
||||
const std::string& method_name,
|
||||
const std::vector<std::pair<std::string, std::string>>& strings) {
|
||||
dts->type_prop_settings.locked = true;
|
||||
dts->type_prop_settings.reset();
|
||||
dts->type_prop_settings.allow_pair = allow_pairs;
|
||||
dts->type_prop_settings.current_method_type = method_name;
|
||||
auto program = parser->parse_program(code);
|
||||
// printf("prg:\n%s\n\n", program.print().c_str());
|
||||
auto test = std::make_unique<TestData>(program.instructions.size());
|
||||
test->file.words_by_seg.resize(3);
|
||||
test->file.labels = program.labels;
|
||||
test->func.ir2.env.file = &test->file;
|
||||
test->func.instructions = program.instructions;
|
||||
test->func.guessed_name.set_as_global("test-function");
|
||||
test->func.type = function_type;
|
||||
|
||||
for (auto& str : strings) {
|
||||
test->add_string_at_label(str.first, str.second);
|
||||
}
|
||||
|
||||
test->func.basic_blocks = find_blocks_in_function(test->file, 0, test->func);
|
||||
test->func.analyze_prologue(test->file);
|
||||
test->func.cfg = build_cfg(test->file, 0, test->func);
|
||||
EXPECT_TRUE(test->func.cfg->is_fully_resolved());
|
||||
|
||||
auto ops = convert_function_to_atomic_ops(test->func, program.labels);
|
||||
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
|
||||
test->func.ir2.atomic_ops_succeeded = true;
|
||||
|
||||
EXPECT_TRUE(test->func.run_type_analysis_ir2(function_type, *dts, test->file, {}));
|
||||
|
||||
test->func.ir2.env.set_reg_use(analyze_ir2_register_usage(test->func));
|
||||
|
||||
auto result = run_variable_renaming(test->func, test->func.ir2.env.reg_use(),
|
||||
*test->func.ir2.atomic_ops, *dts);
|
||||
if (result.has_value()) {
|
||||
test->func.ir2.env.set_local_vars(*result);
|
||||
} else {
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
|
||||
build_initial_forms(test->func);
|
||||
EXPECT_TRUE(test->func.ir2.top_form);
|
||||
|
||||
// for now, just test that this can at least be called.
|
||||
VariableSet vars;
|
||||
test->func.ir2.top_form->collect_vars(vars);
|
||||
|
||||
if (do_expressions) {
|
||||
bool success =
|
||||
convert_to_expressions(test->func.ir2.top_form, test->func.ir2.form_pool, test->func);
|
||||
|
||||
EXPECT_TRUE(success);
|
||||
if (!success) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
void FormRegressionTest::test(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool do_expressions,
|
||||
bool allow_pairs,
|
||||
const std::string& method_name,
|
||||
const std::vector<std::pair<std::string, std::string>>& strings) {
|
||||
auto ts = dts->parse_type_spec(type);
|
||||
auto test = make_function(code, ts, do_expressions, allow_pairs, method_name, strings);
|
||||
ASSERT_TRUE(test);
|
||||
auto expected_form =
|
||||
pretty_print::get_pretty_printer_reader().read_from_string(expected, false).as_pair()->car;
|
||||
auto actual_form =
|
||||
pretty_print::get_pretty_printer_reader()
|
||||
.read_from_string(test->func.ir2.top_form->to_form(test->func.ir2.env).print(), false)
|
||||
.as_pair()
|
||||
->car;
|
||||
if (expected_form != actual_form) {
|
||||
printf("Got:\n%s\n\nExpected\n%s\n", actual_form.print().c_str(),
|
||||
expected_form.print().c_str());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(expected_form == actual_form);
|
||||
}
|
||||
|
||||
std::unique_ptr<InstructionParser> FormRegressionTest::parser;
|
||||
std::unique_ptr<DecompilerTypeSystem> FormRegressionTest::dts;
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "gtest/gtest.h"
|
||||
#include "decompiler/Disasm/InstructionParser.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
#include "decompiler/Function/Function.h"
|
||||
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
||||
|
||||
class FormRegressionTest : public ::testing::Test {
|
||||
protected:
|
||||
static std::unique_ptr<decompiler::InstructionParser> parser;
|
||||
static std::unique_ptr<decompiler::DecompilerTypeSystem> dts;
|
||||
|
||||
static void SetUpTestCase();
|
||||
static void TearDownTestCase();
|
||||
|
||||
struct TestData {
|
||||
explicit TestData(int instrs) : func(0, instrs) {}
|
||||
decompiler::Function func;
|
||||
decompiler::LinkedObjectFile file;
|
||||
|
||||
void add_string_at_label(const std::string& label_name, const std::string& data);
|
||||
};
|
||||
|
||||
std::unique_ptr<TestData> make_function(
|
||||
const std::string& code,
|
||||
const TypeSpec& function_type,
|
||||
bool do_expressions,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {});
|
||||
|
||||
void test(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool do_expressions,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {});
|
||||
|
||||
void test_no_expr(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {}) {
|
||||
test(code, type, expected, false, allow_pairs, method_name, strings);
|
||||
}
|
||||
|
||||
void test_with_expr(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {}) {
|
||||
test(code, type, expected, true, allow_pairs, method_name, strings);
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "decompiler/IR2/AtomicOp.h"
|
||||
#include "decompiler/IR2/atomic_op_builder.h"
|
||||
#include "decompiler/analysis/atomic_op_builder.h"
|
||||
#include "decompiler/Disasm/InstructionParser.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "third-party/fmt/format.h"
|
||||
|
||||
+41
-194
@@ -1,162 +1,9 @@
|
||||
#include <memory>
|
||||
#include "gtest/gtest.h"
|
||||
#include "decompiler/Disasm/InstructionParser.h"
|
||||
#include "decompiler/Disasm/DecompilerLabel.h"
|
||||
#include "decompiler/Function/Function.h"
|
||||
#include "decompiler/ObjectFile/ObjectFileDB.h"
|
||||
#include "decompiler/IR2/variable_naming.h"
|
||||
#include "decompiler/IR2/cfg_builder.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "FormRegressionTest.h"
|
||||
|
||||
using namespace decompiler;
|
||||
|
||||
class DecompilerRegressionTest : public ::testing::Test {
|
||||
protected:
|
||||
static std::unique_ptr<InstructionParser> parser;
|
||||
static std::unique_ptr<DecompilerTypeSystem> dts;
|
||||
|
||||
static void SetUpTestCase() {
|
||||
parser = std::make_unique<InstructionParser>();
|
||||
dts = std::make_unique<DecompilerTypeSystem>();
|
||||
dts->parse_type_defs({"decompiler", "config", "all-types.gc"});
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
parser.reset();
|
||||
dts.reset();
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
struct TestData {
|
||||
explicit TestData(int instrs) : func(0, instrs) {}
|
||||
Function func;
|
||||
LinkedObjectFile file;
|
||||
|
||||
void add_string_at_label(const std::string& label_name, const std::string& data) {
|
||||
// first, align segment 1:
|
||||
while (file.words_by_seg.at(1).size() % 4) {
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(0));
|
||||
}
|
||||
|
||||
// add string type tag:
|
||||
LinkedWord type_tag(0);
|
||||
type_tag.kind = LinkedWord::Kind::TYPE_PTR;
|
||||
type_tag.symbol_name = "string";
|
||||
file.words_by_seg.at(1).push_back(type_tag);
|
||||
int string_start = 4 * int(file.words_by_seg.at(1).size());
|
||||
|
||||
// add size
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(int(data.length())));
|
||||
|
||||
// add string:
|
||||
std::vector<char> bytes;
|
||||
bytes.resize(((data.size() + 1 + 3) / 4) * 4);
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
bytes[i] = data[i];
|
||||
}
|
||||
for (size_t i = 0; i < bytes.size() / 4; i++) {
|
||||
auto word = ((uint32_t*)bytes.data())[i];
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(word));
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
file.words_by_seg.at(1).push_back(LinkedWord(0));
|
||||
}
|
||||
// will be already null terminated.
|
||||
|
||||
for (auto& label : file.labels) {
|
||||
if (label.name == label_name) {
|
||||
label.target_segment = 1;
|
||||
label.offset = string_start;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<TestData> make_function(
|
||||
const std::string& code,
|
||||
const TypeSpec& function_type,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {}) {
|
||||
dts->type_prop_settings.locked = true;
|
||||
dts->type_prop_settings.reset();
|
||||
dts->type_prop_settings.allow_pair = allow_pairs;
|
||||
dts->type_prop_settings.current_method_type = method_name;
|
||||
auto program = parser->parse_program(code);
|
||||
// printf("prg:\n%s\n\n", program.print().c_str());
|
||||
auto test = std::make_unique<TestData>(program.instructions.size());
|
||||
test->file.words_by_seg.resize(3);
|
||||
test->file.labels = program.labels;
|
||||
test->func.ir2.env.file = &test->file;
|
||||
test->func.instructions = program.instructions;
|
||||
test->func.guessed_name.set_as_global("test-function");
|
||||
|
||||
for (auto& str : strings) {
|
||||
test->add_string_at_label(str.first, str.second);
|
||||
}
|
||||
|
||||
test->func.basic_blocks = find_blocks_in_function(test->file, 0, test->func);
|
||||
test->func.analyze_prologue(test->file);
|
||||
test->func.cfg = build_cfg(test->file, 0, test->func);
|
||||
EXPECT_TRUE(test->func.cfg->is_fully_resolved());
|
||||
|
||||
auto ops = convert_function_to_atomic_ops(test->func, program.labels);
|
||||
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
|
||||
test->func.ir2.atomic_ops_succeeded = true;
|
||||
|
||||
EXPECT_TRUE(test->func.run_type_analysis_ir2(function_type, *dts, test->file, {}));
|
||||
|
||||
test->func.ir2.env.set_reg_use(analyze_ir2_register_usage(test->func));
|
||||
|
||||
auto result = run_variable_renaming(test->func, test->func.ir2.env.reg_use(),
|
||||
*test->func.ir2.atomic_ops, *dts);
|
||||
if (result.has_value()) {
|
||||
test->func.ir2.env.set_local_vars(*result);
|
||||
} else {
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
|
||||
build_initial_forms(test->func);
|
||||
EXPECT_TRUE(test->func.ir2.top_form);
|
||||
|
||||
// for now, just test that this can at least be called.
|
||||
VariableSet vars;
|
||||
test->func.ir2.top_form->collect_vars(vars);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
void test(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {}) {
|
||||
auto ts = dts->parse_type_spec(type);
|
||||
auto test = make_function(code, ts, allow_pairs, method_name, strings);
|
||||
auto expected_form =
|
||||
pretty_print::get_pretty_printer_reader().read_from_string(expected, false).as_pair()->car;
|
||||
auto actual_form =
|
||||
pretty_print::get_pretty_printer_reader()
|
||||
.read_from_string(test->func.ir2.top_form->to_form(test->func.ir2.env).print(), false)
|
||||
.as_pair()
|
||||
->car;
|
||||
if (expected_form != actual_form) {
|
||||
printf("Got:\n%s\n\nExpected\n%s\n", actual_form.print().c_str(),
|
||||
expected_form.print().c_str());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(expected_form == actual_form);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<InstructionParser> DecompilerRegressionTest::parser;
|
||||
std::unique_ptr<DecompilerTypeSystem> DecompilerRegressionTest::dts;
|
||||
|
||||
TEST_F(DecompilerRegressionTest, StringTest) {
|
||||
TEST_F(FormRegressionTest, StringTest) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L100:\n"
|
||||
@@ -164,7 +11,7 @@ TEST_F(DecompilerRegressionTest, StringTest) {
|
||||
"L101:\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
auto test = make_function(func, TypeSpec("function", {TypeSpec("none")}), false, "",
|
||||
auto test = make_function(func, TypeSpec("function", {TypeSpec("none")}), false, false, "",
|
||||
{{"L100", "testing-string"}, {"L101", "testing-string-2"}});
|
||||
|
||||
EXPECT_EQ(test->file.get_goal_string_by_label(test->file.get_label_by_name("L100")),
|
||||
@@ -173,7 +20,7 @@ TEST_F(DecompilerRegressionTest, StringTest) {
|
||||
"testing-string-2");
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, SimplestTest) {
|
||||
TEST_F(FormRegressionTest, SimplestTest) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" or v0, a0, r0\n"
|
||||
@@ -181,10 +28,10 @@ TEST_F(DecompilerRegressionTest, SimplestTest) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function object object)";
|
||||
std::string expected = "(set! v0-0 a0-0)";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, FloatingPointBasic) {
|
||||
TEST_F(FormRegressionTest, FloatingPointBasic) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L345:\n"
|
||||
@@ -206,10 +53,10 @@ TEST_F(DecompilerRegressionTest, FloatingPointBasic) {
|
||||
" (set! f0-1 (/.s f0-0 f1-0))\n"
|
||||
" (set! v0-0 (fpr->gpr f0-1))\n"
|
||||
" )";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Op3) {
|
||||
TEST_F(FormRegressionTest, Op3) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L308:\n"
|
||||
@@ -218,10 +65,10 @@ TEST_F(DecompilerRegressionTest, Op3) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(set! v0-0 (*.si a0-0 a1-0))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Division) {
|
||||
TEST_F(FormRegressionTest, Division) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L307:\n"
|
||||
@@ -231,10 +78,10 @@ TEST_F(DecompilerRegressionTest, Division) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(set! v0-0 (/.si a0-0 a1-0))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Ash) {
|
||||
TEST_F(FormRegressionTest, Ash) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L305:\n"
|
||||
@@ -251,10 +98,10 @@ TEST_F(DecompilerRegressionTest, Ash) {
|
||||
" sll r0, r0, 0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v1-0 a0-0) (set! v0-0 (ash.si v1-0 a1-0)))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Abs) {
|
||||
TEST_F(FormRegressionTest, Abs) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L301:\n"
|
||||
@@ -267,10 +114,10 @@ TEST_F(DecompilerRegressionTest, Abs) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int)";
|
||||
std::string expected = "(begin (set! v0-0 a0-0) (set! v0-1 (abs v0-0)))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Min) {
|
||||
TEST_F(FormRegressionTest, Min) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" or v0, a0, r0\n"
|
||||
@@ -281,10 +128,10 @@ TEST_F(DecompilerRegressionTest, Min) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v0-0 a0-0) (set! v1-0 a1-0) (set! v0-1 (min.si v0-0 v1-0)))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Max) {
|
||||
TEST_F(FormRegressionTest, Max) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L299:\n"
|
||||
@@ -296,10 +143,10 @@ TEST_F(DecompilerRegressionTest, Max) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v0-0 a0-0) (set! v1-0 a1-0) (set! v0-1 (max.si v0-0 v1-0)))";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, FormatString) {
|
||||
TEST_F(FormRegressionTest, FormatString) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L343:\n"
|
||||
@@ -336,10 +183,10 @@ TEST_F(DecompilerRegressionTest, FormatString) {
|
||||
" (set! v0-0 (call! a0-1 a1-0 a2-0))\n" // #t, "~f", the float
|
||||
" (set! v0-1 gp-0)\n"
|
||||
" )";
|
||||
test(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
test_no_expr(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, WhileLoop) {
|
||||
TEST_F(FormRegressionTest, WhileLoop) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L285:\n"
|
||||
@@ -378,11 +225,11 @@ TEST_F(DecompilerRegressionTest, WhileLoop) {
|
||||
" )\n"
|
||||
" (set! v0-1 '#f)\n"
|
||||
" )";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
// Note - this test looks weird because or's aren't fully processed at this point.
|
||||
TEST_F(DecompilerRegressionTest, Or) {
|
||||
TEST_F(FormRegressionTest, Or) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L280:\n"
|
||||
@@ -443,10 +290,10 @@ TEST_F(DecompilerRegressionTest, Or) {
|
||||
" )\n"
|
||||
" (set! v0-1 '#f)\n"
|
||||
" )";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, DynamicMethodAccess) {
|
||||
TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -520,10 +367,10 @@ TEST_F(DecompilerRegressionTest, DynamicMethodAccess) {
|
||||
" )\n"
|
||||
" (set! v1-5 '#f)\n"
|
||||
" )";
|
||||
test(func, type, expected);
|
||||
test_no_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, SimpleLoopMergeCheck) {
|
||||
TEST_F(FormRegressionTest, SimpleLoopMergeCheck) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -563,10 +410,10 @@ TEST_F(DecompilerRegressionTest, SimpleLoopMergeCheck) {
|
||||
" (set! v1-2 '#f)\n"
|
||||
" (set! v0-0 (l.w (+ a0-0 -2)))\n"
|
||||
" )";
|
||||
test(func, type, expected, true);
|
||||
test_no_expr(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, And) {
|
||||
TEST_F(FormRegressionTest, And) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -632,10 +479,10 @@ TEST_F(DecompilerRegressionTest, And) {
|
||||
" (set! v1-2 '#f)\n" // while's false, I think.
|
||||
" )\n"
|
||||
" )";
|
||||
test(func, type, expected, true);
|
||||
test_no_expr(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, FunctionCall) {
|
||||
TEST_F(FormRegressionTest, FunctionCall) {
|
||||
// nmember
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
@@ -715,10 +562,10 @@ TEST_F(DecompilerRegressionTest, FunctionCall) {
|
||||
" )\n"
|
||||
" (set! v0-2 gp-0)\n" // not empty, so return the result
|
||||
" )"; // the (set! v0 #f) from the if is added later.
|
||||
test(func, type, expected, true);
|
||||
test_no_expr(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, NestedAndOr) {
|
||||
TEST_F(FormRegressionTest, NestedAndOr) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -886,10 +733,10 @@ TEST_F(DecompilerRegressionTest, NestedAndOr) {
|
||||
" (set! v1-12 '#f)\n"
|
||||
" (set! v0-1 gp-0)\n"
|
||||
" )";
|
||||
test(func, type, expected, true);
|
||||
test_no_expr(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, NewMethod) {
|
||||
TEST_F(FormRegressionTest, NewMethod) {
|
||||
// inline-array-class new
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
@@ -941,10 +788,10 @@ TEST_F(DecompilerRegressionTest, NewMethod) {
|
||||
" (s.w! v0-0 gp-0)\n" // store size
|
||||
" (s.w! (+ v0-0 4) gp-0)\n"
|
||||
" )";
|
||||
test(func, type, expected, false, "inline-array-class");
|
||||
test_no_expr(func, type, expected, false, "inline-array-class");
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, Recursive) {
|
||||
TEST_F(FormRegressionTest, Recursive) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -985,10 +832,10 @@ TEST_F(DecompilerRegressionTest, Recursive) {
|
||||
" (set! v0-2 (*.si gp-0 v0-1))\n" // not quite a tail call...
|
||||
" )\n"
|
||||
" )";
|
||||
test(func, type, expected, false);
|
||||
test_no_expr(func, type, expected, false);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerRegressionTest, TypeOf) {
|
||||
TEST_F(FormRegressionTest, TypeOf) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
|
||||
@@ -1020,5 +867,5 @@ TEST_F(DecompilerRegressionTest, TypeOf) {
|
||||
" (set! t9-0 (l.wu (+ v1-1 24)))\n" // print method.
|
||||
" (set! v0-0 (call! a0-0))\n"
|
||||
" )";
|
||||
test(func, type, expected, false);
|
||||
test_no_expr(func, type, expected, false);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "FormRegressionTest.h"
|
||||
|
||||
using namespace decompiler;
|
||||
|
||||
TEST_F(FormRegressionTest, ExprIdentity) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" or v0, a0, r0\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function object object)";
|
||||
std::string expected = "a0-0";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFloatingPoint) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
"L345:\n"
|
||||
" daddiu sp, sp, -16\n"
|
||||
" sd fp, 8(sp)\n"
|
||||
" or fp, t9, r0\n"
|
||||
" lwc1 f0, L345(fp)\n"
|
||||
" mtc1 f1, a0\n"
|
||||
" div.s f0, f0, f1\n"
|
||||
" mfc1 v0, f0\n"
|
||||
" ld fp, 8(sp)\n"
|
||||
" jr ra\n"
|
||||
" daddiu sp, sp, 16";
|
||||
std::string type = "(function float float)";
|
||||
std::string expected = "(/ (l.f L345) a0-0)";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, AdditionSigned) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" daddu v0, a0, a1\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(+ a0-0 a1-0)";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, AdditionUnSigned) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" daddu v0, a0, a1\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint uint uint)";
|
||||
std::string expected = "(+ a0-0 a1-0)";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, AdditionMixed1) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" daddu v0, a0, a1\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int uint int)";
|
||||
std::string expected = "(+ a0-0 (the-as int a1-0))";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, AdditionMixed2) {
|
||||
std::string func =
|
||||
" sll r0, r0, 0\n"
|
||||
" daddu v0, a0, a1\n"
|
||||
" jr ra\n"
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint int uint)";
|
||||
std::string expected = "(+ a0-0 (the-as uint a1-0))";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
// TODO - test the additions, but with the wrong return types.
|
||||
@@ -2,15 +2,5 @@
|
||||
#include "test_collections.cpp"
|
||||
#include "test_compiler.cpp"
|
||||
#include "test_control_statements.cpp"
|
||||
#include "test_float.cpp"
|
||||
#include "test_functions.cpp"
|
||||
#include "test_library.cpp"
|
||||
#include "test_logic.cpp"
|
||||
#include "test_loop_recur.cpp"
|
||||
#include "test_macros.cpp"
|
||||
#include "test_methods.cpp"
|
||||
#include "test_pointers.cpp"
|
||||
#include "test_strings.cpp"
|
||||
#include "test_symbols.cpp"
|
||||
#include "test_variables.cpp"
|
||||
#include "test_with_game.cpp"
|
||||
|
||||
@@ -121,15 +121,21 @@ class ArithmeticTests : public testing::TestWithParam<IntegerParam> {
|
||||
// Per-test-suite set-up.
|
||||
// Called before the first test in this test suite.
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
compiler = std::make_unique<Compiler>();
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
}
|
||||
|
||||
// Per-test-suite tear-down.
|
||||
// Called after the last test in this test suite.
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
compiler->shutdown_target();
|
||||
runtime_thread->join();
|
||||
|
||||
runtime_thread.reset();
|
||||
compiler.reset();
|
||||
runner.reset();
|
||||
}
|
||||
|
||||
// You can define per-test set-up logic as usual.
|
||||
@@ -142,9 +148,9 @@ class ArithmeticTests : public testing::TestWithParam<IntegerParam> {
|
||||
void TearDown() {}
|
||||
|
||||
// Common Resources Across all Tests in the Suite
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
static std::unique_ptr<std::thread> runtime_thread;
|
||||
static std::unique_ptr<Compiler> compiler;
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
// Just to promote better test organization, supports nesting the test files 1 directory deep
|
||||
std::string testCategory = "arithmetic";
|
||||
@@ -154,9 +160,9 @@ class ArithmeticTests : public testing::TestWithParam<IntegerParam> {
|
||||
|
||||
// You must initialize the static variables outside of the declaration, or you'll run into
|
||||
// unresolved external errors
|
||||
std::thread ArithmeticTests::runtime_thread;
|
||||
Compiler ArithmeticTests::compiler;
|
||||
GoalTest::CompilerTestRunner ArithmeticTests::runner;
|
||||
std::unique_ptr<std::thread> ArithmeticTests::runtime_thread;
|
||||
std::unique_ptr<Compiler> ArithmeticTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> ArithmeticTests::runner;
|
||||
|
||||
// Finally, we define our generic test, given our custom class that represents our test inputs
|
||||
// we can generate the lisp file, and pass along the path to the test runner
|
||||
@@ -169,7 +175,7 @@ TEST_P(ArithmeticTests, EvalIntegers) {
|
||||
|
||||
std::string testFile = "eval-integer-" + std::to_string(param.index) + ".generated.gc";
|
||||
env.write("eval-integer.template.gc", data, testFile);
|
||||
runner.run_test(testCategory, testFile, {param.eval()});
|
||||
runner->run_test(testCategory, testFile, {param.eval()});
|
||||
}
|
||||
|
||||
// ValuesIn, is not the only way to use a parameterized test, but the most applicable for this
|
||||
@@ -184,65 +190,102 @@ INSTANTIATE_TEST_SUITE_P(EvalIntegers,
|
||||
IntegerParam(0), IntegerParam(-0)})));
|
||||
|
||||
TEST_F(ArithmeticTests, Addition) {
|
||||
runner.run_static_test(env, testCategory, "add-int-literals.static.gc", {"13\n"});
|
||||
runner.run_static_test(env, testCategory, "add-let.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "add-int-literals.static.gc", {"13\n"});
|
||||
runner->run_static_test(env, testCategory, "add-let.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, AddIntegerFunction) {
|
||||
runner.run_static_test(env, testCategory, "add-function.static.gc", {"21\n"});
|
||||
runner->run_static_test(env, testCategory, "add-function.static.gc", {"21\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, AddIntegerMultiple) {
|
||||
runner.run_static_test(env, testCategory, "add-int-multiple.static.gc", {"15\n"});
|
||||
runner.run_static_test(env, testCategory, "add-int-multiple-2.static.gc", {"15\n"});
|
||||
runner->run_static_test(env, testCategory, "add-int-multiple.static.gc", {"15\n"});
|
||||
runner->run_static_test(env, testCategory, "add-int-multiple-2.static.gc", {"15\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, AddIntegerVariables) {
|
||||
runner.run_static_test(env, testCategory, "add-int-vars.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "add-int-vars.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, AshFunction) {
|
||||
runner.run_static_test(env, testCategory, "ash.static.gc", {"18\n"});
|
||||
runner->run_static_test(env, testCategory, "ash.static.gc", {"18\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Division) {
|
||||
runner.run_static_test(env, testCategory, "divide-1.static.gc", {"6\n"});
|
||||
runner.run_static_test(env, testCategory, "divide-2.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "divide-1.static.gc", {"6\n"});
|
||||
runner->run_static_test(env, testCategory, "divide-2.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, IntegerSymbol) {
|
||||
runner.run_static_test(env, testCategory, "negative-int-symbol.static.gc", {"-123\n"});
|
||||
runner->run_static_test(env, testCategory, "negative-int-symbol.static.gc", {"-123\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Modulus) {
|
||||
runner.run_static_test(env, testCategory, "mod.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "mod.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Multiplication) {
|
||||
runner.run_static_test(env, testCategory, "multiply.static.gc", {"-12\n"});
|
||||
runner.run_static_test(env, testCategory, "multiply-let.static.gc", {"3\n"});
|
||||
runner->run_static_test(env, testCategory, "multiply.static.gc", {"-12\n"});
|
||||
runner->run_static_test(env, testCategory, "multiply-let.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, NestedFunctionCall) {
|
||||
runner.run_static_test(env, testCategory, "nested-function.static.gc", {"10\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-function.static.gc", {"10\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, VariableShift) {
|
||||
runner.run_static_test(env, testCategory, "shiftvs.static.gc", {"11\n"});
|
||||
runner->run_static_test(env, testCategory, "shiftvs.static.gc", {"11\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, FixedShift) {
|
||||
// same math as the variable shift test, just using the fixed shift operators.
|
||||
runner.run_static_test(env, testCategory, "shift-fixed.static.gc", {"11\n"});
|
||||
runner->run_static_test(env, testCategory, "shift-fixed.static.gc", {"11\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Subtraction) {
|
||||
runner.run_static_test(env, testCategory, "subtract-1.static.gc", {"4\n"});
|
||||
runner.run_static_test(env, testCategory, "subtract-2.static.gc", {"4\n"});
|
||||
runner.run_static_test(env, testCategory, "subtract-let.static.gc", {"3\n"});
|
||||
runner->run_static_test(env, testCategory, "subtract-1.static.gc", {"4\n"});
|
||||
runner->run_static_test(env, testCategory, "subtract-2.static.gc", {"4\n"});
|
||||
runner->run_static_test(env, testCategory, "subtract-let.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Multiplication2) {
|
||||
runner.run_static_test(env, testCategory, "multiply32.static.gc", {"-1234478448\n"});
|
||||
runner.run_static_test(env, testCategory, "multiply64.static.gc", {"93270638141856400\n"});
|
||||
}
|
||||
runner->run_static_test(env, testCategory, "multiply32.static.gc", {"-1234478448\n"});
|
||||
runner->run_static_test(env, testCategory, "multiply64.static.gc", {"93270638141856400\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Constants) {
|
||||
runner->run_static_test(env, testCategory, "float.static.gc", {"1067316150\n"});
|
||||
runner->run_static_test(env, testCategory, "function-return-float-constant.static.gc",
|
||||
{"3.14149\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Operations) {
|
||||
runner->run_static_test(env, testCategory, "float-pow.static.gc", {"256\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "float-product.static.gc", {"120.0000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Symbols) {
|
||||
runner->run_static_test(env, testCategory, "float-in-symbol.static.gc", {"2345.6000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Functions) {
|
||||
runner->run_static_test(env, testCategory, "float-function.static.gc", {"10.152\n0\n"});
|
||||
runner->run_static_test(
|
||||
env, testCategory, "nested-float-functions.static.gc",
|
||||
{"i 1.4400 3.4000\nr 10.1523\ni 1.2000 10.1523\nr 17.5432\n17.543 10.152\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, MinMax) {
|
||||
runner->run_static_test(env, testCategory, "float-max.static.gc", {"3.70\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "float-min.static.gc", {"-1.20\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, LogicalOperators) {
|
||||
runner->run_static_test(env, testCategory, "logand.static.gc", {"4\n"});
|
||||
runner->run_static_test(env, testCategory, "logior.static.gc", {"60\n"});
|
||||
runner->run_static_test(env, testCategory, "logxor.static.gc", {"56\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Comparison) {
|
||||
runner->run_static_test(env, testCategory, "signed-int-compare.static.gc", {"12\n"});
|
||||
}
|
||||
|
||||
@@ -25,13 +25,19 @@ struct CollectionParam {
|
||||
class CollectionTests : public testing::TestWithParam<CollectionParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
compiler = std::make_unique<Compiler>();
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
compiler->shutdown_target();
|
||||
runtime_thread->join();
|
||||
|
||||
runtime_thread.reset();
|
||||
compiler.reset();
|
||||
runner.reset();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
@@ -41,36 +47,36 @@ class CollectionTests : public testing::TestWithParam<CollectionParam> {
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
static std::unique_ptr<std::thread> runtime_thread;
|
||||
static std::unique_ptr<Compiler> compiler;
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "collections";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread CollectionTests::runtime_thread;
|
||||
Compiler CollectionTests::compiler;
|
||||
GoalTest::CompilerTestRunner CollectionTests::runner;
|
||||
std::unique_ptr<std::thread> CollectionTests::runtime_thread;
|
||||
std::unique_ptr<Compiler> CollectionTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> CollectionTests::runner;
|
||||
|
||||
TEST_F(CollectionTests, Pairs) {
|
||||
runner.run_static_test(env, testCategory, "empty-pair.static.gc", {"()\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "pair-check.static.gc", {"#t#f\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "empty-pair.static.gc", {"()\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "pair-check.static.gc", {"#t#f\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, Lists) {
|
||||
runner.run_static_test(env, testCategory, "list.static.gc", {"(a b c d)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "list.static.gc", {"(a b c d)\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, InlineArray) {
|
||||
runner.run_static_test(env, testCategory, "inline-array-field.static.gc", {"16\n"});
|
||||
runner->run_static_test(env, testCategory, "inline-array-field.static.gc", {"16\n"});
|
||||
}
|
||||
|
||||
TEST_F(CollectionTests, Operations) {
|
||||
runner.run_static_test(env, testCategory, "cons.static.gc", {"(a . b)\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "car-cdr-get.static.gc", {"ab\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "car-cdr-set.static.gc", {"(c . d)\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "nested-car-cdr-set.static.gc",
|
||||
{"efgh\n((e . g) f . h)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "cons.static.gc", {"(a . b)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "car-cdr-get.static.gc", {"ab\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "car-cdr-set.static.gc", {"(c . d)\n0\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-car-cdr-set.static.gc",
|
||||
{"efgh\n((e . g) f . h)\n0\n"});
|
||||
}
|
||||
|
||||
@@ -25,13 +25,19 @@ struct ControlStatementParam {
|
||||
class ControlStatementTests : public testing::TestWithParam<ControlStatementParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
runtime_thread = std::make_unique<std::thread>(std::thread((GoalTest::runtime_no_kernel)));
|
||||
compiler = std::make_unique<Compiler>();
|
||||
runner = std::make_unique<GoalTest::CompilerTestRunner>();
|
||||
runner->c = compiler.get();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
compiler->shutdown_target();
|
||||
runtime_thread->join();
|
||||
|
||||
runtime_thread.reset();
|
||||
compiler.reset();
|
||||
runner.reset();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
@@ -41,33 +47,152 @@ class ControlStatementTests : public testing::TestWithParam<ControlStatementPara
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
static std::unique_ptr<std::thread> runtime_thread;
|
||||
static std::unique_ptr<Compiler> compiler;
|
||||
static std::unique_ptr<GoalTest::CompilerTestRunner> runner;
|
||||
|
||||
std::string testCategory = "control-statements";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread ControlStatementTests::runtime_thread;
|
||||
Compiler ControlStatementTests::compiler;
|
||||
GoalTest::CompilerTestRunner ControlStatementTests::runner;
|
||||
std::unique_ptr<std::thread> ControlStatementTests::runtime_thread;
|
||||
std::unique_ptr<Compiler> ControlStatementTests::compiler;
|
||||
std::unique_ptr<GoalTest::CompilerTestRunner> ControlStatementTests::runner;
|
||||
|
||||
TEST_F(ControlStatementTests, ConditionalCompilation) {
|
||||
runner.run_static_test(env, testCategory, "conditional-compilation.static.gc", {"3\n"});
|
||||
runner->run_static_test(env, testCategory, "conditional-compilation.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Blocks) {
|
||||
runner.run_static_test(env, testCategory, "nested-blocks-1.static.gc", {"7\n"});
|
||||
runner.run_static_test(env, testCategory, "nested-blocks-2.static.gc", {"8\n"});
|
||||
runner.run_static_test(env, testCategory, "nested-blocks-3.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-1.static.gc", {"7\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-2.static.gc", {"8\n"});
|
||||
runner->run_static_test(env, testCategory, "nested-blocks-3.static.gc", {"7\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, GoTo) {
|
||||
runner.run_static_test(env, testCategory, "goto.static.gc", {"3\n"});
|
||||
runner->run_static_test(env, testCategory, "goto.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Branch) {
|
||||
runner.run_static_test(env, testCategory, "return-value-of-if.static.gc", {"123\n"});
|
||||
runner->run_static_test(env, testCategory, "return-value-of-if.static.gc", {"123\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, DoTimes) {
|
||||
runner->run_static_test(env, testCategory, "dotimes.static.gc", {"4950\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Factorial) {
|
||||
runner->run_static_test(env, testCategory, "factorial-recursive.static.gc", {"3628800\n"});
|
||||
runner->run_static_test(env, testCategory, "factorial-iterative.static.gc", {"3628800\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Definitions) {
|
||||
runner->run_static_test(env, testCategory, "defun-return-constant.static.gc", {"12\n"});
|
||||
runner->run_static_test(env, testCategory, "defun-return-symbol.static.gc", {"42\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnValue) {
|
||||
runner->run_static_test(env, testCategory, "return.static.gc", {"77\n"});
|
||||
runner->run_static_test(env, testCategory, "return-arg.static.gc", {"23\n"});
|
||||
runner->run_static_test(env, testCategory, "return-colors.static.gc", {"77\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Calling) {
|
||||
runner->run_static_test(env, testCategory, "nested-call.static.gc", {"2\n"});
|
||||
runner->run_static_test(env, testCategory, "inline-call.static.gc", {"44\n"});
|
||||
runner->run_static_test(env, testCategory, "simple-call.static.gc", {"30\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Anonymous) {
|
||||
runner->run_static_test(env, testCategory, "declare-inline.static.gc", {"32\n"});
|
||||
runner->run_static_test(env, testCategory, "lambda-1.static.gc", {"2\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineIsInline) {
|
||||
auto code = compiler->get_goos().reader.read_from_file(
|
||||
{"test/goalc/source_templates/control-statements/declare-inline.static.gc"});
|
||||
auto compiled = compiler->compile_object_file("test-code", code, true);
|
||||
EXPECT_EQ(compiled->functions().size(), 2);
|
||||
auto& ir = compiled->top_level_function().code();
|
||||
bool got_mult = false;
|
||||
for (auto& x : ir) {
|
||||
EXPECT_EQ(dynamic_cast<IR_FunctionCall*>(x.get()), nullptr);
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(x.get());
|
||||
if (as_im) {
|
||||
EXPECT_EQ(as_im->get_kind(), IntegerMathKind::IMUL_32);
|
||||
got_mult = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(got_mult);
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, AllowInline) {
|
||||
auto code = compiler->get_goos().reader.read_from_file(
|
||||
{"test/goalc/source_templates/control-statements/inline-call.static.gc"});
|
||||
auto compiled = compiler->compile_object_file("test-code", code, true);
|
||||
EXPECT_EQ(compiled->functions().size(), 2);
|
||||
auto& ir = compiled->top_level_function().code();
|
||||
int got_mult = 0;
|
||||
int got_call = 0;
|
||||
for (auto& x : ir) {
|
||||
if (dynamic_cast<IR_FunctionCall*>(x.get())) {
|
||||
got_call++;
|
||||
}
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(x.get());
|
||||
if (as_im && as_im->get_kind() == IntegerMathKind::IMUL_32) {
|
||||
got_mult++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(got_mult, 1);
|
||||
EXPECT_EQ(got_call, 1);
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnNone) {
|
||||
runner->run_static_test(env, testCategory, "function-returning-none.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock1) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-1.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock2) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-2.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock3) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-3.static.gc", {"4\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, InlineBlock4) {
|
||||
runner->run_static_test(env, testCategory, "inline-with-block-4.static.gc", {"3.0000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, ReturnFromTrick) {
|
||||
runner->run_static_test(env, testCategory, "return-from-trick.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Set) {
|
||||
runner->run_static_test(env, testCategory, "set-symbol.static.gc", {"22\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Protect) {
|
||||
runner->run_static_test(env, testCategory, "protect.static.gc", {"33\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Align) {
|
||||
runner->run_static_test(env, testCategory, "align16-1.static.gc", {"80\n"});
|
||||
runner->run_static_test(env, testCategory, "align16-2.static.gc", {"64\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Defsmacro) {
|
||||
runner->run_static_test(env, testCategory, "defsmacro-defgmacro.static.gc", {"20\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, Desfun) {
|
||||
runner->run_static_test(env, testCategory, "desfun.static.gc", {"4\n"});
|
||||
}
|
||||
|
||||
TEST_F(ControlStatementTests, DeReference) {
|
||||
runner->run_static_test(env, testCategory, "methods.static.gc", {"#t#t\n0\n"});
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct FloatParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class FloatTests : public testing::TestWithParam<FloatParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "float";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread FloatTests::runtime_thread;
|
||||
Compiler FloatTests::compiler;
|
||||
GoalTest::CompilerTestRunner FloatTests::runner;
|
||||
|
||||
TEST_F(FloatTests, Constants) {
|
||||
runner.run_static_test(env, testCategory, "float.static.gc", {"1067316150\n"});
|
||||
runner.run_static_test(env, testCategory, "function-return-float-constant.static.gc",
|
||||
{"3.14149\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FloatTests, Operations) {
|
||||
runner.run_static_test(env, testCategory, "float-pow.static.gc", {"256\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "float-product.static.gc", {"120.0000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FloatTests, Symbols) {
|
||||
runner.run_static_test(env, testCategory, "float-in-symbol.static.gc", {"2345.6000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FloatTests, Functions) {
|
||||
runner.run_static_test(env, testCategory, "float-function.static.gc", {"10.152\n0\n"});
|
||||
runner.run_static_test(
|
||||
env, testCategory, "nested-float-functions.static.gc",
|
||||
{"i 1.4400 3.4000\nr 10.1523\ni 1.2000 10.1523\nr 17.5432\n17.543 10.152\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FloatTests, MinMax) {
|
||||
runner.run_static_test(env, testCategory, "float-max.static.gc", {"3.70\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "float-min.static.gc", {"-1.20\n0\n"});
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct FunctionParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class FunctionTests : public testing::TestWithParam<FunctionParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "functions";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread FunctionTests::runtime_thread;
|
||||
Compiler FunctionTests::compiler;
|
||||
GoalTest::CompilerTestRunner FunctionTests::runner;
|
||||
|
||||
TEST_F(FunctionTests, Definitions) {
|
||||
runner.run_static_test(env, testCategory, "defun-return-constant.static.gc", {"12\n"});
|
||||
runner.run_static_test(env, testCategory, "defun-return-symbol.static.gc", {"42\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, ReturnValue) {
|
||||
runner.run_static_test(env, testCategory, "return.static.gc", {"77\n"});
|
||||
runner.run_static_test(env, testCategory, "return-arg.static.gc", {"23\n"});
|
||||
runner.run_static_test(env, testCategory, "return-colors.static.gc", {"77\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, Calling) {
|
||||
runner.run_static_test(env, testCategory, "nested-call.static.gc", {"2\n"});
|
||||
runner.run_static_test(env, testCategory, "inline-call.static.gc", {"44\n"});
|
||||
runner.run_static_test(env, testCategory, "simple-call.static.gc", {"30\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, Anonymous) {
|
||||
runner.run_static_test(env, testCategory, "declare-inline.static.gc", {"32\n"});
|
||||
runner.run_static_test(env, testCategory, "lambda-1.static.gc", {"2\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, InlineIsInline) {
|
||||
auto code = compiler.get_goos().reader.read_from_file(
|
||||
{"test/goalc/source_templates/functions/declare-inline.static.gc"});
|
||||
auto compiled = compiler.compile_object_file("test-code", code, true);
|
||||
EXPECT_EQ(compiled->functions().size(), 2);
|
||||
auto& ir = compiled->top_level_function().code();
|
||||
bool got_mult = false;
|
||||
for (auto& x : ir) {
|
||||
EXPECT_EQ(dynamic_cast<IR_FunctionCall*>(x.get()), nullptr);
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(x.get());
|
||||
if (as_im) {
|
||||
EXPECT_EQ(as_im->get_kind(), IntegerMathKind::IMUL_32);
|
||||
got_mult = true;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(got_mult);
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, AllowInline) {
|
||||
auto code = compiler.get_goos().reader.read_from_file(
|
||||
{"test/goalc/source_templates/functions/inline-call.static.gc"});
|
||||
auto compiled = compiler.compile_object_file("test-code", code, true);
|
||||
EXPECT_EQ(compiled->functions().size(), 2);
|
||||
auto& ir = compiled->top_level_function().code();
|
||||
int got_mult = 0;
|
||||
int got_call = 0;
|
||||
for (auto& x : ir) {
|
||||
if (dynamic_cast<IR_FunctionCall*>(x.get())) {
|
||||
got_call++;
|
||||
}
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(x.get());
|
||||
if (as_im && as_im->get_kind() == IntegerMathKind::IMUL_32) {
|
||||
got_mult++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(got_mult, 1);
|
||||
EXPECT_EQ(got_call, 1);
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, ReturnNone) {
|
||||
runner.run_static_test(env, testCategory, "function-returning-none.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, InlineBlock1) {
|
||||
runner.run_static_test(env, testCategory, "inline-with-block-1.static.gc", {"1\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, InlineBlock2) {
|
||||
runner.run_static_test(env, testCategory, "inline-with-block-2.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, InlineBlock3) {
|
||||
runner.run_static_test(env, testCategory, "inline-with-block-3.static.gc", {"4\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, InlineBlock4) {
|
||||
runner.run_static_test(env, testCategory, "inline-with-block-4.static.gc", {"3.0000\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FunctionTests, ReturnFromTrick) {
|
||||
runner.run_static_test(env, testCategory, "return-from-trick.static.gc", {"1\n"});
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct LibraryParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class LibraryTests : public testing::TestWithParam<LibraryParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "library";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread LibraryTests::runtime_thread;
|
||||
Compiler LibraryTests::compiler;
|
||||
GoalTest::CompilerTestRunner LibraryTests::runner;
|
||||
|
||||
TEST_F(LibraryTests, Set) {
|
||||
runner.run_static_test(env, testCategory, "set-symbol.static.gc", {"22\n"});
|
||||
}
|
||||
|
||||
TEST_F(LibraryTests, Protect) {
|
||||
runner.run_static_test(env, testCategory, "protect.static.gc", {"33\n"});
|
||||
}
|
||||
|
||||
TEST_F(LibraryTests, Align) {
|
||||
runner.run_static_test(env, testCategory, "align16-1.static.gc", {"80\n"});
|
||||
runner.run_static_test(env, testCategory, "align16-2.static.gc", {"64\n"});
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct LogicParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class LogicTests : public testing::TestWithParam<LogicParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "logic";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread LogicTests::runtime_thread;
|
||||
Compiler LogicTests::compiler;
|
||||
GoalTest::CompilerTestRunner LogicTests::runner;
|
||||
|
||||
TEST_F(LogicTests, LogicalOperators) {
|
||||
runner.run_static_test(env, testCategory, "logand.static.gc", {"4\n"});
|
||||
runner.run_static_test(env, testCategory, "logior.static.gc", {"60\n"});
|
||||
runner.run_static_test(env, testCategory, "logxor.static.gc", {"56\n"});
|
||||
}
|
||||
|
||||
TEST_F(LogicTests, Comparison) {
|
||||
runner.run_static_test(env, testCategory, "signed-int-compare.static.gc", {"12\n"});
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct LoopRecurParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class LoopRecurTests : public testing::TestWithParam<LoopRecurParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "loop_recur";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread LoopRecurTests::runtime_thread;
|
||||
Compiler LoopRecurTests::compiler;
|
||||
GoalTest::CompilerTestRunner LoopRecurTests::runner;
|
||||
|
||||
TEST_F(LoopRecurTests, DoTimes) {
|
||||
runner.run_static_test(env, testCategory, "dotimes.static.gc", {"4950\n"});
|
||||
}
|
||||
|
||||
TEST_F(LoopRecurTests, Factorial) {
|
||||
runner.run_static_test(env, testCategory, "factorial-recursive.static.gc", {"3628800\n"});
|
||||
runner.run_static_test(env, testCategory, "factorial-iterative.static.gc", {"3628800\n"});
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct MacroParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class MacroTests : public testing::TestWithParam<MacroParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "macros";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread MacroTests::runtime_thread;
|
||||
Compiler MacroTests::compiler;
|
||||
GoalTest::CompilerTestRunner MacroTests::runner;
|
||||
|
||||
TEST_F(MacroTests, Defsmacro) {
|
||||
runner.run_static_test(env, testCategory, "defsmacro-defgmacro.static.gc", {"20\n"});
|
||||
}
|
||||
|
||||
TEST_F(MacroTests, Desfun) {
|
||||
runner.run_static_test(env, testCategory, "desfun.static.gc", {"4\n"});
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct MethodParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class MethodTests : public testing::TestWithParam<MethodParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "methods";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread MethodTests::runtime_thread;
|
||||
Compiler MethodTests::compiler;
|
||||
GoalTest::CompilerTestRunner MethodTests::runner;
|
||||
|
||||
TEST_F(MethodTests, DeReference) {
|
||||
runner.run_static_test(env, testCategory, "methods.static.gc", {"#t#t\n0\n"});
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct PointerParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class PointerTests : public testing::TestWithParam<PointerParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "pointers";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread PointerTests::runtime_thread;
|
||||
Compiler PointerTests::compiler;
|
||||
GoalTest::CompilerTestRunner PointerTests::runner;
|
||||
|
||||
TEST_F(PointerTests, DeReference) {
|
||||
runner.run_static_test(env, testCategory, "deref-simple.static.gc", {"structure\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(PointerTests, Pointers) {
|
||||
runner.run_static_test(env, testCategory, "pointers.static.gc", {"13\n"});
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct StringParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class StringTests : public testing::TestWithParam<StringParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "strings";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread StringTests::runtime_thread;
|
||||
Compiler StringTests::compiler;
|
||||
GoalTest::CompilerTestRunner StringTests::runner;
|
||||
|
||||
TEST_F(StringTests, Constants) {
|
||||
// TODO - runner.run_static_test(env, testCategory, "string-constant-1.static.gc");
|
||||
std::string expected = "\"test string!\"";
|
||||
runner.run_static_test(env, testCategory, "string-constant-2.static.gc", {expected},
|
||||
expected.size());
|
||||
}
|
||||
|
||||
TEST_F(StringTests, Symbols) {
|
||||
runner.run_static_test(env, testCategory, "quote-symbol.static.gc", {"banana\n0\n"});
|
||||
std::string expected = "test-string";
|
||||
runner.run_static_test(env, testCategory, "string-symbol.static.gc", {expected}, expected.size());
|
||||
}
|
||||
|
||||
TEST_F(StringTests, Formatting) {
|
||||
runner.run_static_test(env, testCategory, "format-reg-order.static.gc",
|
||||
{"test 1 2 3 4 5 6\n0\n"});
|
||||
}
|
||||
|
||||
// expected =
|
||||
// "test newline\nnewline\ntest tilde ~ \ntest A print boxed-string: \"boxed string!\"\ntest
|
||||
// A " "print symbol: a-symbol\ntest A make boxed object longer: \"srt\"!\ntest A
|
||||
// " "non-default pad: zzzzzzpad-me\ntest A shorten(4): a23~\ntest A don'tchange(4):
|
||||
// a234\ntest A " "shorten with pad(4): sho~\ntest A a few things \"one thing\" a-second
|
||||
// integer #<compiled " "function @ #x161544>\n";
|
||||
//
|
||||
// expected += "test S a string a-symbol another string!\n";
|
||||
// expected += "test C ) ]\n";
|
||||
// expected += "test P (no type) #<compiled function @ #x161544>\n";
|
||||
// expected += "test P (with type) 1447236\n";
|
||||
//
|
||||
// // todo, finish format testing.
|
||||
// runner.run_test_from_file("test-format.gc", {expected}, expected.size());
|
||||
@@ -1,62 +0,0 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "game/runtime.h"
|
||||
#include "goalc/listener/Listener.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "inja.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
#include <test/goalc/framework/test_runner.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
|
||||
struct SymbolParam {
|
||||
// TODO - Not Needed Yet
|
||||
};
|
||||
|
||||
class SymbolTests : public testing::TestWithParam<SymbolParam> {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
runtime_thread = std::thread((GoalTest::runtime_no_kernel));
|
||||
runner.c = &compiler;
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
compiler.shutdown_target();
|
||||
runtime_thread.join();
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
GoalTest::createDirIfAbsent(GoalTest::getTemplateDir(testCategory));
|
||||
GoalTest::createDirIfAbsent(GoalTest::getGeneratedDir(testCategory));
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::thread runtime_thread;
|
||||
static Compiler compiler;
|
||||
static GoalTest::CompilerTestRunner runner;
|
||||
|
||||
std::string testCategory = "symbols";
|
||||
inja::Environment env{GoalTest::getTemplateDir(testCategory),
|
||||
GoalTest::getGeneratedDir(testCategory)};
|
||||
};
|
||||
|
||||
std::thread SymbolTests::runtime_thread;
|
||||
Compiler SymbolTests::compiler;
|
||||
GoalTest::CompilerTestRunner SymbolTests::runner;
|
||||
|
||||
TEST_F(SymbolTests, GetSymbol) {
|
||||
runner.run_static_test(env, testCategory, "get-symbol-1.static.gc",
|
||||
{"1342756\n"}); // 0x147d24 in hex
|
||||
runner.run_static_test(env, testCategory, "get-symbol-2.static.gc",
|
||||
{"1342764\n"}); // 0x147d2c in hex
|
||||
}
|
||||
@@ -93,4 +93,52 @@ TEST_F(VariableTests, StackArrayAlignment) {
|
||||
|
||||
TEST_F(VariableTests, StackStructureAlignment) {
|
||||
runner.run_static_test(env, testCategory, "stack-structure-align.gc", {"1234\n"});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, GetSymbol) {
|
||||
runner.run_static_test(env, testCategory, "get-symbol-1.static.gc",
|
||||
{"1342756\n"}); // 0x147d24 in hex
|
||||
runner.run_static_test(env, testCategory, "get-symbol-2.static.gc",
|
||||
{"1342764\n"}); // 0x147d2c in hex
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Constants) {
|
||||
// TODO - runner.run_static_test(env, testCategory, "string-constant-1.static.gc");
|
||||
std::string expected = "\"test string!\"";
|
||||
runner.run_static_test(env, testCategory, "string-constant-2.static.gc", {expected},
|
||||
expected.size());
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Symbols) {
|
||||
runner.run_static_test(env, testCategory, "quote-symbol.static.gc", {"banana\n0\n"});
|
||||
std::string expected = "test-string";
|
||||
runner.run_static_test(env, testCategory, "string-symbol.static.gc", {expected}, expected.size());
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Formatting) {
|
||||
runner.run_static_test(env, testCategory, "format-reg-order.static.gc",
|
||||
{"test 1 2 3 4 5 6\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, DeReference) {
|
||||
runner.run_static_test(env, testCategory, "deref-simple.static.gc", {"structure\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(VariableTests, Pointers) {
|
||||
runner.run_static_test(env, testCategory, "pointers.static.gc", {"13\n"});
|
||||
}
|
||||
|
||||
// expected =
|
||||
// "test newline\nnewline\ntest tilde ~ \ntest A print boxed-string: \"boxed string!\"\ntest
|
||||
// A " "print symbol: a-symbol\ntest A make boxed object longer: \"srt\"!\ntest A
|
||||
// " "non-default pad: zzzzzzpad-me\ntest A shorten(4): a23~\ntest A don'tchange(4):
|
||||
// a234\ntest A " "shorten with pad(4): sho~\ntest A a few things \"one thing\" a-second
|
||||
// integer #<compiled " "function @ #x161544>\n";
|
||||
//
|
||||
// expected += "test S a string a-symbol another string!\n";
|
||||
// expected += "test C ) ]\n";
|
||||
// expected += "test P (no type) #<compiled function @ #x161544>\n";
|
||||
// expected += "test P (with type) 1447236\n";
|
||||
//
|
||||
// // todo, finish format testing.
|
||||
// runner.run_test_from_file("test-format.gc", {expected}, expected.size());
|
||||
|
||||
@@ -58,7 +58,7 @@ TEST(Listener, CheckConnectionStaysAlive) {
|
||||
}
|
||||
|
||||
EXPECT_TRUE(s.check_for_listener());
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2)); // sorry for making tests slow.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
EXPECT_TRUE(s.check_for_listener());
|
||||
EXPECT_TRUE(l.is_connected());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user