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 #include <thread>
18
19 #include "accesstoken_kit.h"
20 #include "pasteboard_client.h"
21 #include "pasteboard_error.h"
22 #include "pasteboard_hilog.h"
23 #include "permission/permission_utils.h"
24 #include "token_setproc.h"
25
26 namespace OHOS::MiscServices {
27 using namespace testing::ext;
28 using namespace OHOS::Security::AccessToken;
29
30 constexpr pid_t SELECTION_SERVICE_UID = 1080;
31 const std::string BUNDLE_NAME = "com.pasteboard.disposableTest";
32
33 class PasteboardDisposableClientTest : public testing::Test {
34 public:
35 static void SetUpTestCase();
36 static void TearDownTestCase();
37 void SetUp();
38 void TearDown();
39
40 static void AllocTestAppTokenId();
41 static inline pid_t selfUid_ = 0;
42 static inline uint64_t selfTokenId_ = 0;
43 static inline uint64_t testAppTokenId_ = 0;
44 };
45
SetUpTestCase()46 void PasteboardDisposableClientTest::SetUpTestCase()
47 {
48 selfTokenId_ = GetSelfTokenID();
49 AllocTestAppTokenId();
50 selfUid_ = getuid();
51 setuid(SELECTION_SERVICE_UID);
52 }
53
TearDownTestCase()54 void PasteboardDisposableClientTest::TearDownTestCase()
55 {
56 AccessTokenKit::DeleteToken(testAppTokenId_);
57 SetSelfTokenID(selfTokenId_);
58 setuid(selfUid_);
59 }
60
SetUp()61 void PasteboardDisposableClientTest::SetUp()
62 {
63 PasteboardClient::GetInstance()->Clear();
64 }
65
TearDown()66 void PasteboardDisposableClientTest::TearDown()
67 {
68 }
69
AllocTestAppTokenId()70 void PasteboardDisposableClientTest::AllocTestAppTokenId()
71 {
72 HapInfoParams infoParams = {
73 .userID = 100,
74 .bundleName = BUNDLE_NAME,
75 .instIndex = 0,
76 .appIDDesc = "desc",
77 };
78 PermissionStateFull testState = {
79 .permissionName = PermissionUtils::PERMISSION_READ_PASTEBOARD,
80 .isGeneral = true,
81 .resDeviceID = { "local" },
82 .grantStatus = { PermissionState::PERMISSION_GRANTED },
83 .grantFlags = { 1 },
84 };
85 HapPolicyParams policyParams = {
86 .apl = APL_NORMAL,
87 .domain = "test.domain.pasteboard",
88 .permList = {},
89 .permStateList = { testState },
90 };
91
92 AccessTokenKit::AllocHapToken(infoParams, policyParams);
93 testAppTokenId_ = Security::AccessToken::AccessTokenKit::GetHapTokenID(infoParams.userID, infoParams.bundleName,
94 infoParams.instIndex);
95 SetSelfTokenID(testAppTokenId_);
96 AccessTokenKit::GrantPermission(testAppTokenId_, PermissionUtils::PERMISSION_READ_PASTEBOARD, PERMISSION_USER_SET);
97 }
98
99 class DisposableObserverImpl : public PasteboardDisposableObserver {
100 public:
OnTextReceived(const std::string & text,int32_t errCode)101 void OnTextReceived(const std::string &text, int32_t errCode) override
102 {
103 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "text=%{public}s, errCode=%{public}d", text.c_str(), errCode);
104 text_ = text;
105 errCode_ = errCode;
106 }
107
108 std::string text_;
109 int32_t errCode_;
110 };
111
112 /**
113 * @tc.name: TestDisposable001
114 * @tc.desc: should callback text when set paste data with disposable observer
115 * @tc.type: FUNC
116 */
117 HWTEST_F(PasteboardDisposableClientTest, TestDisposable001, TestSize.Level0)
118 {
119 DisposableType type = DisposableType::PLAIN_TEXT;
120 uint32_t maxLen = 100;
121 std::string bundleName = BUNDLE_NAME;
122 sptr<DisposableObserverImpl> observer = sptr<DisposableObserverImpl>::MakeSptr();
123 int32_t ret = PasteboardClient::GetInstance()->SubscribeDisposableObserver(observer, bundleName, type, maxLen);
124 ASSERT_EQ(ret, ERR_OK);
125
126 std::string setText = "123456";
127 PasteData setData;
128 setData.AddTextRecord(setText);
129 ret = PasteboardClient::GetInstance()->SetPasteData(setData);
130 EXPECT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
131
132 std::this_thread::sleep_for(std::chrono::seconds(1));
133 EXPECT_EQ(observer->errCode_, IPasteboardDisposableObserver::ERR_OK);
134 EXPECT_STREQ(observer->text_.c_str(), setText.c_str());
135 }
136
137 /**
138 * @tc.name: TestDisposable002
139 * @tc.desc: should callback timeout when subscribe disposable observer but not set paste data
140 * @tc.type: FUNC
141 */
142 HWTEST_F(PasteboardDisposableClientTest, TestDisposable002, TestSize.Level0)
143 {
144 DisposableType type = DisposableType::PLAIN_TEXT;
145 uint32_t maxLen = 100;
146 std::string bundleName = BUNDLE_NAME;
147 sptr<DisposableObserverImpl> observer = sptr<DisposableObserverImpl>::MakeSptr();
148 int32_t ret = PasteboardClient::GetInstance()->SubscribeDisposableObserver(observer, bundleName, type, maxLen);
149 ASSERT_EQ(ret, ERR_OK);
150
151 std::this_thread::sleep_for(std::chrono::seconds(1));
152 EXPECT_EQ(observer->errCode_, IPasteboardDisposableObserver::ERR_TIMEOUT);
153 EXPECT_STREQ(observer->text_.c_str(), "");
154 }
155
156 /**
157 * @tc.name: TestDisposable003
158 * @tc.desc: should get paste data failed when set paste data with disposable observer
159 * @tc.type: FUNC
160 */
161 HWTEST_F(PasteboardDisposableClientTest, TestDisposable003, TestSize.Level0)
162 {
163 DisposableType type = DisposableType::PLAIN_TEXT;
164 uint32_t maxLen = 100;
165 std::string bundleName = BUNDLE_NAME;
166 sptr<DisposableObserverImpl> observer = sptr<DisposableObserverImpl>::MakeSptr();
167 int32_t ret = PasteboardClient::GetInstance()->SubscribeDisposableObserver(observer, bundleName, type, maxLen);
168 ASSERT_EQ(ret, ERR_OK);
169
170 std::string setText = "123456";
171 PasteData setData;
172 setData.AddTextRecord(setText);
173 ret = PasteboardClient::GetInstance()->SetPasteData(setData);
174 ASSERT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
175
176 std::this_thread::sleep_for(std::chrono::seconds(1));
177 EXPECT_EQ(observer->errCode_, IPasteboardDisposableObserver::ERR_OK);
178 EXPECT_STREQ(observer->text_.c_str(), setText.c_str());
179
180 PasteData getData;
181 ret = PasteboardClient::GetInstance()->GetPasteData(getData);
182 EXPECT_NE(ret, static_cast<int32_t>(PasteboardError::E_OK));
183 }
184
185 /**
186 * @tc.name: TestDisposable004
187 * @tc.desc: should get paste data success when set paste data without disposable observer
188 * @tc.type: FUNC
189 */
190 HWTEST_F(PasteboardDisposableClientTest, TestDisposable004, TestSize.Level0)
191 {
192 DisposableType type = DisposableType::PLAIN_TEXT;
193 uint32_t maxLen = 100;
194 std::string bundleName = BUNDLE_NAME;
195 sptr<DisposableObserverImpl> observer = sptr<DisposableObserverImpl>::MakeSptr();
196 int32_t ret = PasteboardClient::GetInstance()->SubscribeDisposableObserver(observer, bundleName, type, maxLen);
197 ASSERT_EQ(ret, ERR_OK);
198
199 std::string setText = "123456";
200 PasteData setData;
201 setData.AddTextRecord(setText);
202 ret = PasteboardClient::GetInstance()->SetPasteData(setData);
203 ASSERT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
204
205 std::this_thread::sleep_for(std::chrono::seconds(1));
206 EXPECT_EQ(observer->errCode_, IPasteboardDisposableObserver::ERR_OK);
207 EXPECT_STREQ(observer->text_.c_str(), setText.c_str());
208
209 ret = PasteboardClient::GetInstance()->SetPasteData(setData);
210 ASSERT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
211
212 PasteData getData;
213 ret = PasteboardClient::GetInstance()->GetPasteData(getData);
214 ASSERT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
215 std::shared_ptr<std::string> getText = getData.GetPrimaryText();
216 ASSERT_TRUE(getText != nullptr);
217 EXPECT_STREQ(getText->c_str(), setText.c_str());
218 }
219
220 /**
221 * @tc.name: TestDisposable005
222 * @tc.desc: should callback ERR_DATA_IN_APP when set paste data with ShareOption::InApp
223 * @tc.type: FUNC
224 */
225 HWTEST_F(PasteboardDisposableClientTest, TestDisposable005, TestSize.Level0)
226 {
227 DisposableType type = DisposableType::PLAIN_TEXT;
228 uint32_t maxLen = 100;
229 std::string bundleName = BUNDLE_NAME;
230 sptr<DisposableObserverImpl> observer = sptr<DisposableObserverImpl>::MakeSptr();
231 int32_t ret = PasteboardClient::GetInstance()->SubscribeDisposableObserver(observer, bundleName, type, maxLen);
232 ASSERT_EQ(ret, ERR_OK);
233
234 std::string setText = "123456";
235 PasteData setData;
236 setData.AddTextRecord(setText);
237 setData.SetShareOption(ShareOption::InApp);
238 ret = PasteboardClient::GetInstance()->SetPasteData(setData);
239 ASSERT_EQ(ret, static_cast<int32_t>(PasteboardError::E_OK));
240
241 std::this_thread::sleep_for(std::chrono::seconds(1));
242 EXPECT_EQ(observer->errCode_, IPasteboardDisposableObserver::ERR_DATA_IN_APP);
243 EXPECT_STREQ(observer->text_.c_str(), "");
244 }
245 } // namespace OHOS::MiscServices
246