feat(tests): added parenting tests
This commit is contained in:
parent
47ad44bb83
commit
e6a1e6f57b
6 changed files with 138 additions and 16 deletions
|
|
@ -7,6 +7,11 @@ class NoSuchInstance : public Error {
|
|||
inline NoSuchInstance(std::string className) : Error("NoSuchInstance", "Cannot create instance of unknown type " + className) {}
|
||||
};
|
||||
|
||||
class NotCreatableInstance : public Error {
|
||||
public:
|
||||
inline NotCreatableInstance(std::string className) : Error("NotCreatableInstance", "Instance class " + className + " is not creatable") {}
|
||||
};
|
||||
|
||||
class NoSuchService : public Error {
|
||||
public:
|
||||
inline NoSuchService(std::string className) : Error("NoSuchService", "Unknown service type " + className) {}
|
||||
|
|
|
|||
|
|
@ -524,4 +524,17 @@ std::string Instance::GetFullName() {
|
|||
}
|
||||
|
||||
return currentName;
|
||||
}
|
||||
|
||||
result<std::shared_ptr<Instance>, NoSuchInstance, NotCreatableInstance> Instance::New(std::string className) {
|
||||
const InstanceType* type = INSTANCE_MAP[className];
|
||||
|
||||
if (type == nullptr) {
|
||||
return NoSuchInstance(className);
|
||||
}
|
||||
|
||||
if (type->flags & (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE) || type->constructor == nullptr)
|
||||
return NotCreatableInstance(className);
|
||||
|
||||
return type->constructor();
|
||||
}
|
||||
|
|
@ -114,6 +114,9 @@ public:
|
|||
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
||||
nullable std::shared_ptr<Instance> FindFirstChild(std::string);
|
||||
std::string GetFullName();
|
||||
|
||||
// Dynamically create an instance
|
||||
static result<std::shared_ptr<Instance>, NoSuchInstance, NotCreatableInstance> New(std::string className);
|
||||
|
||||
// Properties
|
||||
result<Variant, MemberNotFound> GetProperty(std::string name);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ add_executable(obtest
|
|||
src/lua/luasched.cpp
|
||||
src/lua/luasignal.cpp
|
||||
src/lua/luageneric.cpp
|
||||
src/objectmodel/basic.cpp
|
||||
)
|
||||
target_link_libraries(obtest PRIVATE openblocks Catch2::Catch2WithMain)
|
||||
target_include_directories(obtest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ public:
|
|||
void testRunStarting(Catch::TestRunInfo const&) override {
|
||||
// TODO: Make physicsInit optional in headless environments
|
||||
physicsInit();
|
||||
|
||||
gTestModel = DataModel::New();
|
||||
gTestModel->Init(true);
|
||||
Logger::initTest(&testLogOutput);
|
||||
}
|
||||
|
||||
|
|
@ -33,21 +30,12 @@ public:
|
|||
void testCasePartialStarting(const Catch::TestCaseInfo &testInfo, uint64_t partNumber) override {
|
||||
// Clear the log output prior to each test
|
||||
testLogOutput.str("");
|
||||
|
||||
gTestModel = DataModel::New();
|
||||
gTestModel->Init(true);
|
||||
}
|
||||
|
||||
void testCasePartialEnded(const Catch::TestCaseStats &testCaseStats, uint64_t partNumber) override {
|
||||
auto ctx = gTestModel->GetService<ScriptContext>();
|
||||
ctx->DebugClearSleepingThreads();
|
||||
|
||||
// Clean up remaining scripts from ServerScriptService
|
||||
for (auto& obj : gTestModel->GetService<ServerScriptService>()->GetChildren()) {
|
||||
obj->Destroy();
|
||||
}
|
||||
|
||||
// Also clear workspace
|
||||
for (auto& obj : gTestModel->GetService<Workspace>()->GetChildren()) {
|
||||
obj->Destroy();
|
||||
}
|
||||
void testCasePartialEnded(const Catch::TestCaseStats &testCaseStats, uint64_t partNumber) override {
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
112
tests/src/objectmodel/basic.cpp
Normal file
112
tests/src/objectmodel/basic.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// Basic operations such as instantiation, re-parenting, and destruction
|
||||
|
||||
#include "common.h"
|
||||
#include "error/instance.h"
|
||||
#include "objects/model.h"
|
||||
#include "objects/part/part.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
static auto& m = gDataModel;
|
||||
|
||||
TEST_CASE("Construction") {
|
||||
auto folder = Model::New();
|
||||
m->AddChild(folder);
|
||||
|
||||
SECTION("Constructing container") {
|
||||
bool found = false;
|
||||
for (auto& obj : m->GetChildren()) {
|
||||
if (obj == folder) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(found);
|
||||
REQUIRE(folder->GetParent() != nullptr);
|
||||
REQUIRE(folder->GetParent() == m);
|
||||
}
|
||||
|
||||
SECTION("Constructing Part") {
|
||||
auto part = Part::New();
|
||||
folder->AddChild(part);
|
||||
|
||||
REQUIRE(folder->GetChildren().size() == 1);
|
||||
REQUIRE(folder->GetChildren()[0] == part);
|
||||
REQUIRE(part->GetParent() != nullptr);
|
||||
REQUIRE(part->GetParent() == folder);
|
||||
}
|
||||
|
||||
SECTION("Dynamic construction of part") {
|
||||
auto result = Instance::New("Part");
|
||||
REQUIRE(result.isSuccess());
|
||||
}
|
||||
|
||||
SECTION("Invalid construction of service") {
|
||||
auto result = Instance::New("Workspace");
|
||||
REQUIRE(result.isError());
|
||||
REQUIRE(std::holds_alternative<NotCreatableInstance>(result.error().value()));
|
||||
}
|
||||
|
||||
SECTION("Invalid construction of nonexistent type") {
|
||||
auto result = Instance::New("__INVALID");
|
||||
REQUIRE(result.isError());
|
||||
REQUIRE(std::holds_alternative<NoSuchInstance>(result.error().value()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Parenting") {
|
||||
auto folder = Model::New();
|
||||
m->AddChild(folder);
|
||||
|
||||
SECTION("Reparent part to another folder") {
|
||||
auto folder2 = Model::New();
|
||||
m->AddChild(folder2);
|
||||
|
||||
auto part = Part::New();
|
||||
folder->AddChild(part);
|
||||
|
||||
// Verify initial folder
|
||||
REQUIRE(folder->GetChildren().size() == 1);
|
||||
REQUIRE(folder->GetChildren()[0] == part);
|
||||
REQUIRE(part->GetParent() != nullptr);
|
||||
REQUIRE(part->GetParent() == folder);
|
||||
|
||||
folder2->AddChild(part); // AddChild just internally calls SetParent, so it should automatically take care of cleanup
|
||||
|
||||
// Verify new folder
|
||||
REQUIRE(folder->GetChildren().size() == 0);
|
||||
REQUIRE(folder2->GetChildren().size() == 1);
|
||||
REQUIRE(folder2->GetChildren()[0] == part);
|
||||
REQUIRE(part->GetParent() != nullptr);
|
||||
REQUIRE(part->GetParent() == folder2);
|
||||
}
|
||||
|
||||
SECTION("Unparenting") {
|
||||
auto part = Part::New();
|
||||
folder->AddChild(part);
|
||||
|
||||
part->SetParent(nullptr);
|
||||
REQUIRE(folder->GetChildren().size() == 0);
|
||||
REQUIRE(part->GetParent() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("Nested reparent") {
|
||||
auto folder2 = Model::New();
|
||||
m->AddChild(folder2);
|
||||
|
||||
auto part = Part::New();
|
||||
folder->AddChild(part);
|
||||
auto part2 = Part::New();
|
||||
part->AddChild(part2);
|
||||
|
||||
REQUIRE(part->GetChildren().size() == 1);
|
||||
REQUIRE(part->GetChildren()[0] == part2);
|
||||
REQUIRE(part2->GetParent() == part);
|
||||
|
||||
folder2->AddChild(part); // AddChild just internally calls SetParent, so it should automatically take care of cleanup
|
||||
|
||||
// Make sure nothing changed
|
||||
REQUIRE(part->GetChildren().size() == 1);
|
||||
REQUIRE(part->GetChildren()[0] == part2);
|
||||
REQUIRE(part2->GetParent() == part);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue