diff --git a/include/scratchcpp/virtualmachine.h b/include/scratchcpp/virtualmachine.h index efacb16a..0e262cff 100644 --- a/include/scratchcpp/virtualmachine.h +++ b/include/scratchcpp/virtualmachine.h @@ -105,7 +105,11 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine void setBytecode(unsigned int *code); + unsigned int **procedures() const; + const BlockFunc *functions() const; const Value *constValues() const; + Value **variables() const; + List **lists() const; unsigned int *bytecode() const; diff --git a/src/engine/script_p.h b/src/engine/script_p.h index 5a321c6b..9a311eef 100644 --- a/src/engine/script_p.h +++ b/src/engine/script_p.h @@ -19,16 +19,16 @@ struct ScriptPrivate ScriptPrivate(Target *target, IEngine *engine); ScriptPrivate(const ScriptPrivate &) = delete; - unsigned int *bytecode; + unsigned int *bytecode = nullptr; std::vector bytecodeVector; - Target *target; - IEngine *engine; + Target *target = nullptr; + IEngine *engine = nullptr; unsigned int **procedures = nullptr; std::vector proceduresVector; - BlockFunc *functions; + BlockFunc *functions = nullptr; std::vector functionsVector; const Value *constValues = nullptr; diff --git a/src/engine/virtualmachine.cpp b/src/engine/virtualmachine.cpp index 68b7c945..dc9b3c58 100644 --- a/src/engine/virtualmachine.cpp +++ b/src/engine/virtualmachine.cpp @@ -57,12 +57,36 @@ void VirtualMachine::setBytecode(unsigned int *code) impl->pos = code; } +/*! Returns the array of procedures. */ +unsigned int **VirtualMachine::procedures() const +{ + return impl->procedures; +} + +/*! Returns the array of functions (block implementation function pointers). */ +const BlockFunc *VirtualMachine::functions() const +{ + return impl->functions; +} + /*! Returns the array of constant values. */ const Value *VirtualMachine::constValues() const { return impl->constValues; } +/*! Returns the array of Value pointers of variables. */ +Value **VirtualMachine::variables() const +{ + return impl->variables; +} + +/*! Returns the array of lists. */ +List **VirtualMachine::lists() const +{ + return impl->lists; +} + /*! Returns the bytecode array. */ unsigned int *VirtualMachine::bytecode() const { diff --git a/src/engine/virtualmachine_p.h b/src/engine/virtualmachine_p.h index 6d17b163..af00076b 100644 --- a/src/engine/virtualmachine_p.h +++ b/src/engine/virtualmachine_p.h @@ -56,7 +56,7 @@ struct VirtualMachinePrivate bool updatePos = false; unsigned int **procedures = nullptr; - BlockFunc *functions; + BlockFunc *functions = nullptr; const Value *constValues = nullptr; Value **variables = nullptr; List **lists = nullptr; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 04b734ab..41f75403 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,3 +25,4 @@ add_subdirectory(target_interfaces) add_subdirectory(blocks) add_subdirectory(scratchconfiguration) add_subdirectory(assets) +add_subdirectory(script) diff --git a/test/script/CMakeLists.txt b/test/script/CMakeLists.txt new file mode 100644 index 00000000..35186984 --- /dev/null +++ b/test/script/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable( + script_test + script_test.cpp +) + +target_link_libraries( + script_test + GTest::gtest_main + GTest::gmock_main + scratchcpp + scratchcpp_mocks +) + +gtest_discover_tests(script_test) diff --git a/test/script/script_test.cpp b/test/script/script_test.cpp new file mode 100644 index 00000000..36ac6cc1 --- /dev/null +++ b/test/script/script_test.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +#include "../common.h" + +using namespace libscratchcpp; + +class ScriptTest : public testing::Test +{ + public: + Target m_target; + EngineMock m_engine; +}; + +TEST_F(ScriptTest, Bytecode) +{ + Script script(nullptr, nullptr); + ASSERT_EQ(script.bytecode(), nullptr); + ASSERT_TRUE(script.bytecodeVector().empty()); + + script.setBytecode({ vm::OP_START, vm::OP_HALT }); + ASSERT_EQ(script.bytecode()[0], vm::OP_START); + ASSERT_EQ(script.bytecode()[1], vm::OP_HALT); + ASSERT_EQ(script.bytecodeVector(), std::vector({ vm::OP_START, vm::OP_HALT })); +} + +unsigned int testFunction(VirtualMachine *) +{ + return 0; +} + +TEST_F(ScriptTest, Start) +{ + static std::vector bytecode = { vm::OP_START, vm::OP_HALT }; + static std::vector procedures = { bytecode.data() }; + static std::vector functions = { &testFunction }; + static std::vector constValues = { "test" }; + + std::unique_ptr var = std::make_unique(); + static std::vector variables = { var.get() }; + + std::unique_ptr list = std::make_unique("", ""); + static std::vector lists = { list.get() }; + + Script script1(nullptr, nullptr); + + std::shared_ptr vm = script1.start(); + ASSERT_TRUE(vm); + ASSERT_EQ(vm->target(), nullptr); + ASSERT_EQ(vm->engine(), nullptr); + ASSERT_EQ(vm->bytecode(), nullptr); + ASSERT_EQ(vm->procedures(), nullptr); + ASSERT_EQ(vm->functions(), nullptr); + ASSERT_EQ(vm->constValues(), nullptr); + ASSERT_EQ(vm->variables(), nullptr); + ASSERT_EQ(vm->lists(), nullptr); + + Script script2(&m_target, &m_engine); + + vm = script2.start(); + ASSERT_TRUE(vm); + ASSERT_EQ(vm->target(), &m_target); + ASSERT_EQ(vm->engine(), &m_engine); + + Script script3(&m_target, &m_engine); + script3.setBytecode(bytecode); + script3.setProcedures(procedures); + script3.setFunctions(functions); + script3.setConstValues(constValues); + script3.setVariables(variables); + script3.setLists(lists); + + vm = script3.start(); + ASSERT_TRUE(vm); + ASSERT_EQ(vm->bytecode()[0], bytecode[0]); + ASSERT_EQ(vm->procedures()[0], procedures[0]); + ASSERT_EQ(vm->functions()[0], functions[0]); + ASSERT_EQ(vm->constValues()[0].toString(), constValues[0].toString()); + ASSERT_EQ(vm->variables()[0], variables[0]); + ASSERT_EQ(vm->lists()[0], lists[0]); +} diff --git a/test/virtual_machine/virtual_machine_test.cpp b/test/virtual_machine/virtual_machine_test.cpp index d9a0b027..8de089fd 100644 --- a/test/virtual_machine/virtual_machine_test.cpp +++ b/test/virtual_machine/virtual_machine_test.cpp @@ -25,6 +25,17 @@ TEST(VirtualMachineTest, Constructors) ASSERT_EQ(vm2.script(), &script); } +TEST(VirtualMachineTest, Procedures) +{ + static unsigned int procedure[] = { OP_START, OP_HALT }; + static unsigned int *procedures[] = { procedure }; + + VirtualMachine vm; + ASSERT_EQ(vm.procedures(), nullptr); + vm.setProcedures(procedures); + ASSERT_EQ(vm.procedures(), procedures); +} + TEST(VirtualMachineTest, ConstValues) { static Value constValues[] = { "test1", "test2" }; @@ -35,6 +46,28 @@ TEST(VirtualMachineTest, ConstValues) ASSERT_EQ(vm.constValues(), constValues); } +TEST(VirtualMachineTest, Variables) +{ + Value var; + Value *variables[] = { &var }; + + VirtualMachine vm; + ASSERT_EQ(vm.variables(), nullptr); + vm.setVariables(variables); + ASSERT_EQ(vm.variables(), variables); +} + +TEST(VirtualMachineTest, Lists) +{ + List list("", ""); + List *lists[] = { &list }; + + VirtualMachine vm; + ASSERT_EQ(vm.lists(), nullptr); + vm.setLists(lists); + ASSERT_EQ(vm.lists(), lists); +} + TEST(VirtualMachineTest, Bytecode) { static unsigned int bytecode[] = { OP_START, OP_HALT }; @@ -1240,7 +1273,17 @@ TEST(VirtualMachineTest, OP_EXEC) } } -TEST(VirtualMachineTest, Procedures) +TEST(VirtualMachineTest, Functions) +{ + static BlockFunc functions[] = { &testFunction1, &testFunction2 }; + + VirtualMachine vm; + ASSERT_EQ(vm.functions(), nullptr); + vm.setFunctions(functions); + ASSERT_EQ(vm.functions(), functions); +} + +TEST(VirtualMachineTest, RunProcedures) { static unsigned int bytecode[] = { OP_START, OP_INIT_PROCEDURE, OP_CONST, 0, OP_ADD_ARG, OP_CONST, 1, OP_ADD_ARG, OP_CALL_PROCEDURE, 0, OP_NULL, OP_EXEC, 0, OP_INIT_PROCEDURE, OP_CALL_PROCEDURE, 1, OP_HALT