diff --git a/docs/docs/cli/test.md b/docs/docs/cli/test.md index a12b852cd..5efd23e4f 100644 --- a/docs/docs/cli/test.md +++ b/docs/docs/cli/test.md @@ -21,8 +21,6 @@ You can apply following options to the `test` subcommand: | Option | Long | Description | |--------------|----------------------|---------------------------------------------------------------------------------------------| -| `-a` | `--run-all` | Print compiler output for debugging. | -| `-t` | `--test` | Runs a single test case by its name | | `-d` | `--debug-output` | Print compiler output for debugging. | | `-cst` | `--dump-cst` | Dump CST as serialized string and SVG image | | `-ast` | `--dump-ast` | Dump AST as serialized string and SVG image | diff --git a/src/driver/Driver.cpp b/src/driver/Driver.cpp index e43fe0356..8e74981e5 100644 --- a/src/driver/Driver.cpp +++ b/src/driver/Driver.cpp @@ -40,7 +40,8 @@ void Driver::init() { // Prepare the installation path std::filesystem::path installPath = FileUtil::getSpiceBinDir(); installPath /= cliOptions.mainSourceFile.stem(); - std::filesystem::create_directories(installPath); + if (!dryRun) + std::filesystem::create_directories(installPath); #if OS_WINDOWS installPath.replace_extension("exe"); #endif @@ -50,7 +51,7 @@ void Driver::init() { cliOptions.outputPath = installPath; // If the binary should be uninstalled, check if the executable exists and uninstall it - if (shouldUninstall) { + if (shouldUninstall && !dryRun) { if (std::filesystem::exists(installPath) && std::filesystem::remove(installPath)) std::cout << "Successfully uninstalled.\n"; else @@ -107,7 +108,7 @@ void Driver::init() { * @param argv Argument vector * @return Return code */ -int Driver::parse(int argc, char **argv) { +int Driver::parse(int argc, const char *argv[]) { try { app.parse(argc, argv); return EXIT_SUCCESS; diff --git a/src/driver/Driver.h b/src/driver/Driver.h index 1154d0bcb..a858a9124 100644 --- a/src/driver/Driver.h +++ b/src/driver/Driver.h @@ -79,12 +79,13 @@ struct CliOptions { class Driver { public: // Constructors - explicit Driver() = default; + Driver() = default; + explicit Driver(bool dryRun) : dryRun(dryRun) {} Driver(const Driver &) = delete; // Public methods void init(); - int parse(int argc, char **argv); + int parse(int argc, const char *argv[]); void enrich(); void runBinary() const; @@ -94,6 +95,7 @@ class Driver { bool shouldInstall = false; bool shouldUninstall = false; bool shouldExecute = false; + bool dryRun = false; // For unit testing purposes private: // Private methods diff --git a/src/irgenerator/GenImplicit.cpp b/src/irgenerator/GenImplicit.cpp index 27f5d10b0..7f26d8982 100644 --- a/src/irgenerator/GenImplicit.cpp +++ b/src/irgenerator/GenImplicit.cpp @@ -81,7 +81,8 @@ void IRGenerator::generateCtorOrDtorCall(SymbolTableEntry *entry, const Function generateCtorOrDtorCall(structAddr, ctorOrDtor, args); } -void IRGenerator::generateCtorOrDtorCall(llvm::Value *structAddr, const Function *ctorOrDtor, const std::vector &args) const { +void IRGenerator::generateCtorOrDtorCall(llvm::Value *structAddr, const Function *ctorOrDtor, + const std::vector &args) const { assert(ctorOrDtor != nullptr); // Retrieve metadata for the function diff --git a/src/main.cpp b/src/main.cpp index 815f327e2..16b98c861 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,7 +63,7 @@ bool compileProject(CliOptions &cliOptions) { * @param argv Argument vector * @return Return code */ -int main(int argc, char **argv) { +int main(int argc, const char *argv[]) { // Initialize command line parser Driver driver; driver.init(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a56c3172..4504c3878 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,7 +9,8 @@ set(SOURCES util/TestUtil.cpp util/TestUtil.h unittest/UnitBlockAllocator.cpp - unittest/UnitCommonUtil.cpp) + unittest/UnitCommonUtil.cpp + unittest/UnitDriver.cpp) add_executable(spicetest ${SOURCES} ${ANTLR_Spice_CXX_OUTPUTS}) diff --git a/test/unittest/UnitDriver.cpp b/test/unittest/UnitDriver.cpp new file mode 100644 index 000000000..d2a679f2e --- /dev/null +++ b/test/unittest/UnitDriver.cpp @@ -0,0 +1,181 @@ +// Copyright (c) 2021-2024 ChilliBits. All rights reserved. + +#include + +#include + +namespace spice::testing { + +using namespace spice::compiler; + +TEST(DriverTest, TestBuildSubcommandMinimal) { + const char *argv[] = {"spice", "build", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_FALSE(driver.shouldExecute); + ASSERT_FALSE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_EQ(BuildMode::DEBUG, driver.cliOptions.buildMode); + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); +} + +TEST(DriverTest, TestBuildSubcommandComplex) { + const char *argv[] = {"spice", "b", "-d", "-ir", "-g", "-Os", "-m", "release", "-lto", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_FALSE(driver.shouldExecute); + ASSERT_FALSE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::Os, driver.cliOptions.optLevel); // -Os + ASSERT_EQ(BuildMode::RELEASE, driver.cliOptions.buildMode); // -m release + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); + ASSERT_TRUE(driver.cliOptions.generateDebugInfo); // -g + ASSERT_TRUE(driver.cliOptions.useLTO); // -lto + ASSERT_TRUE(driver.cliOptions.printDebugOutput); // -d + ASSERT_TRUE(driver.cliOptions.dumpSettings.dumpIR); // -ir +} + +TEST(DriverTest, TestRunSubcommandMinimal) { + const char *argv[] = {"spice", "run", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_TRUE(driver.shouldExecute); + ASSERT_TRUE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); +} + +TEST(DriverTest, TestRunSubcommandComplex) { + const char *argv[] = {"spice", "r", "-O2", "-j", "8", "-ast", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_TRUE(driver.shouldExecute); + ASSERT_TRUE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O2, driver.cliOptions.optLevel); // -O2 + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); + ASSERT_EQ(8, driver.cliOptions.compileJobCount); // -j 8 + ASSERT_TRUE(driver.cliOptions.dumpSettings.dumpAST); // -ast +} + +TEST(DriverTest, TestTestSubcommandMinimal) { + const char *argv[] = {"spice", "test", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_TRUE(driver.shouldExecute); + ASSERT_TRUE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_TRUE(driver.cliOptions.generateTestMain); + ASSERT_TRUE(driver.cliOptions.testMode); + ASSERT_TRUE(driver.cliOptions.noEntryFct); +} + +TEST(DriverTest, TestTestSubcommandComplex) { + const char *argv[] = {"spice", "t", "-s", "-cst", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_TRUE(driver.shouldExecute); + ASSERT_TRUE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_TRUE(driver.cliOptions.generateTestMain); + ASSERT_TRUE(driver.cliOptions.testMode); + ASSERT_TRUE(driver.cliOptions.noEntryFct); + ASSERT_TRUE(driver.cliOptions.dumpSettings.dumpCST); // -cst + ASSERT_TRUE(driver.cliOptions.dumpSettings.dumpAssembly); // -s +} + +TEST(DriverTest, TestInstallSubcommandMinimal) { + const char *argv[] = {"spice", "install", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_TRUE(driver.shouldCompile); + ASSERT_TRUE(driver.shouldInstall); + ASSERT_FALSE(driver.shouldUninstall); + ASSERT_FALSE(driver.shouldExecute); + ASSERT_FALSE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); +} + +TEST(DriverTest, TestUninstallSubcommandMinimal) { + const char *argv[] = {"spice", "uninstall", "../../media/test-project/test.spice"}; + const int argc = sizeof(argv) / sizeof(argv[0]); + Driver driver = Driver(true); + driver.init(); + ASSERT_EQ(EXIT_SUCCESS, driver.parse(argc, argv)); + driver.enrich(); + + ASSERT_FALSE(driver.shouldCompile); + ASSERT_FALSE(driver.shouldInstall); + ASSERT_TRUE(driver.shouldUninstall); + ASSERT_FALSE(driver.shouldExecute); + ASSERT_FALSE(driver.cliOptions.execute); + ASSERT_EQ("../../media/test-project/test.spice", driver.cliOptions.mainSourceFile.relative_path().string()); + ASSERT_EQ(OptLevel::O0, driver.cliOptions.optLevel); + ASSERT_FALSE(driver.cliOptions.generateTestMain); + ASSERT_FALSE(driver.cliOptions.testMode); + ASSERT_FALSE(driver.cliOptions.noEntryFct); +} + +} // namespace spice::testing