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 "gtest/gtest.h"
17
18 #ifdef ROSEN_OHOS
19 #include <parcel.h>
20 #include <message_parcel.h>
21 #endif
22
23 #include "effect/blend_shader_obj.h"
24 #include "effect/shader_effect.h"
25
26 #define private public
27 #include "effect/shader_effect_lazy.h"
28 #undef private
29
30 #include "effect_test_utils.h"
31 #include "transaction/rs_marshalling_helper.h"
32 #include "utils/object_helper.h"
33
34 using namespace testing;
35 using namespace testing::ext;
36
37 namespace OHOS {
38 namespace Rosen {
39 namespace Drawing {
40 class ShaderEffectLazyTest : public testing::Test {
41 public:
42 static void SetUpTestCase();
43 static void TearDownTestCase();
44 void SetUp() override;
45 void TearDown() override;
46 };
47
48
SetUpTestCase()49 void ShaderEffectLazyTest::SetUpTestCase()
50 {
51 #ifdef ROSEN_OHOS
52 EffectTestUtils::SetupMarshallingCallbacks();
53 #endif
54 }
55
TearDownTestCase()56 void ShaderEffectLazyTest::TearDownTestCase()
57 {
58 #ifdef ROSEN_OHOS
59 EffectTestUtils::RestoreMarshallingCallbacks();
60 #endif
61 }
SetUp()62 void ShaderEffectLazyTest::SetUp() {}
TearDown()63 void ShaderEffectLazyTest::TearDown() {}
64
65 /*
66 * @tc.name: CreateFromShaderEffectObj001
67 * @tc.desc: Test ShaderEffectLazy creation from ShaderEffectObj and GetShaderEffectObj functionality
68 * @tc.type: FUNC
69 * @tc.require: AR000GGNV3
70 * @tc.author:
71 */
72 HWTEST_F(ShaderEffectLazyTest, CreateFromShaderEffectObj001, TestSize.Level1)
73 {
74 // Test 1: CreateFromShaderEffectObj with valid BlendShaderObj
75 auto dstShader = ShaderEffect::CreateColorShader(0xFF00FF00);
76 auto srcShader = ShaderEffect::CreateColorShader(0xFF0000FF);
77 auto shaderObj = BlendShaderObj::Create(dstShader, srcShader, BlendMode::SRC_OVER);
78
79 auto lazyShader = ShaderEffectLazy::CreateFromShaderEffectObj(shaderObj);
80 EXPECT_TRUE(lazyShader != nullptr);
81 EXPECT_TRUE(lazyShader->IsLazy());
82 EXPECT_EQ(lazyShader->GetType(), ShaderEffect::ShaderEffectType::LAZY_SHADER);
83
84 // Test GetShaderEffectObj functionality
85 auto retrievedObj = lazyShader->GetShaderEffectObj();
86 EXPECT_TRUE(retrievedObj != nullptr);
87 EXPECT_EQ(retrievedObj->GetType(), static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
88 EXPECT_EQ(retrievedObj->GetSubType(), static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
89
90 // Verify that the original and retrieved objects are consistent
91 EXPECT_EQ(shaderObj->GetType(), retrievedObj->GetType());
92 EXPECT_EQ(shaderObj->GetSubType(), retrievedObj->GetSubType());
93 EXPECT_EQ(shaderObj.get(), retrievedObj.get()); // Should be the same object instance
94
95 // Test 2: CreateFromShaderEffectObj with null object
96 std::shared_ptr<ShaderEffectObj> nullObj = nullptr;
97 auto nullLazyShader = ShaderEffectLazy::CreateFromShaderEffectObj(nullObj);
98 EXPECT_TRUE(nullLazyShader == nullptr);
99 }
100
101 /*
102 * @tc.name: Materialize001
103 * @tc.desc: Test ShaderEffectLazy::Materialize functionality
104 * @tc.type: FUNC
105 * @tc.require: AR000GGNV3
106 * @tc.author:
107 */
108 HWTEST_F(ShaderEffectLazyTest, Materialize001, TestSize.Level1)
109 {
110 auto dstShader = ShaderEffect::CreateColorShader(0xFFFF0000);
111 auto srcShader = ShaderEffect::CreateColorShader(0xFF00FF00);
112 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
113 EXPECT_TRUE(lazyShader != nullptr);
114
115 auto materializedShader = lazyShader->Materialize();
116 EXPECT_TRUE(materializedShader != nullptr);
117 EXPECT_FALSE(materializedShader->IsLazy());
118 EXPECT_EQ(materializedShader->GetType(), ShaderEffect::ShaderEffectType::BLEND);
119 }
120
121 /*
122 * @tc.name: CreateBlendShader001
123 * @tc.desc: Test ShaderEffectLazy::CreateBlendShader with various parameter scenarios
124 * @tc.type: FUNC
125 * @tc.require: AR000GGNV3
126 * @tc.author:
127 */
128 HWTEST_F(ShaderEffectLazyTest, CreateBlendShader001, TestSize.Level1)
129 {
130 // Test 1: CreateBlendShader with valid shaders
131 auto dstShader = ShaderEffect::CreateColorShader(0xFF0000FF);
132 auto srcShader = ShaderEffect::CreateColorShader(0xFF00FF00);
133 EXPECT_TRUE(dstShader != nullptr);
134 EXPECT_TRUE(srcShader != nullptr);
135
136 auto lazyBlendShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
137 EXPECT_TRUE(lazyBlendShader != nullptr);
138
139 // Verify it's a Lazy shader with correct type
140 EXPECT_TRUE(lazyBlendShader->IsLazy());
141 EXPECT_EQ(lazyBlendShader->GetType(), ShaderEffect::ShaderEffectType::LAZY_SHADER);
142
143 // Verify the underlying object
144 auto shaderObj = lazyBlendShader->GetShaderEffectObj();
145 EXPECT_TRUE(shaderObj != nullptr);
146 EXPECT_EQ(shaderObj->GetType(), static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
147 EXPECT_EQ(shaderObj->GetSubType(), static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
148
149 // Test 2: CreateBlendShader with null dst shader
150 std::shared_ptr<ShaderEffect> nullDst = nullptr;
151 auto nullDstResult = ShaderEffectLazy::CreateBlendShader(nullDst, srcShader, BlendMode::MULTIPLY);
152 EXPECT_TRUE(nullDstResult == nullptr); // Should return nullptr for null dst
153
154 // Test 3: CreateBlendShader with null src shader
155 std::shared_ptr<ShaderEffect> nullSrc = nullptr;
156 auto nullSrcResult = ShaderEffectLazy::CreateBlendShader(dstShader, nullSrc, BlendMode::SCREEN);
157 EXPECT_TRUE(nullSrcResult == nullptr); // Should return nullptr for null src
158 }
159
160 /*
161 * @tc.name: CreateBlendShader002
162 * @tc.desc: Test ShaderEffectLazy::CreateBlendShader with Lazy shaders as input
163 * @tc.type: FUNC
164 * @tc.require: AR000GGNV3
165 * @tc.author:
166 */
167 HWTEST_F(ShaderEffectLazyTest, CreateBlendShader002, TestSize.Level1)
168 {
169 // Create Lazy shaders as input
170 auto baseShader1 = ShaderEffect::CreateColorShader(0xFF0000FF);
171 auto baseShader2 = ShaderEffect::CreateColorShader(0xFF00FF00);
172 auto lazyDst = ShaderEffectLazy::CreateBlendShader(baseShader1, baseShader1, BlendMode::SRC_OVER);
173 auto lazySrc = ShaderEffectLazy::CreateBlendShader(baseShader2, baseShader2, BlendMode::SRC_OVER);
174
175 EXPECT_TRUE(lazyDst != nullptr);
176 EXPECT_TRUE(lazySrc != nullptr);
177 EXPECT_TRUE(lazyDst->IsLazy());
178 EXPECT_TRUE(lazySrc->IsLazy());
179
180 // CreateBlendShader should accept Lazy shaders as input
181 auto lazyBlendShader = ShaderEffectLazy::CreateBlendShader(lazyDst, lazySrc, BlendMode::OVERLAY);
182 EXPECT_TRUE(lazyBlendShader != nullptr);
183 EXPECT_TRUE(lazyBlendShader->IsLazy());
184 EXPECT_EQ(lazyBlendShader->GetType(), ShaderEffect::ShaderEffectType::LAZY_SHADER);
185
186 // Get ShaderEffectObj and verify subType
187 auto shaderEffectObj = lazyBlendShader->GetShaderEffectObj();
188 EXPECT_TRUE(shaderEffectObj != nullptr);
189 EXPECT_EQ(shaderEffectObj->GetType(), static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
190 EXPECT_EQ(shaderEffectObj->GetSubType(), static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
191 }
192
193 /*
194 * @tc.name: SerializeDeserialize001
195 * @tc.desc: Test ShaderEffectLazy defensive Serialize/Deserialize methods
196 * @tc.type: FUNC
197 * @tc.require: AR000GGNV3
198 * @tc.author:
199 */
200 HWTEST_F(ShaderEffectLazyTest, SerializeDeserialize001, TestSize.Level1)
201 {
202 auto dstShader = ShaderEffect::CreateColorShader(0xFF123456);
203 auto srcShader = ShaderEffect::CreateColorShader(0xFF654321);
204 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
205 EXPECT_TRUE(lazyShader != nullptr);
206
207 // Test defensive Serialize - should return nullptr
208 auto serializedData = lazyShader->Serialize();
209 EXPECT_TRUE(serializedData == nullptr);
210
211 // Test defensive Deserialize - should return false
212 auto dummyData = std::make_shared<Data>();
213 bool deserializeResult = lazyShader->Deserialize(dummyData);
214 EXPECT_FALSE(deserializeResult);
215 }
216
217 /*
218 * @tc.name: MaterializeWithEmptyShader001
219 * @tc.desc: Test ShaderEffectLazy::Materialize with empty underlying shader
220 * @tc.type: FUNC
221 * @tc.require: AR000GGNV3
222 */
223 HWTEST_F(ShaderEffectLazyTest, MaterializeWithEmptyShader001, TestSize.Level1)
224 {
225 // Create a mock ShaderEffectObj that returns empty shader
226 class MockShaderEffectObj : public ShaderEffectObj {
227 public:
MockShaderEffectObj()228 MockShaderEffectObj() : ShaderEffectObj(static_cast<int32_t>(ShaderEffect::ShaderEffectType::COLOR_SHADER)) {}
229
GenerateBaseObject()230 std::shared_ptr<void> GenerateBaseObject() override
231 {
232 // Return a shader that will have empty Serialize data
233 class MockShaderEffect : public ShaderEffect {
234 public:
235 MockShaderEffect() : ShaderEffect(ShaderEffectType::COLOR_SHADER) {}
236 std::shared_ptr<Data> Serialize() const override
237 {
238 return nullptr; // Simulate failed serialization
239 }
240 };
241 return std::static_pointer_cast<void>(std::make_shared<MockShaderEffect>());
242 }
243
244 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel)245 bool Marshalling(Parcel& parcel) override { return true; }
Unmarshalling(Parcel & parcel,bool & isValid,int32_t depth)246 bool Unmarshalling(Parcel& parcel, bool& isValid, int32_t depth) override { isValid = true; return true; }
247 #endif
248 };
249
250 auto mockObj = std::make_shared<MockShaderEffectObj>();
251 auto lazyShader = ShaderEffectLazy::CreateFromShaderEffectObj(mockObj);
252 EXPECT_NE(lazyShader, nullptr);
253
254 // Materialize should succeed even with empty underlying shader
255 auto materializedShader = lazyShader->Materialize();
256 EXPECT_NE(materializedShader, nullptr);
257 EXPECT_EQ(materializedShader->GetType(), ShaderEffect::ShaderEffectType::COLOR_SHADER);
258 }
259
260 /*
261 * @tc.name: LazyContainingException001
262 * @tc.desc: Test Lazy shader containing exception NoLazy shader scenarios
263 * @tc.type: FUNC
264 * @tc.require: AR000GGNV3
265 */
266 HWTEST_F(ShaderEffectLazyTest, LazyContainingException001, TestSize.Level1)
267 {
268 // Create shaders that may fail during creation/serialization
269 auto baseShader = ShaderEffect::CreateColorShader(0xFF0000FF);
270 auto blendShader = ShaderEffect::CreateColorShader(0xFF00FF00);
271
272 // Create lazy shader with these base shaders
273 auto lazyShader = ShaderEffectLazy::CreateBlendShader(baseShader, blendShader, BlendMode::SRC_OVER);
274 EXPECT_NE(lazyShader, nullptr);
275 EXPECT_TRUE(lazyShader->IsLazy());
276
277 // Test materialization - should handle potential exceptions gracefully
278 auto materializedShader = lazyShader->Materialize();
279 EXPECT_NE(materializedShader, nullptr);
280 EXPECT_FALSE(materializedShader->IsLazy());
281 EXPECT_EQ(materializedShader->GetType(), ShaderEffect::ShaderEffectType::BLEND);
282
283 // Test that materialized shader can be used normally
284 auto secondMaterialization = lazyShader->Materialize();
285 EXPECT_NE(secondMaterialization, nullptr);
286 EXPECT_EQ(secondMaterialization->GetType(), materializedShader->GetType());
287 }
288
289 /*
290 * @tc.name: UnmarshallingReadTypeFailure001
291 * @tc.desc: Test ShaderEffectLazy::Unmarshalling with parcel.ReadInt32(type) failure
292 * @tc.type: FUNC
293 * @tc.require: AR000GGNV3
294 */
295 HWTEST_F(ShaderEffectLazyTest, UnmarshallingReadTypeFailure001, TestSize.Level1)
296 {
297 #ifdef ROSEN_OHOS
298 // Create an empty Parcel - ReadInt32 will fail due to no data
299 Parcel emptyParcel;
300 bool isValid = true;
301 auto result = ShaderEffectLazy::Unmarshalling(emptyParcel, isValid, 0);
302 EXPECT_EQ(result, nullptr);
303 #endif
304 }
305
306 /*
307 * @tc.name: UnmarshallingReadSubTypeFailure001
308 * @tc.desc: Test ShaderEffectLazy::Unmarshalling with parcel.ReadInt32(subType) failure
309 * @tc.type: FUNC
310 * @tc.require: AR000GGNV3
311 */
312 HWTEST_F(ShaderEffectLazyTest, UnmarshallingReadSubTypeFailure001, TestSize.Level1)
313 {
314 #ifdef ROSEN_OHOS
315 // Create a Parcel with only one int32 - first ReadInt32 succeeds, second fails
316 Parcel parcel;
317 parcel.WriteInt32(static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
318 // No second int32 written, so second ReadInt32 will fail
319 bool isValid = true;
320 auto result = ShaderEffectLazy::Unmarshalling(parcel, isValid, 0);
321 EXPECT_EQ(result, nullptr);
322 #endif
323 }
324
325 /*
326 * @tc.name: ChainedLazyShaders001
327 * @tc.desc: Test chained lazy shaders with Marshalling/Unmarshalling and serialization data comparison
328 * @tc.type: FUNC
329 * @tc.require: AR000GGNV3
330 * @tc.author:
331 */
332 HWTEST_F(ShaderEffectLazyTest, ChainedLazyShaders001, TestSize.Level1)
333 {
334 #ifdef ROSEN_OHOS
335 // Create base color shaders
336 auto baseShader1 = ShaderEffect::CreateColorShader(0xFF0000FF); // Blue
337 auto baseShader2 = ShaderEffect::CreateColorShader(0xFF00FF00); // Green
338 auto baseShader3 = ShaderEffect::CreateColorShader(0xFFFF0000); // Red
339 auto baseShader4 = ShaderEffect::CreateColorShader(0xFFFFFF00); // Yellow
340 ASSERT_NE(baseShader1, nullptr);
341 ASSERT_NE(baseShader2, nullptr);
342 ASSERT_NE(baseShader3, nullptr);
343 ASSERT_NE(baseShader4, nullptr);
344
345 // Create first level lazy shaders
346 auto lazyShader1 = ShaderEffectLazy::CreateBlendShader(baseShader1, baseShader2, BlendMode::SRC_OVER);
347 auto lazyShader2 = ShaderEffectLazy::CreateBlendShader(baseShader3, baseShader4, BlendMode::MULTIPLY);
348 ASSERT_NE(lazyShader1, nullptr);
349 ASSERT_NE(lazyShader2, nullptr);
350 EXPECT_TRUE(lazyShader1->IsLazy());
351 EXPECT_TRUE(lazyShader2->IsLazy());
352
353 // Create second level lazy shader by chaining first level lazy shaders
354 auto chainedLazyShader = ShaderEffectLazy::CreateBlendShader(lazyShader1, lazyShader2, BlendMode::OVERLAY);
355 ASSERT_NE(chainedLazyShader, nullptr);
356 EXPECT_TRUE(chainedLazyShader->IsLazy());
357 EXPECT_EQ(chainedLazyShader->GetType(), ShaderEffect::ShaderEffectType::LAZY_SHADER);
358
359 // Verify the underlying object structure
360 auto shaderObj = chainedLazyShader->GetShaderEffectObj();
361 ASSERT_NE(shaderObj, nullptr);
362 EXPECT_EQ(shaderObj->GetType(), static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
363 EXPECT_EQ(shaderObj->GetSubType(), static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
364
365 // Test Marshalling
366 Parcel parcel;
367 bool marshalResult = chainedLazyShader->Marshalling(parcel);
368 EXPECT_TRUE(marshalResult);
369
370 // Test Unmarshalling
371 parcel.RewindRead(0);
372 bool isValid = true;
373 auto unmarshalledShader = ShaderEffectLazy::Unmarshalling(parcel, isValid);
374 EXPECT_TRUE(isValid);
375 ASSERT_NE(unmarshalledShader, nullptr);
376 EXPECT_TRUE(unmarshalledShader->IsLazy());
377 EXPECT_EQ(unmarshalledShader->GetType(), ShaderEffect::ShaderEffectType::LAZY_SHADER);
378
379 // Verify unmarshalled object structure
380 auto unmarshalledObj = unmarshalledShader->GetShaderEffectObj();
381 ASSERT_NE(unmarshalledObj, nullptr);
382 EXPECT_EQ(unmarshalledObj->GetType(), static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
383 EXPECT_EQ(unmarshalledObj->GetSubType(), static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
384
385 // Test Materialize for both original and unmarshalled shaders
386 auto originalMaterialized = chainedLazyShader->Materialize();
387 auto unmarshalledMaterialized = unmarshalledShader->Materialize();
388 ASSERT_NE(originalMaterialized, nullptr);
389 ASSERT_NE(unmarshalledMaterialized, nullptr);
390 EXPECT_FALSE(originalMaterialized->IsLazy());
391 EXPECT_FALSE(unmarshalledMaterialized->IsLazy());
392 EXPECT_EQ(originalMaterialized->GetType(), ShaderEffect::ShaderEffectType::BLEND);
393 EXPECT_EQ(unmarshalledMaterialized->GetType(), ShaderEffect::ShaderEffectType::BLEND);
394
395 // Test serialization data comparison
396 auto originalSerializedData = originalMaterialized->Serialize();
397 auto unmarshalledSerializedData = unmarshalledMaterialized->Serialize();
398 ASSERT_NE(originalSerializedData, nullptr);
399 ASSERT_NE(unmarshalledSerializedData, nullptr);
400 EXPECT_GT(originalSerializedData->GetSize(), 0);
401 EXPECT_GT(unmarshalledSerializedData->GetSize(), 0);
402 // Compare serialized data sizes
403 EXPECT_EQ(originalSerializedData->GetSize(), unmarshalledSerializedData->GetSize());
404
405 // Compare serialized data content byte by byte
406 const uint8_t* originalBytes = static_cast<const uint8_t*>(originalSerializedData->GetData());
407 const uint8_t* unmarshalledBytes = static_cast<const uint8_t*>(unmarshalledSerializedData->GetData());
408 int memResult = memcmp(originalBytes, unmarshalledBytes, originalSerializedData->GetSize());
409 EXPECT_EQ(memResult, 0);
410
411 // Test round-trip marshalling consistency
412 Parcel parcel2;
413 bool marshalResult2 = unmarshalledShader->Marshalling(parcel2);
414 EXPECT_TRUE(marshalResult2);
415
416 // Compare marshalled data sizes
417 size_t originalMarshalledSize = parcel.GetDataSize();
418 size_t unmarshalledMarshalledSize = parcel2.GetDataSize();
419 EXPECT_EQ(originalMarshalledSize, unmarshalledMarshalledSize);
420 EXPECT_GT(originalMarshalledSize, 0);
421
422 // Compare marshalled data content
423 const uint8_t* originalMarshalledData = reinterpret_cast<const uint8_t*>(parcel.GetData());
424 const uint8_t* unmarshalledMarshalledData = reinterpret_cast<const uint8_t*>(parcel2.GetData());
425 int marshalledMemResult = memcmp(originalMarshalledData, unmarshalledMarshalledData, originalMarshalledSize);
426 EXPECT_EQ(marshalledMemResult, 0);
427 #endif
428 }
429
430 /*
431 * @tc.name: LazyShaderEquivalenceTest001
432 * @tc.desc: Test chained lazy shaders equivalence with direct shader creation
433 * @tc.type: FUNC
434 * @tc.require: AR000GGNV3
435 * @tc.author:
436 */
437 HWTEST_F(ShaderEffectLazyTest, LazyShaderEquivalenceTest001, TestSize.Level1)
438 {
439 // Define common parameters - use same parameters for both methods
440 ColorQuad baseColor1 = 0xFF0000FF; // Blue
441 ColorQuad baseColor2 = 0xFF00FF00; // Green
442 ColorQuad baseColor3 = 0xFFFF0000; // Red
443 ColorQuad baseColor4 = 0xFFFFFF00; // Yellow
444
445 // Method 1: Create chain using ShaderEffectLazy (nested blend shaders)
446 auto lazyBase1 = ShaderEffect::CreateColorShader(baseColor1);
447 auto lazyBase2 = ShaderEffect::CreateColorShader(baseColor2);
448 auto lazyBase3 = ShaderEffect::CreateColorShader(baseColor3);
449 auto lazyBase4 = ShaderEffect::CreateColorShader(baseColor4);
450 ASSERT_NE(lazyBase1, nullptr);
451 ASSERT_NE(lazyBase2, nullptr);
452 ASSERT_NE(lazyBase3, nullptr);
453 ASSERT_NE(lazyBase4, nullptr);
454
455 // Create first level lazy blend shaders
456 auto lazyBlend1 = ShaderEffectLazy::CreateBlendShader(lazyBase1, lazyBase2, BlendMode::SRC_OVER);
457 auto lazyBlend2 = ShaderEffectLazy::CreateBlendShader(lazyBase3, lazyBase4, BlendMode::MULTIPLY);
458 ASSERT_NE(lazyBlend1, nullptr);
459 ASSERT_NE(lazyBlend2, nullptr);
460 EXPECT_TRUE(lazyBlend1->IsLazy());
461 EXPECT_TRUE(lazyBlend2->IsLazy());
462
463 // Create second level lazy blend shader by chaining first level lazy shaders
464 auto chainedLazyShader = ShaderEffectLazy::CreateBlendShader(lazyBlend1, lazyBlend2, BlendMode::OVERLAY);
465 ASSERT_NE(chainedLazyShader, nullptr);
466 EXPECT_TRUE(chainedLazyShader->IsLazy());
467
468 // Materialize the lazy chain
469 auto materializedLazy = chainedLazyShader->Materialize();
470 ASSERT_NE(materializedLazy, nullptr);
471 EXPECT_FALSE(materializedLazy->IsLazy());
472 EXPECT_EQ(materializedLazy->GetType(), ShaderEffect::ShaderEffectType::BLEND);
473
474 // Method 2: Create equivalent chain using direct ShaderEffect calls with SAME parameters
475 auto directBase1 = ShaderEffect::CreateColorShader(baseColor1);
476 auto directBase2 = ShaderEffect::CreateColorShader(baseColor2);
477 auto directBase3 = ShaderEffect::CreateColorShader(baseColor3);
478 auto directBase4 = ShaderEffect::CreateColorShader(baseColor4);
479 ASSERT_NE(directBase1, nullptr);
480 ASSERT_NE(directBase2, nullptr);
481 ASSERT_NE(directBase3, nullptr);
482 ASSERT_NE(directBase4, nullptr);
483
484 // Create first level direct blend shaders
485 auto directBlend1 = ShaderEffect::CreateBlendShader(*directBase1, *directBase2, BlendMode::SRC_OVER);
486 auto directBlend2 = ShaderEffect::CreateBlendShader(*directBase3, *directBase4, BlendMode::MULTIPLY);
487 ASSERT_NE(directBlend1, nullptr);
488 ASSERT_NE(directBlend2, nullptr);
489 EXPECT_FALSE(directBlend1->IsLazy());
490 EXPECT_FALSE(directBlend2->IsLazy());
491
492 // Create second level direct blend shader
493 auto directChainedShader = ShaderEffect::CreateBlendShader(*directBlend1, *directBlend2, BlendMode::OVERLAY);
494 ASSERT_NE(directChainedShader, nullptr);
495 EXPECT_FALSE(directChainedShader->IsLazy());
496 EXPECT_EQ(directChainedShader->GetType(), ShaderEffect::ShaderEffectType::BLEND);
497
498 // Compare serialized data to verify equivalence
499 auto lazyData = materializedLazy->Serialize();
500 auto directData = directChainedShader->Serialize();
501 ASSERT_NE(lazyData, nullptr);
502 ASSERT_NE(directData, nullptr);
503 EXPECT_GT(lazyData->GetSize(), 0);
504 EXPECT_GT(directData->GetSize(), 0);
505 // Compare data sizes
506 EXPECT_EQ(lazyData->GetSize(), directData->GetSize());
507
508 // Compare serialized content byte by byte
509 const uint8_t* lazyBytes = static_cast<const uint8_t*>(lazyData->GetData());
510 const uint8_t* directBytes = static_cast<const uint8_t*>(directData->GetData());
511 int memResult = memcmp(lazyBytes, directBytes, lazyData->GetSize());
512 EXPECT_EQ(memResult, 0);
513 }
514
515 /*
516 * @tc.name: CreateFromShaderEffectObjInvalidType001
517 * @tc.desc: Test ShaderEffectLazy::CreateFromShaderEffectObj with invalid object type
518 * @tc.type: FUNC
519 * @tc.require: AR000GGNV3
520 */
521 HWTEST_F(ShaderEffectLazyTest, CreateFromShaderEffectObjInvalidType001, TestSize.Level1)
522 {
523 // Create a mock object with wrong type by inheriting from ShaderEffectObj and modifying type
524 class MockInvalidShaderEffectObj : public ShaderEffectObj {
525 public:
MockInvalidShaderEffectObj()526 MockInvalidShaderEffectObj() : ShaderEffectObj(static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND)) {
527 // Override the type to be IMAGE_FILTER instead of SHADER_EFFECT
528 type_ = static_cast<int32_t>(Object::ObjectType::IMAGE_FILTER);
529 }
530
GenerateBaseObject()531 std::shared_ptr<void> GenerateBaseObject() override {
532 return nullptr; // Not used in this test
533 }
534
535 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel)536 bool Marshalling(Parcel& parcel) override { return true; }
Unmarshalling(Parcel & parcel,bool & isValid,int32_t depth)537 bool Unmarshalling(Parcel& parcel, bool& isValid, int32_t depth) override {
538 isValid = true;
539 return true;
540 }
541 #endif
542 };
543
544 // Create mock object with invalid type
545 auto invalidObj = std::make_shared<MockInvalidShaderEffectObj>();
546 EXPECT_EQ(invalidObj->GetType(), static_cast<int32_t>(Object::ObjectType::IMAGE_FILTER));
547
548 // Test the validation branch - should return nullptr due to invalid type
549 auto result = ShaderEffectLazy::CreateFromShaderEffectObj(invalidObj);
550 EXPECT_EQ(result, nullptr);
551
552 // Test with NO_TYPE
553 class MockNoTypeShaderEffectObj : public ShaderEffectObj {
554 public:
MockNoTypeShaderEffectObj()555 MockNoTypeShaderEffectObj() :
556 ShaderEffectObj(static_cast<int32_t>(ShaderEffect::ShaderEffectType::COLOR_SHADER)) {
557 // Override the type to be NO_TYPE instead of SHADER_EFFECT
558 type_ = static_cast<int32_t>(Object::ObjectType::NO_TYPE);
559 }
560
GenerateBaseObject()561 std::shared_ptr<void> GenerateBaseObject() override { return nullptr; }
562
563 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel)564 bool Marshalling(Parcel& parcel) override { return true; }
Unmarshalling(Parcel & parcel,bool & isValid,int32_t depth)565 bool Unmarshalling(Parcel& parcel, bool& isValid, int32_t depth) override {
566 isValid = true;
567 return true;
568 }
569 #endif
570 };
571
572 auto noTypeObj = std::make_shared<MockNoTypeShaderEffectObj>();
573 EXPECT_EQ(noTypeObj->GetType(), static_cast<int32_t>(Object::ObjectType::NO_TYPE));
574
575 // Test with NO_TYPE - should also return nullptr
576 auto noTypeResult = ShaderEffectLazy::CreateFromShaderEffectObj(noTypeObj);
577 EXPECT_EQ(noTypeResult, nullptr);
578 }
579
580 /*
581 * @tc.name: UnmarshallingCreateLazyFailure001
582 * @tc.desc: Test ShaderEffectLazy::Unmarshalling CreateFromShaderEffectObj failure branch
583 * @tc.type: FUNC
584 * @tc.require: AR000GGNV3
585 */
586 HWTEST_F(ShaderEffectLazyTest, UnmarshallingCreateLazyFailure001, TestSize.Level1)
587 {
588 #ifdef ROSEN_OHOS
589 // Create a mock object that will cause CreateFromShaderEffectObj to fail
590 class MockFailingShaderEffectObj : public ShaderEffectObj {
591 public:
MockFailingShaderEffectObj()592 MockFailingShaderEffectObj() : ShaderEffectObj(static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND)) {
593 // Override the type to be IMAGE_FILTER to make CreateFromShaderEffectObj fail
594 type_ = static_cast<int32_t>(Object::ObjectType::IMAGE_FILTER);
595 }
596
GenerateBaseObject()597 std::shared_ptr<void> GenerateBaseObject() override {
598 return nullptr;
599 }
600
Marshalling(Parcel & parcel)601 bool Marshalling(Parcel& parcel) override { return true; }
Unmarshalling(Parcel & parcel,bool & isValid,int32_t depth)602 bool Unmarshalling(Parcel& parcel, bool& isValid, int32_t depth) override {
603 isValid = true;
604 return true;
605 }
606 };
607
608 // Register a mock function that returns an object with wrong type
609 auto originalFunc = ObjectHelper::Instance().GetFunc(
610 static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT),
611 static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
612
613 // Register a mock function that returns an object that will cause CreateFromShaderEffectObj to fail
614 ObjectHelper::Instance().Register(
615 static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT),
616 static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND),
__anon3146fff70102(Parcel& parcel, bool& isValid, int32_t depth) 617 [](Parcel& parcel, bool& isValid, int32_t depth) -> std::shared_ptr<Object> {
618 auto obj = std::make_shared<MockFailingShaderEffectObj>();
619 return std::static_pointer_cast<Object>(obj);
620 });
621
622 // Create parcel with valid data for SHADER_EFFECT/BLEND
623 Parcel parcel;
624 parcel.WriteInt32(static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
625 parcel.WriteInt32(static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND));
626
627 // Test Unmarshalling - should fail due to CreateFromShaderEffectObj returning nullptr
628 bool isValid = true;
629 auto result = ShaderEffectLazy::Unmarshalling(parcel, isValid, 0);
630 EXPECT_EQ(result, nullptr);
631
632 // Restore original function
633 if (originalFunc) {
634 ObjectHelper::Instance().Register(
635 static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT),
636 static_cast<int32_t>(ShaderEffect::ShaderEffectType::BLEND),
637 originalFunc);
638 }
639 #endif
640 }
641
642 /*
643 * @tc.name: MarshallingWriteTypeFailure001
644 * @tc.desc: Test ShaderEffectLazy::Marshalling with WriteInt32(type) failure
645 * @tc.type: FUNC
646 * @tc.require: AR000GGNV3
647 */
648 HWTEST_F(ShaderEffectLazyTest, MarshallingWriteTypeFailure001, TestSize.Level1)
649 {
650 #ifdef ROSEN_OHOS
651 // Create a valid lazy shader using CreateBlendShader
652 auto dstShader = ShaderEffect::CreateColorShader(Color::COLOR_BLUE);
653 auto srcShader = ShaderEffect::CreateColorShader(Color::COLOR_RED);
654 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
655 ASSERT_NE(lazyShader, nullptr);
656
657 // Create buffer to fill parcel capacity (200K minimum)
658 const size_t BUFFER_SIZE = 200 * 1024; // 200K
659 std::vector<uint8_t> fillBuffer(BUFFER_SIZE, 0xFF);
660
661 // Fill parcel completely, then try Marshalling (should fail on WriteInt32(type))
662 Parcel parcel;
663 parcel.SetMaxCapacity(BUFFER_SIZE);
664 bool fillResult = parcel.WriteBuffer(fillBuffer.data(), BUFFER_SIZE);
665 EXPECT_TRUE(fillResult);
666
667 bool result = lazyShader->Marshalling(parcel);
668 EXPECT_FALSE(result); // Should fail due to WriteInt32 failure
669 #endif
670 }
671
672 /*
673 * @tc.name: MarshallingWriteSubTypeFailure001
674 * @tc.desc: Test ShaderEffectLazy::Marshalling with WriteInt32(subType) failure
675 * @tc.type: FUNC
676 * @tc.require: AR000GGNV3
677 */
678 HWTEST_F(ShaderEffectLazyTest, MarshallingWriteSubTypeFailure001, TestSize.Level1)
679 {
680 #ifdef ROSEN_OHOS
681 // Create a valid lazy shader using CreateBlendShader
682 auto dstShader = ShaderEffect::CreateColorShader(Color::COLOR_RED);
683 auto srcShader = ShaderEffect::CreateColorShader(Color::COLOR_GREEN);
684 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
685 ASSERT_NE(lazyShader, nullptr);
686
687 // Create buffer to fill parcel capacity (200K minimum)
688 const size_t BUFFER_SIZE = 200 * 1024; // 200K
689 std::vector<uint8_t> fillBuffer(BUFFER_SIZE, 0xFF);
690
691 // Fill parcel leaving space for first int32 only (4 bytes), should fail on WriteInt32(subType)
692 Parcel parcel;
693 parcel.SetMaxCapacity(BUFFER_SIZE);
694 bool fillResult = parcel.WriteBuffer(fillBuffer.data(), BUFFER_SIZE - 4);
695 EXPECT_TRUE(fillResult);
696
697 bool result = lazyShader->Marshalling(parcel);
698 EXPECT_FALSE(result); // Should fail due to WriteInt32(subType) failure
699 #endif
700 }
701
702 /*
703 * @tc.name: MarshallingNullShaderEffectObj001
704 * @tc.desc: Test ShaderEffectLazy::Marshalling with null shaderEffectObj_
705 * @tc.type: FUNC
706 * @tc.require: AR000GGNV3
707 */
708 HWTEST_F(ShaderEffectLazyTest, MarshallingNullShaderEffectObj001, TestSize.Level1)
709 {
710 // Create a lazy shader using CreateBlendShader
711 auto dstShader = ShaderEffect::CreateColorShader(Color::COLOR_GREEN);
712 auto srcShader = ShaderEffect::CreateColorShader(Color::COLOR_BLUE);
713 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
714 ASSERT_NE(lazyShader, nullptr);
715
716 // Set shaderEffectObj_ to null to trigger the (!shaderEffectObj_) branch
717 lazyShader->shaderEffectObj_ = nullptr;
718
719 Parcel parcel;
720 bool result = lazyShader->Marshalling(parcel);
721 EXPECT_FALSE(result); // Should fail due to null shaderEffectObj_
722 }
723
724 /*
725 * @tc.name: MarshallingShaderEffectObjFailure001
726 * @tc.desc: Test ShaderEffectLazy::Marshalling with shaderEffectObj_->Marshalling() failure
727 * @tc.type: FUNC
728 * @tc.require: AR000GGNV3
729 */
730 HWTEST_F(ShaderEffectLazyTest, MarshallingShaderEffectObjFailure001, TestSize.Level1)
731 {
732 #ifdef ROSEN_OHOS
733 // Create a valid lazy shader using CreateBlendShader
734 auto dstShader = ShaderEffect::CreateColorShader(Color::COLOR_YELLOW);
735 auto srcShader = ShaderEffect::CreateColorShader(Color::COLOR_CYAN);
736 auto lazyShader = ShaderEffectLazy::CreateBlendShader(dstShader, srcShader, BlendMode::SRC_OVER);
737 ASSERT_NE(lazyShader, nullptr);
738
739 // Clear marshalling callback to make shaderEffectObj_->Marshalling() fail
740 auto originalCallback = ObjectHelper::Instance().GetDataMarshallingCallback();
741 ObjectHelper::Instance().SetDataMarshallingCallback(nullptr);
742
743 Parcel parcel;
744 bool result = lazyShader->Marshalling(parcel);
745 EXPECT_FALSE(result); // Should fail due to shaderEffectObj_->Marshalling() failure
746
747 // Restore original callback
748 ObjectHelper::Instance().SetDataMarshallingCallback(originalCallback);
749 #endif
750 }
751
752 /*
753 * @tc.name: UnmarshallingGetFuncNull001
754 * @tc.desc: Test ShaderEffectLazy::Unmarshalling with ObjectHelper::GetFunc() returning null
755 * @tc.type: FUNC
756 * @tc.require: AR000GGNV3
757 */
758 HWTEST_F(ShaderEffectLazyTest, UnmarshallingGetFuncNull001, TestSize.Level1)
759 {
760 #ifdef ROSEN_OHOS
761 Parcel parcel;
762 // Write a valid type but unregistered subType to make GetFunc return null
763 parcel.WriteInt32(static_cast<int32_t>(Object::ObjectType::SHADER_EFFECT));
764 parcel.WriteInt32(9999); // Invalid/unregistered subType
765
766 bool isValid = true;
767 auto result = ShaderEffectLazy::Unmarshalling(parcel, isValid, 0);
768 EXPECT_EQ(result, nullptr); // Should fail due to GetFunc returning null
769 #endif
770 }
771 } // namespace Drawing
772 } // namespace Rosen
773 } // namespace OHOS