• 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 "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