blob: 7dfb9c70bf6402d1e98d1a46c9600d84a595db4d [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <gtest/gtest.h>
#include <tvm/ffi/container/map.h>
#include <tvm/ffi/object.h>
#include <tvm/ffi/reflection/access_path.h>
#include <tvm/ffi/reflection/accessor.h>
#include <tvm/ffi/reflection/creator.h>
#include <tvm/ffi/reflection/overload.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ffi/string.h>
namespace {
using namespace tvm::ffi;
struct TestOverloadObj : public Object {
explicit TestOverloadObj(int32_t x) : type(Type::INT) {}
explicit TestOverloadObj(float y) : type(Type::FLOAT) {}
static int AddOneInt(int x) { return x + 1; }
static float AddOneFloat(float x) { return x + 1.0f; }
template <typename T>
auto Holds(T) const {
if constexpr (std::is_same_v<T, int32_t>) {
return type == Type::INT;
} else if constexpr (std::is_same_v<T, float>) {
return type == Type::FLOAT;
} else {
static_assert(sizeof(T) == 0, "Unsupported type");
}
}
enum class Type { INT, FLOAT } type;
TVM_FFI_DECLARE_OBJECT_INFO("test.TestOverloadObj", TestOverloadObj, Object);
};
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::OverloadObjectDef<TestOverloadObj>()
.def(refl::init<int32_t>())
.def(refl::init<float>())
.def("hold_same_type", &TestOverloadObj::Holds<int32_t>)
.def("hold_same_type", &TestOverloadObj::Holds<float>)
.def_static("add_one_static", &TestOverloadObj::AddOneInt)
.def_static("add_one_static", &TestOverloadObj::AddOneFloat);
}
TEST(Reflection, CallOverloadedInitMethod) {
Function init_method = reflection::GetMethod("test.TestOverloadObj", "__ffi_init__");
Any obj_a = init_method(10); // choose the int constructor
EXPECT_TRUE(obj_a.as<TestOverloadObj>() != nullptr);
EXPECT_EQ(obj_a.as<TestOverloadObj>()->type, TestOverloadObj::Type::INT);
Any obj_b = init_method(3.14f); // choose the float constructor
EXPECT_TRUE(obj_b.as<TestOverloadObj>() != nullptr);
EXPECT_EQ(obj_b.as<TestOverloadObj>()->type, TestOverloadObj::Type::FLOAT);
}
TEST(Reflection, CallOverloadedMethod) {
Function init_method = reflection::GetMethod("test.TestOverloadObj", "__ffi_init__");
Function hold_same_type = reflection::GetMethod("test.TestOverloadObj", "hold_same_type");
Any obj_a = init_method(10); // choose the int constructor
Any res_a = hold_same_type(obj_a, 20);
EXPECT_EQ(res_a.as<bool>(), true);
Any res_b = hold_same_type(obj_a, 3.14f);
EXPECT_EQ(res_b.as<bool>(), false);
}
TEST(Reflection, CallOverloadedStaticMethod) {
Function add_one = reflection::GetMethod("test.TestOverloadObj", "add_one_static");
Any res_a = add_one(20);
EXPECT_EQ(res_a.as<int>(), 21);
Any res_b = add_one(1.0f);
static_assert(1.0f + 1.0f == 2.0f);
EXPECT_EQ(res_b.as<float>(), 2.0f);
}
} // namespace