1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common_components/heap/heap.h"
17 #include "common_interfaces/base_runtime.h"
18 #include "common_components/tests/test_helper.h"
19 #include <thread>
20
21 namespace common::test {
22
23 class BaseRuntimeTest : public BaseTestWithScope {
24 protected:
SetUp()25 void SetUp() override {}
TearDown()26 void TearDown() override {}
ResetRuntime()27 void ResetRuntime()
28 {
29 if (auto* instance = BaseRuntime::GetInstance()) {
30 BaseRuntime::DestroyInstance();
31 }
32 }
33 };
34
HWTEST_F_L0(BaseRuntimeTest,RequestGC_Test1)35 HWTEST_F_L0(BaseRuntimeTest, RequestGC_Test1)
36 {
37 BaseRuntime* runtime = BaseRuntime::GetInstance();
38 ASSERT_TRUE(runtime != nullptr);
39 runtime->RequestGC(static_cast<GCReason>(-1), false, static_cast<GCType>(-1));
40
41 BaseObject obj;
42 RefField<false> field(reinterpret_cast<HeapAddress>(&obj));
43 auto result = runtime->ReadBarrier(reinterpret_cast<void*>(&field));
44 EXPECT_TRUE(result != nullptr);
45 }
46
HWTEST_F_L0(BaseRuntimeTest,GetInstance_NotNull)47 HWTEST_F_L0(BaseRuntimeTest, GetInstance_NotNull) {
48 auto* instance = BaseRuntime::GetInstance();
49 ASSERT_NE(instance, nullptr);
50 }
51
HWTEST_F_L0(BaseRuntimeTest,DestroyInstance_SafeIfUninitialized)52 HWTEST_F_L0(BaseRuntimeTest, DestroyInstance_SafeIfUninitialized) {
53 auto* instance = BaseRuntime::GetInstance();
54 ASSERT_NE(instance, nullptr);
55
56 EXPECT_NO_FATAL_FAILURE(BaseRuntime::DestroyInstance());
57
58 instance = BaseRuntime::GetInstance();
59 ASSERT_NE(instance, nullptr);
60 }
HWTEST_F_L0(BaseRuntimeTest,GetInstance_ReturnsValidInstance)61 HWTEST_F_L0(BaseRuntimeTest, GetInstance_ReturnsValidInstance) {
62 ResetRuntime();
63 BaseRuntime* instance1 = BaseRuntime::GetInstance();
64 BaseRuntime* instance2 = BaseRuntime::GetInstance();
65
66 ASSERT_NE(instance1, nullptr);
67 EXPECT_EQ(instance1, instance2);
68 }
69
HWTEST_F_L0(BaseRuntimeTest,ThreadSafe_GetInstance)70 HWTEST_F_L0(BaseRuntimeTest, ThreadSafe_GetInstance) {
71 ResetRuntime();
72 constexpr int kThreads = 4;
73 std::vector<BaseRuntime*> instances(kThreads);
74 std::vector<std::thread> threads;
75
76 for (int i = 0; i < kThreads; ++i) {
77 threads.emplace_back([&instances, i]() {
78 instances[i] = BaseRuntime::GetInstance();
79 });
80 }
81
82 for (auto& t : threads) {
83 t.join();
84 }
85
86 for (int i = 1; i < kThreads; ++i) {
87 EXPECT_EQ(instances[0], instances[i]);
88 }
89 }
90
HWTEST_F_L0(BaseRuntimeTest,RequestGC_Sync_CallsHeapManager)91 HWTEST_F_L0(BaseRuntimeTest, RequestGC_Sync_CallsHeapManager) {
92 auto* runtime = BaseRuntime::GetInstance();
93 ASSERT_NE(runtime, nullptr);
94 runtime->Init();
95 struct TestCase {
96 GCReason reason;
97 bool async;
98 GCType gcType;
99 };
100
101 const std::vector<TestCase> testCases = {
102 {GC_REASON_USER, false, GC_TYPE_FULL},
103 {GC_REASON_USER, true, GC_TYPE_FULL},
104 {GC_REASON_BACKUP, false, GC_TYPE_FULL},
105 {GC_REASON_APPSPAWN, false, GC_TYPE_FULL}
106 };
107
108 for (TestCase tc : testCases) {
109 testing::internal::CaptureStderr();
110 EXPECT_NO_FATAL_FAILURE(runtime->RequestGC(tc.reason, tc.async, tc.gcType));
111 std::string output = testing::internal::GetCapturedStderr();
112
113 EXPECT_TRUE(output.empty()) << "GC reason " << static_cast<int>(tc.reason)
114 << " produced unexpected stderr output.";
115 }
116
117 runtime->Fini();
118 BaseRuntime::DestroyInstance();
119 }
120
121 } // namespace common::test
122