XTS Acts套件账号子系统用例提示导出的枚举值无效问题分析报告
1 关键字 napi;XTS;账号子系统;枚举值无效 2 问题描述 测试用例 ActsOsAccountLocalIdSerial_0600 无法跑通过。 3 问题原因 3.1 正常机制 测试用例正常通过后打印日志: JSApp: app Log: [pass]ActsOsAccountLocalIdSerial_0600 ; 3.2 异常机制 测试用例报错后打印日志: JSApp: app Lo
1 关键字
napi;XTS;账号子系统;枚举值无效
2 问题描述
测试用例 ActsOsAccountLocalIdSerial_0600
无法跑通过。
3 问题原因
3.1 正常机制
测试用例正常通过后打印日志:
JSApp: app Log: [pass]ActsOsAccountLocalIdSerial_0600 ;
3.2 异常机制
测试用例报错后打印日志:
JSApp: app Log: [error]ActsOsAccountLocalIdSerial_0600 ;
4 解决方案
由于hap应用在使用napi层导出的枚举时,未按正确的值来赋值,导致xts运行时,在napi层不能正常解析参数,返回错误,导致xts执行不过。 正确使用napi导出的枚举值即可正常获取参数,使xts正常通过。
5 定位过程
-
用例代码
-
执行xts,查看日志。
-
通过
ActsOsAccountLocalIdSerial_0600
用例名称查找日志,可以看到用例在日志的53719行开始执行,进程ID为 5988 -
依次往后查 5988 的日志,可以在日志53749行看到打印出napi层错误信息
-
在日志53757行打印出hap的错误信息
-
在tvos的源代码的 os_account 模块下分别搜索两个错误信息的字符串
Get type failed
和The type of arg 2 must be number
,可以定位到函数ParseParaCreateOA
中24,25行bool ParseParaCreateOA(napi_env env, napi_callback_info cbInfo, CreateOAAsyncContext *asyncContext) { size_t argc = ARGS_SIZE_THREE; napi_value argv[ARGS_SIZE_THREE] = {0}; napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr); if (argc == ARGS_SIZE_THREE) { if (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1)) { ACCOUNT_LOGE("Get callbackRef failed"); std::string errMsg = "The type of arg " + std::to_string(argc) + " must be function"; AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr); return false; } } if (!GetStringProperty(env, argv[PARAMZERO], asyncContext->name)) { ACCOUNT_LOGE("Get name failed"); std::string errMsg = "The type of arg 1 must be string"; AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr); return false; } int32_t type = 0; if (!GetIntProperty(env, argv[PARAMONE], type)) { ACCOUNT_LOGE("Get type failed"); std::string errMsg = "The type of arg 2 must be number"; AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr); return false; } asyncContext->type = static_cast<OsAccountType>(type); return true; }
在js对应的napi层函数
CreateOsAccount
中12行确实有调用ParseParaCreateOA
napi_value CreateOsAccount(napi_env env, napi_callback_info cbInfo) { CreateOAAsyncContext *createOACB = new (std::nothrow) CreateOAAsyncContext(); if (createOACB == nullptr) { ACCOUNT_LOGE("insufficient memory for createOACB!"); return WrapVoidToJS(env); } createOACB->env = env; createOACB->callbackRef = nullptr; createOACB->throwErr = true; if (!ParseParaCreateOA(env, cbInfo, createOACB)) { delete createOACB; return nullptr; } napi_value result = nullptr; if (createOACB->callbackRef == nullptr) { napi_create_promise(env, &createOACB->deferred, &result); } else { napi_get_undefined(env, &result); } napi_value resource = nullptr; napi_create_string_utf8(env, "CreateOsAccount", NAPI_AUTO_LENGTH, &resource); napi_create_async_work(env, nullptr, resource, CreateOAExecuteCB, CreateOACallbackCompletedCB, reinterpret_cast<void *>(createOACB), &createOACB->work); napi_queue_async_work(env, createOACB->work); return result; }
-
在
ParseParaCreateOA
的7 - 14行,获取js调用时第3个参数,判断是callback还是promise调用。 -
在
ParseParaCreateOA
的16 - 21行,获取js调用时第1个参数,并判断是否为js的string类型。 -
在
ParseParaCreateOA
的22 - 28行,获取js调用时第2个参数,并判断是否为js的number类型。通过错误日志定位,可以发现js调用时第2个参数传入有误导致错误。 -
回到hap包的js代码中,可以发现代码第4行调用时,第2个参数传入的值为 osaccount.OsAccountType.Guest
var osAccountManager = osaccount.getAccountManager(); console.debug("====>get AccountManager finish===="); var localId; var OsAccountInfo = await osAccountManager.createOsAccount("accountIdSerialB", osaccount.OsAccountType.Guest); console.debug("====>create os account OsAccountInfo: " + JSON.stringify(OsAccountInfo));
-
传入的值 osaccount.OsAccountType.Guest 为napi导出的枚举值,转到napi层导出枚举值的地方。
napi_value osAccountType = nullptr; napi_create_object(env, &osAccountType); SetEnumProperty(env, osAccountType, OS_ACCOUNT_TYPE_ADMIN, "ADMIN"); SetEnumProperty(env, osAccountType, OS_ACCOUNT_TYPE_NORMAL, "NORMAL"); SetEnumProperty(env, osAccountType, OS_ACCOUNT_TYPE_GUEST, "GUEST"); napi_value constraintSourceType = nullptr; napi_create_object(env, &constraintSourceType); SetEnumProperty(env, constraintSourceType, CONSTRAINT_NOT_EXIST, "CONSTRAINT_NOT_EXIST"); SetEnumProperty(env, constraintSourceType, CONSTRAINT_TYPE_BASE, "CONSTRAINT_TYPE_BASE"); SetEnumProperty(env, constraintSourceType, CONSTRAINT_TYPE_DEVICE_OWNER, "CONSTRAINT_TYPE_DEVICE_OWNER"); SetEnumProperty(env, constraintSourceType, CONSTRAINT_TYPE_PROFILE_OWNER, "CONSTRAINT_TYPE_PROFILE_OWNER"); napi_property_descriptor exportEnum[] = { DECLARE_NAPI_PROPERTY("OsAccountType", osAccountType), DECLARE_NAPI_PROPERTY("ConstraintSourceType", constraintSourceType), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(exportEnum) / sizeof(*exportEnum), exportEnum));
-
分析代码发现,代码19行导出16 - 17行两个枚举
OsAccountType
和ConstraintSourceType
,其中OsAccountType
包括4 - 6行的3个值:ADMIN,NORMAL,GUEST 。 -
此时可以确认hap包js调用时传入的 OsAccountType.Guest 与napi实际导出的值 OsAccountType.GUEST 不匹配而导致报错。
-
将hap包js调用时传入的值改为正确的值,即执行成功。
6 知识分享
在hap的开发中,在使用tvos-o提供的js sdk api时,必须与各模块napi导出的方法,枚举,属性以及声明文件*.d.ts等等保存一致,避免出现类似的问题。
更多推荐
所有评论(0)