This commit is contained in:
2026-02-04 19:37:03 +08:00
parent 5aa4efede7
commit 36d273e09f
11 changed files with 335 additions and 93 deletions

View File

@@ -0,0 +1,59 @@
#include "camellya.h"
#include "exceptions.h"
#include <catch2/catch_all.hpp>
#include <cmath>
using namespace camellya;
// Simple Vector3D wrapper for testing
class Vector3DValue : public NativeValue {
public:
double x, y, z;
Vector3DValue(double x, double y, double z) : NativeValue("Vector3D"), x(x), y(y), z(z) {}
std::string to_string() const override {
return "Vector3D(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")";
}
ValuePtr clone() const override {
return std::make_shared<Vector3DValue>(x, y, z);
}
};
TEST_CASE("Generic built-in class (Vector3D) test", "[generic]") {
Camellya c;
// 1. Create the ClassValue for Vector3D
auto v3d_klass = std::make_shared<ClassValue>("Vector3D");
// 2. Add a native method 'length'
v3d_klass->add_method("length", std::make_shared<FunctionValue>("length",
[](const std::vector<ValuePtr>& args) -> ValuePtr {
if (args.size() != 1) throw RuntimeError("Vector3D.length() expects 0 arguments.");
auto vec = std::dynamic_pointer_cast<Vector3DValue>(args[0]);
double len = std::sqrt(vec->x * vec->x + vec->y * vec->y + vec->z * vec->z);
return std::make_shared<NumberValue>(len);
}));
// 3. Register it as a built-in class for type "Vector3D"
c.register_builtin_class("Vector3D", v3d_klass);
// 4. Register a factory function to create Vector3D instances from script
c.register_function("Vector3D", [](const std::vector<ValuePtr>& args) -> ValuePtr {
if (args.size() != 3) throw RuntimeError("Vector3D() expects 3 arguments.");
double x = std::dynamic_pointer_cast<NumberValue>(args[0])->value;
double y = std::dynamic_pointer_cast<NumberValue>(args[1])->value;
double z = std::dynamic_pointer_cast<NumberValue>(args[2])->value;
return std::make_shared<Vector3DValue>(x, y, z);
});
SECTION("vector3d methods") {
REQUIRE(c.do_string(R"(
var v = Vector3D(3, 4, 0);
var len = v.length();
)"));
auto len = c.get_global("len");
REQUIRE(std::dynamic_pointer_cast<NumberValue>(len)->value == 5.0);
}
}

18
tests/test_list.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include "camellya.h"
#include <catch2/catch_all.hpp>
using namespace camellya;
TEST_CASE("Basic List test", "[list]") {
Camellya c;
SECTION("len function") {
REQUIRE(c.do_string(R"(
var arr = [1, 2, 3, 4];
var size = len(arr);
arr.push(5);
size = arr.len();
)"));
auto size = c.get_global("size");
REQUIRE(std::dynamic_pointer_cast<NumberValue>(size)->value == 5.0);
}
}

View File

@@ -0,0 +1,32 @@
#include "camellya.h"
#include <catch2/catch_all.hpp>
using namespace camellya;
TEST_CASE("Map built-in class test", "[map]") {
Camellya c;
SECTION("map methods") {
REQUIRE(c.do_string(R"(
var m = {"a": 1, "b": 2};
var s1 = m.len();
m.set("c", 3);
var s2 = m.len();
var has_a = m.has("a");
var has_z = m.has("z");
var val_b = m.get("b");
)"));
auto s1 = c.get_global("s1");
auto s2 = c.get_global("s2");
auto has_a = c.get_global("has_a");
auto has_z = c.get_global("has_z");
auto val_b = c.get_global("val_b");
REQUIRE(std::dynamic_pointer_cast<NumberValue>(s1)->value == 2.0);
REQUIRE(std::dynamic_pointer_cast<NumberValue>(s2)->value == 3.0);
REQUIRE(std::dynamic_pointer_cast<BoolValue>(has_a)->value == true);
REQUIRE(std::dynamic_pointer_cast<BoolValue>(has_z)->value == false);
REQUIRE(std::dynamic_pointer_cast<NumberValue>(val_b)->value == 2.0);
}
}