1 /*
2  * Copyright (c) 2023 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 #include <cerrno>
16 #include <gtest/gtest.h>
17 #include <securec.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 
21 #include "c_mock_common.h"
22 #define private public
23 #include "dlp_link_manager.h"
24 #undef private
25 #include "dlp_permission.h"
26 #include "dlp_permission_log.h"
27 #include "fuse_daemon.h"
28 
29 namespace OHOS {
30 namespace Security {
31 namespace DlpPermission {
32 using namespace testing::ext;
33 
34 namespace {
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "FuseDaemonTest"};
36 
37 static const fuse_ino_t ROOT_INODE = 1;
38 static const int DEFAULT_ATTR_TIMEOUT = 10000;
39 static const uint32_t MAX_FUSE_READ_BUFF_SIZE = 10 * 1024 * 1024; // 10M
40 static const uint32_t MAX_READ_DIR_BUF_SIZE = 100 * 1024;  // 100K
41 
42 static int g_fuseReplyErr = 0;
43 static struct fuse_file_info g_fuseReplyOpen;
44 static struct fuse_entry_param g_fuseReplyEntry;
45 static struct stat g_fuseReplyAttr;
46 static double g_fuseReplyAttrTimeout = 0.0F;
47 static size_t g_fuseReplyBufSize = 0;
48 static int g_session;
49 static const std::string DLP_TEST_DIR = "/data/dlpTest/";
50 
FuseReplyErrMock(fuse_req_t req,int err)51 static int FuseReplyErrMock(fuse_req_t req, int err)
52 {
53     (void)req;
54     g_fuseReplyErr = err;
55     return 0;
56 }
57 
FuseReplyOpenMock(fuse_req_t req,const struct fuse_file_info * f)58 static int FuseReplyOpenMock(fuse_req_t req, const struct fuse_file_info *f)
59 {
60     (void)req;
61     g_fuseReplyOpen = *f;
62     return 0;
63 }
64 
FuseReplyEntryMock(fuse_req_t req,const struct fuse_entry_param * e)65 int FuseReplyEntryMock(fuse_req_t req, const struct fuse_entry_param *e)
66 {
67     (void)req;
68     g_fuseReplyEntry = *e;
69     return 0;
70 }
71 
FuseReplyAttrMock(fuse_req_t req,const struct stat * attr,double attr_timeout)72 int FuseReplyAttrMock(fuse_req_t req, const struct stat *attr, double attr_timeout)
73 {
74     (void)req;
75     g_fuseReplyAttr = *attr;
76     g_fuseReplyAttrTimeout = attr_timeout;
77     return 0;
78 }
79 
80 static const size_t ADD_DIRENTRY_BUFF_LEN = 100;
FuseAddDirentryMockCurDirFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)81 size_t FuseAddDirentryMockCurDirFail(fuse_req_t req, char *buf, size_t bufsize,
82     const char *name, const struct stat *stbuf, off_t off)
83 {
84     (void)req;
85     (void)buf;
86     (void)bufsize;
87     (void)name;
88     (void)stbuf;
89     (void)off;
90     return ADD_DIRENTRY_BUFF_LEN + 1;
91 }
92 
FuseAddDirentryMockUpperDirFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)93 size_t FuseAddDirentryMockUpperDirFail(fuse_req_t req, char *buf, size_t bufsize,
94     const char *name, const struct stat *stbuf, off_t off)
95 {
96     (void)req;
97     (void)buf;
98     (void)bufsize;
99     (void)stbuf;
100     (void)off;
101     if (strcmp(name, ".") == 0) {
102         return strlen(".");
103     }
104     return ADD_DIRENTRY_BUFF_LEN + 1;
105 }
106 
FuseAddDirentryMockTestFileFail(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)107 size_t FuseAddDirentryMockTestFileFail(fuse_req_t req, char *buf, size_t bufsize,
108     const char *name, const struct stat *stbuf, off_t off)
109 {
110     (void)req;
111     (void)buf;
112     (void)bufsize;
113     (void)stbuf;
114     (void)off;
115     if (strcmp(name, "test") != 0) {
116         return strlen(name);
117     }
118     return ADD_DIRENTRY_BUFF_LEN + 1;
119 }
120 
FuseReplyBufMock(fuse_req_t req,const char * buf,size_t size)121 int FuseReplyBufMock(fuse_req_t req, const char *buf, size_t size)
122 {
123     (void)req;
124     (void)buf;
125     (void)size;
126     g_fuseReplyBufSize = 0;
127     return 0;
128 }
129 
130 
FuseSessionNewMock(struct fuse_args * args,const struct fuse_lowlevel_ops * op,size_t opSize,void * userdata)131 struct fuse_session *FuseSessionNewMock(struct fuse_args *args, const struct fuse_lowlevel_ops *op,
132     size_t opSize, void *userdata)
133 {
134     (void)args;
135     (void)op;
136     (void)opSize;
137     (void)userdata;
138     return reinterpret_cast<struct fuse_session *>(&g_session);
139 }
140 
FuseSessionMountMock(struct fuse_session * se,const char * mountpoint)141 int FuseSessionMountMock(struct fuse_session *se, const char *mountpoint)
142 {
143     (void)se;
144     (void)mountpoint;
145     return 0;
146 }
147 }
148 
149 class FuseDaemonTest : public testing::Test {
150 public:
SetUpTestCase()151     static void SetUpTestCase()
152     {
153         struct stat fstat;
154         if (stat(DLP_TEST_DIR.c_str(), &fstat) != 0) {
155             if (errno == ENOENT) {
156                 int32_t ret = mkdir(DLP_TEST_DIR.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
157                 if (ret < 0) {
158                     DLP_LOG_ERROR(LABEL, "mkdir mount point failed errno %{public}d", errno);
159                     return;
160                 }
161             } else {
162                 DLP_LOG_ERROR(LABEL, "get mount point failed errno %{public}d", errno);
163                 return;
164             }
165         }
166     };
167 
TearDownTestCase()168     static void TearDownTestCase()
169     {
170         rmdir(DLP_TEST_DIR.c_str());
171     };
172 
SetUp()173     void SetUp() {};
174 
TearDown()175     void TearDown() {};
176 };
177 
178 /**
179  * @tc.name: FuseDaemonLookup001
180  * @tc.desc: test fuse lookup callback abnormal branch
181  * @tc.type: FUNC
182  * @tc.require:AR000GVIGC
183  */
184 HWTEST_F(FuseDaemonTest, FuseDaemonLookup001, TestSize.Level1)
185 {
186     DLP_LOG_INFO(LABEL, "FuseDaemonLookup001");
187     DlpLinkFile linkfile("test", nullptr);
188     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
189     fuse_req_t req = nullptr;
190 
191     // file name null
192     DlpCMockCondition condition;
193     condition.mockSequence = { true };
194     SetMockConditions("fuse_reply_err", condition);
195     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
196     g_fuseReplyErr = 0;
197     FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, nullptr);
198     EXPECT_EQ(ENOENT, g_fuseReplyErr);
199     CleanMockConditions();
200 
201     // ino != ROOT_INODE
202     condition.mockSequence = { true };
203     SetMockConditions("fuse_reply_err", condition);
204     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
205     g_fuseReplyErr = 0;
206     FuseDaemon::fuseDaemonOper_.lookup(req, ino, "test");
207     EXPECT_EQ(ENOENT, g_fuseReplyErr);
208     CleanMockConditions();
209 
210     // name = '.'
211     condition.mockSequence = { true };
212     SetMockConditions("fuse_reply_entry", condition);
213     SetMockCallback("fuse_reply_entry", reinterpret_cast<CommonMockFuncT>(FuseReplyEntryMock));
214     (void)memset_s(&g_fuseReplyEntry, sizeof(g_fuseReplyEntry), 0, sizeof(g_fuseReplyEntry));
215     FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, ".");
216     EXPECT_EQ(ROOT_INODE, g_fuseReplyEntry.ino);
217     CleanMockConditions();
218 
219     // name = '..'
220     condition.mockSequence = { true };
221     SetMockConditions("fuse_reply_entry", condition);
222     SetMockCallback("fuse_reply_entry", reinterpret_cast<CommonMockFuncT>(FuseReplyEntryMock));
223     (void)memset_s(&g_fuseReplyEntry, sizeof(g_fuseReplyEntry), 0, sizeof(g_fuseReplyEntry));
224     FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, "..");
225     EXPECT_EQ(ROOT_INODE, g_fuseReplyEntry.ino);
226     CleanMockConditions();
227 
228     // name = '..'
229     condition.mockSequence = { true };
230     SetMockConditions("fuse_reply_err", condition);
231     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
232     g_fuseReplyErr = 0;
233     FuseDaemon::fuseDaemonOper_.lookup(req, ROOT_INODE, "test");
234     EXPECT_EQ(ENOENT, g_fuseReplyErr);
235     CleanMockConditions();
236 }
237 
238 /**
239  * @tc.name: FuseDaemonGetattr001
240  * @tc.desc: test fuse getattr callback abnormal branch
241  * @tc.type: FUNC
242  * @tc.require:AR000GVIGC
243  */
244 HWTEST_F(FuseDaemonTest, FuseDaemonGetattr001, TestSize.Level1)
245 {
246     DLP_LOG_INFO(LABEL, "FuseDaemonGetattr001");
247     fuse_req_t req = nullptr;
248 
249     // get ROOT_INODE attr
250     DlpCMockCondition condition;
251     condition.mockSequence = { true };
252     SetMockConditions("fuse_reply_attr", condition);
253     SetMockCallback("fuse_reply_attr", reinterpret_cast<CommonMockFuncT>(FuseReplyAttrMock));
254     (void)memset_s(&g_fuseReplyAttr, sizeof(g_fuseReplyAttr), 0, sizeof(g_fuseReplyAttr));
255     g_fuseReplyAttrTimeout = 0.0F;
256     FuseDaemon::fuseDaemonOper_.getattr(req, ROOT_INODE, nullptr);
257     EXPECT_EQ(memcmp(&FuseDaemon::rootFileStat_, &g_fuseReplyAttr, sizeof(struct stat)), 0);
258     EXPECT_EQ(DEFAULT_ATTR_TIMEOUT, g_fuseReplyAttrTimeout);
259     CleanMockConditions();
260 
261     // get not exist link file
262     SetMockConditions("fuse_reply_err", condition);
263     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
264     g_fuseReplyErr = 0;
265     FuseDaemon::fuseDaemonOper_.getattr(req, 0, nullptr);
266     EXPECT_EQ(ENOENT, g_fuseReplyErr);
267     CleanMockConditions();
268 }
269 
270 /**
271  * @tc.name: FuseDaemonOpen001
272  * @tc.desc: test fuse open callback abnormal branch
273  * @tc.type: FUNC
274  * @tc.require:AR000GVIGC
275  */
276 HWTEST_F(FuseDaemonTest, FuseDaemonOpen001, TestSize.Level1)
277 {
278     DLP_LOG_INFO(LABEL, "FuseDaemonOpen001");
279     fuse_req_t req = nullptr;
280 
281     // open ROOT_INODE
282     DlpCMockCondition condition;
283     condition.mockSequence = { true };
284     SetMockConditions("fuse_reply_err", condition);
285     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
286     g_fuseReplyErr = 0;
287     FuseDaemon::fuseDaemonOper_.open(req, ROOT_INODE, nullptr);
288     EXPECT_EQ(ENOENT, g_fuseReplyErr);
289     CleanMockConditions();
290 
291     // open null file
292     condition.mockSequence = { true };
293     SetMockConditions("fuse_reply_err", condition);
294     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
295     g_fuseReplyErr = 0;
296     FuseDaemon::fuseDaemonOper_.open(req, 0, nullptr);
297     EXPECT_EQ(ENOENT, g_fuseReplyErr);
298     CleanMockConditions();
299 
300     // open readonly dlp with O_TRUNC
301     std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
302     ASSERT_NE(dlpFile, nullptr);
303     DlpLinkFile linkfile("test", dlpFile);
304     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
305     struct fuse_file_info fi;
306     fi.flags = O_TRUNC;
307 
308     condition.mockSequence = { true };
309     SetMockConditions("fuse_reply_err", condition);
310     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
311     g_fuseReplyErr = 0;
312     FuseDaemon::fuseDaemonOper_.open(req, ino, &fi);
313     EXPECT_EQ(EINVAL, g_fuseReplyErr);
314     CleanMockConditions();
315 
316     fi.flags = O_RDWR;
317     condition.mockSequence = { true };
318     SetMockConditions("fuse_reply_open", condition);
319     SetMockCallback("fuse_reply_open", reinterpret_cast<CommonMockFuncT>(FuseReplyOpenMock));
320     (void)memset_s(&g_fuseReplyOpen, sizeof(g_fuseReplyOpen), 0, sizeof(g_fuseReplyOpen));
321     FuseDaemon::fuseDaemonOper_.open(req, ino, &fi);
322     EXPECT_EQ(O_RDWR, g_fuseReplyOpen.flags);
323     CleanMockConditions();
324 }
325 
326 /**
327  * @tc.name: FuseDaemonRead001
328  * @tc.desc: test fuse read callback abnormal branch
329  * @tc.type: FUNC
330  * @tc.require:AR000GVIGC
331  */
332 HWTEST_F(FuseDaemonTest, FuseDaemonRead001, TestSize.Level1)
333 {
334     DLP_LOG_INFO(LABEL, "FuseDaemonRead001");
335     fuse_req req;
336     req.ctx.uid = getuid();
337 
338     // offset < 0
339     DlpCMockCondition condition;
340     condition.mockSequence = { true };
341     SetMockConditions("fuse_reply_err", condition);
342     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
343     g_fuseReplyErr = 0;
344     FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 1, -1, nullptr);
345     EXPECT_EQ(EINVAL, g_fuseReplyErr);
346     CleanMockConditions();
347 
348     // offset > DLP_MAX_CONTENT_SIZE
349     condition.mockSequence = { true };
350     SetMockConditions("fuse_reply_err", condition);
351     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
352     g_fuseReplyErr = 0;
353     FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 1, DLP_MAX_CONTENT_SIZE + 1, nullptr);
354     EXPECT_EQ(EINVAL, g_fuseReplyErr);
355     CleanMockConditions();
356 
357     // size > MAX_FUSE_READ_BUFF_SIZE
358     condition.mockSequence = { true };
359     SetMockConditions("fuse_reply_err", condition);
360     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
361     g_fuseReplyErr = 0;
362     FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, MAX_FUSE_READ_BUFF_SIZE + 1, 0, nullptr);
363     EXPECT_EQ(EINVAL, g_fuseReplyErr);
364     CleanMockConditions();
365 }
366 
367 /**
368  * @tc.name: FuseDaemonRead002
369  * @tc.desc: test fuse read callback abnormal branch2
370  * @tc.type: FUNC
371  * @tc.require:AR000GVIGC
372  */
373 HWTEST_F(FuseDaemonTest, FuseDaemonRead002, TestSize.Level1)
374 {
375     DLP_LOG_INFO(LABEL, "FuseDaemonRead002");
376     fuse_req req;
377     req.ctx.uid = getuid();
378 
379     // ino ROOT_INODE
380     DlpCMockCondition condition;
381     condition.mockSequence = { true };
382     SetMockConditions("fuse_reply_err", condition);
383     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
384     g_fuseReplyErr = 0;
385     FuseDaemon::fuseDaemonOper_.read(&req, ROOT_INODE, 10, 0, nullptr);
386     EXPECT_EQ(ENOENT, g_fuseReplyErr);
387     CleanMockConditions();
388 
389     // ino 0
390     condition.mockSequence = { true };
391     SetMockConditions("fuse_reply_err", condition);
392     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
393     g_fuseReplyErr = 0;
394     FuseDaemon::fuseDaemonOper_.read(&req, 0, 10, 0, nullptr);
395     EXPECT_EQ(EBADF, g_fuseReplyErr);
396     CleanMockConditions();
397 
398     // can not read dlp file
399     std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
400     ASSERT_NE(dlpFile, nullptr);
401     DlpLinkFile linkfile("test", dlpFile);
402     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
403 
404     condition.mockSequence = { true };
405     SetMockConditions("fuse_reply_err", condition);
406     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
407     g_fuseReplyErr = 0;
408     FuseDaemon::fuseDaemonOper_.read(&req, ino, 10, 0, nullptr);
409     EXPECT_EQ(EIO, g_fuseReplyErr);
410     CleanMockConditions();
411 }
412 
413 /**
414  * @tc.name: FuseDaemonWrite001
415  * @tc.desc: test fuse write callback abnormal branch
416  * @tc.type: FUNC
417  * @tc.require:AR000GVIGC
418  */
419 HWTEST_F(FuseDaemonTest, FuseDaemonWrite001, TestSize.Level1)
420 {
421     DLP_LOG_INFO(LABEL, "FuseDaemonWrite001");
422     fuse_req_t req = nullptr;
423 
424     // offset < 0
425     DlpCMockCondition condition;
426     condition.mockSequence = { true };
427     SetMockConditions("fuse_reply_err", condition);
428     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
429     g_fuseReplyErr = 0;
430     FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, -1, nullptr);
431     EXPECT_EQ(EINVAL, g_fuseReplyErr);
432     CleanMockConditions();
433 
434     // offset > DLP_MAX_CONTENT_SIZE
435     condition.mockSequence = { true };
436     SetMockConditions("fuse_reply_err", condition);
437     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
438     g_fuseReplyErr = 0;
439     FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, DLP_MAX_CONTENT_SIZE + 1, nullptr);
440     EXPECT_EQ(EINVAL, g_fuseReplyErr);
441     CleanMockConditions();
442 
443     // size > DLP_FUSE_MAX_BUFFLEN
444     condition.mockSequence = { true };
445     SetMockConditions("fuse_reply_err", condition);
446     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
447     g_fuseReplyErr = 0;
448     FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, DLP_FUSE_MAX_BUFFLEN + 1, 100, nullptr);
449     EXPECT_EQ(EINVAL, g_fuseReplyErr);
450     CleanMockConditions();
451 
452     // ino ROOT_INODE
453     condition.mockSequence = { true };
454     SetMockConditions("fuse_reply_err", condition);
455     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
456     g_fuseReplyErr = 0;
457     FuseDaemon::fuseDaemonOper_.write(req, ROOT_INODE, nullptr, 1, 0, nullptr);
458     EXPECT_EQ(ENOENT, g_fuseReplyErr);
459     CleanMockConditions();
460 
461     // can not write dlp file
462     std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
463     ASSERT_NE(dlpFile, nullptr);
464     DlpLinkFile linkfile("test", dlpFile);
465     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
466 
467     condition.mockSequence = { true };
468     SetMockConditions("fuse_reply_err", condition);
469     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
470     g_fuseReplyErr = 0;
471     FuseDaemon::fuseDaemonOper_.write(req, ino, nullptr, 1, 0, nullptr);
472     EXPECT_EQ(EIO, g_fuseReplyErr);
473     CleanMockConditions();
474 }
475 
476 /**
477  * @tc.name: FuseDaemonForget001
478  * @tc.desc: test fuse forget callback abnormal branch
479  * @tc.type: FUNC
480  * @tc.require:AR000GVIGC
481  */
482 HWTEST_F(FuseDaemonTest, FuseDaemonForget001, TestSize.Level1)
483 {
484     DLP_LOG_INFO(LABEL, "FuseDaemonForget001");
485     fuse_req_t req = nullptr;
486 
487     // ino ROOT_INODE
488     DlpCMockCondition condition;
489     condition.mockSequence = { true };
490     SetMockConditions("fuse_reply_err", condition);
491     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
492     g_fuseReplyErr = 0;
493     FuseDaemon::fuseDaemonOper_.forget(req, ROOT_INODE, 1);
494     EXPECT_EQ(ENOENT, g_fuseReplyErr);
495     CleanMockConditions();
496 
497     condition.mockSequence = { true };
498     SetMockConditions("fuse_reply_err", condition);
499     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
500     g_fuseReplyErr = 0;
501     FuseDaemon::fuseDaemonOper_.forget(req, 0, 1);
502     EXPECT_EQ(EBADF, g_fuseReplyErr);
503     CleanMockConditions();
504 }
505 
506 /**
507  * @tc.name: FuseDaemonReadDir001
508  * @tc.desc: test fuse read dir callback abnormal branch
509  * @tc.type: FUNC
510  * @tc.require:AR000GVIGC
511  */
512 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir001, TestSize.Level1)
513 {
514     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir001");
515     fuse_req_t req = nullptr;
516 
517     // off < 0
518     DlpCMockCondition condition;
519     condition.mockSequence = { true };
520     SetMockConditions("fuse_reply_err", condition);
521     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
522     g_fuseReplyErr = 0;
523     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, 10, -1, nullptr);
524     EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
525 
526     // off > DLP_MAX_CONTENT_SIZE
527     condition.mockSequence = { true };
528     SetMockConditions("fuse_reply_err", condition);
529     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
530     g_fuseReplyErr = 0;
531     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, 10, DLP_MAX_CONTENT_SIZE + 1, nullptr);
532     EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
533     CleanMockConditions();
534 
535     // ino != ROOT_INODE
536     condition.mockSequence = { true };
537     SetMockConditions("fuse_reply_err", condition);
538     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
539     g_fuseReplyErr = 0;
540     FuseDaemon::fuseDaemonOper_.readdir(req, 0, 10, 0, nullptr);
541     EXPECT_EQ(ENOTDIR, g_fuseReplyErr);
542     CleanMockConditions();
543 
544     // size > MAX_READ_DIR_BUF_SIZE
545     condition.mockSequence = { true };
546     SetMockConditions("fuse_reply_err", condition);
547     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
548     g_fuseReplyErr = 0;
549     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, MAX_READ_DIR_BUF_SIZE + 1, 0, nullptr);
550     EXPECT_EQ(EINVAL, g_fuseReplyErr);
551     CleanMockConditions();
552 }
553 
554 /**
555  * @tc.name: FuseDaemonReadDir002
556  * @tc.desc: test fuse AddDirentry callback CUR_DIR entry too large
557  * @tc.type: FUNC
558  * @tc.require:AR000GVIGC
559  */
560 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir002, TestSize.Level1)
561 {
562     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir002");
563     fuse_req_t req = nullptr;
564 
565     DlpCMockCondition condition;
566     condition.mockSequence = { true };
567     SetMockConditions("fuse_reply_err", condition);
568     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
569 
570     DlpCMockCondition condition1;
571     condition1.mockSequence = { true };
572     SetMockConditions("fuse_add_direntry", condition1);
573     SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockCurDirFail));
574 
575     g_fuseReplyErr = 0;
576     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
577     EXPECT_EQ(EINVAL, g_fuseReplyErr);
578     CleanMockConditions();
579 }
580 
581 /**
582  * @tc.name: FuseDaemonReadDir003
583  * @tc.desc: test fuse AddDirentry callback UPPER_DIR entry too large
584  * @tc.type: FUNC
585  * @tc.require:AR000GVIGC
586  */
587 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir003, TestSize.Level1)
588 {
589     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir003");
590     fuse_req_t req = nullptr;
591 
592     DlpCMockCondition condition;
593     condition.mockSequence = { true };
594     SetMockConditions("fuse_reply_err", condition);
595     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
596 
597     DlpCMockCondition condition1;
598     condition1.mockSequence = { true, true, true };
599     SetMockConditions("fuse_add_direntry", condition1);
600     SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockUpperDirFail));
601 
602     g_fuseReplyErr = 0;
603     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
604     EXPECT_EQ(EINVAL, g_fuseReplyErr);
605     CleanMockConditions();
606 }
607 
608 /**
609  * @tc.name: FuseDaemonReadDir004
610  * @tc.desc: test fuse AddDirentry callback test file entry fail
611  * @tc.type: FUNC
612  * @tc.require:AR000GVIGC
613  */
614 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir004, TestSize.Level1)
615 {
616     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir004");
617     fuse_req_t req = nullptr;
618     std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
619     ASSERT_NE(filePtr, nullptr);
620     DlpLinkManager::GetInstance().g_DlpLinkFileNameMap_.clear();
621     DlpLinkManager::GetInstance().AddDlpLinkFile(filePtr, "test");
622 
623     DlpCMockCondition condition;
624     condition.mockSequence = { true };
625     SetMockConditions("fuse_reply_err", condition);
626     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
627 
628     DlpCMockCondition condition1;
629     condition1.mockSequence = { true, true, true, true, true };
630     SetMockConditions("fuse_add_direntry", condition1);
631     SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockTestFileFail));
632     g_fuseReplyErr = 0;
633     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, 0, nullptr);
634     EXPECT_EQ(EINVAL, g_fuseReplyErr);
635     CleanMockConditions();
636 
637     DlpLinkManager::GetInstance().DeleteDlpLinkFile(filePtr);
638 }
639 
640 /**
641  * @tc.name: FuseDaemonReadDir005
642  * @tc.desc: test fuse AddDirentry callback test file entry fail
643  * @tc.type: FUNC
644  * @tc.require:AR000GVIGC
645  */
646 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir005, TestSize.Level1)
647 {
648     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir005");
649     fuse_req_t req = nullptr;
650     std::shared_ptr<DlpFile> filePtr = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
651     DlpLinkManager::GetInstance().AddDlpLinkFile(filePtr, "test");
652     DlpCMockCondition condition;
653     condition.mockSequence = { true };
654     SetMockConditions("fuse_reply_err", condition);
655     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
656 
657     DlpCMockCondition condition1;
658     condition1.mockSequence = { true, true, true, true, true };
659     SetMockConditions("fuse_add_direntry", condition1);
660     SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockTestFileFail));
661 
662     DlpCMockCondition condition2;
663     condition2.mockSequence = { true };
664     SetMockConditions("fuse_reply_buf", condition2);
665     SetMockCallback("fuse_reply_buf", reinterpret_cast<CommonMockFuncT>(FuseReplyBufMock));
666 
667     g_fuseReplyBufSize = 1;
668     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN, ADD_DIRENTRY_BUFF_LEN + 1, nullptr);
669     EXPECT_EQ(static_cast<size_t>(1), g_fuseReplyBufSize);
670     CleanMockConditions();
671     DlpLinkManager::GetInstance().DeleteDlpLinkFile(filePtr);
672 }
673 
674 /**
675  * @tc.name: FuseDaemonReadDir006
676  * @tc.desc: test fuse AddDirentry callback CUR_DIR entry too large
677  * @tc.type: FUNC
678  * @tc.require:AR000GVIGC
679  */
680 HWTEST_F(FuseDaemonTest, FuseDaemonReadDir006, TestSize.Level1)
681 {
682     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir006");
683     fuse_req_t req = nullptr;
684 
685     DlpCMockCondition condition;
686     condition.mockSequence = { true };
687     SetMockConditions("fuse_reply_err", condition);
688     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
689 
690     DlpCMockCondition condition1;
691     condition1.mockSequence = { true };
692     SetMockConditions("fuse_add_direntry", condition1);
693     SetMockCallback("fuse_add_direntry", reinterpret_cast<CommonMockFuncT>(FuseAddDirentryMockCurDirFail));
694 
695     DlpCMockCondition condition2;
696     condition2.mockSequence = { true };
697     SetMockConditions("fuse_reply_buf", condition2);
698     SetMockCallback("fuse_reply_buf", reinterpret_cast<CommonMockFuncT>(FuseReplyBufMock));
699 
700     g_fuseReplyErr = 0;
701     FuseDaemon::fuseDaemonOper_.readdir(req, ROOT_INODE, ADD_DIRENTRY_BUFF_LEN + 1, DLP_MAX_CONTENT_SIZE, nullptr);
702     EXPECT_EQ(static_cast<size_t>(0), g_fuseReplyBufSize);
703     CleanMockConditions();
704 }
705 
706 /**
707  * @tc.name: FuseDaemonSetAttr001
708  * @tc.desc: test fuse set attr callback abnormal test
709  * @tc.type: FUNC
710  * @tc.require:AR000GVIGC
711  */
712 HWTEST_F(FuseDaemonTest, FuseDaemonSetAttr001, TestSize.Level1)
713 {
714     DLP_LOG_INFO(LABEL, "FuseDaemonReadDir005");
715     fuse_req_t req = nullptr;
716 
717     // attr = nullptr
718     DlpCMockCondition condition;
719     condition.mockSequence = { true };
720     SetMockConditions("fuse_reply_err", condition);
721     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
722     g_fuseReplyErr = 0;
723     FuseDaemon::fuseDaemonOper_.setattr(req, 0, nullptr, 0, nullptr);
724     EXPECT_EQ(EINVAL, g_fuseReplyErr);
725     CleanMockConditions();
726 
727     // ino = ROOT_INODE
728     condition.mockSequence = { true };
729     SetMockConditions("fuse_reply_err", condition);
730     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
731     g_fuseReplyErr = 0;
732     struct stat attr;
733     FuseDaemon::fuseDaemonOper_.setattr(req, ROOT_INODE, &attr, 0, nullptr);
734     EXPECT_EQ(EACCES, g_fuseReplyErr);
735     CleanMockConditions();
736 
737     // ino = 0
738     condition.mockSequence = { true };
739     SetMockConditions("fuse_reply_err", condition);
740     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
741     g_fuseReplyErr = 0;
742     FuseDaemon::fuseDaemonOper_.setattr(req, 0, &attr, 0, nullptr);
743     EXPECT_EQ(ENOENT, g_fuseReplyErr);
744     CleanMockConditions();
745 
746     // truncate fail
747     std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
748     ASSERT_NE(dlpFile, nullptr);
749     DlpLinkFile linkfile("test", dlpFile);
750     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
751 
752     condition.mockSequence = { true };
753     SetMockConditions("fuse_reply_err", condition);
754     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
755     g_fuseReplyErr = 0;
756     attr.st_size = 0;
757     FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
758     EXPECT_EQ(EINVAL, g_fuseReplyErr);
759     CleanMockConditions();
760 }
761 
762 /**
763  * @tc.name: FuseDaemonSetAttr002
764  * @tc.desc: test fuse set attr callback abnormal test
765  * @tc.type: FUNC
766  * @tc.require:AR000GVIGC
767  */
768 HWTEST_F(FuseDaemonTest, FuseDaemonSetAttr002, TestSize.Level1)
769 {
770     DLP_LOG_INFO(LABEL, "FuseDaemonSetAttr002");
771     fuse_req_t req = nullptr;
772 
773     // attr = nullptr
774     DlpCMockCondition condition;
775 
776     std::shared_ptr<DlpFile> dlpFile = std::make_shared<DlpFile>(-1, DLP_TEST_DIR, 0, false);
777     ASSERT_NE(dlpFile, nullptr);
778     DlpLinkFile linkfile("test", dlpFile);
779     fuse_ino_t ino = static_cast<fuse_ino_t>(reinterpret_cast<uintptr_t>(&linkfile));
780     struct stat attr;
781     g_fuseReplyErr = 0;
782 
783     condition.mockSequence = { true };
784     SetMockConditions("fuse_reply_err", condition);
785     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
786     attr.st_size = DLP_MAX_CONTENT_SIZE + 1;
787     FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
788     EXPECT_EQ(EINVAL, g_fuseReplyErr);
789     CleanMockConditions();
790 
791     condition.mockSequence = { true };
792     SetMockConditions("fuse_reply_err", condition);
793     SetMockCallback("fuse_reply_err", reinterpret_cast<CommonMockFuncT>(FuseReplyErrMock));
794     attr.st_size = -1;
795     FuseDaemon::fuseDaemonOper_.setattr(req, ino, &attr, FUSE_SET_ATTR_SIZE, nullptr);
796     EXPECT_EQ(EINVAL, g_fuseReplyErr);
797     CleanMockConditions();
798 }
799 
800 /**
801  * @tc.name: InitFuseFs001
802  * @tc.desc: test fuse daemon init
803  * @tc.type: FUNC
804  * @tc.require:AR000GVIGC
805  */
806 HWTEST_F(FuseDaemonTest, InitFuseFs001, TestSize.Level1)
807 {
808     DLP_LOG_INFO(LABEL, "InitFuseFs001");
809     FuseDaemon::init_ = false;
810     EXPECT_EQ(-1, FuseDaemon::InitFuseFs());
811     // second init will fail whatever last init result is.
812     EXPECT_EQ(-1, FuseDaemon::InitFuseFs());
813 
814     // fuse fd is wrong
815     FuseDaemon::init_ = false;
816     EXPECT_EQ(-1, FuseDaemon::InitFuseFs());
817 }
818 
819 /**
820  * @tc.name: FuseFsDaemonThread001
821  * @tc.desc: test fuse daemon thread abnormal
822  * @tc.type: FUNC
823  * @tc.require:AR000GVIGC
824  */
825 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread001, TestSize.Level1)
826 {
827     DLP_LOG_INFO(LABEL, "FuseFsDaemonThread001");
828 
829     DlpCMockCondition condition;
830     condition.mockSequence = { true };
831     SetMockConditions("fuse_opt_add_arg", condition);
832     DlpCMockCondition condition1;
833     condition1.mockSequence = { true };
834     SetMockConditions("fuse_session_new", condition1);
835     DlpCMockCondition condition2;
836     condition2.mockSequence = { true };
837     SetMockConditions("fuse_opt_free_args", condition2);
838     FuseDaemon::FuseFsDaemonThread(1);
839     EXPECT_EQ(-1, FuseDaemon::WaitDaemonEnable());
840     CleanMockConditions();
841 }
842 
843 /**
844  * @tc.name: FuseFsDaemonThread002
845  * @tc.desc: test fuse daemon thread abnormal
846  * @tc.type: FUNC
847  * @tc.require:AR000GVIGC
848  */
849 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread002, TestSize.Level1)
850 {
851     DLP_LOG_INFO(LABEL, "FuseFsDaemonThread002");
852 
853     DlpCMockCondition condition;
854     condition.mockSequence = { true };
855     SetMockConditions("fuse_opt_add_arg", condition);
856     DlpCMockCondition condition1;
857     condition1.mockSequence = { true };
858     SetMockConditions("fuse_session_new", condition1);
859     SetMockCallback("fuse_session_new", reinterpret_cast<CommonMockFuncT>(FuseSessionNewMock));
860     DlpCMockCondition condition2;
861     condition2.mockSequence = { true };
862     SetMockConditions("fuse_session_mount", condition2);
863     DlpCMockCondition condition3;
864     condition3.mockSequence = { true };
865     SetMockConditions("fuse_session_destroy", condition3);
866     DlpCMockCondition condition4;
867     condition4.mockSequence = { true };
868     SetMockConditions("fuse_opt_free_args", condition4);
869 
870     FuseDaemon::FuseFsDaemonThread(1);
871     EXPECT_EQ(-1, FuseDaemon::WaitDaemonEnable());
872     CleanMockConditions();
873 }
874 
875 /**
876  * @tc.name: FuseFsDaemonThread003
877  * @tc.desc: test fuse daemon thread abnormal
878  * @tc.type: FUNC
879  * @tc.require:AR000GVIGC
880  */
881 HWTEST_F(FuseDaemonTest, FuseFsDaemonThread003, TestSize.Level1)
882 {
883     DLP_LOG_INFO(LABEL, "FuseFsDaemonThread003");
884 
885     DlpCMockCondition condition;
886     condition.mockSequence = { true };
887     SetMockConditions("fuse_opt_add_arg", condition);
888     DlpCMockCondition condition1;
889     condition1.mockSequence = { true };
890     SetMockConditions("fuse_session_new", condition1);
891     SetMockCallback("fuse_session_new", reinterpret_cast<CommonMockFuncT>(FuseSessionNewMock));
892     DlpCMockCondition condition2;
893     condition2.mockSequence = { true };
894     SetMockConditions("fuse_session_mount", condition2);
895     SetMockCallback("fuse_session_mount", reinterpret_cast<CommonMockFuncT>(FuseSessionMountMock));
896     DlpCMockCondition condition3;
897     condition3.mockSequence = { true };
898     SetMockConditions("fuse_session_destroy", condition3);
899     DlpCMockCondition condition4;
900     condition4.mockSequence = { true };
901     SetMockConditions("fuse_opt_free_args", condition4);
902     DlpCMockCondition condition5;
903     condition5.mockSequence = { true };
904     SetMockConditions("fuse_session_loop", condition5);
905 
906     FuseDaemon::FuseFsDaemonThread(1);
907     EXPECT_EQ(0, FuseDaemon::WaitDaemonEnable());
908     CleanMockConditions();
909 }
910 
911 /**
912  * @tc.name: FuseDaemonInit001
913  * @tc.desc: FuseDaemonInit
914  * @tc.type: FUNC
915  * @tc.require:AR000GVIGC
916  */
917 HWTEST_F(FuseDaemonTest, FuseDaemonInit001, TestSize.Level1)
918 {
919     DLP_LOG_INFO(LABEL, "FuseDaemonInit001");
920 
921     FuseDaemon::fuseDaemonOper_.init(nullptr, nullptr);
922 
923     fuse_conn_info conn = { 0 };
924     FuseDaemon::fuseDaemonOper_.init(nullptr, &conn);
925     EXPECT_EQ(FUSE_CAP_WRITEBACK_CACHE, conn.want);
926 }
927 }  // namespace DlpPermission
928 }  // namespace Security
929 }  // namespace OHOS