• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vector>
17 
18 #include "common_components/heap/barrier/barrier.h"
19 #include "common_components/heap/collector/collector.h"
20 #include "common_interfaces/objects/ref_field.h"
21 #include "common_interfaces/objects/base_object.h"
22 
23 #include "common_components/tests/test_helper.h"
24 
25 using namespace common;
26 
27 
28 class DummyObject : public BaseObject {
29 public:
GetTypeInfo() const30     const common::TypeInfo* GetTypeInfo() const
31     {
32         return nullptr;
33     }
GetSize() const34     size_t GetSize() const
35     {
36         return sizeof(DummyObject);
37     }
38 };
39 
40 
41 class MockCollector : public Collector {
42 public:
Init(const RuntimeParam & param)43     void Init(const RuntimeParam& param) override {}
RunGarbageCollection(uint64_t,GCReason,GCType)44     void RunGarbageCollection(uint64_t, GCReason, GCType) override {}
ForwardObject(BaseObject *)45     BaseObject* ForwardObject(BaseObject*) override
46     {
47         return nullptr;
48     }
ShouldIgnoreRequest(GCRequest &)49     bool ShouldIgnoreRequest(GCRequest&) override
50     {
51         return false;
52     }
IsFromObject(BaseObject *) const53     bool IsFromObject(BaseObject*) const override
54     {
55         return false;
56     }
IsUnmovableFromObject(BaseObject *) const57     bool IsUnmovableFromObject(BaseObject*) const override
58     {
59         return false;
60     }
FindToVersion(BaseObject *) const61     BaseObject* FindToVersion(BaseObject*) const override
62     {
63         return nullptr;
64     }
65 
TryUpdateRefField(BaseObject * Obj,RefField<> & field,BaseObject * & toVersion) const66     bool TryUpdateRefField(BaseObject* Obj, RefField<>& field, BaseObject*& toVersion) const override
67     {
68         toVersion = reinterpret_cast<BaseObject*>(field.GetFieldValue());
69         return true;
70     }
71 
TryForwardRefField(BaseObject *,RefField<> &,BaseObject * &) const72     bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override
73     {
74         return false;
75     }
TryUntagRefField(BaseObject *,RefField<> &,BaseObject * &) const76     bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override
77     {
78         return false;
79     }
GetAndTryTagRefField(BaseObject *) const80     RefField<> GetAndTryTagRefField(BaseObject*) const override
81     {
82         return RefField<>(nullptr);
83     }
IsOldPointer(RefField<> &) const84     bool IsOldPointer(RefField<>&) const override
85     {
86         return false;
87     }
IsCurrentPointer(RefField<> &) const88     bool IsCurrentPointer(RefField<>&) const override
89     {
90         return false;
91     }
AddRawPointerObject(BaseObject *)92     void AddRawPointerObject(BaseObject*) override {}
RemoveRawPointerObject(BaseObject *)93     void RemoveRawPointerObject(BaseObject*) override {}
94 };
95 
96 
97 class BarrierTest : public common::test::BaseTestWithScope {
98 protected:
99     MockCollector collector;
100     Barrier barrier{collector};
101     std::unique_ptr<DummyObject> dummyObj;
102 
SetUp()103     void SetUp() override
104     {
105         dummyObj = std::make_unique<DummyObject>();
106     }
107 };
108 
HWTEST_F_L0(BarrierTest,ReadRefField_ReturnsExpectedValue)109 HWTEST_F_L0(BarrierTest, ReadRefField_ReturnsExpectedValue) {
110     uint64_t value = reinterpret_cast<uint64_t>(dummyObj.get());
111     RefField<false> field(value);
112 
113     BaseObject* result = barrier.ReadRefField(nullptr, field);
114     EXPECT_EQ(result, dummyObj.get());
115 }
116 
HWTEST_F_L0(BarrierTest,WriteRefField_SetsTargetObject)117 HWTEST_F_L0(BarrierTest, WriteRefField_SetsTargetObject) {
118     uint64_t initValue = 0;
119     RefField<false> field(initValue);
120     BaseObject* newRef = dummyObj.get();
121 
122     barrier.WriteRefField(nullptr, field, newRef);
123     EXPECT_EQ(field.GetTargetObject(), newRef);
124 }
125 
HWTEST_F_L0(BarrierTest,WriteStaticRef_SetsTargetObject)126 HWTEST_F_L0(BarrierTest, WriteStaticRef_SetsTargetObject) {
127     uint64_t initValue = 0;
128     RefField<false> field(initValue);
129     BaseObject* newRef = dummyObj.get();
130 
131     barrier.WriteStaticRef(field, newRef);
132     EXPECT_EQ(field.GetTargetObject(), newRef);
133 }
134 
HWTEST_F_L0(BarrierTest,AtomicWriteRefField_UpdatesWithMemoryOrder)135 HWTEST_F_L0(BarrierTest, AtomicWriteRefField_UpdatesWithMemoryOrder) {
136     uint64_t initValue = 0;
137     RefField<true> field(initValue);
138     BaseObject* newRef = dummyObj.get();
139 
140     barrier.AtomicWriteRefField(nullptr, field, newRef, std::memory_order_relaxed);
141     EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), newRef);
142 }
143 
HWTEST_F_L0(BarrierTest,CompareAndSwapRefField_WorksWithSuccessAndFailure)144 HWTEST_F_L0(BarrierTest, CompareAndSwapRefField_WorksWithSuccessAndFailure) {
145     uint64_t initValue = 0;
146     RefField<true> field(initValue);
147     BaseObject* oldRef = nullptr;
148     BaseObject* newRef = dummyObj.get();
149 
150     bool result = barrier.CompareAndSwapRefField(nullptr, field, oldRef, newRef,
151                                                  std::memory_order_seq_cst, std::memory_order_relaxed);
152     EXPECT_TRUE(result);
153     EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), newRef);
154 }
155 
HWTEST_F_L0(BarrierTest,WriteStruct_HandlesDifferentLengths)156 HWTEST_F_L0(BarrierTest, WriteStruct_HandlesDifferentLengths) {
157     size_t srcBufferSize = 512;
158     size_t dstBufferSize = 1024;
159     char* srcBuffer = new char[srcBufferSize];
160     char* dstBuffer = new char[dstBufferSize];
161 
162     for (size_t i = 0; i < srcBufferSize; ++i) {
163         srcBuffer[i] = static_cast<char>(i % 256);
164     }
165 
166     barrier.WriteStruct(nullptr, reinterpret_cast<HeapAddress>(dstBuffer), dstBufferSize,
167                      reinterpret_cast<HeapAddress>(srcBuffer), srcBufferSize);
168 
169     EXPECT_EQ(memcmp(dstBuffer, srcBuffer, srcBufferSize), 0);
170 
171     for (size_t i = srcBufferSize; i < dstBufferSize; ++i) {
172         EXPECT_EQ(dstBuffer[i], 0);
173     }
174 
175     delete[] srcBuffer;
176     delete[] dstBuffer;
177 }
178 
HWTEST_F_L0(BarrierTest,ReadStaticRef_ReturnsExpectedValue)179 HWTEST_F_L0(BarrierTest, ReadStaticRef_ReturnsExpectedValue) {
180     uint64_t value = reinterpret_cast<uint64_t>(dummyObj.get());
181     RefField<false> field(value);
182 
183     BaseObject* result = barrier.ReadStaticRef(field);
184     EXPECT_EQ(result, dummyObj.get());
185 }
186 
HWTEST_F_L0(BarrierTest,AtomicSwapRefField_ExchangesCorrectly)187 HWTEST_F_L0(BarrierTest, AtomicSwapRefField_ExchangesCorrectly) {
188     uint64_t initValue = reinterpret_cast<uint64_t>(dummyObj.get());
189     RefField<true> field(initValue);
190     BaseObject* newRef = reinterpret_cast<BaseObject*>(0x1234567890);
191     BaseObject* oldValue = barrier.AtomicSwapRefField(nullptr, field, newRef, std::memory_order_seq_cst);
192 
193     EXPECT_EQ(oldValue, dummyObj.get());
194     EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), newRef);
195 }
196 
HWTEST_F_L0(BarrierTest,AtomicReadRefField_ReadsCorrectly)197 HWTEST_F_L0(BarrierTest, AtomicReadRefField_ReadsCorrectly) {
198     uint64_t initValue = reinterpret_cast<uint64_t>(dummyObj.get());
199     RefField<true> field(initValue);
200 
201     BaseObject* value = barrier.AtomicReadRefField(nullptr, field, std::memory_order_seq_cst);
202 
203     EXPECT_EQ(value, dummyObj.get());
204 }
205 
HWTEST_F_L0(BarrierTest,CopyStructArray_CopiesDataCorrectly)206 HWTEST_F_L0(BarrierTest, CopyStructArray_CopiesDataCorrectly) {
207     constexpr size_t arraySize = 100;
208     char* srcBuffer = new char[arraySize];
209     char* dstBuffer = new char[arraySize];
210 
211     for (size_t i = 0; i < arraySize; ++i) {
212         srcBuffer[i] = static_cast<char>(i % 256);
213     }
214 
215     BaseObject srcObj;
216     BaseObject dstObj;
217 
218     HeapAddress srcFieldAddr = reinterpret_cast<HeapAddress>(srcBuffer);
219     HeapAddress dstFieldAddr = reinterpret_cast<HeapAddress>(dstBuffer);
220 
221     barrier.CopyStructArray(&dstObj, dstFieldAddr, arraySize, &srcObj, srcFieldAddr, arraySize);
222 
223     EXPECT_EQ(memcmp(dstBuffer, srcBuffer, arraySize), 0);
224 
225     delete[] srcBuffer;
226     delete[] dstBuffer;
227 }
228 
HWTEST_F_L0(BarrierTest,ReadStruct_ReadsCorrectly)229 HWTEST_F_L0(BarrierTest, ReadStruct_ReadsCorrectly) {
230     struct TestStruct {
231         int a;
232         double b;
233     };
234 
235     TestStruct* initValue = new TestStruct{42, 3.14};
236     RefField<false> field(reinterpret_cast<uint64_t>(initValue));
237 
238     char dstBuffer[sizeof(TestStruct)];
239     HeapAddress dstAddr = reinterpret_cast<HeapAddress>(dstBuffer);
240 
241     BaseObject dummyObj;
242     HeapAddress srcAddr = reinterpret_cast<HeapAddress>(field.GetTargetObject());
243 
244     barrier.ReadStruct(dstAddr, &dummyObj, srcAddr, sizeof(TestStruct));
245 
246     TestStruct* result = reinterpret_cast<TestStruct*>(dstBuffer);
247     EXPECT_EQ(result->a, initValue->a);
248     EXPECT_EQ(result->b, initValue->b);
249 
250     delete initValue;
251 }
252 
HWTEST_F_L0(BarrierTest,AtomicWriteStaticRef_NonConcurrent)253 HWTEST_F_L0(BarrierTest, AtomicWriteStaticRef_NonConcurrent)
254 {
255     DummyObject* targetObj = new DummyObject();
256     DummyObject* initialObj = new DummyObject();
257 
258     RefField<true> field(reinterpret_cast<BaseObject*>(0x1));
259     field.SetTargetObject(initialObj);
260 
261     MockCollector collector;
262     Barrier barrier(collector);
263 
264     barrier.AtomicWriteRefField(nullptr, field, targetObj, std::memory_order_relaxed);
265 
266     EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), targetObj);
267 }