* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* Licensed 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 <iostream>
#include <ostream>
#include <string>
#include "base/utils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "user_common_func.h"
#include "yr/yr.h"
#include "utils.h"
const static size_t g_threadPoolSize = 4;
class ActorTest : public testing::Test {
public:
ActorTest(){};
~ActorTest(){};
static void SetUpTestCase(){};
static void TearDownTestCase(){};
void SetUp()
{
YR::Config config;
config.mode = YR::Config::Mode::CLUSTER_MODE;
config.threadPoolSize = g_threadPoolSize;
config.logLevel = "DEBUG";
auto info = YR::Init(config);
std::cout << "job id: " << info.jobId << std::endl;
};
void TearDown()
{
YR::Finalize();
};
};
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
*/
TEST_F(ActorTest, CreateSuccessful)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
}
* @title: direct call test
* @precondition:
* @step: 创建actor,连续调用
*/
TEST_F(ActorTest, DirectCall)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
int count = 20;
auto start = std::chrono::steady_clock::now();
for (int i = 0; i < count; i++) {
auto ret = creator.Function(&Counter::Add).Invoke(1);
YR::Wait(ret);
}
auto end = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
std::cout << "duration is " << duration / static_cast<double>(count) << " microseconds per invoke" << std::endl;
}
TEST_F(ActorTest, DISABLED_DetachedTestWith2Jobs)
{
std::string name = "name001_1";
YR::InvokeOptions option1;
option1.cpu = 500.0;
option1.memory = 500.0;
option1.customExtensions["lifecycle"] = "detached";
option1.preferredAntiOtherLabels = false;
YR::NamedInstance instance = YR::Instance(Counter::FactoryCreate, name).Options(std::move(option1)).Invoke(1);
auto res = instance.Function(&Counter::Add).Invoke(1);
std::cout << "res is " << *YR::Get(res) << std::endl;
YR::Finalize();
YR::Config config;
config.mode = YR::Config::Mode::CLUSTER_MODE;
config.threadPoolSize = g_threadPoolSize;
config.logLevel = "DEBUG";
auto info = YR::Init(config);
std::cout << "job id: " << info.jobId << std::endl;
auto instance2 = YR::Instance(Counter::FactoryCreate, name).Options(std::move(option1)).Invoke(1);
auto res2 = instance2.Function(&Counter::Add).Invoke(1);
std::cout << "res2 is " << *YR::Get(res2) << std::endl;
ASSERT_TRUE(*YR::Get(res2) == 3);
instance2.Terminate();
}
* @title: kill创建好的actor,调用失败
* @precondition:
* @step: 1. 创建多个actor
* @step: 2. 每个actor发起100个成员函数调用
* @step: 3. kill实例
* @step: 4. 每个actor发起10个成员函数调用
* @expect: 1.每个actor的100个invoke无异常抛出
* @expect: 2.每个actor的10个invoke抛出异常
*/
TEST_F(ActorTest, InvokeFailedWhenKillRuntime)
{
std::vector<YR::NamedInstance<Counter>> instances;
for (int i = 0; i < 2; i++) {
YR::InvokeOptions option;
option.cpu = 500;
option.memory = 500.0;
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
instances.push_back(creator);
}
std::vector<YR::ObjectRef<int>> addResults;
for (int j = 0; j < 100; j++) {
for (auto i : instances) {
auto ret = i.Function(&Counter::Add).Invoke(1);
addResults.push_back(ret);
}
}
ASSERT_NO_THROW(YR::Get(addResults));
std::vector<YR::ObjectRef<int>> addResults2;
for (int j = 0; j < 10; j++) {
for (auto i : instances) {
auto ret = i.Function(&Counter::Sleep).Invoke();
addResults2.push_back(ret);
}
}
system("kill -6 $(ps -ef|grep cppruntime |grep -v grep |awk '{print $2}')");
ASSERT_THROW(YR::Get(addResults2), YR::Exception);
}
* @title: 手动注入kill -9 创建好的actor,调用失败
* @precondition:
* @step: 1. 创建actor
* @step: 2. 每个actor发起10个成员函数调用
* @step: 3. kill -9 实例
* @step: 4. 每个actor发起10个成员函数调用
* @expect: 1.actor的10个invoke抛出异常
*/
TEST_F(ActorTest, InvokeFailedWhenKillSig9Runtime)
{
YR::InvokeOptions option;
option.cpu = 500;
option.memory = 500.0;
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
std::vector<YR::ObjectRef<int>> addResults;
auto ret = creator.Function(&Counter::Add).Invoke(1);
YR::Get(ret);
for (int j = 0; j < 10; j++) {
auto ret = creator.Function(&Counter::Sleep).Invoke();
addResults.push_back(ret);
}
system("kill -9 $(ps -ef|grep cppruntime |grep -v grep |awk '{print $2}')");
ASSERT_THROW(YR::Get(addResults), YR::Exception);
}
* @title: 串行依赖 ins.a->ins.b->ins.c
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Add
* @step: 2. 以1的返回objref作为入参,调用actor成员函数Add
* @step: 3. 以2的返回objref作为入参,调用actor成员函数Add
* @expect: 预期无异常抛出
*/
TEST_F(ActorTest, DependentMutliRef)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
auto ret2 = creator.Function(&Counter::Add).Invoke(ret);
auto ret3 = creator.Function(&Counter::Add).Invoke(ret2);
ASSERT_NO_THROW(YR::Get(ret3));
}
* @title: 串行依赖 ins.a->ins.b->ins.c ins.a返回错误
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Raise
* @step: 2. 以1的返回objref作为入参,调用actor成员函数Add
* @step: 3. 以2的返回objref作为入参,调用actor成员函数Add
* @expect: 预期无异常抛出
*/
TEST_F(ActorTest, DependentMutliRefError)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Raise).Invoke();
auto ret2 = creator.Function(&Counter::Add).Invoke(ret);
auto ret3 = creator.Function(&Counter::Add).Invoke(ret2);
ASSERT_THROW(YR::Get(ret3, 5), YR::Exception);
}
* @title: actor函数依赖成员函数的输出
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Add
* @step: 2. 调用actor成员函数Add
* @step: 3. 以1,2的返回objref作为入参,调用actor成员函数Add
* @expect: 预期无异常抛出
*/
TEST_F(ActorTest, DependentTwoMemberRetRef)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
auto ret2 = creator.Function(&Counter::Add).Invoke(1);
auto ret3 = creator.Function(&Counter::AddTwo).Invoke(ret, ret2);
ASSERT_NO_THROW(YR::Get(ret3));
}
* @title: actor函数依赖成员函数的错误输出
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Raise
* @step: 2. 调用actor成员函数Add
* @step: 3. 以1,2的返回objref作为入参,调用actor成员函数Add
* @expect: 预期异常抛出
*/
TEST_F(ActorTest, DependentTwoMemberRetRefError)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Raise).Invoke();
auto ret2 = creator.Function(&Counter::Add).Invoke(1);
auto ret3 = creator.Function(&Counter::AddTwo).Invoke(ret, ret2);
ASSERT_THROW(YR::Get(ret3, 5), YR::Exception);
}
* @title: 同一个错误返回值依赖两次
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Raise
* @step: 2. 以1的返回objref作为入参,调用actor成员函数Add
* @step: 3. 以1的返回objref作为入参,调用actor成员函数Add
* @expect: 预期异常抛出
*/
TEST_F(ActorTest, DependentSameErrorRef)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Raise).Invoke();
auto ret2 = creator.Function(&Counter::Add).Invoke(ret);
auto ret3 = creator.Function(&Counter::Add).Invoke(ret);
ASSERT_THROW(YR::Get(ret2, 5), YR::Exception);
ASSERT_THROW(YR::Get(ret3, 5), YR::Exception);
}
* @title: 同一个返回值依赖两次
* @precondition:
* @step: 1. 创建actor,调用actor成员函数Add
* @step: 2. 以1的返回objref作为入参,调用actor成员函数Add
* @step: 3. 以1的返回objref作为入参,调用actor成员函数Add
* @expect: 预期异常抛出
*/
TEST_F(ActorTest, DependentSameRef)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
auto ret2 = creator.Function(&Counter::Add).Invoke(ret);
auto ret3 = creator.Function(&Counter::Add).Invoke(ret);
ASSERT_NO_THROW(YR::Get(ret2));
ASSERT_NO_THROW(YR::Get(ret3));
}
* @title: 创建actor成功,并发起调用引起异常的函数
* @precondition:
* @step: 1.创建actor,调用成员函数Add
* @step: 2.创建actor,调用成员函数Raise
* @expect: 1.预期无异常抛出
* @expect: 1.预期异常抛出
*/
TEST_F(ActorTest, InvokeFailedWhenRuntimeSEGV)
{
YR::InvokeOptions option;
option.cpu = 500;
option.memory = 500.0;
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto ret = creator.Function(&Counter::Add).Invoke(1);
ASSERT_NO_THROW(YR::Get(ret));
auto ret2 = creator.Function(&Counter::SEGV).Invoke();
bool raise = false;
try {
YR::Get(ret2, 5);
} catch (YR::Exception &e) {
std::cout << e.Msg() << std::endl;
SignalErrorMsgCheck("SEGV", "exit code:139", e.Msg());
raise = true;
}
ASSERT_TRUE(raise);
}
* @title: 创建指定gpuactor失败
* @precondition:
* @step: 1.指定gpu=1.0,创建actor
* @expect: 1.预期异常抛出
*/
TEST_F(ActorTest, DISABLED_NotEnoughGpuCheck)
{
YR::InvokeOptions option;
try {
option.customResources.insert({"nvidia.com/gpu", 1.0});
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto member = creator.Function(&Counter::Add).Invoke(3);
auto res = *YR::Get(member, 5);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 1006";
std::string errorMsg = "invalid resource parameter, request resource is greater than each node's max resource";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
* @title: 创建指定非法资源actor失败
* @precondition:
* @step: 1.指定cpu=299,创建actor
* @step: 2.指定gpu=1.0,创建actor
* @step: 3.指定cpu=16001.0,创建actor
* @step: 4.指定mem=127.0,创建actor
* @expect: 1.预期异常抛出
* @expect: 2.预期异常抛出
* @expect: 3.预期异常抛出
* @expect: 4.预期异常抛出
*/
TEST_F(ActorTest, InvalidResource)
{
YR::InvokeOptions option;
option.cpu = 299.0;
option.memory = 128.0;
option.customResources.insert({"nvidia.com/gpu", 0.0});
try {
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto member = creator.Function(&Counter::Add).Invoke(3);
auto res = *YR::Get(member, 5);
} catch (YR::Exception &e) {
printf("Exception:%s,\n", e.what());
std::string errorCode = "ErrCode: 1006";
std::string errorMsg =
"Required CPU resource size 299 millicores is invalid. Valid value range is [0,16000] millicores";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
option.cpu = 16001.0;
option.memory = 128.0;
try {
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto member = creator.Function(&Counter::Add).Invoke(3);
auto res = *YR::Get(member, 5);
} catch (YR::Exception &e) {
printf("Exception:%s,\n", e.what());
std::string errorCode = "ErrCode: 1006";
std::string errorMsg =
"Required CPU resource size 16001 millicores is invalid. Valid value range is [0,16000] millicores";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
option.cpu = 300.0;
option.memory = 127.0;
try {
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto member = creator.Function(&Counter::Add).Invoke(3);
auto res = *YR::Get(member, 5);
} catch (YR::Exception &e) {
printf("Exception:%s,\n", e.what());
std::string errorCode = "ErrCode: 1006";
std::string errorMsg = "Required memory resource size 127 MB is invalid. Valid value range is [128, 1073741824] MB";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
* @title: 指定gpu=0创建actor成功
* @precondition:
* @step: 2.指定gpu=0.0,创建actor
* @expect: 1.预期无异常抛出
*/
TEST_F(ActorTest, ZeroGPU)
{
YR::InvokeOptions option;
option.cpu = 333.0;
option.memory = 222.0;
option.customResources.insert({"nvidia.com/gpu", 0.0});
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
auto member = creator.Function(&Counter::Add).Invoke(3);
auto res = *YR::Get(member, 5);
printf("instance result is %d\n", *YR::Get(member, 5));
EXPECT_EQ(res, 4);
creator.Terminate();
}
* @title: actor函数,类成员函数互相调用
* @precondition:
* @step: 1.创建actor A,A在init中创建B
* @step: 2.A的成员函数会调用B的函数进行各自状态累加操作
* @step: 3.获取A的状态
* @step: 4.通过A获取B状态
* @step: 5.通过A删除B
* @expect: 1.状态值正确,无异常抛出
*/
TEST_F(ActorTest, ActorCordination)
{
printf("=========初始化两个class,worker正常拉起,A的成员函数会调用B的函数=========\n");
auto instance = YR::Instance(CounterA::FactoryCreate).Invoke(1);
printf("=========调用A的add成员函数,状态值正常累加=========\n");
auto r1 = instance.Function(&CounterA::Add).Invoke(1);
auto v1 = *YR::Get(r1);
printf("result is %d\n", v1);
EXPECT_LE(v1, 4);
printf("=========调用A的GetCountB成员函数,获取ClassB的状态值=========\n");
r1 = instance.Function(&CounterA::GetCountB).Invoke();
v1 = *YR::Get(r1);
printf("GetCountB is %d\n", *YR::Get(r1));
EXPECT_LE(v1, 2);
printf("=========调用A的GetCountA成员函数,获取状态值=========\n");
r1 = instance.Function(&CounterA::GetCountA).Invoke();
v1 = *YR::Get(r1);
printf("GetCountA is %d\n", *YR::Get(r1));
EXPECT_LE(v1, 2);
printf("=========调用A的TerminateB成员函数,清除B的状态值=========\n");
r1 = instance.Function(&CounterA::TerminateB).Invoke(1);
v1 = *YR::Get(r1);
printf("TerminateB is %d\n", *YR::Get(r1));
EXPECT_LE(v1, 1);
}
* @title: actor函数,类成员函数互相调用
* @precondition:
* @step: 1.初始化classA,A初始化B,B初始化C
* @step: 2.使用invoke调用A的成员函数,函数按A调用B,B调用C链式invoke
* @step: 3.调用A,B,C的查询方法获取状态结果
* @step: 4.执行terminate方法
* @expect: 1.状态值正确,无异常抛出
*/
TEST_F(ActorTest, ActorsCordination)
{
printf("=========函数按A调用B,B调用C链式invoke=========\n");
auto instance = YR::Instance(CounterC::FactoryCreate).Invoke(1);
auto r1 = instance.Function(&CounterC::Add).Invoke(1);
auto v1 = *YR::Get(r1);
printf("result is %d\n", *YR::Get(r1));
r1 = instance.Function(&CounterC::GetCountB).Invoke();
v1 = *YR::Get(r1);
printf("GetCountB is %d\n", *YR::Get(r1));
r1 = instance.Function(&CounterC::GetCountA).Invoke();
v1 = *YR::Get(r1);
printf("GetCountA is %d\n", *YR::Get(r1));
EXPECT_LE(v1, 2);
r1 = instance.Function(&CounterC::GetCountC).Invoke();
v1 = *YR::Get(r1);
printf("GetCountA is %d\n", *YR::Get(r1));
EXPECT_LE(v1, 2);
}
* @title: 删除actor实例后调用实例
* @precondition:
* @step: 1.创建实例
* @step: 2.正常调用
* @step: 3.执行terminate方法
* @step: 4.继续
* @expect: 1.异常抛出
*/
TEST_F(ActorTest, NotExistInstanceMsgCheck)
{
auto instance = YR::Instance(CounterC::FactoryCreate).Invoke(1);
auto r1 = instance.Function(&CounterC::Add).Invoke(1);
auto v1 = *YR::Get(r1);
instance.Terminate();
sleep(2);
try {
auto r2 = instance.Function(&CounterC::Add).Invoke(1);
auto v2 = *YR::Get(r2, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCodeExit = "ErrCode: 1007";
std::string errorCodeNotFound = "ErrCode: 1003";
std::string excepMsg = e.what();
std::string::size_type codeExitIdx = excepMsg.find(errorCodeExit);
std::string::size_type codeNotFoundIdx = excepMsg.find(errorCodeNotFound);
ASSERT_TRUE(codeExitIdx != std::string::npos || codeNotFoundIdx != std::string::npos);
}
}
* @title: 创建actor实例后,调用实例成员方法抛出SIGILL
* @precondition:
* @step: 1.创建实例
* @step: 2.调用get_sigill
* @expect: 1.异常抛出
*/
TEST_F(ActorTest, ExceptionIllegalInstruction)
{
printf("=====云上invoke 检测非法指令=====\n");
auto instance = YR::Instance(Actor::FactoryCreate).Invoke(100);
auto ins = instance.Function(&Actor::get_sigill).Invoke();
try {
int n1 = *YR::Get(ins, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "SIGILL";
std::string exitCodeMsg = "exit code:132";
std::string excepMsg = e.what();
SignalErrorMsgCheck(errorCode, errorMsg, exitCodeMsg, excepMsg);
}
}
* @title: 创建actor实例后,调用实例成员方法抛出SIGINT
* @precondition:
* @step: 1.创建实例
* @step: 2.调用get_sigill
* @expect: 1.异常抛出
*/
TEST_F(ActorTest, ExceptionInterruptSignal)
{
printf("=====云上invoke 程序终止信号=====\n");
auto instance = YR::Instance(Actor::FactoryCreate).Invoke(100);
auto ins = instance.Function(&Actor::get_sigint).Invoke();
try {
int n1 = *YR::Get(ins, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
* @title: 创建actor,并因为资源不足失败,Wait不卡住
* @precondition:
* @step: 1.指定cpu=2000,创建500个actor
* @step: 2.调用一次invoke
* @step: 3.调用wait等待结果
* @expect: 抛出资源不足异常,不卡住
*/
TEST_F(ActorTest, DISABLED_ResourceNotEnough)
{
std::vector<YR::NamedInstance<Counter>> ins;
std::vector<YR::ObjectRef<int>> rets;
for (int i = 0; i < 500; i++) {
YR::InvokeOptions option;
option.cpu = 2000;
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(option)).Invoke(1);
ins.push_back(creator);
auto member = creator.Function(&Counter::Add).Invoke(3);
rets.push_back(member);
}
try {
auto ret = YR::Wait(rets, rets.size(), -1);
std::cout << ret.first.size() << std::endl;
for (auto i : ret.first) {
std::cout << i.ID() << std::endl;
}
std::cout << ret.second.size() << std::endl;
for (auto i : ret.second) {
std::cout << i.ID() << std::endl;
}
ASSERT_TRUE(false);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 1002";
std::string errorMsg = "resources not enough";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
* @title: 配置子目录,创建actor成功,并发起调用
* @precondition:
* @step: 创建actor,获取子目录环境变量,返回子目录
* @expect: 返回用户定义子目录
*/
TEST_F(ActorTest, SubDir)
{
YR::InvokeOptions opts;
opts.customExtensions["DELEGATE_DIRECTORY_INFO"] = "/tmp";
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(opts)).Invoke(1);
auto r1 = creator.Function(&Counter::GetDir).Invoke();
auto v1 = *YR::Get(r1);
std::string::size_type idx = v1.find("/tmp");
ASSERT_TRUE(idx != std::string::npos);
creator.Terminate();
}
* @title: 创建actor
* @precondition:
* @step: 1.设置Concurrency并发度为4
* @step: 2.调用4次Invoke,执行ParallelFor
* @step: 3.调用wait等待结果
* @step: 4.调用GetCtxIdsSize获取runtime启动的线程数量
* @expect: 不卡住
* @expect: GetCtxIdsSize() == threadPoolSize
*/
TEST_F(ActorTest, TestConcurrencyParallelFor)
{
YR::InvokeOptions option;
option.customExtensions[YR::CONCURRENCY_KEY] = "4";
auto counter = YR::Instance(CounterB::FactoryCreate).Options(std::move(option)).Invoke(1);
std::vector<YR::ObjectRef<int>> rets;
for (int i = 0; i < 4; i++) {
rets.emplace_back(counter.Function(&CounterB::ParallelFor).Invoke());
}
YR::Wait(rets, rets.size(), -1);
counter.Function(&CounterB::ParallelFor).Invoke();
auto ret = *(YR::Get(counter.Function(&CounterB::GetCtxIdsSize).Invoke()));
counter.Terminate();
EXPECT_GE(ret, 1);
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.返回值为2
*/
TEST_F(ActorTest, CreateCppActorSuccessful)
{
auto cppCls = YR::CppInstanceClass::FactoryCreate("Counter::FactoryCreate");
auto creator =
YR::Instance(cppCls).SetUrn("sn:cn:yrk:default:function:0-yr-stcpp:$latest").Invoke(1);
auto ret = creator.CppFunction<int>("&Counter::Add").Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期有异常抛出
*/
TEST_F(ActorTest, CreateCppActorFailed)
{
try {
auto cppCls = YR::CppInstanceClass::FactoryCreate("Counter::FactoryCreate");
auto creator = YR::Instance(cppCls).SetUrn("abc123").Invoke(1);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 1001";
std::string errorMsg = "Failed to split functionUrn: split num 1 is expected to be 7";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
try {
auto cppCls = YR::CppInstanceClass::FactoryCreate("Counter");
auto creator = YR::Instance(cppCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stcpp:$latest")
.Invoke(1);
auto ret = creator.CppFunction<int>("&Counter::Add").Invoke(1);
YR::Get(ret, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "Counter is not found in FunctionHelper";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
try {
auto cppCls = YR::CppInstanceClass::FactoryCreate("Counter::FactoryCreate");
auto creator = YR::Instance(cppCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stcpp:$latest")
.Invoke(std::string("one"));
auto ret = creator.CppFunction<int>("&Counter::Add").Invoke(1);
YR::Get(ret, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "std::bad_cast";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.返回值为1
*/
TEST_F(ActorTest, CreatePythonActorSuccessful)
{
auto pyCls = YR::PyInstanceClass::FactoryCreate("common", "SimpleInstance");
auto pyIns = YR::Instance(pyCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stpython:$latest")
.Invoke();
auto ret = pyIns.PyFunction<int>("add_one").Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.返回值为1
*/
TEST_F(ActorTest, CreatePythonWithRefActorSuccessful)
{
auto pyCls = YR::PyInstanceClass::FactoryCreate("common", "SimpleInstance");
auto pyIns = YR::Instance(pyCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stpython:$latest")
.Invoke();
auto obj = YR::Put(1);
auto ret = pyIns.PyFunction<int>("add_one").Invoke(obj);
EXPECT_EQ(*YR::Get(ret), 2);
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.返回值为1
*/
TEST_F(ActorTest, DISABLED_CreateJavaActorSuccessful)
{
auto javaCls = YR::JavaInstanceClass::FactoryCreate("org.yuanrong.testutils.TestUtils");
auto creator = YR::Instance(javaCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stjava:$latest")
.Invoke();
auto ret = creator.JavaFunction<int>("returnInt").Invoke(1);
EXPECT_EQ(*YR::Get(ret), 1);
}
* @title: 创建actor成功,并发起调用
* @precondition:
* @step: 创建actor
* @expect: 1.预期有异常抛出
*/
TEST_F(ActorTest, DISABLED_CreateJavaActorFailed)
{
try {
auto javaCls = YR::JavaInstanceClass::FactoryCreate("org.yuanrong.testutils.TestUtils");
auto creator = YR::Instance(javaCls).SetUrn("abc123").Invoke();
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 1001";
std::string errorMsg = "Failed to split functionUrn: split num 1 is expected to be 7";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
try {
auto javaCls = YR::JavaInstanceClass::FactoryCreate("TestUtils");
auto creator = YR::Instance(javaCls)
.SetUrn("sn:cn:yrk:default:function:0-yr-stjava:$latest")
.Invoke();
auto ret = creator.JavaFunction<int>("returnInt").Invoke(1);
YR::Get(ret, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "ClassNotFoundException";
std::string excepMsg = e.what();
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
}
TEST_F(ActorTest, OrderedInvocations)
{
YR::InvokeOptions option;
option.needOrder = true;
auto creator = YR::Instance(Counter::FactoryCreate).Options(option).Invoke(1);
for (int i = 0; i < 3; i++) {
auto ret = creator.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2 + i);
}
}
TEST_F(ActorTest, OrderedInvocations_PassNamedInstance)
{
YR::InvokeOptions option;
option.needOrder = true;
auto adder = YR::Instance(Adder::FactoryCreate).Options(option).Invoke(10);
auto proxy1 = YR::Instance(AdderProxy::FactoryCreate).Invoke();
auto ret1 = proxy1.Function(&AdderProxy::SetAdder).Invoke(adder);
YR::Wait(ret1, 30);
for (int i = 0; i < 3; i++) {
auto ret = proxy1.Function(&AdderProxy::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 11 + i);
}
}
TEST_F(ActorTest, OrderedInvocations_DesignatedNameOfNamedInstance)
{
std::string designateName = "my_name";
YR::InvokeOptions option;
option.needOrder = true;
auto adder = YR::Instance(Adder::FactoryCreate, designateName).Options(option).Invoke(9);
auto ret = adder.Function(&Adder::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret, 30), 10);
auto proxy1 = YR::Instance(AdderProxy::FactoryCreate).Invoke();
auto ret1 = proxy1.Function(&AdderProxy::SetAdderByName).Invoke(designateName);
YR::Wait(ret1, 30);
for (int i = 0; i < 3; i++) {
auto ret = proxy1.Function(&AdderProxy::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 11 + i);
}
}
TEST_F(ActorTest, TestGroup)
{
YR::GroupOptions groupOpts;
std::string groupName = "group1";
auto g = YR::Group(groupName, groupOpts);
YR::InvokeOptions opt;
opt.groupName = groupName;
auto ins = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
g.Invoke();
auto res = ins.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(res), 2);
}
TEST_F(ActorTest, TestGroupSameLifecycleTrue)
{
YR::GroupOptions groupOpts;
groupOpts.sameLifecycle = false;
std::string groupName = "group1";
auto g = YR::Group(groupName, groupOpts);
YR::InvokeOptions opt;
opt.groupName = groupName;
auto ins1 = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto ins2 = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
g.Invoke();
auto res1 = ins1.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(res1), 2);
ins1.Terminate();
sleep(1);
auto res2 = ins2.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(res2), 2);
}
TEST_F(ActorTest, GroupWaitTimeoutZero)
{
YR::GroupOptions groupOpts;
groupOpts.timeout = 0;
std::string groupName = "group1";
auto g = YR::Group(groupName, groupOpts);
YR::InvokeOptions opt1;
opt1.groupName = groupName;
auto inst1 = YR::Instance(Adder::FactoryCreate).Options(opt1).Invoke(10);
g.Invoke();
bool raise = false;
try {
g.Wait();
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 2002";
std::string errorMsg = "group create timeout";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
TEST_F(ActorTest, GroupInvokeAfterTerminate)
{
YR::GroupOptions groupOpts;
std::string groupName = "group1";
auto g = YR::Group(groupName, groupOpts);
YR::InvokeOptions opt;
opt.groupName = groupName;
auto ins = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
g.Invoke();
g.Terminate();
bool raise = false;
try {
auto obj = ins.Function(&Counter::Add).Invoke(1);
auto res = *YR::Get(obj, 5);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 9000";
std::string errorMsg = "group ins had been terminated";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
* @title: 创建actor函数,objID携带workerID
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.objID不携带ds workerID
*/
TEST_F(ActorTest, CheckActorObjIdSuccessfully)
{
auto creator = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto id = creator.GetObjectId();
EXPECT_EQ(id.size(), 20);
auto ret = creator.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
auto obj = YR::Put(3);
auto ret1 = creator.Function(&Counter::Add).Invoke(obj);
EXPECT_EQ(ret1.ID().size(), 20);
EXPECT_EQ(*YR::Get(ret1), 5);
}
* Check whether customextension has been written into the request body by viewing log file.
* Therefore this case is disabled.
*/
TEST_F(ActorTest, DISABLED_InvokeInstanceWithCustomextensionTest)
{
YR::InvokeOptions opt;
opt.customExtensions = {
{"endpoint", "CreateInstance1"}, {"app_name", "CreateInstance2"}, {"tenant_id", "CreateInstance3"}};
auto counter = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
opt.customExtensions = {
{"endpoint", "InvokeInstance1"}, {"app_name", "InvokeInstance2"}, {"tenant_id", "InvokeInstance3"}};
auto ret = counter.Function(&Counter::Add).Options(opt).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
}
* Check whether preferredAntiOtherLabels has been written into the request body by viewing log file.
* Therefore this case is disabled.
*/
TEST_F(ActorTest, DISABLED_AntiOtherLabelsSuccess)
{
YR::InvokeOptions opt;
auto aff1 = YR::ResourcePreferredAffinity(YR::LabelExistsOperator("label_1"));
opt.AddAffinity(aff1);
opt.preferredAntiOtherLabels = true;
auto creator = YR::Instance(Counter::FactoryCreate).Options(std::move(opt)).Invoke(1);
}
TEST_F(ActorTest, testGracefulShutdownWithTerminate)
{
YR::KV().Del("shutdownKey");
auto counter = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = counter.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
counter.Terminate();
std::string result = YR::KV().Get("shutdownKey", 30);
EXPECT_EQ(result, "shutdownValue");
}
TEST_F(ActorTest, testGetWithParam)
{
std::string key = "kv-id-888";
YR::KV().Del(key);
std::string value = "kv-id-888wqdq";
YR::KV().Set(key, value);
YR::GetParam param = {.offset = 0, .size = 0};
YR::GetParams params;
params.getParams.emplace_back(param);
std::vector<std::shared_ptr<YR::Buffer>> res = YR::KV().GetWithParam({key}, params);
EXPECT_EQ(value, std::string((const char *)(res[0]->ImmutableData())));
}
TEST_F(ActorTest, testGetWithParamPartial)
{
std::string key = "kv-cpp-id-testGetWithParamPartial";
std::string value = "kv-value123456";
std::string traceId = "123333";
YR::GetParam param = {.offset = 0, .size = 0};
YR::GetParams p1;
std::vector<std::string> result;
std::vector<std::string> keys;
std::vector<std::shared_ptr<YR::Buffer>> res;
std::string key1 = key + std::to_string(0);
keys.emplace_back(key1);
p1.getParams.emplace_back(param);
YR::KV().Set(key1, value);
std::string key2 = key + std::to_string(1);
keys.emplace_back(key2);
p1.getParams.emplace_back(param);
res = YR::KV().GetWithParam(keys, p1, 4);
for (int i = 0; i < res.size(); i++) {
if (res[i] != nullptr) {
auto getVal = std::string((const char *)(res[i]->ImmutableData()));
result.emplace_back(getVal);
EXPECT_EQ(getVal, value);
}
}
EXPECT_EQ(result.size(), 1);
}
TEST_F(ActorTest, DISABLED_testGracefulShutdownWithManualSigterm)
{
YR::KV().Del("shutdownKey");
auto counter = YR::Instance(Counter::FactoryCreate).Invoke(1);
sleep(10);
std::string result = YR::KV().Get("shutdownKey", 30);
EXPECT_EQ(result, "shutdownValue");
}
TEST_F(ActorTest, testWriteBytes)
{
int cnt = 5;
double data[cnt] = {1.0, 2.0, 3.0, 4.0, 5.0};
size_t size = sizeof(double) * cnt;
int tag = 1;
int index = 0;
int scr = 0;
int dst = 1;
YR::WriteBytes(data, size, tag, index, scr, dst);
double read_data[cnt];
YR::ReadBytes(read_data, size, tag, index, scr, dst);
for (int i = 0; i < cnt; i++) {
std::cout << data[i] << " " << read_data[i] << std::endl;
EXPECT_EQ(data[i], read_data[i]);
}
}
* @title: range调度成功
* @precondition:
* @step: 配置range,创建一组actor实例并调用
* @expect: 1.一组实例调用实例成功
*/
TEST_F(ActorTest, TestRangeSuccess)
{
auto ins = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = ins.Function(&Counter::AddRange).Invoke(1, 1, 1, true, 20, 20);
int ret = *YR::Get(res, 20);
EXPECT_EQ(ret, 21);
}
* @title: range调度成功,其中step>max-min
* @precondition:
* @step: 配置range,创建一组共计2个actor实例并调用
* @expect: 1.一组共计2个实例调用实例成功
*/
TEST_F(ActorTest, TestRangeSuccess_BigStep)
{
auto ins = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = ins.Function(&Counter::AddRange).Invoke(256, 2, 300, true, 20, 20);
int ret = *YR::Get(res, 20);
EXPECT_EQ(ret, 41);
}
* @title: range调度成功, 开启同生共死
* @precondition:
* @step: 配置range,创建一组actor实例并调用
* @expect: 1.一组实例调用实例成功,terminate一个实例,其它实例也被terminate
*/
TEST_F(ActorTest, DISABLED_TestRangeSuccess_SameLifecycle)
{
YR::InstanceRange range;
range.max = 5;
range.min = 2;
range.step = 2;
YR::InvokeOptions opt;
opt.instanceRange = range;
auto instances = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto insList = instances.GetInstances(15);
sleep(1);
insList[0].Terminate();
sleep(1);
bool raise = false;
try {
for (int i = 1; i < insList.size(); ++i) {
auto res = insList[i].Function(&Counter::Add).Invoke(1);
std::cout << "res is " << *YR::Get(res, 12) << std::endl;
}
} catch (YR::Exception &e) {
std::cout << "exception is: " << e.what() << std::endl;
std::string errorCode = "1011";
std::string errorMsg = "instance occurs fatal error";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
* @title: range调度成功, 关闭同生共死
* @precondition:
* @step: 配置range,创建一组actor实例并调用
* @expect: 1.一组实例调用实例成功,terminate一个实例,其它实例不会被terminate
*/
TEST_F(ActorTest, DISABLED_TestRangeSuccess_NoSameLifecycle)
{
YR::InstanceRange range;
range.max = 5;
range.min = 2;
range.step = 2;
range.sameLifecycle = false;
YR::InvokeOptions opt;
opt.instanceRange = range;
auto instances = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto insList = instances.GetInstances(15);
bool raise = false;
try {
for (auto ins : insList) {
auto res = ins.Function(&Counter::Add).Invoke(1);
std::cout << "res is " << *YR::Get(res, 12) << std::endl;
ins.Terminate();
}
} catch (YR::Exception &e) {
raise = true;
}
ASSERT_FALSE(raise);
}
* @title: range调度失败:非法调用
* @precondition:
* @step: 配置range,创建一组actor实例并调用
* @expect: 1.普通实例句柄调用GetInstances抛错
* @expect: 2.range句柄调用Function抛错
*/
TEST_F(ActorTest, TestRangeFailed_IncorrectInvokeUsage)
{
YR::InstanceRange range;
range.max = 3;
range.min = 1;
YR::InvokeOptions opt;
opt.instanceRange = range;
opt.customExtensions.insert({"GRACEFUL_SHUTDOWN_TIME", "1"});
bool raise = false;
try {
auto handler = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto instances = handler.GetInstances();
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 4006";
std::string errorMsg = "this function can only be used for range instance handler";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
raise = false;
try {
auto handler = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto res = handler.Function(&Counter::Add).Invoke(1);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 4008";
std::string errorMsg = "range instance handler cannont be used to invoke directly";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
* @title: range调度失败:非法参数
* @precondition:
* @step: 配置非法参数的range,创建一组actor实例并调用
* @expect: 1.参数校验失败
*/
TEST_F(ActorTest, TestRangeFailed_InvalidParam)
{
YR::InvokeOptions opt;
std::vector<std::vector<int>> testArr;
testArr.push_back({-2, -1});
testArr.push_back({0, -1});
testArr.push_back({-1, -2});
testArr.push_back({-1, 0});
testArr.push_back({1, 2});
for (auto &test : testArr) {
YR::InstanceRange range;
range.max = test.at(0);
range.min = test.at(1);
opt.instanceRange = range;
bool raise = false;
try {
auto handler = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 1001";
std::string errorMsg = "please set the min and the max as follows: max = min = -1 or max >= min > 0";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
std::vector<int> testStep;
testStep.push_back(-2);
testStep.push_back(-1);
testStep.push_back(0);
for (auto &test : testStep) {
YR::InstanceRange range;
range.max = 10;
range.min = 1;
range.step = test;
opt.instanceRange = range;
bool raise = false;
try {
auto handler = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 1001";
std::string errorMsg = "please set the step > 0";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
std::vector<int> testTimeout;
testTimeout.push_back(-2);
for (auto &test : testTimeout) {
YR::InstanceRange range;
range.max = 10;
range.min = 1;
range.step = 2;
YR::RangeOptions rangeOpts;
rangeOpts.timeout = test;
range.rangeOpts = rangeOpts;
opt.instanceRange = range;
bool raise = false;
try {
auto handler = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
} catch (YR::Exception &e) {
std::string errorCode = "ErrCode: 1001";
std::string errorMsg = "please set the timeout >= -1";
std::string excepMsg = e.what();
raise = true;
ErrorMsgCheck(errorCode, errorMsg, excepMsg);
}
ASSERT_TRUE(raise);
}
}
* @title: range调度成功,其中getInstances超时
* @precondition:
* @step: 配置range,创建一组actor实例并调用,设置非法超时
* @expect: 抛出参数错误的异常。返回-1
*/
TEST_F(ActorTest, TestRangeFailed_InvalidGetInstancesTimeout)
{
auto ins = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = ins.Function(&Counter::AddRange).Invoke(2, 2, 2, true, 20, -2);
ASSERT_THROW(*YR::Get(res, 20), YR::Exception);
}
* @title: range调度失败,其中创建instances超时
* @precondition:
* @step: 配置range,创建一组actor实例并调用,设置超时
* @expect: 抛出超时的异常。返回-1
*/
TEST_F(ActorTest, TestRangeFailed_CreateInstancesTimeout)
{
auto ins = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = ins.Function(&Counter::AddRange).Invoke(256, 256, 1, true, 1, 1);
ASSERT_THROW(*YR::Get(res, 20), YR::Exception);
}
* @title: range调度失败,其中getInstances超时
* @precondition:
* @step: 配置range,创建一组actor实例并调用,设置get超时
* @expect: 抛出超时的异常。返回-1
*/
TEST_F(ActorTest, TestRangeFailed_GetInstancesTimeout)
{
auto ins = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = ins.Function(&Counter::AddRange).Invoke(2, 2, 2, true, 20, 0);
ASSERT_THROW(*YR::Get(res, 20), YR::Exception);
}
TEST_F(ActorTest, testLogMessageOfSigterm)
{
auto instance = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ins = instance.Function(&Counter::GetSigterm).Invoke();
try {
int n1 = *YR::Get(ins, 5);
} catch (YR::Exception &e) {
printf("error: %s\n", e.what());
std::string error_code = "ErrCode: 2002";
std::string error_msg = "SIGTERM";
std::string excep_msg = e.what();
ErrorMsgCheck(error_code, error_msg, excep_msg);
}
}
* @title: 创建actor函数,云下put、云上get
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.get成功,返回正确返回值。
*/
TEST_F(ActorTest, DISABLED_TestTenantIdWithSetUrnSuccessfully)
{
auto cppCls = YR::CppInstanceClass::FactoryCreate("Counter::FactoryCreate");
auto creator =
YR::Instance(cppCls).SetUrn("sn:cn:yrk:default:function:0-yr-stcpp:$latest").Invoke(1);
auto ret = creator.CppFunction<int>("&Counter::Add").Invoke(1);
std::vector<YR::ObjectRef<int>> objs;
objs.push_back(ret);
auto instance = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = instance.Function(&Counter::AddRef).Invoke(objs);
EXPECT_EQ(*YR::Get(res), 2);
}
* @title: 创建actor函数,云下put、云上get
* @precondition:
* @step: 创建actor
* @expect: 1.预期无异常抛出,
* @expect: 2.get成功,返回正确返回值。
*/
TEST_F(ActorTest, TestTenantIdSuccessfully)
{
auto instance = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = instance.Function(&Counter::Add).Invoke(1);
std::vector<YR::ObjectRef<int>> objs;
objs.push_back(ret);
auto instance2 = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto res = instance2.Function(&Counter::AddRef).Invoke(objs);
EXPECT_EQ(*YR::Get(res), 3);
}
* @title: 创建actor成功,并调用SaveState、LoadState成功
* @precondition:
* @step: 创建Counter
* @step: 调用SaveState
* @step: 增加计数
* @step: 调用LoadState
* @expect: 1.返回值为0
*/
TEST_F(ActorTest, ActorSaveStateAndLoadStateSuccessfully)
{
auto instance = YR::Instance(Counter::FactoryCreate).Invoke(1);
auto ret = instance.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret), 2);
auto ret1 = instance.Function(&Counter::SaveState).Invoke();
EXPECT_EQ(*YR::Get(ret1), 2);
auto ret2 = instance.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret2), 3);
auto ret3 = instance.Function(&Counter::LoadState).Invoke();
EXPECT_EQ(*YR::Get(ret3), 3);
auto ret4 = instance.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(ret4), 3);
auto ret5 = instance.Function(&Counter::GetRecoverFlag).Invoke();
EXPECT_EQ(*YR::Get(ret5), 1);
}
* @title: 创建actor成功,并Recover成功
* @precondition:
* @step: 创建Counter
* @step: 调用SEGV
* @step: 调用GetRecoverFlag
* @expect: 1.recover次数为1
*/
TEST_F(ActorTest, DISABLED_ActorRecoverSuccessfully)
{
YR::InvokeOptions opt;
opt.recoverRetryTimes = 1;
auto instance = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto ret = instance.Function(&Counter::GetPid).Invoke();
auto pid = *YR::Get(ret);
std::cout << "Counter pid: " << pid << std::endl;
kill(pid, 9);
auto ret1 = instance.Function(&Counter::GetRecoverFlag).Invoke();
EXPECT_EQ(*YR::Get(ret1, 30), 1);
}
* @title: 创建actor成功,并Recover成功
* @precondition:
* @step: 创建Counter
* @step: 调用SEGV
* @step: 调用GetGroupRecoverFlag
* @expect: 1.结果为11
*/
TEST_F(ActorTest, ActorGroupRecoverSuccessfully)
{
YR::InvokeOptions opt;
opt.recoverRetryTimes = 1;
auto instance = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto ret0 = instance.Function(&Counter::SaveGroupState).Invoke();
auto state = *YR::Get(ret0);
std::cout << "Counter state: " << state << std::endl;
auto ret = instance.Function(&Counter::GetPid).Invoke();
auto pid = *YR::Get(ret);
std::cout << "Counter pid: " << pid << std::endl;
kill(pid, 9);
auto ret1 = instance.Function(&Counter::GetGroupRecoverFlag).Invoke();
EXPECT_EQ(*YR::Get(ret1, 30), 11);
}
* @title: 创建actor,配置envVars参数
* @precondition:
* @step: 创建Counter
* @step: 调用returnActorEnvVar
* @expect: 1.返回配置的环境变量值
*/
TEST_F(ActorTest, ActorReturnEnvVars)
{
YR::InvokeOptions opt;
std::string key = "A";
std::string value = "A_VARS";
opt.envVars[key] = value;
auto instance = YR::Instance(Counter::FactoryCreate).Options(opt).Invoke(1);
auto ret = instance.Function(&Counter::returnActorEnvVar).Invoke(key);
auto res = *YR::Get(ret);
EXPECT_EQ(res, value);
}
* @title: 测试实例保序
* @precondition:
* @step: 1.调用Wait接口传入ObjectRef1、ObjectRef2
* @step: 2.ObjectRef1返回,ObjectRef2不返回
* @expect: Wait返回的readyids中仅包含ObjectRef1
* @title: Wait接口传入多个ObjectRef,其中有返回及不返回
*/
TEST_F(ActorTest, ActorOrderTest)
{
std::vector<YR::NamedInstance<Counter>> instances;
for (int i = 0; i < 3; i++) {
instances.push_back(YR::Instance(Counter::FactoryCreate).Invoke(1));
}
std::vector<YR::ObjectRef<int>> vec;
for (auto &instance : instances) {
vec.push_back(instance.Function(&Counter::Add).Invoke(1));
vec.push_back(instance.Function(&Counter::Sleep).Invoke());
}
auto res = YR::Wait(vec, vec.size(), 5);
ASSERT_EQ(res.first.size(), 3);
ASSERT_EQ(res.first.size() + res.second.size(), vec.size());
}
* @title: 测试invoke超时后能够给runtime发送signal请求驱逐pending线程
* @precondition:
* @step: 1.创建并发度为1的actor实例
* @step: 2.调用阻塞方法,设置invoke超时时间
* @step: 3.invoke请求超时后立即调用另一个函数invoke请求
* @expect: 第一次invoke请求失败,第二次invoke请求成功
*/
TEST_F(ActorTest, ActorTaskPendingTest)
{
YR::InvokeOptions opts;
opts.timeout = 2;
opts.customExtensions["Concurrency"] = "2";
auto instance = YR::Instance(Counter::FactoryCreate).Options(opts).Invoke(1);
auto ret1 = instance.Function(&Counter::Sleep).Options(opts).Invoke();
auto ret2 = instance.Function(&Counter::Sleep).Options(opts).Invoke();
ASSERT_THROW(*YR::Get(ret1, 5), YR::Exception);
auto ret3 = instance.Function(&Counter::Add).Invoke(1);
auto res = *YR::Get(ret3);
ASSERT_EQ(res, 2);
}
* @title: 测试获取cpp实例句柄
* @precondition:
* @step: 1.创建具名实例
* @step: 2.发起实例函数调用
* @step: 3.调用getInstance接口获取实例句柄
* @step: 4.基于获取的实例句柄发起函数调用
*/
TEST_F(ActorTest, ActorGetTest)
{
std::string name = "test-cpp-get";
auto ins = YR::Instance(Counter::FactoryCreate, name).Invoke(1);
auto res = ins.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(res), 2);
std::string ns = "";
auto insGet = YR::GetInstance<Counter>(name, ns, 60);
auto resGet = insGet.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(resGet), 3);
}
* @title: 创建实例CounterA和CounterProxy
* @precondition:
* @step: 1. CounterA为保序实例
* @step: 2.分别对CounterA和CounterProxy发起一次Add invoke调用,保证实例正常拉起
* @step: 3.对CounterProxy发起函数请求,该函数会在云上发起get_instance请求,获取CoutnerA实例句柄,并通过该实例句柄发起两次invoke调用,返回两次invoke结果之和。
* @expect: 正常返回函数请求不卡住。
*/
TEST_F(ActorTest, GetOrderInstanceOnCloudTest)
{
std::string name = "CounterOnCloudTest";
auto counter = YR::Instance(Counter::FactoryCreate, name).Invoke(1);
auto counterObj = counter.Function(&Counter::Add).Invoke(1);
EXPECT_EQ(*YR::Get(counterObj), 2);
auto counterProxy = YR::Instance(CounterProxy::FactoryCreate).Invoke(1);
auto proxyObj = counterProxy.Function(&CounterProxy::Add).Invoke();
EXPECT_EQ(*YR::Get(proxyObj), 1);
auto onCloudObj = counterProxy.Function(&CounterProxy::GetCounterAndInvoke).Invoke(name);
EXPECT_EQ(*YR::Get(onCloudObj), 7);
}