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 <functional>
17
18#include <gtest/gtest.h>
19
20#include <meta/api/make_callback.h>
21#include <meta/api/object.h>
22#include <meta/base/capture.h>
23#include <meta/ext/attachment/attachment.h>
24#include <meta/interface/intf_object_registry.h>
25
26#include "src/util.h"
27#include "src/test_runner.h"
28#include "src/testing_objects.h"
29
30using namespace testing::ext;
31
32META_BEGIN_NAMESPACE()
33namespace Test {
34
35class CaptureTest : public testing::Test {
36public:
37    static void SetUpTestSuite()
38    {
39        SetTest();
40    }
41    static void TearDownTestSuite()
42    {
43        ResetTest();
44    }
45    void SetUp() override {}
46    void TearDown() override {}
47};
48
49/**
50 * @tc.name: CaptureTest
51 * @tc.desc: test LambdaAutoLocksCapturedSharedPtr function
52 * @tc.type: FUNC
53 * @tc.require: I7DMS1
54 */
55HWTEST_F(CaptureTest, LambdaAutoLocksCapturedSharedPtr, TestSize.Level1)
56{
57    {
58        auto f = CaptureSafe([](auto p) { *p = 1; }, sp);
59
60        EXPECT_EQ(*sp, 6);
61        EXPECT_NO_THROW(f());
62        EXPECT_EQ(*sp, 1);
63    }
64
65    {
66        auto f = CaptureSafe([](auto p) { *p = 1; }, sp);
67
68        EXPECT_EQ(*sp, 6);
69        EXPECT_NO_THROW(f());
70        EXPECT_EQ(*sp, 1);
71    }
72}
73
74/**
75 * @tc.name: CaptureTest
76 * @tc.desc: test LambdaAutoLocksCapturedWeakPtr function
77 * @tc.type: FUNC
78 * @tc.require: I7DMS1
79 */
80HWTEST_F(CaptureTest, LambdaAutoLocksCapturedWeakPtr, TestSize.Level1)
81{
82    {
83        auto wp = BASE_NS::weak_ptr(sp);
84        auto f = CaptureSafe([](auto p) { *p = 1; }, wp);
85
86        EXPECT_EQ(*sp, 6);
87        EXPECT_NO_THROW(f());
88        EXPECT_EQ(*sp, 1);
89    }
90
91    {
92        const auto wp = BASE_NS::weak_ptr(sp);
93        auto f = CaptureSafe([](auto p) { *p = 1; }, wp);
94
95        EXPECT_EQ(*sp, 6);
96        EXPECT_NO_THROW(f());
97        EXPECT_EQ(*sp, 1);
98    }
99}
100
101/**
102 * @tc.name: CaptureTest
103 * @tc.desc: test LambdaNotThrowsWhenCapturedSharedPointerIsReleased function
104 * @tc.type: FUNC
105 * @tc.require: I7DMS1
106 */
107HWTEST_F(CaptureTest, LambdaNotThrowsWhenCapturedSharedPointerIsReleased, TestSize.Level1)
108{
109    {
110        auto f = CaptureSafe([](auto p) { *p = 1; }, p);
111        p.reset();
112
113        EXPECT_NO_THROW(f());
114    }
115}
116
117/**
118 * @tc.name: CaptureTest
119 * @tc.desc: test LambdaNotThrowsWhenCapturedWeakPointerPointsToInvalidResource function
120 * @tc.type: FUNC
121 * @tc.require: I7DMS1
122 */
123HWTEST_F(CaptureTest, LambdaNotThrowsWhenCapturedWeakPointerPointsToInvalidResource, TestSize.Level1)
124{
125    {
126        auto f = CaptureSafe([](auto p) { *p = 1; }, BASE_NS::weak_ptr(sp));
127        sp.reset();
128        EXPECT_NO_THROW(f());
129    }
130
131    {
132        BASE_NS::weak_ptr<int> wp = BASE_NS::weak_ptr(sp);
133        auto f = CaptureSafe([](auto p) { *p = 1; }, wp);
134        sp.reset();
135        EXPECT_NO_THROW(f());
136    }
137}
138
139/**
140 * @tc.name: CaptureTest
141 * @tc.desc: test SimpleLambda function
142 * @tc.type: FUNC
143 * @tc.require: I7DMS1
144 */
145HWTEST_F(CaptureTest, SimpleLambda, TestSize.Level1)
146{
147    {
148        auto f = Capture([](auto pp) { *pp = 1; }, p);
149        f();
150        EXPECT_EQ(*p, 1);
151    }
152    {
153        auto f = Capture([](auto p, int v) { *p = v; }, p);
154        f(2);
155        EXPECT_EQ(*p, 2);
156    }
157    {
158        auto f = Capture([]() { return true; });
159        EXPECT_TRUE(f());
160    }
161    {
162        auto f = Capture([](int v) { v = 1; });
163        int i = 0;
164        f(i);
165        EXPECT_EQ(i, 0);
166    }
167    {
168        auto f = Capture([](int& v) { v = 1; });
169        int i = 0;
170        f(i);
171        EXPECT_EQ(i, 1);
172    }
173    {
174        auto f = Capture([](auto p) { return (bool)p; }, p);
175        EXPECT_TRUE(f());
176        p.reset();
177        EXPECT_FALSE(f());
178    }
179}
180
181/**
182 * @tc.name: CaptureTest
183 * @tc.desc: test MakeCallback function
184 * @tc.type: FUNC
185 * @tc.require: I7DMS1
186 */
187HWTEST_F(CaptureTest, MakeCallback, TestSize.Level1)
188{
189    auto& registry = GetObjectRegistry();
190    auto p = META_NS::ConstructProperty<int>(registry, "P1", 0);
191
192    p->OnChanged()->AddHandler(MakeCallback<IOnChanged>(
193        [](auto i) {
194            if (i) {
195                ++*i;
196            }
197        },
198        count));
199    p->SetValue(2);
200    EXPECT_EQ(*count, 1);
201}
202
203/**
204 * @tc.name: CaptureTest
205 * @tc.desc: test MakeCallable function
206 * @tc.type: FUNC
207 * @tc.require: I7DMS1
208 */
209HWTEST_F(CaptureTest, MakeCallable, TestSize.Level1)
210{
211    auto& registry = GetObjectRegistry();
212    auto c = CreateTestContainer<IContainer>("Test");
213
214    c->OnAdded()->AddHandler(MakeCallback<IOnChildChanged>(
215        [](auto i, const ChildChangedInfo& info) {
216            if (i) {
217                ++*i;
218            }
219        },
220        count));
221    c->Add(Object {});
222    EXPECT_EQ(*count, 1);
223}
224
225namespace {
226META_REGISTER_CLASS(TestAttachment, "d4e854a2-b169-4b90-ae31-76e78cdf07b0", META_NS::ObjectCategoryBits::APPLICATION)
227
228class TestAttachment : public META_NS::AttachmentFwd<TestAttachment, ClassId::TestAttachment> {
229    bool AttachTo(const META_NS::IAttach::Ptr& target, const IObject::Ptr& dataContext) override
230    {
231        return true;
232    }
233    bool DetachFrom(const META_NS::IAttach::Ptr& target) override
234    {
235        return true;
236    }
237};
238} // namespace
239
240/**
241 * @tc.name: CaptureTest
242 * @tc.desc: test IObject function
243 * @tc.type: FUNC
244 * @tc.require: I7DMS1
245 */
246HWTEST_F(CaptureTest, IObject, TestSize.Level1)
247{
248    RegisterObjectType<TestAttachment>();
249    IObject::Ptr obj = Object {}.GetIObject();
250    auto func = Capture(
251        [](IObject::Ptr p) {
252            if (auto a = interface_cast<IAttach>(p)) {
253                a->Attach(GetObjectRegistry().Create<IAttachment>(ClassId::TestAttachment));
254                return true;
255            }
256            return false;
257        },
258        obj);
259    EXPECT_TRUE(func());
260    EXPECT_EQ(interface_cast<IAttach>(obj)->GetAttachments().size(), 1);
261    obj.reset();
262    EXPECT_FALSE(func());
263    UnregisterObjectType<TestAttachment>();
264}
265} // namespace Test
266META_END_NAMESPACE()