Files
mrubypp/test/test_class.cpp
zekexiao 45bf416230
Some checks failed
ubuntu / Explore-Gitea-Actions (push) Failing after 4m51s
add more test
2025-12-09 18:15:14 +08:00

222 lines
5.4 KiB
C++

//
// Created by ZekeXiao on 2025/10/18.
//
#include <catch2/catch_all.hpp>
#include <mrubypp/bind_class.h>
#include <mrubypp/engine.h>
class Point {
public:
Point(int x, int y) : x_(x), y_(y) {}
void set_values(int x, int y) {
x_ = x;
y_ = y;
}
int get_x() const { return x_; }
void set_x(int x) { x_ = x; }
int get_y() const { return y_; }
void set_y(int y) { y_ = y; }
void add(const Point &other) {
this->x_ += other.x_;
this->y_ += other.y_;
}
static int none() { return 1; }
private:
int x_;
int y_;
};
static mrb_value point_native_init(mrb_state* mrb, mrb_value self) {
auto count = mrb_get_argc(mrb);
Point* p = nullptr;
if (count == 0)
{
p = new Point(0, 0);
} else if (count == 1) {
auto argv = mrb_get_argv(mrb);
p = new Point(mrb_as_float(mrb, argv[0]), 0);
} else if (count == 2) {
auto argv = mrb_get_argv(mrb);
p = new Point(mrb_as_float(mrb, argv[0]), mrb_as_float(mrb, argv[1]));
} else {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Point wrong number of arguments");
}
DATA_PTR(self) = p;
DATA_TYPE(self) = &mrubypp::bind_class<Point>::data_type;
return self;
}
static mrb_value point_native_div(mrb_state *mrb, mrb_value self) {
auto point = mrubypp::bind_class<Point>::get_this(mrb, self);
auto divisor = mrubypp::converter<int>::from_mrb(mrb, mrb_get_arg1(mrb));
point->set_x(point->get_x() / divisor);
point->set_y(point->get_y() / divisor);
return self;
}
template <> struct mrubypp::converter<Point> {
static mrb_value to_mrb(mrb_state *mrb, const Point &var) {
mrb_value obj = mrb_obj_value(
mrb_data_object_alloc(mrb, mrb->object_class, new Point(var),
&mrubypp::bind_class<Point>::data_type));
return obj;
}
static Point from_mrb(mrb_state *mrb, mrb_value value) {
if (mrb_type(value) == MRB_TT_DATA) {
Point *point = static_cast<Point *>(DATA_PTR(value));
return *point;
}
return Point(0, 0);
}
};
class Point3D {
public:
Point3D(int x, int y, int z) : x_(x), y_(y), z_(z) {}
void set_values(int x, int y, int z) {
x_ = x;
y_ = y;
z_ = z;
}
int get_x() const { return x_; }
void set_x(int x) { x_ = x; }
int get_y() const { return y_; }
void set_y(int y) { y_ = y; }
int get_z() const { return z_; }
void set_z(int y) { z_ = y; }
void add(const Point3D& other) {
this->x_ += other.x_;
this->y_ += other.y_;
this->z_ += other.z_;
}
static int none() { return 1; }
private:
int x_;
int y_;
int z_;
};
template <> struct mrubypp::converter<Point3D> {
static mrb_value to_mrb(mrb_state* mrb, const Point3D& var) {
mrb_value obj = mrb_obj_value(
mrb_data_object_alloc(mrb, mrb->object_class, new Point3D(var),
&mrubypp::bind_class<Point3D>::data_type));
return obj;
}
static Point3D from_mrb(mrb_state* mrb, mrb_value value) {
if (mrb_type(value) == MRB_TT_DATA) {
Point3D* point = static_cast<Point3D*>(DATA_PTR(value));
return *point;
}
return Point3D(0, 0,0 );
}
};
TEST_CASE("bind_class", "[class]") {
mrubypp::engine engine;
mrubypp::bind_class<Point>(engine.get_mrb(), "Point")
.def_constructor(point_native_init, MRB_ARGS_OPT(2))
.def_method("add", &Point::add)
.def_class_method("none", &Point::none)
.def_property("x", &Point::get_x, &Point::set_x)
.def_property("y", &Point::get_y, &Point::set_y)
.def_native("div", point_native_div, MRB_ARGS_REQ(1));
mrubypp::bind_class<Point3D>(engine.get_mrb(), "Point3D")
.def_constructor<int, int, int>()
.def_property("x", &Point3D::get_x, &Point3D::set_x)
.def_property("y", &Point3D::get_y, &Point3D::set_y)
.def_property("z", &Point3D::get_z, &Point3D::set_z);
engine.load(R"(
def test_method()
p = Point.new(3, 4)
p.add(p)
return p
end
def test_property()
p = Point.new(3, 4)
p.x = 10
p.y = p.y + p.y
return p
end
def test_native()
p = Point.new(4, 8)
p.div(2)
return p
end
def test_class_method()
return Point::none()
end
def test_class_init()
return Point.new(10)
end
def test_point3d_init()
p = Point.new(10, 11)
p3d = Point3D.new(p.x, p.y, 5)
return p3d
end
)");
SECTION("test_method") {
auto point_result = engine.call<Point>("test_method");
REQUIRE(point_result.get_x() == 6);
REQUIRE(point_result.get_y() == 8);
}
SECTION("test_property") {
auto point_result = engine.call<Point>("test_property");
REQUIRE(point_result.get_x() == 10);
REQUIRE(point_result.get_y() == 8);
}
SECTION("test_native") {
auto point_result = engine.call<Point>("test_native");
REQUIRE(point_result.get_x() == 2);
REQUIRE(point_result.get_y() == 4);
}
SECTION("test_class_method") {
auto result = engine.call<int>("test_class_method");
REQUIRE(result == 1);
}
SECTION("test_class_init") {
auto result = engine.call<Point>("test_class_init");
REQUIRE(result.get_x() == 10);
REQUIRE(result.get_y() == 0);
}
SECTION("test_point3d_init") {
auto result = engine.call<Point3D>("test_point3d_init");
REQUIRE(result.get_x() == 10);
REQUIRE(result.get_y() == 11);
REQUIRE(result.get_z() == 5);
}
}