* Copyright (c) 2026 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 <cstdint>
#include <cstring>
#include <dlfcn.h>
#include <dlfcn_ext.h>
#include <gtest/gtest.h>
#include <string>
#include <sys/sysinfo.h>
#include <unistd.h>
#include "arkweb_preload_common.cpp"
#include "parameters.h"
#include "arkweb_utils.h"
using namespace testing::ext;
#ifdef __cplusplus
extern "C" {
#endif
void *g_dlopenMockValue = reinterpret_cast<void *>(0x1);
void SetDlopenMockValue(void *mockValue)
{
g_dlopenMockValue = mockValue;
}
void *DlopenMock(const char *filename, int flags)
{
(void)filename;
(void)flags;
return g_dlopenMockValue;
}
void *g_dlopenNsMockValue = reinterpret_cast<void *>(0x1);
void SetDlopenNsMockValue(void *mockValue)
{
g_dlopenNsMockValue = mockValue;
}
void *DlopenNsMock(Dl_namespace *dlns, const char *libName, int flag)
{
(void)dlns;
(void)libName;
(void)flag;
return g_dlopenNsMockValue;
}
int g_sysinfoMockValue = 0;
void SetSysinfoMockValue(int mockValue)
{
g_sysinfoMockValue = mockValue;
}
int SysinfoMock(struct sysinfo *info)
{
if (g_sysinfoMockValue == 0) {
info->totalram = 3UL * 1024UL * 1024UL * 1024UL;
return 0;
}
return -1;
}
void DlnsInitMock(Dl_namespace *dlns, const char *name)
{
(void)dlns;
(void)name;
}
int DlnsCreateMock(Dl_namespace *dlns, const char *libPath)
{
(void)dlns;
(void)libPath;
return 0;
}
int DlnsGetMock(const char *name, Dl_namespace *dlns)
{
(void)name;
(void)dlns;
return 0;
}
int DlnsInheritMock(Dl_namespace *dlns, Dl_namespace *inherited, const char *sharedLibs)
{
(void)dlns;
(void)inherited;
(void)sharedLibs;
return 0;
}
#ifdef __cplusplus
}
#endif
namespace OHOS::ArkWeb {
class ArkWebPreloadCommonTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
static std::string savedPackageName;
};
std::string ArkWebPreloadCommonTest::savedPackageName;
void ArkWebPreloadCommonTest::SetUpTestCase(void)
{
savedPackageName = OHOS::system::GetParameter("persist.arkwebcore.package_name", "");
}
void ArkWebPreloadCommonTest::TearDownTestCase(void)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", savedPackageName);
}
void ArkWebPreloadCommonTest::SetUp(void) {}
void ArkWebPreloadCommonTest::TearDown(void) {}
* @brief Empty package name returns empty path
*/
HWTEST_F(ArkWebPreloadCommonTest, GetArkwebBundleInstallLibPath_EmptyPackageName_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "");
auto res = GetArkwebBundleInstallLibPath();
EXPECT_EQ(res, "");
}
* @brief Valid package name with EVERGREEN engine returns correct path
*/
HWTEST_F(ArkWebPreloadCommonTest, GetArkwebBundleInstallLibPath_EvergreenEngine_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
OHOS::system::SetParameter("web.engine.enforce", "0");
setActiveWebEngineVersion(ArkWebEngineVersion::SYSTEM_DEFAULT);
auto res = GetArkwebBundleInstallLibPath();
EXPECT_FALSE(res.empty());
#if defined(webview_arm64)
EXPECT_NE(res.find("arm64"), std::string::npos);
#elif defined(webview_x86_64)
EXPECT_EQ(res, "");
#else
EXPECT_NE(res.find("arm"), std::string::npos);
EXPECT_EQ(res.find("arm64"), std::string::npos);
#endif
OHOS::system::SetParameter("web.engine.enforce", std::to_string(webEngineEnforce));
}
* @brief GetOhosAdptGlueSrcLibPath returns correct path per architecture
*/
HWTEST_F(ArkWebPreloadCommonTest, GetOhosAdptGlueSrcLibPath_ArchPath_001, TestSize.Level1)
{
auto res = GetOhosAdptGlueSrcLibPath();
#if defined(webview_arm64)
EXPECT_EQ(res, "/system/lib64/libohos_adapter_glue_source.z.so");
#elif defined(webview_x86_64)
EXPECT_EQ(res, "");
#else
EXPECT_EQ(res, "/system/lib/libohos_adapter_glue_source.z.so");
#endif
}
* @brief sysinfo success returns positive RAM value
*/
HWTEST_F(ArkWebPreloadCommonTest, GetSysTotalRAMInfo_Success_001, TestSize.Level1)
{
SetSysinfoMockValue(0);
int32_t ram = GetSysTotalRAMInfo();
EXPECT_GT(ram, 0);
}
* @brief sysinfo failure returns 0
*/
HWTEST_F(ArkWebPreloadCommonTest, GetSysTotalRAMInfo_Fail_001, TestSize.Level1)
{
SetSysinfoMockValue(-1);
int32_t ram = GetSysTotalRAMInfo();
EXPECT_EQ(ram, 0);
SetSysinfoMockValue(0);
}
* @brief ramSize well below 8GB threshold results in PRELOAD_NO
*/
HWTEST_F(ArkWebPreloadCommonTest, GetRenderPreLoadMode_SmallRAM_001, TestSize.Level1)
{
int32_t smallRam = 1;
int mode = GetRenderPreLoadMode(smallRam);
EXPECT_EQ(mode, 0);
}
* @brief ramSize exactly at 8GB threshold results in PRELOAD_NO
*/
HWTEST_F(ArkWebPreloadCommonTest, GetRenderPreLoadMode_Exactly8GB_001, TestSize.Level1)
{
int32_t thresholdRam = RAM_SIZE_8G * SIZE_KB;
int mode = GetRenderPreLoadMode(thresholdRam);
EXPECT_EQ(mode, 0);
}
* @brief ramSize > 8GB reads preload mode from system parameter (mode 1)
*/
HWTEST_F(ArkWebPreloadCommonTest, GetRenderPreLoadMode_LargeRAM_Partial_001, TestSize.Level1)
{
int32_t largeRam = RAM_SIZE_8G * SIZE_KB + 1;
int savedPreloadMode = OHOS::system::GetIntParameter("const.startup.nwebspawn.preloadMode", 0);
OHOS::system::SetParameter("const.startup.nwebspawn.preloadMode", "1");
int mode = GetRenderPreLoadMode(largeRam);
EXPECT_EQ(mode, 1);
OHOS::system::SetParameter("const.startup.nwebspawn.preloadMode", std::to_string(savedPreloadMode));
}
* @brief PRELOAD_NO mode does not call any preload
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebLibForRender_NoPreload_001, TestSize.Level1)
{
EXPECT_NO_FATAL_FAILURE(PreloadArkWebLibForRender(0));
}
* @brief PRELOAD_PARTIAL mode preloads only adapter glue lib
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebLibForRender_PartialPreload_001, TestSize.Level1)
{
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadArkWebLibForRender(1));
}
* @brief PRELOAD_FULL mode preloads both adapter glue and engine
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebLibForRender_FullPreload_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
OHOS::system::SetParameter("web.engine.enforce", "0");
setActiveWebEngineVersion(ArkWebEngineVersion::SYSTEM_DEFAULT);
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
SetDlopenNsMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadArkWebLibForRender(2));
OHOS::system::SetParameter("web.engine.enforce", std::to_string(webEngineEnforce));
}
* @brief Empty engine lib path causes early return without crash
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebEngineLib_EmptyPath_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "");
EXPECT_NO_FATAL_FAILURE(PreloadArkWebEngineLib());
}
* @brief Valid path with successful dlopen_ns
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebEngineLib_ValidPath_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
OHOS::system::SetParameter("web.engine.enforce", "0");
setActiveWebEngineVersion(ArkWebEngineVersion::SYSTEM_DEFAULT);
SetDlopenNsMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadArkWebEngineLib());
OHOS::system::SetParameter("web.engine.enforce", std::to_string(webEngineEnforce));
}
* @brief Valid path with dlopen_ns returning nullptr
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebEngineLib_DlopenFail_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
OHOS::system::SetParameter("web.engine.enforce", "0");
setActiveWebEngineVersion(ArkWebEngineVersion::SYSTEM_DEFAULT);
SetDlopenNsMockValue(nullptr);
EXPECT_NO_FATAL_FAILURE(PreloadArkWebEngineLib());
OHOS::system::SetParameter("web.engine.enforce", std::to_string(webEngineEnforce));
}
* @brief Adapter glue preload with successful dlopen
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadOHOSAdptGlueSrcLib_DlopenSuccess_001, TestSize.Level1)
{
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadOHOSAdptGlueSrcLib());
}
* @brief Adapter glue preload with dlopen returning nullptr
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadOHOSAdptGlueSrcLib_DlopenFail_001, TestSize.Level1)
{
SetDlopenMockValue(nullptr);
EXPECT_NO_FATAL_FAILURE(PreloadOHOSAdptGlueSrcLib());
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
}
* @brief Public entry point completes without crash
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebLibForRender_Entry_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
OHOS::system::SetParameter("web.engine.enforce", "0");
setActiveWebEngineVersion(ArkWebEngineVersion::SYSTEM_DEFAULT);
SetSysinfoMockValue(0);
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
SetDlopenNsMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadArkWebLibForRender());
OHOS::system::SetParameter("web.engine.enforce", std::to_string(webEngineEnforce));
}
* @brief sysinfo failure triggers PRELOAD_NO path
*/
HWTEST_F(ArkWebPreloadCommonTest, PreloadArkWebLibForRender_SysinfoFail_001, TestSize.Level1)
{
OHOS::system::SetParameter("persist.arkwebcore.package_name", "com.ohos.arkwebcore");
SetSysinfoMockValue(-1);
SetDlopenMockValue(reinterpret_cast<void *>(0x1));
SetDlopenNsMockValue(reinterpret_cast<void *>(0x1));
EXPECT_NO_FATAL_FAILURE(PreloadArkWebLibForRender());
SetSysinfoMockValue(0);
}
}