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 <gmock/gmock.h>
17#include <gtest/gtest.h>
18
19#include <meta/api/container/container_observer.h>
20#include <meta/api/make_callback.h>
21#include <meta/base/ref_uri.h>
22
23#include "src/test_runner.h"
24#include "src/test_utils.h"
25#include "src/testing_objects.h"
26#include "src/util.h"
27
28using namespace testing;
29using namespace testing::ext;
30
31META_BEGIN_NAMESPACE()
32
33class IntfContainerObserverTest : public testing::Test {
34public:
35    void SetUp() override
36    {
37        container_ = interface_pointer_cast<IContainer>(CreateTestContainer("Base"));
38        ASSERT_NE(container_, nullptr);
39        ASSERT_NE(observer_.GetIObject(), nullptr);
40        container_->Add(CreateTestType<IObject>("Object1_1"));
41        container_->Add(CreateTestType<IObject>("SameNameDifferentUid"));
42        container_->Add(CreateTestType<IObject>("ObjectDupe"));
43        container1_1_ = interface_pointer_cast<IContainer>(CreateTestContainer("Container1_1"));
44        container_->Add(interface_pointer_cast<IObject>(container1_1_));
45        container1_1_->Add(CreateTestType<IObject>("Object2_1"));
46        container1_1_->Add(CreateTestType<IObject>("ObjectDupe"));
47        container1_1_->Add(CreateTestType<IObject>("SameNameDifferentUid"));
48        container_->Add(CreateTestType<IObject>("Object1_3"));
49        container2_1_ = interface_pointer_cast<IContainer>(CreateTestContainer("SameNameDifferentUid"));
50        container1_1_->Add(interface_pointer_cast<IObject>(container2_1_));
51
52        observer_.Container(container_)
53            .OnDescendantAdded([this](const ChildChangedInfo& info) { OnAdded(info); })
54            .OnDescendantRemoved([this](const ChildChangedInfo& info) { OnRemoved(info); })
55            .OnDescendantMoved([this](const ChildMovedInfo& info) { OnMoved(info); });
56    }
57    void TearDown() override
58    {
59        container_.reset();
60        observer_.ResetIObject();
61    }
62    static void SetUpTestSuite()
63    {
64        SetTest();
65    }
66    static void TearDownTestSuite()
67    {
68        ResetTest();
69    }
70
71protected:
72    void OnAdded(const ChildChangedInfo& info)
73    {
74        addedCalls_.push_back(info);
75    }
76    void OnRemoved(const ChildChangedInfo& info)
77    {
78        removedCalls_.push_back(info);
79    }
80    void OnMoved(const ChildMovedInfo& info)
81    {
82        movedCalls_.push_back(info);
83    }
84
85    BASE_NS::vector<ChildChangedInfo> addedCalls_;
86    BASE_NS::vector<ChildChangedInfo> removedCalls_;
87    BASE_NS::vector<ChildMovedInfo> movedCalls_;
88
89    IContainer::Ptr container_;
90    IContainer::Ptr container1_1_;
91    IContainer::Ptr container2_1_;
92    META_NS::ContainerObserver observer_;
93};
94
95/**
96 * @tc.name: IntfContainerObserverTest
97 * @tc.desc: test AddDirectChild function
98 * @tc.type: FUNC
99 * @tc.require: I7DMS1
100 */
101HWTEST_F(IntfContainerObserverTest, AddDirectChild, TestSize.Level1)
102{
103    auto child = CreateTestType<IObject>("DirectChild");
104    ASSERT_TRUE(container_->Add(child));
105
106    ASSERT_THAT(addedCalls_, SizeIs(1));
107    ASSERT_THAT(removedCalls_, SizeIs(0));
108    ASSERT_THAT(movedCalls_, SizeIs(0));
109
110    auto info = addedCalls_[0];
111    EXPECT_EQ(info.object, child);
112    EXPECT_EQ(info.parent.lock(), container_);
113}
114
115/**
116 * @tc.name: IntfContainerObserverTest
117 * @tc.desc: test AddDescendantChild function
118 * @tc.type: FUNC
119 * @tc.require: I7DMS1
120 */
121HWTEST_F(IntfContainerObserverTest, AddDescendantChild, TestSize.Level1)
122{
123    auto child = CreateTestType<IObject>("Descendant");
124    ASSERT_TRUE(container2_1_->Add(child));
125
126    ASSERT_THAT(addedCalls_, SizeIs(1));
127    ASSERT_THAT(removedCalls_, SizeIs(0));
128    ASSERT_THAT(movedCalls_, SizeIs(0));
129
130    auto info = addedCalls_[0];
131    EXPECT_EQ(info.object, child);
132    EXPECT_EQ(info.parent.lock(), container2_1_);
133}
134
135/**
136 * @tc.name: IntfContainerObserverTest
137 * @tc.desc: test ChangedAfterChild function
138 * @tc.type: FUNC
139 * @tc.require: I7DMS1
140 */
141HWTEST_F(IntfContainerObserverTest, ChangeAfterChild, TestSize.Level1)
142{
143    auto container = CreateTestContainer<IContainer>("DescendantContainer");
144    ASSERT_TRUE(container2_1_->Add(container));
145
146    ASSERT_THAT(addedCalls_, SizeIs(1));
147    ASSERT_THAT(removedCalls_, SizeIs(0));
148    ASSERT_THAT(movedCalls_, SizeIs(0));
149
150    auto info = addedCalls_[0];
151    EXPECT_EQ(info.object, interface_pointer_cast<IObject>(container));
152    EXPECT_EQ(info.parent.lock(), container2_1_);
153
154    auto child = CreateTestType<IObject>("DescendantChild");
155    ASSERT_TRUE(container->Add(child));
156
157    ASSERT_THAT(addedCalls_, SizeIs(2));
158    ASSERT_THAT(removedCalls_, SizeIs(0));
159    ASSERT_THAT(movedCalls_, SizeIs(0));
160
161    info = addedCalls_[1];
162    EXPECT_EQ(info.object, child);
163    EXPECT_EQ(info.parent.lock(), container);
164
165    EXPECT_TRUE(container1_1_->Remove(container2_1_));
166
167    EXPECT_TRUE(container->Remove(child));
168    ASSERT_THAT(addedCalls_, SizeIs(2));
169    ASSERT_THAT(removedCalls_, SizeIs(1));
170    ASSERT_THAT(movedCalls_, SizeIs(0));
171
172    info = removedCalls_[0];
173    EXPECT_EQ(info.object, interface_pointer_cast<IObject>(container2_1_));
174    EXPECT_EQ(info.parent.lock(), container1_1_);
175}
176
177/**
178 * @tc.name: IntfContainerObserverTest
179 * @tc.desc: test RemoveDescendant function
180 * @tc.type: FUNC
181 * @tc.require: I7DMS1
182 */
183HWTEST_F(IntfContainerObserverTest, RemoveDescendant, TestSize.Level1)
184{
185    container_->Remove(container1_1_);
186    ASSERT_THAT(addedCalls_, SizeIs(0));
187    ASSERT_THAT(removedCalls_, SizeIs(1));
188    ASSERT_THAT(movedCalls_, SizeIs(0));
189
190    auto info = removedCalls_[0];
191    EXPECT_EQ(info.object, interface_pointer_cast<IObject>(container1_1_));
192    EXPECT_EQ(info.parent.lock(), container_);
193    removedCalls_.clear();
194
195    auto child = CreateTestType<IObject>("Descendant");
196    container1_1_->Add(child);
197
198    ASSERT_THAT(addedCalls_, SizeIs(0));
199    ASSERT_THAT(removedCalls_, SizeIs(0));
200    ASSERT_THAT(movedCalls_, SizeIs(0));
201}
202
203META_END_NAMESPACE()