1/*
2 * Copyright (C) 2024 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#include "image_effect_inner.h"
19#include "efilter_factory.h"
20#include "mock_pixel_map.h"
21#include "brightness_efilter.h"
22#include "contrast_efilter.h"
23#include "test_common.h"
24#include "external_loader.h"
25#include "crop_efilter.h"
26#include "mock_producer_surface.h"
27
28using namespace testing::ext;
29using namespace OHOS::Media::Effect;
30
31static std::string g_jpgPath;
32static std::string g_notJpgPath;
33static std::string g_jpgUri;
34static std::string g_notJpgUri;
35
36namespace OHOS {
37namespace Media {
38namespace Effect {
39namespace Test {
40class CustomTestEFilter : public IFilterDelegate {
41public:
42    bool Render(void *efilter, EffectBuffer *src, EffectBuffer *dst, std::shared_ptr<EffectContext> &context) override
43    {
44        return true;
45    }
46
47    bool Render(void *efilter, EffectBuffer *src, std::shared_ptr<EffectContext> &context) override
48    {
49        return true;
50    }
51
52    bool SetValue(void *efilter, const std::string &key, const Plugin::Any &value) override
53    {
54        return true;
55    }
56
57    bool Save(void *efilter, EffectJsonPtr &res) override
58    {
59        auto *filter = static_cast<EFilter *>(efilter);
60        return filter != nullptr && filter->Save(res) == ErrorCode::SUCCESS;
61    }
62
63    void *Restore(const EffectJsonPtr &values) override
64    {
65        filter_ = EFilterFactory::Instance()->Create(CUSTOM_TEST_EFILTER);
66        Plugin::Any brightness = values->GetFloat("brightness");
67        filter_->SetValue("brightness", brightness);
68        return filter_.get();
69    }
70
71    void *GetEffectInfo() override
72    {
73        if (info_ != nullptr) {
74            return &info_;
75        }
76        info_ = std::make_unique<EffectInfo>();
77        info_->formats_.emplace(IEffectFormat::RGBA8888, std::vector<IPType>{ IPType::CPU });
78        info_->category_ = Category::SHAPE_ADJUST;
79        return &info_;
80    }
81private:
82    static std::shared_ptr<EffectInfo> info_;
83    std::shared_ptr<EFilter> filter_;
84};
85std::shared_ptr<EffectInfo> CustomTestEFilter::info_ = nullptr;
86
87class TestImageEffect : public testing::Test {
88public:
89    TestImageEffect() = default;
90
91    ~TestImageEffect() override = default;
92
93    static void SetUpTestCase()
94    {
95        g_jpgPath = std::string("/data/test/resource/image_effect_test1.jpg");
96        g_notJpgPath = std::string("/data/test/resource/image_effect_test2.png");
97        g_jpgUri = std::string("file:///data/test/resource/image_effect_test1.jpg");
98        g_notJpgUri = std::string("file:///data/test/resource/image_effect_test2.png");
99    }
100
101    static void TearDownTestCase() {}
102
103    void SetUp() override
104    {
105        mockPixelMap_ = new MockPixelMap();
106        imageEffect_ = new ImageEffect();
107        ExternLoader::Instance()->InitExt();
108        EFilterFactory::Instance()->functions_.clear();
109        EFilterFactory::Instance()->RegisterEFilter<BrightnessEFilter>(BRIGHTNESS_EFILTER);
110        EFilterFactory::Instance()->RegisterEFilter<ContrastEFilter>(CONTRAST_EFILTER);
111        EFilterFactory::Instance()->RegisterEFilter<CropEFilter>(CROP_EFILTER);
112    }
113
114    void TearDown() override
115    {
116        delete mockPixelMap_;
117        mockPixelMap_ = nullptr;
118        delete imageEffect_;
119        imageEffect_ = nullptr;
120    }
121    PixelMap *mockPixelMap_ = nullptr;
122    ImageEffect *imageEffect_ = nullptr;
123};
124
125HWTEST_F(TestImageEffect, AddEfilter001, TestSize.Level1)
126{
127    std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
128    std::shared_ptr<EFilter> brightnessEFilter = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
129    imageEffect->AddEFilter(brightnessEFilter);
130    ASSERT_EQ(imageEffect->efilters_.size(), 1);
131    ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter);
132
133    std::shared_ptr<EFilter> cropEFilter1 = EFilterFactory::Instance()->Create(CROP_EFILTER);
134    imageEffect->AddEFilter(cropEFilter1);
135    ASSERT_EQ(imageEffect->efilters_.size(), 2);
136    ASSERT_EQ(imageEffect->efilters_.at(0), cropEFilter1);
137    ASSERT_EQ(imageEffect->efilters_.at(1), brightnessEFilter);
138
139    std::shared_ptr<EFilter> cropEFilter2 = EFilterFactory::Instance()->Create(CROP_EFILTER);
140    imageEffect->AddEFilter(cropEFilter2);
141    ASSERT_EQ(imageEffect->efilters_.size(), 3);
142    ASSERT_EQ(imageEffect->efilters_.at(0), cropEFilter1);
143    ASSERT_EQ(imageEffect->efilters_.at(1), cropEFilter2);
144    ASSERT_EQ(imageEffect->efilters_.at(2), brightnessEFilter);
145}
146
147HWTEST_F(TestImageEffect, Start001, TestSize.Level1)
148{
149    std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
150    std::shared_ptr<EFilter> efilter = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
151    Plugin::Any value = 100.f;
152    ErrorCode result = efilter->SetValue(KEY_FILTER_INTENSITY, value);
153    ASSERT_EQ(result, ErrorCode::SUCCESS);
154    imageEffect->AddEFilter(efilter);
155    result = imageEffect->SetInputPixelMap(mockPixelMap_);
156    ASSERT_EQ(result, ErrorCode::SUCCESS);
157    result = imageEffect->SetOutputPixelMap(mockPixelMap_);
158    ASSERT_EQ(result, ErrorCode::SUCCESS);
159    result = imageEffect->Start();
160    ASSERT_EQ(result, ErrorCode::SUCCESS);
161}
162
163HWTEST_F(TestImageEffect, InsertEfilter001, TestSize.Level1)
164{
165    std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
166    std::shared_ptr<EFilter> brightnessEFilter1 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
167    imageEffect->InsertEFilter(brightnessEFilter1, 0);
168    ASSERT_EQ(imageEffect->efilters_.size(), 1);
169    ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
170
171    std::shared_ptr<EFilter> contrastEFilter = EFilterFactory::Instance()->Create(CONTRAST_EFILTER);
172    imageEffect->AddEFilter(contrastEFilter);
173    ASSERT_EQ(imageEffect->efilters_.size(), 2);
174    ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
175    ASSERT_EQ(imageEffect->efilters_.at(1), contrastEFilter);
176
177    std::shared_ptr<EFilter> brightnessEFilter2 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
178    imageEffect->InsertEFilter(brightnessEFilter2, 1);
179    ASSERT_EQ(imageEffect->efilters_.size(), 3);
180    ASSERT_EQ(imageEffect->efilters_.at(0), brightnessEFilter1);
181    ASSERT_EQ(imageEffect->efilters_.at(1), brightnessEFilter2);
182    ASSERT_EQ(imageEffect->efilters_.at(2), contrastEFilter);
183}
184
185HWTEST_F(TestImageEffect, InsertEfilter002, TestSize.Level1)
186{
187    std::shared_ptr<ImageEffect> imageEffect = std::make_unique<ImageEffect>(IMAGE_EFFECT_NAME);
188    std::shared_ptr<EFilter> brightnessEFilter1 = EFilterFactory::Instance()->Create(BRIGHTNESS_EFILTER);
189    ErrorCode result = imageEffect->InsertEFilter(brightnessEFilter1, 1);
190    ASSERT_NE(result, ErrorCode::SUCCESS);
191}
192
193/**
194 * Feature: ImageEffect
195 * Function: Test ImageEffect::SetInputPath with normal param
196 * SubFunction: NA
197 * FunctionPoints: NA
198 * EnvConditions: NA
199 * CaseDescription: Test ImageEffect::SetInputPath with normal param
200 */
201HWTEST_F(TestImageEffect, SetInputPath001, TestSize.Level1)
202{
203    ErrorCode result = imageEffect_->SetInputPath(g_jpgPath);
204    ASSERT_EQ(result, ErrorCode::SUCCESS);
205}
206
207/**
208 * Feature: ImageEffect
209 * Function: Test ImageEffect::SetInputPath with nullptr param
210 * SubFunction: NA
211 * FunctionPoints: NA
212 * EnvConditions: NA
213 * CaseDescription: Test ImageEffect::SetInputPath with nullptr param
214 */
215HWTEST_F(TestImageEffect, SetInputPath002, TestSize.Level1)
216{
217    ErrorCode result = imageEffect_->SetInputPath(nullptr);
218    ASSERT_NE(result, ErrorCode::SUCCESS);
219}
220
221/**
222 * Feature: ImageEffect
223 * Function: Test ImageEffect::SetInputPath with not support type param
224 * SubFunction: NA
225 * FunctionPoints: NA
226 * EnvConditions: NA
227 * CaseDescription: Test ImageEffect::SetInputPath with not support type param
228 */
229HWTEST_F(TestImageEffect, SetInputPath003, TestSize.Level1)
230{
231    ErrorCode result = imageEffect_->SetInputPath(g_notJpgPath);
232    ASSERT_NE(result, ErrorCode::SUCCESS);
233}
234
235/**
236 * Feature: ImageEffect
237 * Function: Test ImageEffect::SetOutputPath with normal param
238 * SubFunction: NA
239 * FunctionPoints: NA
240 * EnvConditions: NA
241 * CaseDescription: Test ImageEffect::SetOutputPath with normal param
242 */
243HWTEST_F(TestImageEffect, SetOutputPath001, TestSize.Level1)
244{
245    ErrorCode result = imageEffect_->SetOutputPath(g_jpgPath);
246    ASSERT_EQ(result, ErrorCode::SUCCESS);
247}
248
249/**
250 * Feature: ImageEffect
251 * Function: Test ImageEffect::SetOutputPath with nullptr param
252 * SubFunction: NA
253 * FunctionPoints: NA
254 * EnvConditions: NA
255 * CaseDescription: Test ImageEffect::SetOutputPath with nullptr param
256 */
257HWTEST_F(TestImageEffect, SetOutputPath002, TestSize.Level1)
258{
259    ErrorCode result = imageEffect_->SetOutputPath(nullptr);
260    ASSERT_EQ(result, ErrorCode::SUCCESS);
261}
262
263/**
264 * Feature: ImageEffect
265 * Function: Test ImageEffect::SetOutputPath with not support type param
266 * SubFunction: NA
267 * FunctionPoints: NA
268 * EnvConditions: NA
269 * CaseDescription: Test ImageEffect::SetOutputPath with not support type param
270 */
271HWTEST_F(TestImageEffect, SetOutputPath003, TestSize.Level1)
272{
273    ErrorCode result = imageEffect_->SetOutputPath(g_notJpgPath);
274    ASSERT_NE(result, ErrorCode::SUCCESS);
275}
276
277/**
278 * Feature: ImageEffect
279 * Function: Test ImageEffect::SetInputUri with normal param
280 * SubFunction: NA
281 * FunctionPoints: NA
282 * EnvConditions: NA
283 * CaseDescription: Test ImageEffect::SetInputUri with normal param
284 */
285HWTEST_F(TestImageEffect, SetInputUri001, TestSize.Level1)
286{
287    ErrorCode result = imageEffect_->SetInputUri(g_jpgUri);
288    ASSERT_EQ(result, ErrorCode::SUCCESS);
289}
290
291/**
292 * Feature: ImageEffect
293 * Function: Test ImageEffect::SetInputUri with nullptr param
294 * SubFunction: NA
295 * FunctionPoints: NA
296 * EnvConditions: NA
297 * CaseDescription: Test ImageEffect::SetInputUri with nullptr param
298 */
299HWTEST_F(TestImageEffect, SetInputUri002, TestSize.Level1)
300{
301    ErrorCode result = imageEffect_->SetInputUri(nullptr);
302    ASSERT_NE(result, ErrorCode::SUCCESS);
303}
304
305/**
306 * Feature: ImageEffect
307 * Function: Test ImageEffect::SetInputUri with not support type param
308 * SubFunction: NA
309 * FunctionPoints: NA
310 * EnvConditions: NA
311 * CaseDescription: Test ImageEffect::SetInputUri with not support type param
312 */
313HWTEST_F(TestImageEffect, SetInputUri003, TestSize.Level1)
314{
315    ErrorCode result = imageEffect_->SetInputUri(g_notJpgUri);
316    ASSERT_NE(result, ErrorCode::SUCCESS);
317}
318
319/**
320 * Feature: ImageEffect
321 * Function: Test ImageEffect::SetOutputUri with normal param
322 * SubFunction: NA
323 * FunctionPoints: NA
324 * EnvConditions: NA
325 * CaseDescription: Test ImageEffect::SetOutputUri with normal param
326 */
327HWTEST_F(TestImageEffect, SetOutputUri001, TestSize.Level1)
328{
329    ErrorCode result = imageEffect_->SetOutputUri(g_jpgUri);
330    ASSERT_EQ(result, ErrorCode::SUCCESS);
331}
332
333/**
334 * Feature: ImageEffect
335 * Function: Test ImageEffect::SetOutputUri with nullptr param
336 * SubFunction: NA
337 * FunctionPoints: NA
338 * EnvConditions: NA
339 * CaseDescription: Test ImageEffect::SetOutputUri with nullptr param
340 */
341HWTEST_F(TestImageEffect, SetOutputUri002, TestSize.Level1)
342{
343    ErrorCode result = imageEffect_->SetOutputUri(nullptr);
344    ASSERT_EQ(result, ErrorCode::SUCCESS);
345}
346
347/**
348 * Feature: ImageEffect
349 * Function: Test ImageEffect::SetOutputUri with not support type param
350 * SubFunction: NA
351 * FunctionPoints: NA
352 * EnvConditions: NA
353 * CaseDescription: Test ImageEffect::SetOutputUri with not support type param
354 */
355HWTEST_F(TestImageEffect, SetOutputUri003, TestSize.Level1)
356{
357    ErrorCode result = imageEffect_->SetOutputUri(g_notJpgUri);
358    ASSERT_NE(result, ErrorCode::SUCCESS);
359}
360
361HWTEST_F(TestImageEffect, Restore001, TestSize.Level1)
362{
363    std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"Brightness\",\"values\":{\"FilterIntensity\":"
364        "100.0}},{\"name\":\"Contrast\",\"values\":{\"FilterIntensity\":50.0}}],\"name\":\"imageEdit\"}}";
365    std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
366    ASSERT_NE(imageEffect, nullptr);
367    std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
368    ASSERT_EQ(efilters.size(), 2);
369    ASSERT_STREQ(efilters.at(0)->GetName().c_str(), BRIGHTNESS_EFILTER);
370    Plugin::Any value;
371    ASSERT_EQ(efilters.at(0)->GetValue(KEY_FILTER_INTENSITY, value), ErrorCode::SUCCESS);
372    auto brightnessRatio = Plugin::AnyCast<float>(&value);
373    ASSERT_NE(brightnessRatio, nullptr);
374    ASSERT_FLOAT_EQ(*brightnessRatio, 100.f);
375
376    Plugin::Any any;
377    ASSERT_STREQ(efilters.at(1)->GetName().c_str(), CONTRAST_EFILTER);
378    ASSERT_EQ(efilters.at(1)->GetValue(KEY_FILTER_INTENSITY, any), ErrorCode::SUCCESS);
379    auto contrastRatio = Plugin::AnyCast<float>(&any);
380    ASSERT_NE(contrastRatio, nullptr);
381    ASSERT_FLOAT_EQ(*contrastRatio, 50.f);
382}
383
384HWTEST_F(TestImageEffect, Restore002, TestSize.Level1)
385{
386    std::shared_ptr<IFilterDelegate> customTestEFilter = std::make_unique<CustomTestEFilter>();
387    auto *effectInfo = static_cast<std::shared_ptr<EffectInfo> *>(customTestEFilter->GetEffectInfo());
388    ASSERT_NE(effectInfo, nullptr);
389    EFilterFactory::Instance()->RegisterDelegate(CUSTOM_TEST_EFILTER, customTestEFilter, *effectInfo);
390
391    std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"CustomTestEFilter\",\"values\":{\"brightness\":"
392        "60.0}},{\"name\":\"Contrast\",\"values\":{\"FilterIntensity\":50.0}}],\"name\":\"imageEdit\"}}";
393
394    std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
395    ASSERT_NE(imageEffect, nullptr);
396    std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
397    ASSERT_EQ(efilters.size(), 2);
398    ASSERT_STREQ(efilters.at(0)->GetName().c_str(), "CustomTestEFilter");
399    Plugin::Any value;
400    ASSERT_EQ(efilters.at(0)->GetValue("brightness", value), ErrorCode::SUCCESS);
401    auto brightness = Plugin::AnyCast<float>(&value);
402    ASSERT_NE(brightness, nullptr);
403    ASSERT_FLOAT_EQ(*brightness, 60.f);
404
405    ErrorCode errorCode = imageEffect->SetInputPixelMap(mockPixelMap_);
406    ASSERT_EQ(errorCode, ErrorCode::SUCCESS);
407    errorCode = imageEffect->Start();
408    ASSERT_EQ(errorCode, ErrorCode::SUCCESS);
409}
410
411HWTEST_F(TestImageEffect, Restore003, TestSize.Level1)
412{
413    std::string info = "{\"imageEffect\":{\"filters\":[{\"name\":\"Crop\"}],\"name\":\"imageEdit\"}}";
414    std::shared_ptr<ImageEffect> imageEffect = ImageEffect::Restore(info);
415    ASSERT_NE(imageEffect, nullptr);
416    std::vector<std::shared_ptr<EFilter>> efilters = imageEffect->GetEFilters();
417    ASSERT_EQ(efilters.size(), 1);
418    ASSERT_STREQ(efilters.at(0)->GetName().c_str(), CROP_EFILTER);
419}
420
421HWTEST_F(TestImageEffect, Surface001, TestSize.Level1)
422{
423    sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("UnitTest");
424    sptr<IBufferProducer> producer = consumerSurface->GetProducer();
425    sptr<ProducerSurface> surf = new(std::nothrow) MockProducerSurface(producer);
426    surf->Init();
427    sptr<Surface> outputSurface = surf;
428
429    ErrorCode result = imageEffect_->SetOutputSurface(outputSurface);
430    ASSERT_EQ(result, ErrorCode::SUCCESS);
431
432    sptr<Surface> inputSurface = imageEffect_->GetInputSurface();
433    ASSERT_NE(inputSurface, nullptr);
434
435    sptr<SurfaceBuffer> surfaceBuffer;
436    MockProducerSurface::AllocDmaMemory(surfaceBuffer);
437    OHOS::Rect damages;
438    int64_t timeStamp = 0;
439
440    // running without filter
441    imageEffect_->ConsumerBufferAvailable(surfaceBuffer, damages, timeStamp);
442
443    std::shared_ptr<EFilter> contrastEFilter = EFilterFactory::Instance()->Create(CONTRAST_EFILTER);
444    Plugin::Any value = 50.f;
445    result = contrastEFilter->SetValue(KEY_FILTER_INTENSITY, value);
446    ASSERT_EQ(result, ErrorCode::SUCCESS);
447    imageEffect_->AddEFilter(contrastEFilter);
448
449    result = imageEffect_->Start();
450    ASSERT_EQ(result, ErrorCode::SUCCESS);
451
452    // contrast filter
453    imageEffect_->ConsumerBufferAvailable(surfaceBuffer, damages, timeStamp);
454    MockProducerSurface::ReleaseDmaBuffer(surfaceBuffer);
455}
456} // namespace Test
457} // namespace Effect
458} // namespace Media
459} // namespace OHOS