From 40548f9f198dd3dabf2da0c869d1fee69f1ebffd Mon Sep 17 00:00:00 2001 From: arutiunianani Date: Mon, 11 Aug 2025 12:56:17 +0300 Subject: [PATCH 1/2] VerifyANI: Implement checkers for methods Add verification for ani_method Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICQ72A Signed-off-by: arutiunianani --- .../plugins/ets/runtime/CMakeLists.txt | 1 + .../runtime/ani/verify/env_ani_verifier.cpp | 54 +- .../ets/runtime/ani/verify/env_ani_verifier.h | 10 +- .../ets/runtime/ani/verify/types/venv.h | 6 + .../ets/runtime/ani/verify/types/vmethod.cpp | 47 + .../ets/runtime/ani/verify/types/vmethod.h | 69 ++ .../runtime/ani/verify/verify_ani_cast_api.h | 16 + .../runtime/ani/verify/verify_ani_checker.cpp | 120 ++- .../runtime/ani/verify/verify_ani_checker.h | 81 +- .../ani/verify/verify_ani_interaction_api.cpp | 757 +++++++++++---- static_core/plugins/ets/subproject_sources.gn | 1 + .../tests/verifyani/object_ops/CMakeLists.txt | 5 + ...verify_call_object_method_boolean_test.cpp | 912 ++++++++++++++++++ ...verify_call_object_method_boolean_test.ets | 34 + .../object_ops/verify_object_new_a_test.cpp | 38 +- .../object_ops/verify_object_new_test.cpp | 40 +- 16 files changed, 1907 insertions(+), 284 deletions(-) create mode 100644 static_core/plugins/ets/runtime/ani/verify/types/vmethod.cpp create mode 100644 static_core/plugins/ets/runtime/ani/verify/types/vmethod.h create mode 100644 static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.cpp create mode 100644 static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.ets diff --git a/static_core/plugins/ets/runtime/CMakeLists.txt b/static_core/plugins/ets/runtime/CMakeLists.txt index be56e23fe0..fc951fd5da 100644 --- a/static_core/plugins/ets/runtime/CMakeLists.txt +++ b/static_core/plugins/ets/runtime/CMakeLists.txt @@ -23,6 +23,7 @@ set(ETS_RUNTIME_SOURCES ${ETS_EXT_SOURCES}/ani/verify/ani_verifier.cpp ${ETS_EXT_SOURCES}/ani/verify/env_ani_verifier.cpp ${ETS_EXT_SOURCES}/ani/verify/types/venv.cpp + ${ETS_EXT_SOURCES}/ani/verify/types/vmethod.cpp ${ETS_EXT_SOURCES}/ani/verify/verify_ani_checker.cpp ${ETS_EXT_SOURCES}/ani/verify/verify_ani_interaction_api.cpp ${ETS_EXT_SOURCES}/ani/verify/verify_ani_vm_api.cpp diff --git a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp index dcd435ae48..2a5b35bc28 100644 --- a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp @@ -16,6 +16,7 @@ #include "plugins/ets/runtime/ani/verify/env_ani_verifier.h" #include "plugins/ets/runtime/ani/verify/ani_verifier.h" +#include "plugins/ets/runtime/ani/ani_converters.h" namespace ark::ets::ani::verify { @@ -39,8 +40,12 @@ VEnv *EnvANIVerifier::AttachThread(ani_env *env) void EnvANIVerifier::DoPushNatveFrame() { - Frame frame { - SubFrameType::NATIVE_FRAME, 0, {}, MakePandaUnique(SpaceType::SPACE_TYPE_INTERNAL), nullptr}; + Frame frame {SubFrameType::NATIVE_FRAME, + 0, + {}, + {}, + MakePandaUnique(SpaceType::SPACE_TYPE_INTERNAL), + nullptr}; frame.refsAllocator = frame.refsAllocatorHolder.get(); frames_.push_back(std::move(frame)); } @@ -71,7 +76,7 @@ void EnvANIVerifier::CreateLocalScope() { ASSERT(!frames_.empty()); ArenaAllocator *allocator = frames_.back().refsAllocator; - frames_.push_back(Frame {SubFrameType::LOCAL_SCOPE, 0, {}, {}, allocator}); + frames_.push_back(Frame {SubFrameType::LOCAL_SCOPE, 0, {}, {}, {}, allocator}); } std::optional EnvANIVerifier::DestroyLocalScope() @@ -94,7 +99,7 @@ void EnvANIVerifier::CreateEscapeLocalScope() { ASSERT(!frames_.empty()); ArenaAllocator *allocator = frames_.back().refsAllocator; - frames_.push_back(Frame {SubFrameType::ESCAPE_LOCAL_SCOPE, 0, {}, {}, allocator}); + frames_.push_back(Frame {SubFrameType::ESCAPE_LOCAL_SCOPE, 0, {}, {}, {}, allocator}); } std::optional EnvANIVerifier::DestroyEscapeLocalScope([[maybe_unused]] VRef *vref) @@ -127,6 +132,26 @@ VRef *EnvANIVerifier::DoAddLocalVerifiedRef(ani_ref ref, ANIRefType type) return vref; } +VMethod *EnvANIVerifier::WrapMethod(ani_method method) +{ + return reinterpret_cast(DoAddLocalVerifiedMethod(ToInternalMethod(method))); +} +VStaticMethod *EnvANIVerifier::WrapMethod(ani_static_method method) +{ + return reinterpret_cast(DoAddLocalVerifiedMethod(ToInternalMethod(method))); +} + +impl::VMethod *EnvANIVerifier::DoAddLocalVerifiedMethod(EtsMethod *method) +{ + ASSERT(!frames_.empty()); + Frame &frame = frames_.back(); + + auto vmethodptr = MakePandaUnique(method); + impl::VMethod *vmethod = vmethodptr.get(); + frame.methods[vmethod] = std::move(vmethodptr); + return vmethod; +} + void EnvANIVerifier::DeleteLocalVerifiedRef(VRef *vref) { ASSERT(!frames_.empty()); @@ -137,7 +162,7 @@ void EnvANIVerifier::DeleteLocalVerifiedRef(VRef *vref) frame.refs.erase(it); } -bool EnvANIVerifier::IsValidInCurrentFrame(VRef *vref) +bool EnvANIVerifier::IsValidRefInCurrentFrame(VRef *vref) { ASSERT(!frames_.empty()); for (auto it = frames_.crbegin(); it != frames_.crend(); ++it) { @@ -151,6 +176,20 @@ bool EnvANIVerifier::IsValidInCurrentFrame(VRef *vref) return false; } +bool EnvANIVerifier::IsValidMethodInCurrentFrame(VMethod *vmethod) +{ + ASSERT(!frames_.empty()); + for (auto it = frames_.crbegin(); it != frames_.crend(); ++it) { + if (IsValidVerifiedMethod(*it, vmethod)) { + return true; + } + if (it->frameType == SubFrameType::NATIVE_FRAME) { + break; + } + } + return false; +} + bool EnvANIVerifier::CanBeDeletedFromCurrentScope(VRef *vref) { ASSERT(!frames_.empty()); @@ -163,6 +202,11 @@ bool EnvANIVerifier::IsValidVerifiedRef(const Frame &frame, VRef *vref) { return frame.refs.find(vref) != frame.refs.cend(); } +/*static*/ +bool EnvANIVerifier::IsValidVerifiedMethod(const Frame &frame, VMethod *vmethod) +{ + return frame.methods.find(vmethod) != frame.methods.cend(); +} VRef *EnvANIVerifier::AddGloablVerifiedRef(ani_ref gref) { diff --git a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h index 90bd6d05b3..af0b7e26fe 100644 --- a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h +++ b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h @@ -19,6 +19,7 @@ #include "libpandabase/macros.h" #include "plugins/ets/runtime/ani/ani.h" #include "plugins/ets/runtime/ani/verify/types/vref.h" +#include "plugins/ets/runtime/ani/verify/types/vmethod.h" #include "runtime/include/mem/panda_containers.h" #include "runtime/include/mem/panda_smart_pointers.h" #include "runtime/include/mem/panda_string.h" @@ -69,11 +70,16 @@ public: VRef *DoAddLocalVerifiedRef(ani_ref ref, ANIRefType type); void DeleteLocalVerifiedRef(VRef *vref); + VMethod *WrapMethod(ani_method method); + VStaticMethod *WrapMethod(ani_static_method method); + impl::VMethod *DoAddLocalVerifiedMethod(EtsMethod *method); + VRef *AddGloablVerifiedRef(ani_ref gref); void DeleteDeleteGlobalRef(VRef *vgref); bool IsValidGlobalVerifiedRef(VRef *vgref); - bool IsValidInCurrentFrame(VRef *vref); + bool IsValidRefInCurrentFrame(VRef *vref); + bool IsValidMethodInCurrentFrame(VMethod *vmethod); bool CanBeDeletedFromCurrentScope(VRef *vref); const __ani_interaction_api *GetInteractionAPI() const @@ -92,12 +98,14 @@ private: SubFrameType frameType; size_t nrUndef; PandaSet refs; + PandaMap> methods; PandaUniquePtr refsAllocatorHolder; ArenaAllocator *refsAllocator; }; void DoPushNatveFrame(); static bool IsValidVerifiedRef(const Frame &frame, VRef *vref); + static bool IsValidVerifiedMethod(const Frame &frame, VMethod *vmethod); ANIVerifier *verifier_ {}; const __ani_interaction_api *interactionAPI_ {}; diff --git a/static_core/plugins/ets/runtime/ani/verify/types/venv.h b/static_core/plugins/ets/runtime/ani/verify/types/venv.h index 410b877a9a..2e75e18046 100644 --- a/static_core/plugins/ets/runtime/ani/verify/types/venv.h +++ b/static_core/plugins/ets/runtime/ani/verify/types/venv.h @@ -48,6 +48,12 @@ public: } void DeleteLocalVerifiedRef(VRef *vref); + template + auto WrapMethod(MethodType method) + { + return GetEnvANIVerifier()->WrapMethod(method); + } + // Global refs VRef *AddGloablVerifiedRef(ani_ref gref); void DeleteDeleteGlobalRef(VRef *vgref); diff --git a/static_core/plugins/ets/runtime/ani/verify/types/vmethod.cpp b/static_core/plugins/ets/runtime/ani/verify/types/vmethod.cpp new file mode 100644 index 0000000000..318e01f853 --- /dev/null +++ b/static_core/plugins/ets/runtime/ani/verify/types/vmethod.cpp @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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 "vmethod.h" + +#include "plugins/ets/runtime/ani/ani_converters.h" + +namespace ark::ets::ani::verify { + +namespace impl { + +ANIMethodType impl::VMethod::GetType() +{ + if (method_->IsFunction()) { + return ANIMethodType::FUNCTION; + } + if (method_->IsStatic()) { + return ANIMethodType::STATIC_METHOD; + } + return ANIMethodType::METHOD; +} + +} // namespace impl + +ani_method VMethod::GetMethod() +{ + return ToAniMethod(impl::VMethod::GetEtsMethod()); +} + +ani_static_method VStaticMethod::GetMethod() +{ + return ToAniStaticMethod(impl::VMethod::GetEtsMethod()); +} + +} // namespace ark::ets::ani::verify diff --git a/static_core/plugins/ets/runtime/ani/verify/types/vmethod.h b/static_core/plugins/ets/runtime/ani/verify/types/vmethod.h new file mode 100644 index 0000000000..9245a267c4 --- /dev/null +++ b/static_core/plugins/ets/runtime/ani/verify/types/vmethod.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef PANDA_PLUGINS_ETS_RUNTIME_ANI_VERIFY_TYPES_VMETHOD_H +#define PANDA_PLUGINS_ETS_RUNTIME_ANI_VERIFY_TYPES_VMETHOD_H + +#include "libpandabase/macros.h" +#include "plugins/ets/runtime/ani/ani.h" + +namespace ark::ets { +class EtsMethod; +} // namespace ark::ets + +namespace ark::ets::ani::verify { + +enum class ANIMethodType { + FUNCTION, + METHOD, + STATIC_METHOD, +}; + +namespace impl { + +class VMethod { +public: + explicit VMethod(EtsMethod *method) : method_(method) {} + ~VMethod() = default; + + EtsMethod *GetEtsMethod() + { + return method_; + } + + ANIMethodType GetType(); + + DEFAULT_COPY_SEMANTIC(VMethod); + DEFAULT_MOVE_SEMANTIC(VMethod); + +private: + EtsMethod *method_; +}; + +} // namespace impl + +class VMethod : public impl::VMethod { +public: + ani_method GetMethod(); +}; + +class VStaticMethod : public impl::VMethod { +public: + ani_static_method GetMethod(); +}; + +} // namespace ark::ets::ani::verify + +#endif // PANDA_PLUGINS_ETS_RUNTIME_ANI_VERIFY_TYPES_VREF_H diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h b/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h index a800be0613..ed99d1d8f5 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h @@ -28,6 +28,7 @@ class VObject; class VClass; class VString; class VMethod; +class VStaticMethod; class VError; namespace internal { @@ -88,6 +89,11 @@ struct TypeMapping { using Type = ani_object *; }; +template <> +struct TypeMapping { + using Type = ani_object; +}; + template <> struct TypeMapping { using Type = ani_class *; @@ -103,6 +109,16 @@ struct TypeMapping { using Type = ani_method; }; +template <> +struct TypeMapping { + using Type = ani_static_method *; +}; + +template <> +struct TypeMapping { + using Type = ani_method *; +}; + template <> struct TypeMapping { using Type = ani_error *; diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp index 52e8bbf070..7321ea299c 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp @@ -21,6 +21,7 @@ #include "plugins/ets/runtime/ani/verify/types/vvm.h" #include "plugins/ets/runtime/ets_vm.h" #include "plugins/ets/runtime/types/ets_method.h" +#include "plugins/ets/runtime/ani/scoped_objects_fix.h" namespace ark::ets::ani::verify { @@ -81,6 +82,18 @@ std::string_view ANIRefTypeToString(ANIRefType refType) UNREACHABLE(); } +std::string_view ANIFuncTypeToString(ANIMethodType funcType) +{ + // clang-format off + switch (funcType) { + case ANIMethodType::FUNCTION: return "ani_function"; + case ANIMethodType::METHOD: return "ani_method"; + case ANIMethodType::STATIC_METHOD: return "ani_static_method"; + } + // clang-format on + UNREACHABLE(); +} + template void FormatPointer(PandaStringStream &ss, T *ptr) { @@ -129,6 +142,7 @@ PandaString ANIArg::GetStringType() const case ValueType::ANI_SIZE: return "ani_size"; case ValueType::ANI_REF: return "ani_ref"; case ValueType::ANI_CLASS: return "ani_class"; + case ValueType::ANI_OBJECT: return "ani_object"; case ValueType::ANI_METHOD: return "ani_method"; case ValueType::ANI_STRING: return "ani_string"; case ValueType::ANI_VALUE_ARGS: return "const ani_value *"; @@ -183,7 +197,7 @@ static bool IsValidRawAniValue(EnvANIVerifier *envANIVerifier, ani_value v, pand case panda_file::Type::TypeId::F32: return true; // uses double case panda_file::Type::TypeId::F64: return true; case panda_file::Type::TypeId::REFERENCE: - return envANIVerifier->IsValidInCurrentFrame(reinterpret_cast(v.r)); + return envANIVerifier->IsValidRefInCurrentFrame(reinterpret_cast(v.r)); // clang-format on default: break; @@ -200,7 +214,7 @@ static bool IsValidRawAniValue(EnvANIVerifier *envANIVerifier, ani_value v, pand case panda_file::Type::TypeId::F32: return true; case panda_file::Type::TypeId::F64: return true; case panda_file::Type::TypeId::REFERENCE: - return envANIVerifier->IsValidInCurrentFrame(reinterpret_cast(v.r)); + return envANIVerifier->IsValidRefInCurrentFrame(reinterpret_cast(v.r)); // clang-format on default: break; @@ -320,7 +334,7 @@ public: std::optional VerifyRef(VRef *vref) { - if (!GetEnvANIVerifier()->IsValidInCurrentFrame(vref)) { + if (!GetEnvANIVerifier()->IsValidRefInCurrentFrame(vref)) { return "wrong reference"; } return {}; @@ -338,6 +352,9 @@ public: ss << "wrong reference type: " << ANIRefTypeToString(refType); return ss.str(); } + + ScopedManagedCodeFix s(venv_->GetEnv()); + class_ = s.ToInternalType(vclass->GetRef()); return {}; } @@ -374,7 +391,7 @@ public: std::optional VerifyDelLocalRef(VRef *vref) { EnvANIVerifier *envANIVerifier = GetEnvANIVerifier(); - if (!envANIVerifier->IsValidInCurrentFrame(vref)) { + if (!envANIVerifier->IsValidRefInCurrentFrame(vref)) { return "it is not local reference"; } if (!envANIVerifier->CanBeDeletedFromCurrentScope(vref)) { @@ -383,21 +400,76 @@ public: return {}; } - std::optional VerifyCtor(ani_method ctor) + std::optional VerifyThisObject(VObject *vobject) + { + auto err = VerifyRef(vobject); + if (err) { + return err; + } + ANIRefType refType = vobject->GetRefType(); + if (refType != ANIRefType::OBJECT) { + PandaStringStream ss; + ss << "wrong reference type: " << ANIRefTypeToString(refType); + return ss.str(); + } + + ScopedManagedCodeFix s(venv_->GetEnv()); + EtsObject *etsObject = s.ToInternalType(vobject->GetRef()); + class_ = etsObject->GetClass(); + return {}; + } + + std::optional VerifyMethod(VMethod *vmethod, ANIMethodType type, EtsType returnType) + { + ANIMethodType methodType = vmethod->GetType(); + if (methodType != type) { + PandaStringStream ss; + ss << "wrong type: " << ANIFuncTypeToString(methodType) << ", expected: " << ANIFuncTypeToString(type); + return ss.str(); + } + + EtsType methodReturnType = vmethod->GetEtsMethod()->GetReturnValueType(); + if (methodReturnType != returnType) { + return "wrong return type"; + } + return {}; + } + + std::optional VerifyCtor(VMethod *vctor, EtsType returnType) { - if (ctor == nullptr) { - return "wrong ctor value"; + if (!GetEnvANIVerifier()->IsValidMethodInCurrentFrame(vctor)) { + return "wrong ctor"; + } + std::optional err = VerifyMethod(vctor, ANIMethodType::METHOD, returnType); + if (err) { + return err; + } + + if (class_ == nullptr) { + return "wrong class"; + } + if (vctor->GetEtsMethod()->GetClass() != class_) { + return "wrong class for ctor"; } - // NOTE: Add ctor verification, #26993 return {}; } - std::optional VerifyMethod(ani_method method) + std::optional VerifyMethod(VMethod *vmethod, EtsType returnType) { - if (method == nullptr) { - return "wrong method value"; + if (!GetEnvANIVerifier()->IsValidMethodInCurrentFrame(vmethod)) { + return "wrong method"; + } + std::optional err = VerifyMethod(vmethod, ANIMethodType::METHOD, returnType); + if (err) { + return err; + } + + if (class_ == nullptr) { + return "wrong object"; + } + if (!vmethod->GetEtsMethod()->GetClass()->IsAssignableFrom(class_)) { + return "wrong object for method"; } - // NOTE: Add method verification, #26993 return {}; } @@ -418,7 +490,11 @@ public: std::optional DoVerifyMethodArgs(ANIArg::AniMethodArgs *methodArgs) { - CallArgs callArgs(ToInternalMethod(methodArgs->method), methodArgs->vargs); + if (methodArgs->method == nullptr) { + return "wrong method"; + } + + CallArgs callArgs(methodArgs->method, methodArgs->vargs); EnvANIVerifier *envANIVerifier = GetEnvANIVerifier(); std::optional err; callArgs.ForEachArgs([&](ani_value value, panda_file::Type type) -> bool { @@ -441,6 +517,8 @@ private: VVm *vvm_ {}; VEnv *venv_ {}; + + EtsClass *class_ {}; }; using CheckerHandler = std::optional (*)(Verifier &, const ANIArg &); @@ -535,16 +613,22 @@ static std::optional VerifyDelLocalRef(Verifier &v, const ANIArg &a return v.VerifyDelLocalRef(arg.GetValueRef()); } +static std::optional VerifyThisObject(Verifier &v, const ANIArg &arg) +{ + ASSERT(arg.GetAction() == ANIArg::Action::VERIFY_THIS_OBJECT); + return v.VerifyThisObject(arg.GetValueObject()); +} + static std::optional VerifyCtor(Verifier &v, const ANIArg &arg) { ASSERT(arg.GetAction() == ANIArg::Action::VERIFY_CTOR); - return v.VerifyCtor(arg.GetValueMethod()); + return v.VerifyCtor(arg.GetValueMethod(), arg.GetReturnType()); } static std::optional VerifyMethod(Verifier &v, const ANIArg &arg) { ASSERT(arg.GetAction() == ANIArg::Action::VERIFY_METHOD); - return v.VerifyMethod(arg.GetValueMethod()); + return v.VerifyMethod(arg.GetValueMethod(), arg.GetReturnType()); } static std::optional VerifyMethodAArgs(Verifier &v, const ANIArg &arg) @@ -759,8 +843,12 @@ static PandaVector MakeExtArgInfoList(EnvANIVerifier *envANIVerifier PandaVector extArgInfoList; size_t i = 0; - CallArgs callArgs(ToInternalMethod(methodArgs->method), methodArgs->vargs); + if (methodArgs->method == nullptr) { + return {}; + } + + CallArgs callArgs(methodArgs->method, methodArgs->vargs); callArgs.ForEachArgs([&](ani_value value, panda_file::Type type) -> bool { PandaString name = getName(i++); bool isValid = IsValidRawAniValue(envANIVerifier, value, type, methodArgs->isVaArgs); diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h index b99f7ebd1f..cc3eb5d5aa 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h @@ -18,6 +18,7 @@ #include "plugins/ets/runtime/ani/ani.h" #include "runtime/include/mem/panda_containers.h" +#include "plugins/ets/runtime/types/ets_type.h" #include "runtime/include/mem/panda_string.h" // clang-format off @@ -35,6 +36,7 @@ X(VERIFY_STRING, VerifyString) \ X(VERIFY_ERROR, VerifyError) \ X(VERIFY_DEL_LOCAL_REF, VerifyDelLocalRef) \ + X(VERIFY_THIS_OBJECT, VerifyThisObject) \ X(VERIFY_CTOR, VerifyCtor) \ X(VERIFY_METHOD, VerifyMethod) \ X(VERIFY_METHOD_A_ARGS, VerifyMethodAArgs) \ @@ -54,11 +56,11 @@ X(VERIFY_ERROR_STORAGE, VerifyErrorStorage) \ // CC-OFFNXT(G.PRE.02-CPP, G.PRE.06) solid logic -#define ANI_ARG_TYPES_MAP \ - X(ANI_VM, Vm, VVm *) \ - X(ANI_ENV, Env, VEnv *) \ - X(ANI_OPTIONS, Options, const ani_options *) \ - X(ANI_SIZE, Size, ani_size) \ +#define ANI_ARG_TYPES_MAP \ + X(ANI_VM, Vm, VVm *) \ + X(ANI_ENV, Env, VEnv *) \ + X(ANI_OPTIONS, Options, const ani_options *) \ + X(ANI_SIZE, Size, ani_size) \ X(ANI_BOOLEAN, Boolean, ani_boolean) \ X(ANI_CHAR, Char, ani_char) \ X(ANI_BYTE, Byte, ani_byte) \ @@ -67,14 +69,16 @@ X(ANI_LONG, Long, ani_long) \ X(ANI_FLOAT, Float, ani_float) \ X(ANI_DOUBLE, Double, ani_double) \ - X(ANI_REF, Ref, VRef *) \ - X(ANI_CLASS, Class, VClass *) \ - X(ANI_METHOD, Method, ani_method) \ - X(ANI_STRING, String, VString *) \ - X(ANI_ERROR, Error, VError *) \ - X(ANI_VALUE_ARGS, ValueArgs, const ani_value *) \ - X(ANI_ENV_STORAGE, EnvStorage, VEnv **) \ - X(ANI_VM_STORAGE, VmStorage, ani_vm **) \ + X(ANI_REF, Ref, VRef *) \ + X(ANI_CLASS, Class, VClass *) \ + X(ANI_OBJECT, Object, VObject *) \ + X(ANI_METHOD, Method, VMethod *) \ + X(ANI_STATIC_METHOD, StaticMethod, VStaticMethod *) \ + X(ANI_STRING, String, VString *) \ + X(ANI_ERROR, Error, VError *) \ + X(ANI_VALUE_ARGS, ValueArgs, const ani_value *) \ + X(ANI_ENV_STORAGE, EnvStorage, VEnv **) \ + X(ANI_VM_STORAGE, VmStorage, ani_vm **) \ X(ANI_BOOLEAN_STORAGE, BooleanStorage, ani_boolean *) \ X(ANI_CHAR_STORAGE, CharStorage, ani_char *) \ X(ANI_BYTE_STORAGE, ByteStorage, ani_byte *) \ @@ -83,18 +87,18 @@ X(ANI_LONG_STORAGE, LontStorage, ani_long *) \ X(ANI_FLOAT_STORAGE, FloatStorage, ani_float *) \ X(ANI_DOUBLE_STORAGE, DoubleStorage, ani_double *) \ - X(ANI_REF_STORAGE, RefStorage, VRef **) \ - X(ANI_OBJECT_STORAGE, ObjectStorage, VObject **) \ - X(ANI_STRING_STORAGE, StringStorage, VString **) \ - X(ANI_SIZE_STORAGE, SizeStorage, ani_size *) \ - X(ANI_UTF8_BUFFER, UTF8Buffer, char *) \ - X(ANI_UTF16_BUFFER, UTF16Buffer, uint16_t *) \ - X(ANI_UTF8_STRING, UTF8String, const char *) \ - X(ANI_UTF16_STRING, UTF16String, const uint16_t *) \ - X(ANI_ERROR_STORAGE, ErrorStorage, VError **) \ - X(UINT32, U32, uint32_t) \ - X(UINT32x, U32x, uint32_t) \ - X(METHOD_ARGS, MethodArgs, AniMethodArgs *) + X(ANI_REF_STORAGE, RefStorage, VRef **) \ + X(ANI_OBJECT_STORAGE, ObjectStorage, VObject **) \ + X(ANI_STRING_STORAGE, StringStorage, VString **) \ + X(ANI_SIZE_STORAGE, SizeStorage, ani_size *) \ + X(ANI_UTF8_BUFFER, UTF8Buffer, char *) \ + X(ANI_UTF16_BUFFER, UTF16Buffer, uint16_t *) \ + X(ANI_UTF8_STRING, UTF8String, const char *) \ + X(ANI_UTF16_STRING, UTF16String, const uint16_t *) \ + X(ANI_ERROR_STORAGE, ErrorStorage, VError **) \ + X(UINT32, U32, uint32_t) \ + X(UINT32x, U32x, uint32_t) \ + X(METHOD_ARGS, MethodArgs, AniMethodArgs *) // NOLINTEND(cppcoreguidelines-macro-usage) // clang-format on @@ -110,13 +114,15 @@ class VEnv; class VRef; class VObject; class VClass; +class VMethod; +class VStaticMethod; class VString; class VError; class ANIArg { public: struct AniMethodArgs { - ani_method method; + EtsMethod *method; const ani_value *vargs; // NOTE: Reblace ani_value by VValue PandaSmallVector argsStorage; bool isVaArgs; @@ -217,12 +223,17 @@ public: return ANIArg(ArgValueByRef(vref), name, Action::VERIFY_DEL_LOCAL_REF); } - static ANIArg MakeForMethod(ani_method method, std::string_view name, bool isConstructor = false) + static ANIArg MakeForObject(VObject *vobject, std::string_view name) + { + return ANIArg(ArgValueByObject(vobject), name, Action::VERIFY_THIS_OBJECT); + } + + static ANIArg MakeForMethod(VMethod *vmethod, std::string_view name, EtsType returnType, bool isConstructor = false) { if (isConstructor) { - return ANIArg(ArgValueByMethod(method), name, Action::VERIFY_CTOR); + return ANIArg(ArgValueByMethod(vmethod), name, Action::VERIFY_CTOR, returnType); } - return ANIArg(ArgValueByMethod(method), name, Action::VERIFY_METHOD); + return ANIArg(ArgValueByMethod(vmethod), name, Action::VERIFY_METHOD, returnType); } static ANIArg MakeForMethodArgs(AniMethodArgs *aniMethodArgs, std::string_view name) @@ -297,6 +308,11 @@ public: return reinterpret_cast(value_.vVm); // NOLINT(cppcoreguidelines-pro-type-union-access) } + EtsType GetReturnType() const + { + return returnType_; + } + private: // NOLINTBEGIN(cppcoreguidelines-macro-usage) union RawValue { @@ -325,6 +341,11 @@ private: { } + explicit ANIArg(ArgValue value, std::string_view name, Action action, EtsType returnType) + : value_(value.value), type_(value.type), name_(name), action_(action), returnType_(returnType) + { + } + // NOLINTBEGIN(cppcoreguidelines-macro-usage,cppcoreguidelines-pro-type-union-access) // Generate methods: // static ArgValue ArgValueBy( value); @@ -343,6 +364,8 @@ private: ValueType type_; std::string_view name_; Action action_ {}; + + EtsType returnType_ {}; }; bool VerifyANIArgs(std::string_view functionName, std::initializer_list args); diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp b/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp index 57f9cd113f..b06ffe24d7 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp @@ -49,6 +49,14 @@ *(vresult) = (venv)->AddLocalVerifiedRef(result); \ } \ } while (false) + +// CC-OFFNXT(G.PRE.02) should be with define +#define ADD_VERIFIED_LOCAL_METHOD_IF_OK(status, venv, result, vresult) \ + do { \ + if (LIKELY((status) == ANI_OK)) { \ + *(vresult) = (venv)->WrapMethod(result); \ + } \ + } while (false) // NOLINTEND(cppcoreguidelines-macro-usage) namespace ark::ets::ani::verify { @@ -58,10 +66,20 @@ static const __ani_interaction_api *GetInteractionAPI(VEnv *venv) return PandaEnv::FromAniEnv(venv->GetEnv())->GetEnvANIVerifier()->GetInteractionAPI(); } +static EtsMethod *GetEtsMethod(VMethod *vmethod) +{ + ani_env *env = EtsCoroutine::GetCurrent()->GetEtsNapiEnv(); + EnvANIVerifier *envANIVerifier = PandaEnv::FromAniEnv(env)->GetEnvANIVerifier(); + if (!envANIVerifier->IsValidMethodInCurrentFrame(vmethod)) { + return nullptr; + } + return vmethod->GetEtsMethod(); +} + static PandaSmallVector GetVValueArgs(VEnv *venv, const ANIArg::AniMethodArgs &methodArgs) { (void)venv; - EtsMethod *etsMethod = ToInternalMethod(methodArgs.method); + EtsMethod *etsMethod = methodArgs.method; PandaSmallVector args; // NOTE: Check correcting number of args for ani_method/ani_static_method/ani_function @@ -89,18 +107,17 @@ static PandaSmallVector GetVValueArgs(VEnv *venv, const ANIArg::AniMe return args; } -// CC-OFFNXT(G.FUD.05) solid logic -static ANIArg::AniMethodArgs GetVArgsByVVAArgs(ani_method method, va_list vvaArgs) +static ANIArg::AniMethodArgs GetVArgsByVVAArgs(VMethod *vmethod, va_list vvaArgs) { - // NOTE: Add method validation - ASSERT(method != nullptr); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(vmethod), nullptr, {}, true}; + if (methodArgs.method == nullptr) { + return methodArgs; + } - ANIArg::AniMethodArgs methodArgs {method, nullptr, {}, true}; auto &args = methodArgs.argsStorage; - EtsMethod *etsMethod = ToInternalMethod(method); // NOTE: Check correcting number of args for ani_method/ani_static_method/ani_function - args.reserve(etsMethod->GetNumArgs()); - panda_file::ShortyIterator it(etsMethod->GetPandaMethod()->GetShorty()); + args.reserve(vmethod->GetEtsMethod()->GetNumArgs()); + panda_file::ShortyIterator it(vmethod->GetEtsMethod()->GetPandaMethod()->GetShorty()); panda_file::ShortyIterator end; ++it; // skip the return value for (; it != end; ++it) { @@ -165,7 +182,7 @@ NO_UB_SANITIZE static ani_status GetVM(VEnv *venv, ani_vm **result) } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_New(VEnv *venv, VClass *vclass, ani_method ctor, VObject **vresult, ...) +NO_UB_SANITIZE static ani_status Object_New(VEnv *venv, VClass *vclass, VMethod *ctor, VObject **vresult, ...) { // NOTE: Validate ctor method before usage @@ -178,7 +195,7 @@ NO_UB_SANITIZE static ani_status Object_New(VEnv *venv, VClass *vclass, ani_meth VERIFY_ANI_ARGS( ANIArg::MakeForEnv(venv, "env"), ANIArg::MakeForClass(vclass, "cls"), - ANIArg::MakeForMethod(ctor, "ctor", true), + ANIArg::MakeForMethod(ctor, "ctor", EtsType::VOID, true), ANIArg::MakeForObjectStorage(vresult, "result"), ANIArg::MakeForMethodArgs(&methodVArgs, "..."), ); @@ -186,22 +203,22 @@ NO_UB_SANITIZE static ani_status Object_New(VEnv *venv, VClass *vclass, ani_meth auto args = GetVValueArgs(venv, methodVArgs); ani_object result {}; - ani_status status = - GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor, &result, args.data()); + ani_status status = GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor->GetMethod(), + &result, args.data()); ADD_VERIFIED_LOCAL_REF_IF_OK(status, venv, result, vresult); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_New_A(VEnv *venv, VClass *vclass, ani_method ctor, VObject **vresult, +NO_UB_SANITIZE static ani_status Object_New_A(VEnv *venv, VClass *vclass, VMethod *ctor, VObject **vresult, const ani_value *vargs) { - ANIArg::AniMethodArgs methodArgs {ctor, vargs, {}, false}; + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(ctor), vargs, {}, false}; // clang-format off VERIFY_ANI_ARGS( ANIArg::MakeForEnv(venv, "env"), ANIArg::MakeForClass(vclass, "cls"), - ANIArg::MakeForMethod(ctor, "ctor", true), + ANIArg::MakeForMethod(ctor, "ctor", EtsType::VOID, true), ANIArg::MakeForObjectStorage(vresult, "result"), ANIArg::MakeForMethodAArgs(&methodArgs, "args"), ); @@ -209,14 +226,14 @@ NO_UB_SANITIZE static ani_status Object_New_A(VEnv *venv, VClass *vclass, ani_me auto args = GetVValueArgs(venv, methodArgs); ani_object result {}; - ani_status status = - GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor, &result, args.data()); + ani_status status = GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor->GetMethod(), + &result, args.data()); ADD_VERIFIED_LOCAL_REF_IF_OK(status, venv, result, vresult); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_New_V(VEnv *venv, VClass *vclass, ani_method ctor, VObject **vresult, +NO_UB_SANITIZE static ani_status Object_New_V(VEnv *venv, VClass *vclass, VMethod *ctor, VObject **vresult, va_list vvaArgs) { ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(ctor, vvaArgs); @@ -224,7 +241,7 @@ NO_UB_SANITIZE static ani_status Object_New_V(VEnv *venv, VClass *vclass, ani_me VERIFY_ANI_ARGS( ANIArg::MakeForEnv(venv, "env"), ANIArg::MakeForClass(vclass, "cls"), - ANIArg::MakeForMethod(ctor, "ctor", true), + ANIArg::MakeForMethod(ctor, "ctor", EtsType::VOID, true), ANIArg::MakeForObjectStorage(vresult, "result"), ANIArg::MakeForMethodArgs(&methodArgs, "args"), ); @@ -232,8 +249,8 @@ NO_UB_SANITIZE static ani_status Object_New_V(VEnv *venv, VClass *vclass, ani_me auto args = GetVValueArgs(venv, methodArgs); ani_object result {}; - ani_status status = - GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor, &result, args.data()); + ani_status status = GetInteractionAPI(venv)->Object_New_A(venv->GetEnv(), vclass->GetRef(), ctor->GetMethod(), + &result, args.data()); ADD_VERIFIED_LOCAL_REF_IF_OK(status, venv, result, vresult); return status; } @@ -1649,18 +1666,26 @@ NO_UB_SANITIZE static ani_status Class_FindStaticField(VEnv *venv, VClass *vclas // NOLINTNEXTLINE(readability-identifier-naming) NO_UB_SANITIZE static ani_status Class_FindMethod(VEnv *venv, VClass *vclass, const char *name, const char *signature, - ani_method *result) + VMethod **vresult) { VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_FindMethod(venv->GetEnv(), vclass->GetRef(), name, signature, result); + ani_method result {}; + ani_status status = + GetInteractionAPI(venv)->Class_FindMethod(venv->GetEnv(), vclass->GetRef(), name, signature, &result); + ADD_VERIFIED_LOCAL_METHOD_IF_OK(status, venv, result, vresult); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) NO_UB_SANITIZE static ani_status Class_FindStaticMethod(VEnv *venv, VClass *vclass, const char *name, - const char *signature, ani_static_method *result) + const char *signature, VStaticMethod **vresult) { VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_FindStaticMethod(venv->GetEnv(), vclass->GetRef(), name, signature, result); + ani_static_method result {}; + ani_status status = + GetInteractionAPI(venv)->Class_FindStaticMethod(venv->GetEnv(), vclass->GetRef(), name, signature, &result); + ADD_VERIFIED_LOCAL_METHOD_IF_OK(status, venv, result, vresult); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) @@ -3023,286 +3048,668 @@ NO_UB_SANITIZE static ani_status Object_SetPropertyByName_Ref(VEnv *venv, ani_ob } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean(VEnv *venv, ani_object object, ani_method method, +NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean(VEnv *venv, VObject *object, VMethod *method, ani_boolean *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Object_CallMethod_Boolean_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BOOLEAN, false), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Boolean_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean_A(VEnv *venv, ani_object object, ani_method method, - ani_boolean *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean_A(VEnv *venv, VObject *object, VMethod *method, + ani_boolean *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Boolean_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BOOLEAN, false), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Boolean_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean_V(VEnv *venv, ani_object object, ani_method method, - ani_boolean *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Boolean_V(VEnv *venv, VObject *object, VMethod *method, + ani_boolean *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Boolean_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BOOLEAN, false), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Boolean_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Char(VEnv *venv, ani_object object, ani_method method, - ani_char *result, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Char(VEnv *venv, VObject *object, VMethod *method, ani_char *result, + ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Char_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::CHAR, false), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Char_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Char_A(VEnv *venv, ani_object object, ani_method method, - ani_char *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Char_A(VEnv *venv, VObject *object, VMethod *method, + ani_char *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Char_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::CHAR, false), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Char_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Char_V(VEnv *venv, ani_object object, ani_method method, - ani_char *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Char_V(VEnv *venv, VObject *object, VMethod *method, + ani_char *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Char_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::CHAR, false), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Char_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Byte(VEnv *venv, ani_object object, ani_method method, - ani_byte *result, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Byte(VEnv *venv, VObject *object, VMethod *method, ani_byte *result, + ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Byte_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BYTE, false), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Byte_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Byte_A(VEnv *venv, ani_object object, ani_method method, - ani_byte *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Byte_A(VEnv *venv, VObject *object, VMethod *method, + ani_byte *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Byte_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BYTE, false), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Byte_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Byte_V(VEnv *venv, ani_object object, ani_method method, - ani_byte *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Byte_V(VEnv *venv, VObject *object, VMethod *method, + ani_byte *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Byte_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::BYTE, false), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Byte_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Short(VEnv *venv, ani_object object, ani_method method, +NO_UB_SANITIZE static ani_status Object_CallMethod_Short(VEnv *venv, VObject *object, VMethod *method, ani_short *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Object_CallMethod_Short_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::SHORT, false), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Short_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Short_A(VEnv *venv, ani_object object, ani_method method, - ani_short *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Short_A(VEnv *venv, VObject *object, VMethod *method, + ani_short *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Short_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::SHORT, false), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Short_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Short_V(VEnv *venv, ani_object object, ani_method method, - ani_short *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Short_V(VEnv *venv, VObject *object, VMethod *method, + ani_short *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Short_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::SHORT, false), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Short_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Int(VEnv *venv, ani_object object, ani_method method, - ani_int *result, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Int(VEnv *venv, VObject *object, VMethod *method, ani_int *result, + ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Int_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::INT, false), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Int_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Int_A(VEnv *venv, ani_object object, ani_method method, - ani_int *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Int_A(VEnv *venv, VObject *object, VMethod *method, ani_int *result, + const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Int_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::INT, false), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Int_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Int_V(VEnv *venv, ani_object object, ani_method method, - ani_int *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Int_V(VEnv *venv, VObject *object, VMethod *method, ani_int *result, + va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Int_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::INT, false), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Int_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Long(VEnv *venv, ani_object object, ani_method method, - ani_long *result, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Long(VEnv *venv, VObject *object, VMethod *method, ani_long *result, + ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Long_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::LONG, false), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Long_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Long_A(VEnv *venv, ani_object object, ani_method method, - ani_long *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Long_A(VEnv *venv, VObject *object, VMethod *method, + ani_long *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Long_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::LONG, false), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Long_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Long_V(VEnv *venv, ani_object object, ani_method method, - ani_long *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Long_V(VEnv *venv, VObject *object, VMethod *method, + ani_long *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Long_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::LONG, false), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Long_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Float(VEnv *venv, ani_object object, ani_method method, +NO_UB_SANITIZE static ani_status Object_CallMethod_Float(VEnv *venv, VObject *object, VMethod *method, ani_float *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Object_CallMethod_Float_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::FLOAT, false), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Float_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Float_A(VEnv *venv, ani_object object, ani_method method, - ani_float *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Float_A(VEnv *venv, VObject *object, VMethod *method, + ani_float *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Float_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::FLOAT, false), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Float_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Float_V(VEnv *venv, ani_object object, ani_method method, - ani_float *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Float_V(VEnv *venv, VObject *object, VMethod *method, + ani_float *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Float_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::FLOAT, false), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Float_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Double(VEnv *venv, ani_object object, ani_method method, +NO_UB_SANITIZE static ani_status Object_CallMethod_Double(VEnv *venv, VObject *object, VMethod *method, ani_double *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Object_CallMethod_Double_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::DOUBLE, false), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Double_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Double_A(VEnv *venv, ani_object object, ani_method method, - ani_double *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Double_A(VEnv *venv, VObject *object, VMethod *method, + ani_double *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Double_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::DOUBLE, false), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Double_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Double_V(VEnv *venv, ani_object object, ani_method method, - ani_double *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Double_V(VEnv *venv, VObject *object, VMethod *method, + ani_double *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Double_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::DOUBLE, false), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Double_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Ref(VEnv *venv, ani_object object, ani_method method, - ani_ref *result, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Ref(VEnv *venv, VObject *object, VMethod *method, ani_ref *result, + ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Ref_V(venv->GetEnv(), object, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::OBJECT, false), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Ref_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Ref_A(VEnv *venv, ani_object object, ani_method method, - ani_ref *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Ref_A(VEnv *venv, VObject *object, VMethod *method, ani_ref *result, + const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Ref_A(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::OBJECT, false), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Ref_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Ref_V(VEnv *venv, ani_object object, ani_method method, - ani_ref *result, va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Ref_V(VEnv *venv, VObject *object, VMethod *method, ani_ref *result, + va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Ref_V(venv->GetEnv(), object, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::OBJECT, false), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Ref_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Void(VEnv *venv, ani_object object, ani_method method, ...) +NO_UB_SANITIZE static ani_status Object_CallMethod_Void(VEnv *venv, VObject *object, VMethod *method, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, method); - ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Void_V(venv->GetEnv(), object, method, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, method); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::VOID, false), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Void_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Void_A(VEnv *venv, ani_object object, ani_method method, - const ani_value *args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Void_A(VEnv *venv, VObject *object, VMethod *method, + const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Void_A(venv->GetEnv(), object, method, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::VOID, false), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Void_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Object_CallMethod_Void_V(VEnv *venv, ani_object object, ani_method method, - va_list args) +NO_UB_SANITIZE static ani_status Object_CallMethod_Void_V(VEnv *venv, VObject *object, VMethod *method, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Object_CallMethod_Void_V(venv->GetEnv(), object, method, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForObject(object, "object"), + ANIArg::MakeForMethod(method, "method", EtsType::VOID, false), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Object_CallMethod_Void_A(venv->GetEnv(), object->GetRef(), + method->GetMethod(), args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) diff --git a/static_core/plugins/ets/subproject_sources.gn b/static_core/plugins/ets/subproject_sources.gn index 3030854f15..64bcc3be6c 100644 --- a/static_core/plugins/ets/subproject_sources.gn +++ b/static_core/plugins/ets/subproject_sources.gn @@ -101,6 +101,7 @@ srcs_runtime = [ "runtime/ani/verify/ani_verifier.cpp", "runtime/ani/verify/env_ani_verifier.cpp", "runtime/ani/verify/types/venv.cpp", + "runtime/ani/verify/types/vmethod.cpp", "runtime/ani/verify/verify_ani_checker.cpp", "runtime/ani/verify/verify_ani_interaction_api.cpp", "runtime/ani/verify/verify_ani_vm_api.cpp", diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/CMakeLists.txt b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/CMakeLists.txt index 1ec9e96fe7..85752b57f2 100644 --- a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/CMakeLists.txt +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/CMakeLists.txt @@ -11,6 +11,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +ani_verify_add_gtest(ani_verify_test_call_object_method_boolean + CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_call_object_method_boolean_test.cpp + ETS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_call_object_method_boolean_test.ets +) + ani_verify_add_gtest(ani_verify_test_object_new CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_object_new_test.cpp ETS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_object_new_test.ets diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.cpp b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.cpp new file mode 100644 index 0000000000..61bedaf85a --- /dev/null +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.cpp @@ -0,0 +1,912 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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 "verify_ani_gtest.h" + +namespace ark::ets::ani::verify::testing { + +class CallObjectMethodBoolTest : public VerifyAniTest { +public: + void SetUp() override + { + VerifyAniTest::SetUp(); + ASSERT_EQ(env_->FindClass("verify_call_object_method_boolean_test.A", &class_), ANI_OK); + ani_method ctor {}; + ASSERT_EQ(env_->Class_FindMethod(class_, "", ":", &ctor), ANI_OK); + ASSERT_EQ(env_->c_api->Object_New(env_, class_, ctor, &object_), ANI_OK); + ASSERT_EQ(env_->Class_FindMethod(class_, "booleanMethod", "zcbsilfdC{std.core.String}:z", &method_), ANI_OK); + + std::string_view str("ani"); + ASSERT_EQ(env_->String_NewUTF8(str.data(), str.size(), &r_), ANI_OK); + } + +protected: + ani_class class_ {}; // NOLINT(misc-non-private-member-variables-in-classes) + ani_object object_ {}; // NOLINT(misc-non-private-member-variables-in-classes) + ani_method method_ {}; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_boolean z_ = ANI_TRUE; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_char c_ = 'a'; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_byte b_ = 0x24; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_short s_ = 0x2012; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_int i_ = 0xb0ba; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_long l_ = 0xb1bab0ba; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_float f_ = 0.2609; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_double d_ = 21.03; // NOLINT(misc-non-private-member-variables-in-classes) + ani_string r_ {}; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +class CallObjectMethodBoolATest : public CallObjectMethodBoolTest { + void SetUp() override + { + CallObjectMethodBoolTest::SetUp(); + + const int nr0 = 0; + const int nr1 = 1; + const int nr2 = 2; + const int nr3 = 3; + const int nr4 = 4; + const int nr5 = 5; + const int nr6 = 6; + const int nr7 = 7; + const int nr8 = 8; + + args_[nr0].z = z_; + args_[nr1].c = c_; + args_[nr2].b = b_; + args_[nr3].s = s_; + args_[nr4].i = i_; + args_[nr5].l = l_; + args_[nr6].f = f_; + args_[nr7].d = d_; + args_[nr8].r = r_; + } + +protected: + static constexpr size_t NR_ARGS = 9; + std::array args_ {}; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +TEST_F(CallObjectMethodBoolTest, wrong_env) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(nullptr, object_, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_object_0) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, nullptr, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong object"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, cls_1) +{ + ani_object object; + ASSERT_EQ(env_->GetNull(reinterpret_cast(&object)), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong object"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_method_0) +{ + ani_static_method method {}; + ASSERT_EQ(env_->Class_FindStaticMethod(class_, "staticBooleanMethod", "zcbsilfdC{std.core.String}:z", &method), + ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, reinterpret_cast(method), &result, z_, + c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong type: ani_static_method, expected: ani_method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_method_1) +{ + const auto fakeRef = reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, fakeRef, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_method_2) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, nullptr, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_result) +{ + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, nullptr, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_boolean_arg) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, 0xb1ba, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean", "wrong value"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_char_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, 0xb1bab0ba, b_, s_, i_, l_, + f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char", "wrong value"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_byte_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, c_, 0xb1bab0ba, s_, i_, l_, + f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte", "wrong value"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_short_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, c_, b_, 0xb1bab0ba, i_, l_, + f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short", "wrong value"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, DISABLED_wrong_int_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, c_, b_, s_, 0xb1bab0bab1ba, + l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, DISABLED_wrong_ref_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, + nullptr), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref", "wrong value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_all_args) +{ + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean(nullptr, nullptr, nullptr, nullptr, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_return_type) +{ + ani_method method {}; + ASSERT_EQ(env_->Class_FindMethod(class_, "intMethod", "zcbsilfdC{std.core.String}:i", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, method, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong return type"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, wrong_class) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_object_method_boolean_test.C", &cls), ANI_OK); + ani_method ctor {}; + ASSERT_EQ(env_->Class_FindMethod(cls, "", ":", &ctor), ANI_OK); + ani_object object {}; + ASSERT_EQ(env_->c_api->Object_New(env_, cls, ctor, &object), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong object for method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean", testLines); +} + +TEST_F(CallObjectMethodBoolTest, success_0) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_object_method_boolean_test.B", &cls), ANI_OK); + ani_method ctor {}; + ASSERT_EQ(env_->Class_FindMethod(cls, "", ":", &ctor), ANI_OK); + ani_object object {}; + ASSERT_EQ(env_->c_api->Object_New(env_, cls, ctor, &object), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_OK); +} + +TEST_F(CallObjectMethodBoolTest, success_1) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Object_CallMethod_Boolean(env_, object_, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_OK); +} + +TEST_F(CallObjectMethodBoolATest, wrong_env) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(nullptr, object_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_object_0) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, nullptr, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong object"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, cls_1) +{ + ani_object object; + ASSERT_EQ(env_->GetNull(reinterpret_cast(&object)), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong object"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_method_0) +{ + ani_static_method method {}; + ASSERT_EQ(env_->Class_FindStaticMethod(class_, "staticBooleanMethod", "zcbsilfdC{std.core.String}:z", &method), + ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, reinterpret_cast(method), &result, + args_.data()), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong type: ani_static_method, expected: ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_method_1) +{ + const auto fakeRef = reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, fakeRef, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_method_2) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, nullptr, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_result) +{ + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, nullptr, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_args) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong arguments value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_all_args) +{ + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(nullptr, nullptr, nullptr, nullptr, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"object", "ani_object", "wrong reference"}, + {"method", "ani_method", "wrong method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"args", "ani_value *", "wrong arguments value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_boolean_arg) +{ + const int fakeBoolean = 0xb1ba; + args_[0].i = fakeBoolean; + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean", "wrong value"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, DISABLED_wrong_char_arg) +{ + const int64_t fakeChar = 0xb1bab0bab1ba; + const int nr1 = 1; + args_[nr1].l = fakeChar; + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char", "wrong value"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, DISABLED_wrong_byte_arg) +{ + const int64_t fakeByte = 0xb1bab0bab1bab0ba; + const int nr2 = 2; + args_[nr2].l = fakeByte; + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte", "wrong value"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, DISABLED_wrong_short_arg) +{ + const int64_t fakeShort = 0xb1bab0bab1ba; + const int nr3 = 3; + args_[nr3].l = fakeShort; + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short", "wrong value"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_return_type) +{ + ani_method method {}; + ASSERT_EQ(env_->Class_FindMethod(class_, "intMethod", "zcbsilfdC{std.core.String}:i", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong return type"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, wrong_class) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_object_method_boolean_test.C", &cls), ANI_OK); + ani_method ctor {}; + ASSERT_EQ(env_->Class_FindMethod(cls, "", ":", &ctor), ANI_OK); + ani_object object {}; + ASSERT_EQ(env_->c_api->Object_New(env_, cls, ctor, &object), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"object", "ani_object"}, + {"method", "ani_method", "wrong object for method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Object_CallMethod_Boolean_A", testLines); +} + +TEST_F(CallObjectMethodBoolATest, success_0) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_object_method_boolean_test.B", &cls), ANI_OK); + ani_method ctor {}; + ASSERT_EQ(env_->Class_FindMethod(cls, "", ":", &ctor), ANI_OK); + ani_object object {}; + ASSERT_EQ(env_->c_api->Object_New(env_, cls, ctor, &object), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object, method_, &result, args_.data()), ANI_OK); +} + +TEST_F(CallObjectMethodBoolATest, success_1) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Object_CallMethod_Boolean_A(env_, object_, method_, &result, args_.data()), ANI_OK); +} + +} // namespace ark::ets::ani::verify::testing diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.ets b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.ets new file mode 100644 index 0000000000..14bd710030 --- /dev/null +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_call_object_method_boolean_test.ets @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ + +class A { + public booleanMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): boolean { + return true; + } + + public static staticBooleanMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): boolean { + return false; + } + + public intMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): int { + return 24; + } +} + +class B extends A { +} + +class C { +} diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_a_test.cpp b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_a_test.cpp index 01e9f768d2..01063179ee 100644 --- a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_a_test.cpp +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_a_test.cpp @@ -97,7 +97,7 @@ TEST_F(ObjectNewATest, wrong_cls_0) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class", "wrong reference"}, - {"ctor", "ani_method"}, + {"ctor", "ani_method", "wrong class"}, {"result", "ani_object *"}, {"args", "ani_value *"}, {"[0]", "ani_boolean"}, @@ -125,7 +125,7 @@ TEST_F(ObjectNewATest, wrong_cls_1) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class", "wrong reference type: ani_ref"}, - {"ctor", "ani_method"}, + {"ctor", "ani_method", "wrong class"}, {"result", "ani_object *"}, {"args", "ani_value *"}, {"[0]", "ani_boolean"}, @@ -142,8 +142,7 @@ TEST_F(ObjectNewATest, wrong_cls_1) ASSERT_ERROR_ANI_ARGS_MSG("Object_New_A", testLines); } -// NOTE: Enable test when issue #26993 is resolved -TEST_F(ObjectNewATest, DISABLED_wrong_ctor_0) +TEST_F(ObjectNewATest, wrong_ctor_0) { ani_object obj {}; ASSERT_EQ(env_->c_api->Object_New_A(env_, cls_, nullptr, &obj, args_.data()), ANI_ERROR); @@ -151,25 +150,15 @@ TEST_F(ObjectNewATest, DISABLED_wrong_ctor_0) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class"}, - {"ctor", "ani_method", "bla-bla-bla"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *"}, - {"args", "ani_value *"}, - {"[0]", "ani_boolean"}, - {"[1]", "ani_char"}, - {"[2]", "ani_byte"}, - {"[3]", "ani_short"}, - {"[4]", "ani_int"}, - {"[5]", "ani_long"}, - {"[6]", "ani_float"}, - {"[7]", "ani_double"}, - {"[8]", "ani_ref"}, + {"args", "ani_value *", "wrong method"}, }; // clang-format on ASSERT_ERROR_ANI_ARGS_MSG("Object_New_A", testLines); } -// NOTE: Enable test when issue #26993 is resolved -TEST_F(ObjectNewATest, DISABLED_wrong_ctor_1) +TEST_F(ObjectNewATest, wrong_ctor_1) { const auto ctor = reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) ani_object obj {}; @@ -178,18 +167,9 @@ TEST_F(ObjectNewATest, DISABLED_wrong_ctor_1) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class"}, - {"ctor", "ani_method", "bla-bla-bla"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *"}, - {"args", "ani_value *"}, - {"[0]", "ani_boolean"}, - {"[1]", "ani_char"}, - {"[2]", "ani_byte"}, - {"[3]", "ani_short"}, - {"[4]", "ani_int"}, - {"[5]", "ani_long"}, - {"[6]", "ani_float"}, - {"[7]", "ani_double"}, - {"[8]", "ani_ref"}, + {"args", "ani_value *", "wrong method"}, }; // clang-format on ASSERT_ERROR_ANI_ARGS_MSG("Object_New_A", testLines); @@ -332,7 +312,7 @@ TEST_F(ObjectNewATest, wrong_all_args) std::vector testLines { {"env", "ani_env *", "called from incorrect the native scope"}, {"cls", "ani_class", "wrong reference"}, - {"ctor", "ani_method", "wrong ctor value"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *", "wrong pointer for storing 'ani_object'"}, {"args", "ani_value *", "wrong arguments value"}, }; diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_test.cpp b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_test.cpp index d90493b15c..c68642212d 100644 --- a/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_test.cpp +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/object_ops/verify_object_new_test.cpp @@ -94,7 +94,7 @@ TEST_F(ObjectNewTest, wrong_cls_0) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class", "wrong reference"}, - {"ctor", "ani_method"}, + {"ctor", "ani_method", "wrong class"}, {"result", "ani_object *"}, {"...", " "}, {"[0]", "ani_boolean"}, @@ -122,7 +122,7 @@ TEST_F(ObjectNewTest, wrong_cls_1) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class", "wrong reference type: ani_ref"}, - {"ctor", "ani_method"}, + {"ctor", "ani_method", "wrong class"}, {"result", "ani_object *"}, {"...", " "}, {"[0]", "ani_boolean"}, @@ -140,7 +140,7 @@ TEST_F(ObjectNewTest, wrong_cls_1) } // NOTE: Enable when #25617 will be resolved -TEST_F(ObjectNewTest, DISABLED_wrong_ctor_null) +TEST_F(ObjectNewTest, wrong_ctor_null) { ani_object obj {}; ASSERT_EQ(env_->c_api->Object_New(env_, cls_, nullptr, &obj, z_, c_, b_, s_, i_, l_, f_, d_, r_), ANI_ERROR); @@ -148,25 +148,16 @@ TEST_F(ObjectNewTest, DISABLED_wrong_ctor_null) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class"}, - {"ctor", "ani_method", "bla-bla-bla"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *"}, - {"...", " "}, - {"[0]", "ani_boolean"}, - {"[1]", "ani_char"}, - {"[2]", "ani_byte"}, - {"[3]", "ani_short"}, - {"[4]", "ani_int"}, - {"[5]", "ani_long"}, - {"[6]", "ani_float"}, - {"[7]", "ani_double"}, - {"[8]", "ani_ref"}, + {"...", " ", "wrong method"}, }; // clang-format on ASSERT_ERROR_ANI_ARGS_MSG("Object_New", testLines); } // NOTE: Enable when #25617 will be resolved -TEST_F(ObjectNewTest, DISABLED_wrong_ctor_fake) +TEST_F(ObjectNewTest, wrong_ctor_fake) { const auto fakeCtor = reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) ani_object obj {}; @@ -175,18 +166,9 @@ TEST_F(ObjectNewTest, DISABLED_wrong_ctor_fake) std::vector testLines { {"env", "ani_env *"}, {"cls", "ani_class"}, - {"ctor", "ani_method", "bla-bla-bla"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *"}, - {"...", " "}, - {"[0]", "ani_boolean"}, - {"[1]", "ani_char"}, - {"[2]", "ani_byte"}, - {"[3]", "ani_short"}, - {"[4]", "ani_int"}, - {"[5]", "ani_long"}, - {"[6]", "ani_float"}, - {"[7]", "ani_double"}, - {"[8]", "ani_ref"}, + {"...", " ", "wrong method"}, }; // clang-format on ASSERT_ERROR_ANI_ARGS_MSG("Object_New", testLines); @@ -541,16 +523,16 @@ TEST_F(ObjectNewTest, DISABLED_wrong_arg_ref_invalid_type) ASSERT_ERROR_ANI_ARGS_MSG("Object_New", testLines); } -TEST_F(ObjectNewTest, DISABLED_wrong_all_args) +TEST_F(ObjectNewTest, wrong_all_args) { - // NOTE: Add ctor checker ASSERT_EQ(env_->c_api->Object_New(nullptr, nullptr, nullptr, nullptr), ANI_ERROR); // clang-format off std::vector testLines { {"env", "ani_env *", "called from incorrect the native scope"}, {"cls", "ani_class", "wrong reference"}, - {"ctor", "ani_method", "wrong ctor value"}, + {"ctor", "ani_method", "wrong ctor"}, {"result", "ani_object *", "wrong pointer for storing 'ani_object'"}, + {"...", " ", "wrong method"}, }; // clang-format on ASSERT_ERROR_ANI_ARGS_MSG("Object_New", testLines); -- Gitee From cb3a006458e4cc22df1dbab50fbda9b68d71d820 Mon Sep 17 00:00:00 2001 From: arutiunianani Date: Tue, 12 Aug 2025 13:52:01 +0300 Subject: [PATCH 2/2] VerifyANI: Implement checkers for static methods Add verification for ani_static_method Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICXRYZ Signed-off-by: arutiunianani --- .../runtime/ani/verify/env_ani_verifier.cpp | 4 +- .../ets/runtime/ani/verify/env_ani_verifier.h | 4 +- .../runtime/ani/verify/verify_ani_cast_api.h | 13 +- .../runtime/ani/verify/verify_ani_checker.cpp | 28 +- .../runtime/ani/verify/verify_ani_checker.h | 6 + .../ani/verify/verify_ani_interaction_api.cpp | 680 ++++++++++--- .../tests/ani/tests/verifyani/CMakeLists.txt | 1 + .../tests/verifyani/class_ops/CMakeLists.txt | 17 + ...verify_call_static_method_boolean_test.cpp | 895 ++++++++++++++++++ ...verify_call_static_method_boolean_test.ets | 34 + 10 files changed, 1522 insertions(+), 160 deletions(-) create mode 100644 static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/CMakeLists.txt create mode 100644 static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.cpp create mode 100644 static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.ets diff --git a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp index 2a5b35bc28..829c5d4a7e 100644 --- a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.cpp @@ -176,7 +176,7 @@ bool EnvANIVerifier::IsValidRefInCurrentFrame(VRef *vref) return false; } -bool EnvANIVerifier::IsValidMethodInCurrentFrame(VMethod *vmethod) +bool EnvANIVerifier::IsValidMethodInCurrentFrame(impl::VMethod *vmethod) { ASSERT(!frames_.empty()); for (auto it = frames_.crbegin(); it != frames_.crend(); ++it) { @@ -203,7 +203,7 @@ bool EnvANIVerifier::IsValidVerifiedRef(const Frame &frame, VRef *vref) return frame.refs.find(vref) != frame.refs.cend(); } /*static*/ -bool EnvANIVerifier::IsValidVerifiedMethod(const Frame &frame, VMethod *vmethod) +bool EnvANIVerifier::IsValidVerifiedMethod(const Frame &frame, impl::VMethod *vmethod) { return frame.methods.find(vmethod) != frame.methods.cend(); } diff --git a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h index af0b7e26fe..f914add180 100644 --- a/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h +++ b/static_core/plugins/ets/runtime/ani/verify/env_ani_verifier.h @@ -79,7 +79,7 @@ public: bool IsValidGlobalVerifiedRef(VRef *vgref); bool IsValidRefInCurrentFrame(VRef *vref); - bool IsValidMethodInCurrentFrame(VMethod *vmethod); + bool IsValidMethodInCurrentFrame(impl::VMethod *vmethod); bool CanBeDeletedFromCurrentScope(VRef *vref); const __ani_interaction_api *GetInteractionAPI() const @@ -105,7 +105,7 @@ private: void DoPushNatveFrame(); static bool IsValidVerifiedRef(const Frame &frame, VRef *vref); - static bool IsValidVerifiedMethod(const Frame &frame, VMethod *vmethod); + static bool IsValidVerifiedMethod(const Frame &frame, impl::VMethod *vmethod); ANIVerifier *verifier_ {}; const __ani_interaction_api *interactionAPI_ {}; diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h b/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h index ed99d1d8f5..4aa50b7cc4 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_cast_api.h @@ -110,13 +110,18 @@ struct TypeMapping { }; template <> -struct TypeMapping { - using Type = ani_static_method *; +struct TypeMapping { + using Type = ani_method *; }; template <> -struct TypeMapping { - using Type = ani_method *; +struct TypeMapping { + using Type = ani_static_method; +}; + +template <> +struct TypeMapping { + using Type = ani_static_method *; }; template <> diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp index 7321ea299c..060e2ef9f6 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.cpp @@ -144,6 +144,7 @@ PandaString ANIArg::GetStringType() const case ValueType::ANI_CLASS: return "ani_class"; case ValueType::ANI_OBJECT: return "ani_object"; case ValueType::ANI_METHOD: return "ani_method"; + case ValueType::ANI_STATIC_METHOD: return "ani_static_method"; case ValueType::ANI_STRING: return "ani_string"; case ValueType::ANI_VALUE_ARGS: return "const ani_value *"; case ValueType::ANI_UTF8_BUFFER: return "char *"; @@ -419,7 +420,7 @@ public: return {}; } - std::optional VerifyMethod(VMethod *vmethod, ANIMethodType type, EtsType returnType) + std::optional VerifyMethod(impl::VMethod *vmethod, ANIMethodType type, EtsType returnType) { ANIMethodType methodType = vmethod->GetType(); if (methodType != type) { @@ -473,6 +474,25 @@ public: return {}; } + std::optional VerifyStaticMethod(VStaticMethod *vstaticmethod, EtsType returnType) + { + if (!GetEnvANIVerifier()->IsValidMethodInCurrentFrame(vstaticmethod)) { + return "wrong static method"; + } + std::optional err = VerifyMethod(vstaticmethod, ANIMethodType::STATIC_METHOD, returnType); + if (err) { + return err; + } + + if (class_ == nullptr) { + return "wrong class"; + } + if (!vstaticmethod->GetEtsMethod()->GetClass()->IsAssignableFrom(class_)) { + return "wrong class for static method"; + } + return {}; + } + std::optional VerifyMethodAArgs(ANIArg::AniMethodArgs *methodArgs) { ASSERT(methodArgs != nullptr); @@ -631,6 +651,12 @@ static std::optional VerifyMethod(Verifier &v, const ANIArg &arg) return v.VerifyMethod(arg.GetValueMethod(), arg.GetReturnType()); } +static std::optional VerifyStaticMethod(Verifier &v, const ANIArg &arg) +{ + ASSERT(arg.GetAction() == ANIArg::Action::VERIFY_STATIC_METHOD); + return v.VerifyStaticMethod(arg.GetValueStaticMethod(), arg.GetReturnType()); +} + static std::optional VerifyMethodAArgs(Verifier &v, const ANIArg &arg) { ASSERT(arg.GetAction() == ANIArg::Action::VERIFY_METHOD_A_ARGS); diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h index cc3eb5d5aa..001f334bc3 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_checker.h @@ -39,6 +39,7 @@ X(VERIFY_THIS_OBJECT, VerifyThisObject) \ X(VERIFY_CTOR, VerifyCtor) \ X(VERIFY_METHOD, VerifyMethod) \ + X(VERIFY_STATIC_METHOD, VerifyStaticMethod) \ X(VERIFY_METHOD_A_ARGS, VerifyMethodAArgs) \ X(VERIFY_METHOD_V_ARGS, VerifyMethodVArgs) \ X(VERIFY_VM_STORAGE, VerifyVmStorage) \ @@ -236,6 +237,11 @@ public: return ANIArg(ArgValueByMethod(vmethod), name, Action::VERIFY_METHOD, returnType); } + static ANIArg MakeForStaticMethod(VStaticMethod *vstaticMethod, std::string_view name, EtsType returnType) + { + return ANIArg(ArgValueByStaticMethod(vstaticMethod), name, Action::VERIFY_STATIC_METHOD, returnType); + } + static ANIArg MakeForMethodArgs(AniMethodArgs *aniMethodArgs, std::string_view name) { return ANIArg(ArgValueByMethodArgs(aniMethodArgs), name, Action::VERIFY_METHOD_V_ARGS); diff --git a/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp b/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp index b06ffe24d7..3b25d80a39 100644 --- a/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp +++ b/static_core/plugins/ets/runtime/ani/verify/verify_ani_interaction_api.cpp @@ -66,7 +66,7 @@ static const __ani_interaction_api *GetInteractionAPI(VEnv *venv) return PandaEnv::FromAniEnv(venv->GetEnv())->GetEnvANIVerifier()->GetInteractionAPI(); } -static EtsMethod *GetEtsMethod(VMethod *vmethod) +static EtsMethod *GetEtsMethod(impl::VMethod *vmethod) { ani_env *env = EtsCoroutine::GetCurrent()->GetEtsNapiEnv(); EnvANIVerifier *envANIVerifier = PandaEnv::FromAniEnv(env)->GetEnvANIVerifier(); @@ -107,7 +107,7 @@ static PandaSmallVector GetVValueArgs(VEnv *venv, const ANIArg::AniMe return args; } -static ANIArg::AniMethodArgs GetVArgsByVVAArgs(VMethod *vmethod, va_list vvaArgs) +static ANIArg::AniMethodArgs GetVArgsByVVAArgs(impl::VMethod *vmethod, va_list vvaArgs) { ANIArg::AniMethodArgs methodArgs {GetEtsMethod(vmethod), nullptr, {}, true}; if (methodArgs.method == nullptr) { @@ -2014,291 +2014,669 @@ NO_UB_SANITIZE static ani_status Class_SetStaticFieldByName_Ref(VEnv *venv, ani_ } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_boolean *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BOOLEAN), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_boolean *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_boolean *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BOOLEAN), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_boolean *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Boolean_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_boolean *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BOOLEAN), + ANIArg::MakeForBooleanStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Boolean_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_char *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Char_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::CHAR), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Char_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_char *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_char *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Char_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::CHAR), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Char_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_char *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Char_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_char *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Char_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::CHAR), + // ANIArg::MakeForCharStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Char_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_byte *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BYTE), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_byte *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_byte *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BYTE), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_byte *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Byte_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_byte *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::BYTE), + // ANIArg::MakeForByteStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Byte_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_short *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Short_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::SHORT), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Short_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_short *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_short *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Short_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::SHORT), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Short_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_short *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Short_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_short *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Short_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::SHORT), + // ANIArg::MakeForShortStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Short_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_int *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Int_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::INT), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Int_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_int *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_int *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Int_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::INT), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Int_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_int *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Int_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_int *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Int_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::INT), + // ANIArg::MakeForIntStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Int_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_long *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Long_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::LONG), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Long_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_long *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_long *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Long_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::LONG), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Long_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_long *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Long_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_long *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Long_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::LONG), + // ANIArg::MakeForLongStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Long_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_float *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Float_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::FLOAT), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Float_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_float *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_float *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Float_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::FLOAT), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Float_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_float *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Float_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_float *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Float_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::FLOAT), + // ANIArg::MakeForFloatStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Float_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_double *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Double_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::DOUBLE), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Double_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_double *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_double *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Double_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::DOUBLE), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Double_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_double *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Double_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_double *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Double_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::DOUBLE), + // ANIArg::MakeForDoubleStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Double_A( + venv->GetEnv(), vclass->GetRef(), method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref(VEnv *venv, ani_class cls, ani_static_method method, +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref(VEnv *venv, VClass *vclass, VStaticMethod *method, ani_ref *result, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, result); - ani_status status = - GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_V(venv->GetEnv(), cls, method, result, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, result); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::OBJECT), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref_A(VEnv *venv, ani_class cls, ani_static_method method, - ani_ref *result, const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_ref *result, const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_A(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::OBJECT), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref_V(VEnv *venv, ani_class cls, ani_static_method method, - ani_ref *result, va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Ref_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + ani_ref *result, va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_V(venv->GetEnv(), cls, method, result, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::OBJECT), + // ANIArg::MakeForRefStorage(result, "result"), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Ref_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), result, args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void(VEnv *venv, ani_class cls, ani_static_method method, ...) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void(VEnv *venv, VClass *vclass, VStaticMethod *method, ...) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - va_list args; // NOLINT(cppcoreguidelines-pro-type-vararg) - va_start(args, method); - ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Void_V(venv->GetEnv(), cls, method, args); - va_end(args); + va_list vvaArgs; // NOLINT(cppcoreguidelines-pro-type-vararg) + va_start(vvaArgs, method); + ANIArg::AniMethodArgs methodVArgs = GetVArgsByVVAArgs(method, vvaArgs); + va_end(vvaArgs); + + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::VOID), + ANIArg::MakeForMethodArgs(&methodVArgs, "..."), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodVArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Void_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), args.data()); return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void_A(VEnv *venv, ani_class cls, ani_static_method method, - const ani_value *args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void_A(VEnv *venv, VClass *vclass, VStaticMethod *method, + const ani_value *vargs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Void_A(venv->GetEnv(), cls, method, args); + ANIArg::AniMethodArgs methodArgs {GetEtsMethod(method), vargs, {}, false}; + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::VOID), + ANIArg::MakeForMethodAArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Void_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) -NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void_V(VEnv *venv, ani_class cls, ani_static_method method, - va_list args) +NO_UB_SANITIZE static ani_status Class_CallStaticMethod_Void_V(VEnv *venv, VClass *vclass, VStaticMethod *method, + va_list vvaArgs) { - VERIFY_ANI_ARGS(ANIArg::MakeForEnv(venv, "env"), /* NOTE: Add checkers */); - return GetInteractionAPI(venv)->Class_CallStaticMethod_Void_V(venv->GetEnv(), cls, method, args); + ANIArg::AniMethodArgs methodArgs = GetVArgsByVVAArgs(method, vvaArgs); + // clang-format off + VERIFY_ANI_ARGS( + ANIArg::MakeForEnv(venv, "env"), + ANIArg::MakeForClass(vclass, "cls"), + ANIArg::MakeForStaticMethod(method, "method", EtsType::VOID), + ANIArg::MakeForMethodArgs(&methodArgs, "args"), + ); + // clang-format on + + auto args = GetVValueArgs(venv, methodArgs); + ani_status status = GetInteractionAPI(venv)->Class_CallStaticMethod_Void_A(venv->GetEnv(), vclass->GetRef(), + method->GetMethod(), args.data()); + return status; } // NOLINTNEXTLINE(readability-identifier-naming) diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/CMakeLists.txt b/static_core/plugins/ets/tests/ani/tests/verifyani/CMakeLists.txt index 41c6ed577f..743e066a5f 100644 --- a/static_core/plugins/ets/tests/ani/tests/verifyani/CMakeLists.txt +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/CMakeLists.txt @@ -13,6 +13,7 @@ include(cmake/ani_verify_tests.cmake) +add_subdirectory(class_ops) add_subdirectory(error_ops) add_subdirectory(object_ops) add_subdirectory(ref_ops) diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/CMakeLists.txt b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/CMakeLists.txt new file mode 100644 index 0000000000..71dc49db5c --- /dev/null +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# 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. + +ani_verify_add_gtest(ani_verify_test_call_static_method_boolean + CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_call_static_method_boolean_test.cpp + ETS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_call_static_method_boolean_test.ets +) diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.cpp b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.cpp new file mode 100644 index 0000000000..3afbc16fd4 --- /dev/null +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.cpp @@ -0,0 +1,895 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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 "verify_ani_gtest.h" + +namespace ark::ets::ani::verify::testing { + +class CallStaticMethodBoolTest : public VerifyAniTest { +public: + void SetUp() override + { + VerifyAniTest::SetUp(); + ASSERT_EQ(env_->FindClass("verify_call_static_method_boolean_test.A", &class_), ANI_OK); + ASSERT_EQ(env_->Class_FindStaticMethod(class_, "staticBooleanMethod", "zcbsilfdC{std.core.String}:z", &method_), + ANI_OK); + + std::string_view str("ani"); + ASSERT_EQ(env_->String_NewUTF8(str.data(), str.size(), &r_), ANI_OK); + } + +protected: + ani_class class_ {}; // NOLINT(misc-non-private-member-variables-in-classes) + ani_static_method method_ {}; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_boolean z_ = ANI_TRUE; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_char c_ = 'a'; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_byte b_ = 0x24; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_short s_ = 0x2012; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_int i_ = 0xb0ba; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_long l_ = 0xb1bab0ba; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_float f_ = 0.2609; // NOLINT(misc-non-private-member-variables-in-classes) + const ani_double d_ = 21.03; // NOLINT(misc-non-private-member-variables-in-classes) + ani_string r_ {}; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +class CallStaticMethodBoolATest : public CallStaticMethodBoolTest { + void SetUp() override + { + CallStaticMethodBoolTest::SetUp(); + + const int nr0 = 0; + const int nr1 = 1; + const int nr2 = 2; + const int nr3 = 3; + const int nr4 = 4; + const int nr5 = 5; + const int nr6 = 6; + const int nr7 = 7; + const int nr8 = 8; + + args_[nr0].z = z_; + args_[nr1].c = c_; + args_[nr2].b = b_; + args_[nr3].s = s_; + args_[nr4].i = i_; + args_[nr5].l = l_; + args_[nr6].f = f_; + args_[nr7].d = d_; + args_[nr8].r = r_; + } + +protected: + static constexpr size_t NR_ARGS = 9; + std::array args_ {}; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +TEST_F(CallStaticMethodBoolTest, wrong_env) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(nullptr, class_, method_, &result, z_, c_, b_, s_, i_, l_, f_, + d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_class_0) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, nullptr, method_, &result, z_, c_, b_, s_, i_, l_, f_, + d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong class"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_class_1) +{ + ani_class cls; + ASSERT_EQ(env_->GetNull(reinterpret_cast(&cls)), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, cls, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong class"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_method_0) +{ + ani_method method {}; + ASSERT_EQ(env_->Class_FindMethod(class_, "booleanMethod", "zcbsilfdC{std.core.String}:z", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, reinterpret_cast(method), + &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong type: ani_method, expected: ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_method_1) +{ + const auto fakeRef = + reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, fakeRef, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_method_2) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, nullptr, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_result) +{ + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, nullptr, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_boolean_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, 0xb1ba, c_, b_, s_, i_, l_, + f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean", "wrong value"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_char_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, 0xb1bab0ba, b_, s_, i_, + l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char", "wrong value"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_byte_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, c_, 0xb1bab0ba, s_, i_, + l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte", "wrong value"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_short_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, c_, b_, 0xb1bab0ba, i_, + l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short", "wrong value"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, DISABLED_wrong_int_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, c_, b_, s_, + 0xb1bab0bab1ba, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, DISABLED_wrong_ref_arg) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, c_, b_, s_, i_, l_, f_, + d_, nullptr), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"...", " ", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref", "wrong value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_all_args) +{ + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean(nullptr, nullptr, nullptr, nullptr, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"...", " ", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_return_type) +{ + ani_static_method method {}; + ASSERT_EQ(env_->Class_FindStaticMethod(class_, "intMethod", "zcbsilfdC{std.core.String}:i", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong return type"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, wrong_class) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_static_method_boolean_test.C", &cls), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, cls, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong class for static method"}, + {"result", "ani_boolean *"}, + {"...", " "}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean", testLines); +} + +TEST_F(CallStaticMethodBoolTest, success_0) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_static_method_boolean_test.B", &cls), ANI_OK); + + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, cls, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_OK); +} + +TEST_F(CallStaticMethodBoolTest, success_1) +{ + ani_boolean result; + ASSERT_EQ( + env_->c_api->Class_CallStaticMethod_Boolean(env_, class_, method_, &result, z_, c_, b_, s_, i_, l_, f_, d_, r_), + ANI_OK); +} + +TEST_F(CallStaticMethodBoolATest, wrong_env) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(nullptr, class_, method_, &result, args_.data()), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_class_0) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, nullptr, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong class"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_class_1) +{ + ani_class cls; + ASSERT_EQ(env_->GetNull(reinterpret_cast(&cls)), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, cls, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong class"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_method_0) +{ + ani_method method {}; + ASSERT_EQ(env_->Class_FindMethod(class_, "booleanMethod", "zcbsilfdC{std.core.String}:z", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, reinterpret_cast(method), + &result, args_.data()), + ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong type: ani_method, expected: ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_method_1) +{ + const auto fakeRef = + reinterpret_cast(static_cast(0x0ff0f0f)); // NOLINT(google-runtime-int) + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, fakeRef, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_method_2) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, nullptr, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_result) +{ + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, nullptr, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_args) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong arguments value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_all_args) +{ + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(nullptr, nullptr, nullptr, nullptr, nullptr), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *", "called from incorrect the native scope"}, + {"cls", "ani_class", "wrong reference"}, + {"method", "ani_static_method", "wrong static method"}, + {"result", "ani_boolean *", "wrong pointer for storing 'ani_boolean'"}, + {"args", "ani_value *", "wrong arguments value"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_boolean_arg) +{ + const int fakeBoolean = 0xb1ba; + const int nr0 = 0; + args_[nr0].i = fakeBoolean; + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean", "wrong value"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, DISABLED_wrong_char_arg) +{ + const uint64_t fakeChar = 0xb1bab0bab1ba; + const int nr1 = 1; + args_[nr1].l = fakeChar; + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char", "wrong value"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, DISABLED_wrong_byte_arg) +{ + const uint64_t fakeByte = 0xb1bab0bab1ba; + const int nr2 = 2; + args_[nr2].l = fakeByte; + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte", "wrong value"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, DISABLED_wrong_short_arg) +{ + const uint64_t fakeShort = 0xb1bab0bab1ba; + const int nr3 = 3; + args_[nr3].l = fakeShort; + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *", "wrong method arguments"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short", "wrong value"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_return_type) +{ + ani_static_method method {}; + ASSERT_EQ(env_->Class_FindStaticMethod(class_, "intMethod", "zcbsilfdC{std.core.String}:i", &method), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong return type"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, wrong_class) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_static_method_boolean_test.C", &cls), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, cls, method_, &result, args_.data()), ANI_ERROR); + // clang-format off + std::vector testLines { + {"env", "ani_env *"}, + {"cls", "ani_class"}, + {"method", "ani_static_method", "wrong class for static method"}, + {"result", "ani_boolean *"}, + {"args", "ani_value *"}, + {"[0]", "ani_boolean"}, + {"[1]", "ani_char"}, + {"[2]", "ani_byte"}, + {"[3]", "ani_short"}, + {"[4]", "ani_int"}, + {"[5]", "ani_long"}, + {"[6]", "ani_float"}, + {"[7]", "ani_double"}, + {"[8]", "ani_ref"}, + }; + // clang-format on + ASSERT_ERROR_ANI_ARGS_MSG("Class_CallStaticMethod_Boolean_A", testLines); +} + +TEST_F(CallStaticMethodBoolATest, success_0) +{ + ani_class cls {}; + ASSERT_EQ(env_->FindClass("verify_call_static_method_boolean_test.B", &cls), ANI_OK); + + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, cls, method_, &result, args_.data()), ANI_OK); +} + +TEST_F(CallStaticMethodBoolATest, success_1) +{ + ani_boolean result; + ASSERT_EQ(env_->c_api->Class_CallStaticMethod_Boolean_A(env_, class_, method_, &result, args_.data()), ANI_OK); +} + +} // namespace ark::ets::ani::verify::testing diff --git a/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.ets b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.ets new file mode 100644 index 0000000000..f3bfb1c1e4 --- /dev/null +++ b/static_core/plugins/ets/tests/ani/tests/verifyani/class_ops/verify_call_static_method_boolean_test.ets @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ + +class A { + public booleanMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): boolean { + return true; + } + + public static staticBooleanMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): boolean { + return false; + } + + public static intMethod(z: boolean, c: char, b: byte, s: short, i: int, l: long, f: float, d: double, r: string): int { + return 24; + } +} + +class B extends A { +} + +class C { +} -- Gitee