summaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-asm.cpp132
-rw-r--r--tests/test-cpp.cpp78
-rw-r--r--tests/test-cppbnf.cpp45
-rw-r--r--tests/test-elf.cpp71
-rw-r--r--tests/test-flowgraph.cpp50
-rw-r--r--tests/test-grammer.cpp65
-rw-r--r--tests/test-lexer.cpp39
-rw-r--r--tests/test-minicc.cpp8
8 files changed, 488 insertions, 0 deletions
diff --git a/tests/test-asm.cpp b/tests/test-asm.cpp
new file mode 100644
index 0000000..2d3afa0
--- /dev/null
+++ b/tests/test-asm.cpp
@@ -0,0 +1,132 @@
+#include "asm/chunk.h"
+#include "asm/assembler.h"
+#include "asm/segment.h"
+#include "asm/intel64/all_ops.h"
+
+#include "minicc.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace std::string_literals;
+namespace fs = std::filesystem;
+
+class AsmTest: public ::testing::Test
+{
+protected:
+ AsmTest() {
+ //debug = true;
+ }
+ ~AsmTest() {
+ }
+ void SetUp(){
+ }
+ void TearDown(){
+ }
+};
+
+TEST_F(AsmTest, Intel64_add) {
+ Segment segment;
+ Asm::Args args{{Asm::Args::Register32("eax"), Asm::Args::Immediate32(1)}};
+ segment.push_back(makeOp("add", args));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({0x05, 0x01, 0x00, 0x00, 0x00}));
+}
+
+TEST_F(AsmTest, Intel64_int_0) {
+ Segment segment;
+ Asm::Args args{{Asm::Args::Immediate8(0)}};
+ segment.push_back(makeOp("int", args));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>{0xCE});
+}
+
+TEST_F(AsmTest, Intel64_int_1) {
+ Segment segment;
+ Asm::Args args{{Asm::Args::Immediate8(1)}};
+ segment.push_back(makeOp("int", args));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>{0xF1});
+}
+
+TEST_F(AsmTest, Intel64_int_5) {
+ Segment segment;
+ Asm::Args args{{Asm::Args::Immediate8(5)}};
+ segment.push_back(makeOp("int", args));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({0xCD, 0x05}));
+}
+
+TEST_F(AsmTest, Intel64_nop) {
+ Segment segment;
+ segment.push_back(makeOp("nop"));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>{0x90});
+}
+
+TEST_F(AsmTest, Intel64_ret) {
+ Segment segment;
+ segment.push_back(makeOp("ret"));
+
+ ASSERT_EQ(segment.size(), 1);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>{0xC3});
+}
+
+TEST_F(AsmTest, Intel64_multiple) {
+ Segment segment;
+
+ segment.push_back(makeOp("nop"));
+ Asm::Args args0{{Asm::Args::Immediate8(5)}};
+ segment.push_back(makeOp("int", args0));
+ segment.push_back(makeOp("ret"));
+ segment.push_back(makeLabel("data1"));
+ segment.push_back(makeOp("ret"));
+ Asm::Args args1{{Asm::Args::Label("data1")}};
+ segment.push_back(makeOp("jmp", args1));
+ segment.push_back(makeData({1, 2, 3}));
+
+ segment.insertAddresses();
+
+ ASSERT_EQ(segment.size(), 7);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>(
+ {
+ 0x90, // nop
+ 0xCD, 0x05, // int 5
+ 0xC3, // ret
+ // data1:
+ 0xC3, // ret
+ 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, // jmp data1
+ 0x01, 0x02, 0x03 // data
+ }));
+
+ segment.optimize();
+
+ ASSERT_EQ(segment.size(), 7);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>(
+ {
+ 0x90, // nop
+ 0xCD, 0x05, // int 5
+ 0xC3, // ret
+ // data1:
+ 0xC3, // ret
+ 0xEB, 0xFF, // jmp data1
+ 0x01, 0x02, 0x03 // data
+ }));
+}
diff --git a/tests/test-cpp.cpp b/tests/test-cpp.cpp
new file mode 100644
index 0000000..513a3a5
--- /dev/null
+++ b/tests/test-cpp.cpp
@@ -0,0 +1,78 @@
+#include "bnf.h"
+#include "cpp.h"
+#include "cppbnf.h"
+#include "lexer.h"
+#include "grammer.h"
+#include "minicc.h"
+#include "debug.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+class CppTest: public ::testing::Test
+{
+protected:
+ CppTest() {
+ debug = true;
+ }
+ ~CppTest() {
+ }
+};
+
+TEST_F(CppTest, preprocessing_tokenize) {
+ CPP cpp;
+ auto pp_tokens = cpp.preprocessing_tokenize("int main() { return 1; }");
+
+ ASSERT_EQ(pp_tokens.size(), 9);
+
+ auto tokens = cpp.tokens_from_pptokens(pp_tokens);
+
+ ASSERT_EQ(tokens.size(), 9);
+
+ auto nodes = cpp.analysis(tokens);
+
+ ASSERT_EQ(nodes.size(), 60/*44*/);
+}
+
+TEST_F(CppTest, preprocessing_tokenize_compile_error) {
+ CPP cpp;
+ auto ppTree = cpp.preprocessing_tokenize("in ma");
+
+ auto tokens = cpp.tokens_from_pptokens(ppTree);
+
+ ASSERT_EQ(tokens.size(), 2);
+
+ try {
+ auto nodes = cpp.analysis(tokens);
+ } catch (const std::exception& ex) {
+ EXPECT_EQ(ex.what(), "Compile error"s);
+ return;
+ }
+
+ FAIL() << "Exception expected";
+}
+
+TEST(Cpp, compile) {
+ CPP cpp;
+
+ cpp.compile("int main() { return 1 + 1; }");
+}
+
+TEST(Cpp, compile_2_times) {
+ CPP cpp;
+
+ cpp.compile("int main() { return (1 + 2) * 2; }");
+ cpp.compile("int main() { return 1 + 2 * 2; }");
+}
+
diff --git a/tests/test-cppbnf.cpp b/tests/test-cppbnf.cpp
new file mode 100644
index 0000000..e365574
--- /dev/null
+++ b/tests/test-cppbnf.cpp
@@ -0,0 +1,45 @@
+#include "bnf.h"
+#include "cpp.h"
+#include "cppbnf.h"
+#include "lexer.h"
+#include "grammer.h"
+#include "minicc.h"
+#include "debug.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+class CppBnfTest: public ::testing::Test
+{
+protected:
+ CppBnfTest() {
+ //debug = true;
+ }
+ ~CppBnfTest() {
+ }
+};
+
+TEST_F(CppBnfTest, LexicalBnf) {
+ auto bnf = SubBNF(CPPBNF::GetCppBNFLex(), "preprocessing-token");
+
+ EXPECT_TRUE(CPPBNF::valid(bnf));
+ EXPECT_TRUE(CPPBNF::validLex(bnf));
+}
+
+TEST_F(CppBnfTest, GrammarBnf) {
+ auto bnf = SubBNF(CPPBNF::GetCppBNFGram(), "translation-unit");
+
+ EXPECT_TRUE(CPPBNF::valid(bnf));
+}
+
diff --git a/tests/test-elf.cpp b/tests/test-elf.cpp
new file mode 100644
index 0000000..0bf1d42
--- /dev/null
+++ b/tests/test-elf.cpp
@@ -0,0 +1,71 @@
+#include "elf.h"
+#include "minicc.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace std::string_literals;
+namespace fs = std::filesystem;
+
+class ElfTest: public ::testing::Test
+{
+protected:
+ ElfTest() {
+ //debug = true;
+ }
+ ~ElfTest() {
+ }
+ fs::path TempFilename(){return "tempfile.txt";}
+
+ void SetUp(){
+ std::error_code ec;
+ fs::remove(TempFilename(), ec);
+ }
+ void TearDown(){
+ std::error_code ec;
+ fs::remove(TempFilename(), ec);
+ }
+};
+
+#if 0
+TEST_F(ElfTest, read) {
+}
+#endif
+
+TEST_F(ElfTest, write_code) {
+ Elf::Write(TempFilename(),
+ {
+ 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, // mov $0x3c,%rax # syscall 60
+ 0x48, 0x31, 0xff, // xor %rdi,%rdi # exit code 0
+ 0x0f, 0x05, // syscall
+ }, {});
+
+ ASSERT_TRUE(fs::exists(TempFilename()));
+ ASSERT_GT(fs::file_size(TempFilename()), 0);
+}
+
+TEST_F(ElfTest, write_code_data) {
+ Elf::Write(TempFilename(),
+ {
+ 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, // mov $0x3c,%rax # syscall 60
+ 0x48, 0x8b, 0x3c, 0x25, 0x00, 0x20, 0x40, // mov 0x402000,%rdi # use value from data segment as exit code
+ 0,
+ 0x0f, 0x05, // syscall
+ },
+ {1, 0, 0, 0, 0, 0, 0, 0});
+
+ ASSERT_TRUE(fs::exists(TempFilename()));
+ ASSERT_GT(fs::file_size(TempFilename()), 0);
+}
diff --git a/tests/test-flowgraph.cpp b/tests/test-flowgraph.cpp
new file mode 100644
index 0000000..132af4b
--- /dev/null
+++ b/tests/test-flowgraph.cpp
@@ -0,0 +1,50 @@
+#include "flowgraph/data.h"
+#include "flowgraph/graph.h"
+#include "flowgraph/node.h"
+#include "flowgraph/storage.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace std::string_literals;
+namespace fs = std::filesystem;
+
+using namespace FlowGraph;
+
+class FlowGraphTest: public ::testing::Test
+{
+protected:
+ FlowGraphTest() {
+ //debug = true;
+ }
+ ~FlowGraphTest() {
+ }
+ void SetUp(){
+ }
+ void TearDown(){
+ }
+};
+
+TEST_F(FlowGraphTest, build_graph) {
+ Graph graph;
+
+ Data pointer{ MakeLocalPointer("malloc1") };
+ Data size{ MakeLocalSize("size1") };
+ std::shared_ptr<Node> malloc1 {std::make_shared<AllocateDynamic>(pointer, size) };
+ std::shared_ptr<Node> free1{ std::make_shared<DeallocateDynamic>(pointer) };
+
+ graph.push_back(malloc1);
+ graph.push_back(free1);
+}
diff --git a/tests/test-grammer.cpp b/tests/test-grammer.cpp
new file mode 100644
index 0000000..1734da2
--- /dev/null
+++ b/tests/test-grammer.cpp
@@ -0,0 +1,65 @@
+#include "bnf.h"
+#include "cpp.h"
+#include "cppbnf.h"
+#include "lexer.h"
+#include "grammer.h"
+#include "minicc.h"
+#include "debug.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace std::string_literals;
+
+class GrammerTest: public ::testing::Test
+{
+protected:
+ GrammerTest() {
+ //debug = true;
+ }
+ ~GrammerTest() {
+ }
+
+ // Accessors for friend
+ size_t minimumSymbolsNeeded(Gram::Compiler& compiler, std::vector<std::string> list) {
+ return compiler.minimumSymbolsNeeded(list);
+ }
+ size_t minimumSymbolsNeeded(Gram::Compiler& compiler, std::string s) {
+ return compiler.minimumSymbolsNeeded(s);
+ }
+};
+
+TEST_F(GrammerTest, minimumSymbolsNeeded) {
+ auto bnf = SubBNF(CPPBNF::GetCppBNFGram(), "translation-unit");
+
+ Gram::Compiler compiler(bnf, "translation-unit");
+
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, std::vector<std::string>{}), 0);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "translation-unit"), 0);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "logical-or-expression"), 1);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "assignment-expression"), 1);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "declaration"), 1);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "block-declaration"), 3);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "simple-declaration"), 2);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "asm-declaration"), 5);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "namespace-alias-definition"), 5);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "using-declaration"), 4);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "using-enum-declaration"), 4);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "using-directive"), 4);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "static_assert-declaration"), 5);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "alias-declaration"), 7);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "opaque-enum-declaration"), 3);
+ EXPECT_EQ(minimumSymbolsNeeded(compiler, "function-definition"), 4);
+}
+
diff --git a/tests/test-lexer.cpp b/tests/test-lexer.cpp
new file mode 100644
index 0000000..23983f1
--- /dev/null
+++ b/tests/test-lexer.cpp
@@ -0,0 +1,39 @@
+#include "bnf.h"
+#include "cpp.h"
+#include "cppbnf.h"
+#include "lexer.h"
+#include "grammer.h"
+#include "minicc.h"
+#include "debug.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <algorithm>
+#include <cctype>
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+class LexerTest: public ::testing::Test {
+protected:
+ LexerTest(){
+ debug = false;
+ }
+ ~LexerTest() override {}
+};
+
+TEST_F(LexerTest, Lex) {
+ auto bnf{SubBNF(CPPBNF::GetCppBNFLex(), "preprocessing-token")};
+
+ Lex::Lexer lexer(bnf, "preprocessing-token");
+
+ std::vector<Token> tokens{lexer.Lex("int main() { return 1; }")};
+
+ ASSERT_EQ(tokens.size(), 9);
+}
diff --git a/tests/test-minicc.cpp b/tests/test-minicc.cpp
new file mode 100644
index 0000000..baf8b3f
--- /dev/null
+++ b/tests/test-minicc.cpp
@@ -0,0 +1,8 @@
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleMock(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+