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 #include <cstdint>
18 #include <cstdlib>
19 #include <ctime>
20 #include <fstream>
21 #include <iostream>
22 #include <memory>
23 #include <sstream>
24 #include <string>
25 #include <unordered_map>
26 
27 #include <csetjmp>
28 #include <csignal>
29 #include <cstring>
30 #include <dirent.h>
31 #include <execinfo.h>
32 #include <fcntl.h>
33 #include <pwd.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 
37 #include <gmock/gmock-actions.h>
38 #include <gmock/gmock-cardinalities.h>
39 #include <gmock/gmock-spec-builders.h>
40 #include <gmock/gmock.h>
41 #include <gtest/gtest.h>
42 
43 #include "metadata_stream.h"
44 #include "buffer_metadata_stream.h"
45 #include "file_metadata_stream.h"
46 #include "data_buf.h"
47 
48 using namespace testing::ext;
49 using namespace testing;
50 using namespace OHOS::Media;
51 
52 namespace OHOS {
53 namespace Media {
54 const int SIZE_1024 = 1024;
55 const int SIZE_512 = 512;
56 const int SIZE_255 = 255;
57 const int SIZE_20 = 20;
58 const int SIZE_10 = 10;
59 const int TEST_DIR_PERMISSIONS = 0777;
60 
61 class MemoryCheck {
62 public:
Start()63     void Start()
64     {
65         startVmSize = GetVmSize();
66         startVmRSS = GetVmRSS();
67         startFdCount = CountOpenFileDescriptors();
68     }
69 
End()70     void End()
71     {
72         endVmSize = GetVmSize();
73         endVmRSS = GetVmRSS();
74         endFdCount = CountOpenFileDescriptors();
75     }
76 
77     bool check = true;
78 
Compare() const79     bool Compare() const
80     {
81         if (check) {
82             if (startVmSize != endVmSize || startVmRSS != endVmRSS || startFdCount != endFdCount) {
83                 std::cout << "Difference in VmSize: " << endVmSize - startVmSize << std::endl;
84                 std::cout << "Difference in VmRSS: " << endVmRSS - startVmRSS << std::endl;
85                 std::cout << "Difference in File Descriptors: " << endFdCount - startFdCount << std::endl;
86                 return false;
87             }
88         }
89         return true;
90     }
91 
92 private:
GetVmSize() const93     long GetVmSize() const
94     {
95         return GetMemoryInfo("VmSize:");
96     }
97 
GetVmRSS() const98     long GetVmRSS() const
99     {
100         return GetMemoryInfo("VmRSS:");
101     }
102 
CountOpenFileDescriptors() const103     int CountOpenFileDescriptors() const
104     {
105         DIR *dir;
106         int fdCount = 0;
107         std::string dirPath = "/proc/" + std::to_string(getpid()) + "/fd/";
108         if ((dir = opendir(dirPath.c_str())) != nullptr) {
109             while (readdir(dir) != nullptr) {
110                 fdCount++;
111             }
112             closedir(dir);
113         } else {
114             std::cerr << "Could not open " << dirPath << std::endl;
115         }
116 
117         return fdCount;
118     }
119 
GetMemoryInfo(const std::string & name) const120     long GetMemoryInfo(const std::string &name) const
121     {
122         std::string line;
123         std::ifstream statusFile("/proc/self/status");
124 
125         while (std::getline(statusFile, line)) {
126             if (line.find(name) != std::string::npos) {
127                 return std::stol(line.substr(name.length()));
128             }
129         }
130 
131         return 0;
132     }
133 
134     long startVmSize = 0;
135     long startVmRSS = 0;
136     long endVmSize = 0;
137     long endVmRSS = 0;
138     int startFdCount = 0;
139     int endFdCount = 0;
140 };
141 
CountOpenFileDescriptors()142 int CountOpenFileDescriptors()
143 {
144     DIR *dir;
145     int fdCount = 0;
146     std::string dirPath = "/proc/" + std::to_string(getpid()) + "/fd/";
147     if ((dir = opendir(dirPath.c_str())) != nullptr) {
148         while (readdir(dir) != nullptr) {
149             fdCount++;
150         }
151         closedir(dir);
152     } else {
153         std::cerr << "Could not open " << dirPath << std::endl;
154     }
155 
156     return fdCount;
157 }
158 
159 
RemoveFile(const std::string & filePath)160 void RemoveFile(const std::string &filePath)
161 {
162     int result = remove(filePath.c_str());
163     if (result != 0) {
164         char errstr[METADATA_STREAM_ERROR_BUFFER_SIZE];
165         strerror_r(errno, errstr, sizeof(errstr));
166     }
167 }
168 
CreateIfNotExit(const std::string & filePath)169 std::string CreateIfNotExit(const std::string &filePath)
170 {
171     struct stat buffer;
172     if (stat(filePath.c_str(), &buffer) != 0) { // 文件不存在
173         std::ofstream file(filePath);
174         if (!file) {
175             std::cerr << "Failed to create file: " << filePath << std::endl;
176         } else {
177             file.close();
178         }
179     }
180     return filePath;
181 }
182 
183 class MetadataStreamTest : public testing::Test {
184 public:
MetadataStreamTest()185     MetadataStreamTest() {}
~MetadataStreamTest()186     ~MetadataStreamTest() override {}
187     std::string filePath = "/data/local/tmp/image/testfile.txt";
188     std::string filePathSource = "/data/local/tmp/image/test_exif_test.jpg";
189     std::string filePathDest = "/data/local/tmp/image/testfile_dest.png";
190     std::string backupFilePathSource = "/data/local/tmp/image/test_exif.jpg";
191     const ssize_t testSize[4] = {
192         1,
193         METADATA_STREAM_PAGE_SIZE + 1,
194         METADATA_STREAM_PAGE_SIZE,
195         METADATA_STREAM_PAGE_SIZE - 1
196     };
197     MemoryCheck memoryCheck;
198 
SetUp()199     void SetUp() override
200     {
201         // Create the directory
202         std::string dirPath = "/data/local/tmp/image";
203         if (access(dirPath.c_str(), F_OK) != 0) {
204             int ret = mkdir(dirPath.c_str(), TEST_DIR_PERMISSIONS);
205             if (ret != 0) {
206                 char buf[METADATA_STREAM_ERROR_BUFFER_SIZE];
207                 strerror_r(errno, buf, sizeof(buf));
208                 GTEST_LOG_(ERROR) << "Failed to create directory: " << dirPath << ", error: " << buf;
209             }
210         }
211 
212         // Backup the files
213         std::filesystem::copy(backupFilePathSource, filePathSource, std::filesystem::copy_options::overwrite_existing);
214         memoryCheck.check = true;
215         memoryCheck.Start();
216     }
217 
218     const static std::string tmpDirectory;
219     static bool alreadyExist;
220 
TearDown()221     void TearDown() override
222     {
223         memoryCheck.End();
224         memoryCheck.check = false;
225         if (!memoryCheck.Compare()) {
226             GTEST_LOG_(INFO) << "Memory leak detected";
227         }
228         RemoveFile(filePath.c_str());
229         RemoveFile(filePathDest.c_str());
230     }
231 
SetUpTestCase()232     static void SetUpTestCase()
233     {
234         // Create the directory
235         if (access(tmpDirectory.c_str(), F_OK) != 0) {
236             int ret = mkdir(tmpDirectory.c_str(), TEST_DIR_PERMISSIONS);
237             if (ret != 0) {
238                 char buf[METADATA_STREAM_ERROR_BUFFER_SIZE];
239                 strerror_r(errno, buf, sizeof(buf));
240                 GTEST_LOG_(ERROR) << "Failed to create directory: " << tmpDirectory << ", error: " << buf;
241             }
242             alreadyExist = false;
243         } else {
244             alreadyExist = true;
245         }
246     }
TearDownTestCase()247     static void TearDownTestCase()
248     {
249         if (!alreadyExist) {
250             rmdir(tmpDirectory.c_str());
251         }
252     }
253 };
254 
255 bool MetadataStreamTest::alreadyExist = false;
256 const std::string MetadataStreamTest::tmpDirectory = "/data/local/tmp/image";
257 
258 class MockFileWrapper : public FileWrapper {
259 public:
260     MOCK_METHOD(ssize_t, FWrite, (const void *src, size_t size, ssize_t nmemb, FILE *file), (override));
261     MOCK_METHOD(ssize_t, FRead, (void *destv, size_t size, ssize_t nmemb, FILE *file), (override));
262 
MockFileWrapper()263     MockFileWrapper()
264     {
265         // Set the default behavior of write to call the system's write function
266         ON_CALL(*this, FWrite(_, _, _, _))
267             .WillByDefault(Invoke([](const void *src, size_t size, ssize_t nmemb, FILE *file) {
268                 size_t result = ::fwrite(src, size, nmemb, file);
269                 if (result != static_cast<size_t>(nmemb)) {
270                     char errstr[METADATA_STREAM_ERROR_BUFFER_SIZE];
271                     strerror_r(errno, errstr, sizeof(errstr));
272                     std::cerr << "Failed to write to the file: " << errstr << std::endl;
273                 }
274                 return result;
275             }));
276         // Set the default behavior of read to call the system's read function
277         ON_CALL(*this, FRead(_, _, _, _)).WillByDefault(Invoke([](void *destv, size_t size, ssize_t nmemb, FILE *file) {
278             size_t result = ::fread(destv, size, nmemb, file);
279             if (result != static_cast<size_t>(nmemb)) {
280                 char errstr[METADATA_STREAM_ERROR_BUFFER_SIZE];
281                 strerror_r(errno, errstr, sizeof(errstr));
282                 std::cerr << "Failed to read from the file: " << errstr << std::endl;
283             }
284             return result;
285         }));
286     }
287 };
288 
289 /**
290  * @tc.name: FileMetadataStream_Write001
291  * @tc.desc: Test the Write function of FileMetadataStream, whether it can write
292  * normally and verify the written data
293  * @tc.type: FUNC
294  */
295 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write001, TestSize.Level3)
296 {
297     // Create a FileMetadataStream object
298     FileMetadataStream stream(CreateIfNotExit(filePath));
299 
300     // Open the file
301     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
302 
303     // Create some data to write
304     byte data[SIZE_10] = {0};
305 
306     ASSERT_EQ(stream.Tell(), 0);
307 
308     // Write the data to the file
309     size_t bytesWritten = stream.Write(data, sizeof(data));
310 
311     // Check that the correct number of bytes were written
312     ASSERT_EQ(bytesWritten, sizeof(data));
313 
314     // Flush the file
315     stream.Flush();
316 
317     // Open the file again
318     int fileDescriptor = open(filePath.c_str(), O_RDONLY);
319     ASSERT_NE(fileDescriptor, -1);
320 
321     // Read the data from the file
322     byte buffer[SIZE_10];
323     ssize_t bytesRead = read(fileDescriptor, buffer, sizeof(buffer));
324 
325     // Check that the correct number of bytes were read
326     ASSERT_EQ(bytesRead, sizeof(data));
327 
328     // Check that the data read is the same as the data written
329     ASSERT_EQ(memcmp(data, buffer, sizeof(data)), 0);
330 
331     // Close the file
332     close(fileDescriptor);
333 }
334 
335 /**
336  * @tc.name: FileMetadataStream_Write002
337  * @tc.desc: Test the Write function of FileMetadataStream when the file is not
338  * open
339  * @tc.type: FUNC
340  */
341 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write002, TestSize.Level3)
342 {
343     FileMetadataStream stream(filePath);
344     byte data[SIZE_10] = {0};
345     ASSERT_EQ(stream.Write(data, sizeof(data)), -1);
346 }
347 
348 /**
349  * @tc.name: FileMetadataStream_Write003
350  * @tc.desc: Test the Write function of FileMetadataStream when the amount of data
351  * written exceeds the remaining space in the file system
352  * @tc.type: FUNC
353  */
354 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write003, TestSize.Level3)
355 {
356     // This test case requires an MetadataStream object that can simulate a read
357     // failure, so mock technology may be needed in actual testing
358     auto mockFileWrapper = std::make_unique<MockFileWrapper>();
359     // Set the behavior of the write function to always return -1, simulating a
360     // write failure
361     EXPECT_CALL(*mockFileWrapper.get(), FWrite(_, _, _, _)).WillOnce(Return(-1));
362 
363     FileMetadataStream stream(CreateIfNotExit(filePath), std::move(mockFileWrapper));
364 
365     // Test the Write function
366     byte buffer[SIZE_1024];
367     stream.Open(OpenMode::ReadWrite);
368     EXPECT_EQ(stream.Write(buffer, sizeof(buffer)), -1);
369 }
370 
371 /**
372  * @tc.name: FileMetadataStream_Write004
373  * @tc.desc: Test the Write function of FileMetadataStream when all data from the
374  * source image stream has been read
375  * @tc.type: FUNC
376  */
377 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write004, TestSize.Level3)
378 {
379     FileMetadataStream stream1(filePathSource);
380     FileMetadataStream stream2(CreateIfNotExit(filePathDest));
381     ASSERT_TRUE(stream1.Open(OpenMode::ReadWrite));
382     ASSERT_TRUE(stream2.Open(OpenMode::ReadWrite));
383     // Read all data from stream1
384     byte buffer[METADATA_STREAM_PAGE_SIZE];
385     while (stream1.Read(buffer, sizeof(buffer)) > 0) {
386     }
387     // At this point, all data from stream1 has been read, so the write should
388     // return 0
389     byte *buf = new byte[stream1.GetSize()];
390     stream1.Read(buf, stream1.GetSize());
391     ASSERT_EQ(stream2.Write(buf, stream1.GetSize()), stream1.GetSize());
392     stream1.Flush();
393     stream2.Flush();
394     delete[] buf;
395 }
396 
397 /**
398  * @tc.name: FileMetadataStream_Write005
399  * @tc.desc: Test the Write function of FileMetadataStream when reading data from
400  * the source image stream fails
401  * @tc.type: FUNC
402  */
403 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write005, TestSize.Level3)
404 {
405     // This test case requires an MetadataStream object that can simulate a read
406     // failure, so mock technology may be needed in actual testing
407     auto mockSourceFileWrapper = std::make_unique<MockFileWrapper>();
408     auto mockDestFileWrapper = std::make_unique<MockFileWrapper>();
409 
410     // Set the behavior of the write function to always return -1, simulating a
411     // write failure
412     EXPECT_CALL(*mockDestFileWrapper.get(), FWrite(_, _, _, _)).Times(Exactly(0));
413     EXPECT_CALL(*mockSourceFileWrapper.get(), FRead(_, _, _, _)).WillOnce(Return(-1));
414 
415     FileMetadataStream sourceStream(filePathSource, std::move(mockSourceFileWrapper));
416     FileMetadataStream destStream(filePath, std::move(mockDestFileWrapper));
417 
418     // Test the Write function
419     sourceStream.Open();
420     destStream.Open();
421     byte *buf = new byte[sourceStream.GetSize()];
422     EXPECT_EQ(sourceStream.Read(buf, sourceStream.GetSize()), -1);
423     delete[] buf;
424 }
425 
426 /**
427  * @tc.name: FileMetadataStream_Write006
428  * @tc.desc: Test the Write function of FileMetadataStream when the amount of data
429  * written exceeds the remaining space in the file system
430  * @tc.type: FUNC
431  */
432 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write006, TestSize.Level3)
433 {
434     // This test case requires a nearly full file system, so it may be difficult
435     // to implement in actual testing
436     auto mockFileWrapper = std::make_unique<MockFileWrapper>();
437     FileMetadataStream stream(filePath, std::move(mockFileWrapper));
438 }
439 
440 /**
441  * @tc.name: FileMetadataStream_Write001
442  * @tc.desc: Test the Write function of FileMetadataStream, whether it can write
443  * normally and verify the written data
444  * @tc.type: FUNC
445  */
446 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write007, TestSize.Level3)
447 {
448     // Create a FileMetadataStream object
449     FileMetadataStream stream(CreateIfNotExit(filePath));
450 
451     // Open the file
452     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
453 
454     // Create some data to write
455     std::string data = "1Hello, world!";
456 
457     ASSERT_EQ(stream.Seek(0, SeekPos::BEGIN), 0);
458     ASSERT_EQ(stream.Tell(), 0);
459     // Write the data to the file
460     ASSERT_EQ(stream.Write((byte *)data.c_str(), data.size()), data.size());
461     ASSERT_EQ(stream.Tell(), data.size());
462     // Flush the file
463     stream.Flush();
464 
465     // Open the file again
466     int fileDescriptor = open(filePath.c_str(), O_RDONLY);
467     ASSERT_NE(fileDescriptor, -1);
468 
469     // Read the data from the file
470     byte buffer[SIZE_20];
471     read(fileDescriptor, buffer, sizeof(buffer));
472 
473     // Check that the data read is the same as the data written
474     ASSERT_EQ(memcmp(data.c_str(), buffer, data.size()), 0);
475 
476     // Close the file
477     close(fileDescriptor);
478 }
479 
480 HWTEST_F(MetadataStreamTest, FileMetadataStream_Write008, TestSize.Level3)
481 {
482     for (ssize_t size : testSize) {
483         RemoveFile(filePath);
484         FileMetadataStream stream(CreateIfNotExit(filePath));
485         ASSERT_TRUE(stream.Open());
486         byte *buf = new byte[size](); // Dynamically allocate the buffer with the current test size
487         ASSERT_EQ(stream.Write(buf, size), size);
488         ASSERT_EQ(stream.Flush(), true);
489         ASSERT_EQ(stream.GetSize(), size);
490 
491         // Open the file in binary mode and move the file pointer to the end to get the file size
492         std::ifstream file(filePath, std::ios::binary | std::ios::ate);
493         ASSERT_TRUE(file.is_open());
494 
495         // Get the file size
496         std::streamsize fileSize = file.tellg();
497         file.close();
498 
499         // Compare the file size with the current test size
500         ASSERT_EQ(fileSize, size);
501 
502         delete[] buf; // Don't forget to delete the dynamically allocated buffer
503     }
504 }
505 
506 /**
507  * @tc.name: FileMetadataStream_Open001
508  * @tc.desc: Test the Open function of FileMetadataStream when the file path does
509  * not exist
510  * @tc.type: FUNC
511  */
512 HWTEST_F(MetadataStreamTest, FileMetadataStream_Open001, TestSize.Level3)
513 {
514     // Test the case where the file path does not exist
515     std::string nonExistFilePath = "/data/local/tmp/image/non_exist_file.txt";
516     RemoveFile(nonExistFilePath.c_str());
517     FileMetadataStream stream1(CreateIfNotExit(nonExistFilePath));
518     ASSERT_TRUE(stream1.Open());
519     std::string sourceData = "Hello, world!";
520     stream1.Write((byte *)sourceData.c_str(), sourceData.size());
521     // Read data from stream1
522     byte buffer[SIZE_255];
523     stream1.Seek(0, SeekPos::BEGIN);
524     ssize_t bytesRead = stream1.Read(buffer, sourceData.size());
525     ASSERT_EQ(bytesRead, sourceData.size());
526     buffer[bytesRead] = '\0'; // Add string termination character
527     // Check if the read data is the same as the written data
528     ASSERT_STREQ((char *)buffer, sourceData.c_str());
529     ASSERT_TRUE(stream1.Flush());
530     RemoveFile(nonExistFilePath.c_str());
531 }
532 
533 /**
534  * @tc.name: FileMetadataStream_Open002
535  * @tc.desc: Test the Open function of FileMetadataStream when the file path exists
536  * but is not writable
537  * @tc.type: FUNC
538  */
539 HWTEST_F(MetadataStreamTest, FileMetadataStream_Open002, TestSize.Level3)
540 {
541     // Get the username of the current user
542     uid_t uid = getuid();
543     struct passwd *passwordEntry = getpwuid(uid);
544     if (passwordEntry == nullptr) {
545         perror("getpwuid");
546         return;
547     }
548     std::string username(passwordEntry->pw_name);
549 
550     // Test the case where the file path exists but is not writable
551     std::string nonWritableFilePath = "/data/local/tmp/image/non_writable_file.txt";
552     close(open(nonWritableFilePath.c_str(), O_CREAT, S_IRUSR));
553     FileMetadataStream stream2(nonWritableFilePath);
554     if (username == "root") {
555         // If the current user is root, then it can be opened successfully
556         ASSERT_TRUE(stream2.Open());
557     } else {
558         // If the current user is not root, then it cannot be opened
559         ASSERT_FALSE(stream2.Open());
560     }
561     RemoveFile(nonWritableFilePath.c_str());
562 }
563 
564 /**
565  * @tc.name: FileMetadataStream_Open003
566  * @tc.desc: Test the Open function of FileMetadataStream when the file is already
567  * open
568  * @tc.type: FUNC
569  */
570 HWTEST_F(MetadataStreamTest, FileMetadataStream_Open003, TestSize.Level3)
571 {
572     // Test the case where the file is already open
573     FileMetadataStream stream3(CreateIfNotExit(filePath));
574     ASSERT_TRUE(stream3.Open());
575     ASSERT_TRUE(stream3.Open());
576     ASSERT_TRUE(stream3.Flush());
577 }
578 
579 /**
580  * @tc.name: FileMetadataStream_Open004
581  * @tc.desc: Test the Open function of FileMetadataStream when the file does not
582  * exist
583  * @tc.type: FUNC
584  */
585 HWTEST_F(MetadataStreamTest, FileMetadataStream_Open004, TestSize.Level3)
586 {
587     // Test the case where the file does not exist
588     const char *nonExistentFilePath = "/path/to/nonexistent/file";
589     FileMetadataStream stream(nonExistentFilePath);
590     ASSERT_FALSE(stream.Open(OpenMode::Read));
591 }
592 
593 /**
594  * @tc.name: FileMetadataStream_Open005
595  * @tc.desc: Test the Open twice
596  * @tc.type: FUNC
597  */
598 HWTEST_F(MetadataStreamTest, FileMetadataStream_Open005, TestSize.Level3)
599 {
600     FileMetadataStream stream(filePathSource);
601     ASSERT_TRUE(stream.Open(OpenMode::Read));
602     ASSERT_TRUE(stream.Open(OpenMode::Read));
603 }
604 
605 /**
606  * @tc.name: FileMetadataStream_Read001
607  * @tc.desc: Test the Read function of FileMetadataStream, reading 512 bytes
608  * @tc.type: FUNC
609  */
610 HWTEST_F(MetadataStreamTest, FileMetadataStream_Read001, TestSize.Level3)
611 {
612     FileMetadataStream stream(filePathSource);
613     byte buffer[SIZE_1024];
614     stream.Open(OpenMode::ReadWrite);
615     // Simulate reading 512 bytes
616     ssize_t bytesRead = stream.Read(buffer, SIZE_512);
617     EXPECT_EQ(SIZE_512, bytesRead);
618 }
619 
620 /**
621  * @tc.name: FileMetadataStream_Read002
622  * @tc.desc: Test the Read function of FileMetadataStream, trying to read from a
623  * file that has not been opened
624  * @tc.type: FUNC
625  */
626 HWTEST_F(MetadataStreamTest, FileMetadataStream_Read002, TestSize.Level3)
627 {
628     FileMetadataStream stream(filePathSource);
629     byte buffer[SIZE_1024];
630     // Flush the stream to simulate an unopened file
631     ASSERT_FALSE(stream.Flush());
632     ssize_t bytesRead = stream.Read(buffer, SIZE_512);
633     EXPECT_EQ(-1, bytesRead);
634 }
635 
636 // Define a global jmp_buf variable
637 static sigjmp_buf g_jmpBuf;
638 
639 // Define a signal handler function
HandleSigsegv(int sig)640 static void HandleSigsegv(int sig)
641 {
642     siglongjmp(g_jmpBuf, 1);
643 }
644 
645 /**
646  * @tc.name: FileMetadataStream_MMap001
647  * @tc.desc: Test the MMap function of FileMetadataStream, trying to write to a
648  * memory-mapped file that is not writable
649  * @tc.type: FUNC
650  */
651 HWTEST_F(MetadataStreamTest, FileMetadataStream_MMap001, TestSize.Level3)
652 {
653     memoryCheck.check = false; // This test is expected to crash, so memory leak
654                                // check is not needed
655     // Assume there is an appropriate way to create or obtain the resources
656     // needed for the test YourResource test_resource; Test the behavior of the
657     // MMap function when isWriteable is false
658     FileMetadataStream stream(filePathSource);
659     byte *result = stream.GetAddr(false);
660     // Assume that checking whether result is not nullptr, or there is another
661     // appropriate verification method
662     ASSERT_EQ(result, nullptr);
663     stream.Open(OpenMode::ReadWrite);
664     result = stream.GetAddr(false);
665     ASSERT_NE(result, nullptr);
666 
667     // Set the signal handler function
668     signal(SIGSEGV, HandleSigsegv);
669 
670     // Try to write data
671     if (sigsetjmp(g_jmpBuf, 1) == 0) {
672         result[0] = 0;
673         // If no segmentation fault is triggered, then this is an error
674         FAIL() << "Expected a segmentation fault";
675     }
676 }
677 
678 /**
679  * @tc.name: FileMetadataStream_MMap002
680  * @tc.desc: Test the MMap function of FileMetadataStream, trying to write to a
681  * memory-mapped file that is writable
682  * @tc.type: FUNC
683  */
684 HWTEST_F(MetadataStreamTest, FileMetadataStream_MMap002, TestSize.Level3)
685 {
686     // Test the behavior of the MMap function when isWriteable is true
687     FileMetadataStream stream(filePathSource);
688     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
689     byte *result = stream.GetAddr(true);
690     ASSERT_NE(result, nullptr);
691     // Try to write data
692     result[0] = 123;
693 
694     // Read the data and check if it is the same as the written data
695     ASSERT_EQ(result[0], 123);
696 }
697 
698 /**
699  * @tc.name: FileMetadataStream_MMap003
700  * @tc.desc: Test whether the MMap function of FileMetadataStream can actually
701  * modify the content of the file
702  * @tc.type: FUNC
703  */
704 HWTEST_F(MetadataStreamTest, FileMetadataStream_MMap003, TestSize.Level3)
705 {
706     // Test whether MMap can actually modify the content of the file
707     FileMetadataStream stream(filePathSource);
708     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
709     byte *result = stream.GetAddr(true);
710     ASSERT_NE(result, nullptr);
711 
712     // Try to write data
713     result[0] = 123;
714 
715     stream.Seek(0, SeekPos::BEGIN);
716     byte buffer[1];
717     ASSERT_EQ(stream.Read(buffer, 1), 1);
718     ASSERT_EQ(buffer[0], 123);
719 
720     // Flush stream
721     ASSERT_TRUE(stream.Flush());
722     FileMetadataStream checkStream(filePathSource);
723     checkStream.Open(OpenMode::ReadWrite);
724     byte checkBuffer[1];
725     ASSERT_EQ(checkStream.Read(checkBuffer, 1), 1);
726 
727     // Check if the data in the file is the same as the data written
728     ASSERT_EQ(checkBuffer[0], 123);
729 }
730 
731 /**
732  * @tc.name: FileMetadataStream_CopyFrom001
733  * @tc.desc: Test the CopyFrom function of FileMetadataStream, copying data from
734  * one stream to another
735  * @tc.type: FUNC
736  */
737 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom001, TestSize.Level3)
738 {
739     FileMetadataStream src(filePathSource);
740     FileMetadataStream dest(CreateIfNotExit(filePathDest));
741 
742     src.Open();
743     // Write some known data to src
744     std::string data = "Hello, world!";
745     ASSERT_EQ(src.Tell(), 0);
746     ASSERT_GE(src.Write((byte *)data.c_str(), data.size()), 0);
747     ASSERT_TRUE(src.Flush());
748     // Call the Transfer function to transfer data from src to dest
749     dest.Open();
750     ASSERT_TRUE(dest.CopyFrom(src));
751     // Read data from dest and verify that it is the same as the data written to
752     // src
753     byte buffer[SIZE_255] = {0};
754 
755     ASSERT_EQ(dest.Seek(0, SeekPos::BEGIN), 0);
756     ASSERT_EQ(dest.Read(buffer, data.size()), data.size());
757     ASSERT_EQ(std::string(buffer, buffer + data.size()), data);
758 
759     // Verify that src is empty
760     ASSERT_EQ(dest.GetSize(), src.GetSize());
761 }
762 
763 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom002, TestSize.Level3)
764 {
765     BufferMetadataStream src;
766     FileMetadataStream dest(CreateIfNotExit(filePathDest));
767     ASSERT_TRUE(src.Open());
768     ASSERT_EQ(dest.Open(), true);
769     src.Write((byte *)"Hello, world!", 13);
770     char bufSrc[14] = {0};
771     src.Seek(0, SeekPos::BEGIN);
772     src.Read((byte *)bufSrc, 13);
773     ASSERT_STREQ(bufSrc, "Hello, world!");
774     ASSERT_TRUE(dest.CopyFrom(src));
775     dest.Seek(0, SeekPos::BEGIN);
776     char buf[14] = {0};
777     dest.Read((byte *)buf, 13);
778     ASSERT_STREQ(buf, "Hello, world!");
779     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), 13), 0);
780 }
781 
782 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom003, TestSize.Level3)
783 {
784     BufferMetadataStream src;
785     FileMetadataStream dest(CreateIfNotExit(filePathDest));
786     src.Open();
787     dest.Open();
788     char buff[METADATA_STREAM_PAGE_SIZE + 1] = {0};
789     src.Write((byte *)buff, sizeof(buff));
790     ASSERT_TRUE(dest.CopyFrom(src));
791     ASSERT_EQ(src.GetSize(), dest.GetSize());
792     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), 4097), 0);
793 }
794 
795 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom004, TestSize.Level3)
796 {
797     BufferMetadataStream src;
798     FileMetadataStream dest(CreateIfNotExit(filePathDest));
799     src.Open();
800     dest.Open();
801     char buff[METADATA_STREAM_PAGE_SIZE - 1] = {0};
802     src.Write((byte *)buff, sizeof(buff));
803     ASSERT_TRUE(dest.CopyFrom(src));
804     ASSERT_EQ(src.GetSize(), dest.GetSize());
805     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
806 }
807 
808 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom005, TestSize.Level3)
809 {
810     RemoveFile(filePath.c_str());
811     FileMetadataStream src(CreateIfNotExit(filePathDest));
812     BufferMetadataStream dest;
813     src.Open();
814     dest.Open();
815     char buff[METADATA_STREAM_PAGE_SIZE - 1] = {0};
816     ASSERT_EQ(src.Write((byte *)buff, sizeof(buff)), sizeof(buff));
817     ASSERT_TRUE(src.Flush());
818     ASSERT_EQ(src.Tell(), sizeof(buff));
819     ASSERT_EQ(src.GetSize(), sizeof(buff));
820     ASSERT_TRUE(dest.CopyFrom(src));
821     ASSERT_EQ(src.GetSize(), dest.GetSize());
822     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
823 }
824 
825 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom006, TestSize.Level3)
826 {
827     for (ssize_t size : testSize) {
828         RemoveFile(filePathDest.c_str());
829         FileMetadataStream src(CreateIfNotExit(filePathDest));
830         BufferMetadataStream dest;
831         src.Open();
832         dest.Open();
833         byte *buf = new byte[size]();
834         ASSERT_EQ(src.Write(buf, size), size);
835         ASSERT_TRUE(src.Flush());
836         ASSERT_EQ(src.Tell(), size);
837         ASSERT_EQ(src.GetSize(), size);
838         ASSERT_TRUE(dest.CopyFrom(src));
839         ASSERT_EQ(src.GetSize(), dest.GetSize());
840         ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
841         delete[] buf;
842     }
843 }
844 
845 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom007, TestSize.Level3)
846 {
847     for (ssize_t size : testSize) {
848         RemoveFile(filePath.c_str());
849         FileMetadataStream dest(CreateIfNotExit(filePathDest));
850         BufferMetadataStream src;
851         src.Open();
852         dest.Open();
853         byte *buf = new byte[size]();
854         ASSERT_EQ(src.Write(buf, size), size);
855         ASSERT_TRUE(src.Flush());
856         ASSERT_EQ(src.Tell(), size);
857         ASSERT_EQ(src.GetSize(), size);
858         ASSERT_TRUE(dest.CopyFrom(src));
859         ASSERT_EQ(src.GetSize(), dest.GetSize());
860         ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
861         delete[] buf;
862     }
863 }
864 
865 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom008, TestSize.Level3)
866 {
867     for (ssize_t size : testSize) {
868         RemoveFile(filePathDest.c_str());
869         RemoveFile(filePathSource.c_str());
870         FileMetadataStream src(CreateIfNotExit(filePathSource));
871         FileMetadataStream dest(CreateIfNotExit(filePathDest));
872         src.Open();
873         dest.Open();
874         byte *buf = new byte[size]();
875         ASSERT_EQ(src.Write(buf, size), size);
876         ASSERT_TRUE(src.Flush());
877         ASSERT_EQ(src.Tell(), size);
878         ASSERT_EQ(src.GetSize(), size);
879         ASSERT_TRUE(dest.CopyFrom(src));
880         ASSERT_EQ(src.GetSize(), dest.GetSize());
881         ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
882         delete[] buf;
883     }
884 }
885 
886 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom009, TestSize.Level3)
887 {
888     for (ssize_t size : testSize) {
889         RemoveFile(filePath.c_str());
890         BufferMetadataStream src;
891         BufferMetadataStream dest;
892         src.Open();
893         dest.Open();
894         byte *buf = new byte[size]();
895         ASSERT_EQ(src.Write(buf, size), size);
896         ASSERT_TRUE(src.Flush());
897         ASSERT_EQ(src.Tell(), size);
898         ASSERT_EQ(src.GetSize(), size);
899         ASSERT_TRUE(dest.CopyFrom(src));
900         ASSERT_EQ(src.GetSize(), dest.GetSize());
901         ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
902         delete[] buf;
903     }
904 }
905 
906 HWTEST_F(MetadataStreamTest, FileMetadataStream_CopyFrom010, TestSize.Level3)
907 {
908     for (ssize_t size : testSize) {
909         RemoveFile(filePathDest.c_str());
910         std::filesystem::copy(backupFilePathSource, filePathSource, std::filesystem::copy_options::overwrite_existing);
911         FileMetadataStream src(CreateIfNotExit(filePathDest));
912         FileMetadataStream dest(CreateIfNotExit(filePathSource));
913         src.Open();
914         dest.Open();
915         byte *buf = new byte[size]();
916         ASSERT_EQ(src.Write(buf, size), size);
917         ASSERT_TRUE(src.Flush());
918         ASSERT_EQ(src.Tell(), size);
919         ASSERT_EQ(src.GetSize(), size);
920         ASSERT_TRUE(dest.CopyFrom(src));
921         ASSERT_EQ(src.GetSize(), dest.GetSize());
922         ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
923         delete[] buf;
924     }
925 }
926 
927 HWTEST_F(MetadataStreamTest, FileMetadataStream_IsEof001, TestSize.Level3)
928 {
929     FileMetadataStream src(filePathSource);
930     src.Open();
931     byte buffer[1];
932     ASSERT_EQ(src.Seek(0, SeekPos::BEGIN), 0);
933     src.Read(buffer, sizeof(buffer));
934     ASSERT_FALSE(src.IsEof());
935     ASSERT_EQ(src.Seek(0, SeekPos::END), src.GetSize());
936     src.Read(buffer, sizeof(buffer));
937     ASSERT_TRUE(src.IsEof());
938 }
939 
940 /**
941  * @tc.name: FileMetadataStream_ReadByte001
942  * @tc.desc: Test the ReadByte function of FileMetadataStream, comparing its output
943  * with the Read function
944  * @tc.type: FUNC
945  */
946 HWTEST_F(MetadataStreamTest, FileMetadataStream_ReadByte001, TestSize.Level3)
947 {
948     FileMetadataStream stream(filePathSource);
949     stream.Open(OpenMode::ReadWrite);
950 
951     // Read 10 bytes using Read function
952     byte buffer[SIZE_10];
953     stream.Read(buffer, SIZE_10);
954 
955     // Reset the file offset
956     stream.Seek(0, SeekPos::BEGIN);
957 
958     // Read 10 bytes using ReadByte function
959     byte byteBuffer[SIZE_10];
960     for (int i = 0; i < SIZE_10; i++) {
961         byteBuffer[i] = stream.ReadByte();
962     }
963 
964     // Compare the results
965     for (int i = 0; i < SIZE_10; i++) {
966         EXPECT_EQ(buffer[i], byteBuffer[i]);
967     }
968 }
969 
970 /**
971  * @tc.name: FileMetadataStream_ReadByte002
972  * @tc.desc: Test the ReadByte function of FileMetadataStream, trying to read
973  * beyond the end of the file
974  * @tc.type: FUNC
975  */
976 HWTEST_F(MetadataStreamTest, FileMetadataStream_ReadByte002, TestSize.Level3)
977 {
978     FileMetadataStream stream(filePathSource);
979     stream.Open(OpenMode::ReadWrite);
980 
981     // Set the file offset to the end of the file
982     EXPECT_EQ(stream.Seek(0, SeekPos::END), stream.GetSize());
983 
984     // Try to read one more byte
985     int result = stream.ReadByte();
986 
987     // Check if the result is -1
988     EXPECT_EQ(result, -1);
989 }
990 
991 /**
992  * @tc.name: FileMetadataStream_CONSTRUCTOR001
993  * @tc.desc: Test the constructor of FileMetadataStream, checking if it can
994  * correctly initialize a stream from an existing file pointer
995  * @tc.type: FUNC
996  */
997 HWTEST_F(MetadataStreamTest, FileMetadataStream_CONSTRUCTOR001, TestSize.Level3)
998 {
999     FileMetadataStream stream(CreateIfNotExit(filePath));
1000     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
1001     std::string sourceData = "Hello, world!";
1002     ASSERT_EQ(stream.Seek(5, SeekPos::BEGIN), 5);
1003     ASSERT_EQ(stream.Write((byte *)sourceData.c_str(), sourceData.size()), sourceData.size());
1004 
1005     FileMetadataStream cloneStream(fileno(stream.fp_));
1006     ASSERT_TRUE(stream.Flush());
1007     ASSERT_TRUE(cloneStream.Open(OpenMode::ReadWrite));
1008     // Read the data from cloneStream
1009     byte buffer[SIZE_255];
1010     cloneStream.Seek(5, SeekPos::BEGIN);
1011     ssize_t bytesRead = cloneStream.Read(buffer, sourceData.size());
1012     ASSERT_EQ(bytesRead, sourceData.size());
1013     buffer[bytesRead] = '\0'; // Add string termination character
1014 
1015     // Check if the read data is the same as the data in the source file
1016     ASSERT_STREQ((char *)buffer, sourceData.c_str());
1017 
1018     // Write some new data to cloneStream
1019     std::string newData = "New data";
1020     cloneStream.Write((byte *)newData.c_str(), newData.size());
1021 
1022     // Read the data from cloneStream again
1023     cloneStream.Seek(0, SeekPos::BEGIN);
1024     bytesRead = cloneStream.Read(buffer, sizeof(buffer) - 1);
1025     buffer[bytesRead] = '\0'; // Add string termination character
1026 
1027     // Check if the read data contains the new data
1028     ASSERT_STRNE((char *)buffer, newData.c_str());
1029 }
1030 
1031 /**
1032  * @tc.name: FileMetadataStream_CONSTRUCTOR002
1033  * @tc.desc: Test the constructor of FileMetadataStream, checking if it can
1034  * correctly initialize a stream from an existing file descriptor
1035  * @tc.type: FUNC
1036  */
1037 HWTEST_F(MetadataStreamTest, FileMetadataStream_CONSTRUCTOR002, TestSize.Level3)
1038 {
1039     // Create and open a temporary file
1040     std::string tempFile = tmpDirectory + "/testfile";
1041     int fileDescription = open(tempFile.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1042     ASSERT_NE(fileDescription, -1);
1043 
1044     // Use the file descriptor to create a new FileMetadataStream object
1045     FileMetadataStream stream(fileDescription);
1046     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
1047     ASSERT_NE(stream.dupFD_, -1);
1048     // Check the state of the FileMetadataStream object
1049     ASSERT_TRUE(stream.fp_ != nullptr);
1050     ASSERT_EQ(stream.mappedMemory_, nullptr);
1051     ASSERT_EQ(stream.Tell(), 0);
1052 
1053     // Write data
1054     byte writeData[SIZE_10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1055     ssize_t bytesWritten = stream.Write(writeData, sizeof(writeData));
1056     ASSERT_EQ(bytesWritten, sizeof(writeData));
1057 
1058     // Reset the file pointer to the beginning of the file
1059     stream.Seek(0, SeekPos::BEGIN);
1060 
1061     // Read data
1062     byte readData[SIZE_10] = {0};
1063     ssize_t bytesRead = stream.Read(readData, sizeof(readData));
1064     ASSERT_EQ(bytesRead, sizeof(readData));
1065 
1066     // Check if the read data is the same as the written data
1067     for (size_t i = 0; i < sizeof(writeData); ++i) {
1068         ASSERT_EQ(writeData[i], readData[i]);
1069     }
1070 
1071     // Close the file
1072     close(fileDescription);
1073     RemoveFile(tempFile.c_str());
1074 }
1075 
1076 /**
1077  * @tc.name: FileMetadataStream_CONSTRUCTOR003
1078  * @tc.desc: Test the constructor of FileMetadataStream, checking if it can
1079  * correctly initialize a stream from an existing file descriptor and handle
1080  * file operations
1081  * @tc.type: FUNC
1082  */
1083 HWTEST_F(MetadataStreamTest, FileMetadataStream_CONSTRUCTOR003, TestSize.Level3)
1084 {
1085     int fdCount = CountOpenFileDescriptors();
1086     std::string tempFile = tmpDirectory + "/testfile";
1087     int fileDescriptor = open(tempFile.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1088     ASSERT_EQ(fdCount + 1, CountOpenFileDescriptors());
1089     int dupFD = dup(fileDescriptor);
1090     ASSERT_EQ(fdCount + 2, CountOpenFileDescriptors());
1091     ASSERT_NE(fileDescriptor, -1);
1092     FILE *fileStream = fdopen(dupFD, "r+"); // Change "rb" to "wb" for writing in binary mode
1093     ASSERT_EQ(fdCount + 2, CountOpenFileDescriptors());
1094     ;
1095     ASSERT_NE(fileStream, nullptr);
1096     std::string text = "Hello, world!";
1097     ssize_t result = fwrite(text.c_str(), sizeof(char), text.size(),
1098         fileStream); // Use sizeof(char) as the second argument
1099     ASSERT_EQ(ferror(fileStream), 0);
1100     ASSERT_EQ(result, text.size());
1101 
1102     // Reset the file pointer to the beginning of the file
1103     rewind(fileStream);
1104 
1105     ASSERT_EQ(fdCount + 2, CountOpenFileDescriptors());
1106     fileno(fileStream);
1107     ASSERT_EQ(fdCount + 2, CountOpenFileDescriptors());
1108 
1109     // Read and verify the data
1110     char buffer[SIZE_255];
1111     result = fread(buffer, sizeof(char), text.size(), fileStream);
1112     ASSERT_EQ(result, text.size());
1113     buffer[result] = '\0'; // Add string termination character
1114     ASSERT_STREQ(buffer, text.c_str());
1115 
1116     fclose(fileStream);
1117     ASSERT_EQ(fdCount + 1, CountOpenFileDescriptors());
1118     close(fileDescriptor);
1119     ASSERT_EQ(fdCount, CountOpenFileDescriptors());
1120 }
1121 
1122 /**
1123  * @tc.name: FileMetadataStream_CONSTRUCTOR004
1124  * @tc.desc: Test the constructor of FileMetadataStream, checking if it can
1125  * correctly initialize a stream from an existing file descriptor and handle
1126  * file operations using the stream's file pointer
1127  * @tc.type: FUNC
1128  */
1129 HWTEST_F(MetadataStreamTest, FileMetadataStream_CONSTRUCTOR004, TestSize.Level3)
1130 {
1131     std::string tempFile = tmpDirectory + "/testfile";
1132     int fileDescriptor = open(tempFile.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1133     FileMetadataStream stream(fileDescriptor);
1134     int dupFD = stream.dupFD_;
1135     ASSERT_NE(fileDescriptor, -1);
1136     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
1137     FILE *fileStream = stream.fp_; // Change "rb" to "wb" for writing in binary mode
1138     // binary mode
1139     ASSERT_NE(fileStream, nullptr);
1140     std::string text = "Hello, world!";
1141     ssize_t result = fwrite(text.c_str(), sizeof(char), text.size(),
1142         fileStream); // Use sizeof(char) as the second argument
1143     ASSERT_EQ(ferror(fileStream), 0);
1144     ASSERT_EQ(result, text.size());
1145 
1146     // Reset the file pointer to the beginning of the file
1147     rewind(fileStream);
1148 
1149     // Read and verify the data
1150     char buffer[SIZE_255];
1151     result = fread(buffer, sizeof(char), text.size(), fileStream);
1152     ASSERT_EQ(result, text.size());
1153     buffer[result] = '\0'; // Add string termination character
1154     ASSERT_STREQ(buffer, text.c_str());
1155 
1156     fclose(fileStream);
1157     close(dupFD);
1158     close(fileDescriptor);
1159 }
1160 
1161 HWTEST_F(MetadataStreamTest, FileMetadataStream_CONSTRUCTOR005, TestSize.Level3)
1162 {
1163     int fileDescriptor = open(filePathSource.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1164     FileMetadataStream *stream = new FileMetadataStream(fileDescriptor);
1165     ASSERT_FALSE(stream->IsOpen());
1166     ASSERT_TRUE(stream->Open());
1167     delete stream;
1168     stream = new FileMetadataStream(fileDescriptor);
1169     ASSERT_TRUE(stream->Open());
1170     delete stream;
1171 }
1172 
1173 /**
1174  * @tc.name: FileMetadataStream_DESTRUCTOR001
1175  * @tc.desc: Test the destructor of FileMetadataStream, checking if it can
1176  * correctly handle the deletion of a non-existing file
1177  * @tc.type: FUNC
1178  */
1179 HWTEST_F(MetadataStreamTest, FileMetadataStream_DESTRUCTOR001, TestSize.Level3)
1180 {
1181     FileMetadataStream *stream = new FileMetadataStream("/data/fileNotExist");
1182     ASSERT_FALSE(stream->Open());
1183     ASSERT_EQ(stream->Write((byte *)"Hello, the world", 16), -1);
1184     stream->GetAddr();
1185     ASSERT_FALSE(stream->Flush());
1186     delete stream;
1187 }
1188 
1189 /**
1190  * @tc.name: FileMetadataStream_Seek001
1191  * @tc.desc: Test the Seek function of FileMetadataStream, checking if it can
1192  * correctly change the position of the file pointer
1193  * @tc.type: FUNC
1194  */
1195 HWTEST_F(MetadataStreamTest, FileMetadataStream_Seek001, TestSize.Level3)
1196 {
1197     RemoveFile(filePath.c_str());
1198     FileMetadataStream stream(CreateIfNotExit(filePath));
1199     stream.Open(OpenMode::ReadWrite);
1200     std::string sourceData = "Hello, world!";
1201     ASSERT_EQ(stream.Tell(), 0);
1202     stream.Write((byte *)sourceData.c_str(), sourceData.size());
1203     ASSERT_EQ(stream.Tell(), sourceData.size());
1204     stream.Seek(2, SeekPos::BEGIN);
1205     ASSERT_EQ(stream.Tell(), 2);
1206     byte buffer[SIZE_255];
1207     ssize_t bytesRead = stream.Read(buffer, 1);
1208     buffer[bytesRead] = '\0'; // Add string termination character
1209     ASSERT_STREQ((char *)buffer, "l");
1210     ASSERT_EQ(stream.Tell(), 3);
1211     stream.Seek(3, SeekPos::CURRENT);
1212     ASSERT_EQ(stream.Tell(), 6);
1213     bytesRead = stream.Read(buffer, 1);
1214     buffer[bytesRead] = '\0'; // Add string termination character
1215     ASSERT_STREQ((char *)buffer, " ");
1216     stream.Seek(0, SeekPos::END);
1217     ASSERT_EQ(stream.Tell(), sourceData.size());
1218 }
1219 
1220 /**
1221  * @tc.name: BufferMetadataStream_Open001
1222  * @tc.desc: Test the Open function of BufferMetadataStream, checking if it can
1223  * correctly open a stream
1224  * @tc.type: FUNC
1225  */
1226 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Open001, TestSize.Level3)
1227 {
1228     BufferMetadataStream stream;
1229     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
1230 }
1231 
1232 /**
1233  * @tc.name: BufferMetadataStream_Read001
1234  * @tc.desc: Test the Read function of BufferMetadataStream, checking if it can
1235  * correctly read data from the stream
1236  * @tc.type: FUNC
1237  */
1238 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Read001, TestSize.Level3)
1239 {
1240     BufferMetadataStream stream;
1241     ASSERT_TRUE(stream.Open(OpenMode::ReadWrite));
1242 
1243     // Write a string
1244     std::string sourceData = "Hello, world!";
1245     ASSERT_EQ(stream.Tell(), 0);
1246     stream.Write((byte *)sourceData.c_str(), sourceData.size());
1247 
1248     // Read the string
1249     byte buffer[SIZE_255];
1250     stream.Seek(0, SeekPos::BEGIN);
1251     size_t bytesRead = stream.Read(buffer, sourceData.size());
1252     buffer[bytesRead] = '\0'; // Add string termination character
1253 
1254     // Compare the read string with the written string
1255     ASSERT_STREQ((char *)buffer, sourceData.c_str());
1256 }
1257 
1258 /**
1259  * @tc.name: BufferMetadataStream_Write001
1260  * @tc.desc: Test the Write function of BufferMetadataStream, checking if it can
1261  * correctly write data to the stream
1262  * @tc.type: FUNC
1263  */
1264 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write001, TestSize.Level3)
1265 {
1266     BufferMetadataStream stream;
1267     byte data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1268     stream.Open(OpenMode::ReadWrite);
1269     size_t size = sizeof(data) / sizeof(data[0]);
1270     int offset = 0;
1271     stream.Seek(0, SeekPos::BEGIN);
1272     ssize_t bytesWritten = stream.Write(data, size);
1273     ASSERT_EQ(bytesWritten, size);
1274     offset = stream.Tell();
1275     ASSERT_EQ(stream.Tell(), size);
1276     ASSERT_NE(offset, 0);
1277     byte readData[10] = {0};
1278     stream.Seek(0, SeekPos::BEGIN);
1279     ASSERT_EQ(stream.Tell(), 0);
1280     ssize_t bytesRead = stream.Read(readData, size);
1281     ASSERT_EQ(bytesRead, size);
1282 
1283     for (size_t i = 0; i < size; ++i) {
1284         ASSERT_EQ(data[i], readData[i]);
1285     }
1286 }
1287 
1288 /**
1289  * @tc.name: BufferMetadataStream_Write002
1290  * @tc.desc: Test the Write function of BufferMetadataStream, checking if it can
1291  * correctly write a string to the stream
1292  * @tc.type: FUNC
1293  */
1294 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write002, TestSize.Level3)
1295 {
1296     BufferMetadataStream stream;
1297     stream.Open(OpenMode::ReadWrite);
1298     stream.Write((byte *)"Hello, world!", 13);
1299     ASSERT_EQ(stream.capacity_, METADATA_STREAM_PAGE_SIZE);
1300     ASSERT_EQ(stream.Tell(), 13);
1301 }
1302 
1303 /**
1304  * @tc.name: BufferMetadataStream_Write003
1305  * @tc.desc: Test the Write function of BufferMetadataStream, checking if it can
1306  * correctly handle large data
1307  * @tc.type: FUNC
1308  */
1309 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write003, TestSize.Level3)
1310 {
1311     BufferMetadataStream stream;
1312     stream.Open(OpenMode::ReadWrite);
1313     byte data[METADATA_STREAM_PAGE_SIZE + 1] = {0};  // Create a 4097-byte data
1314     stream.Write(data, METADATA_STREAM_PAGE_SIZE + 1); // Write 4097 bytes of data
1315     ASSERT_GE(stream.capacity_,
1316         METADATA_STREAM_PAGE_SIZE + 1);                      // Check if the buffer capacity is at least 4097
1317     ASSERT_EQ(stream.Tell(), METADATA_STREAM_PAGE_SIZE + 1); // Check if the write position is correct
1318 }
1319 
1320 /**
1321  * @tc.name: BufferImageStream_Write004
1322  * @tc.desc: Test the Write function of BufferImageStream, checking if it can
1323  * correctly handle data of the exact buffer capacity
1324  * @tc.type: FUNC
1325  */
1326 HWTEST_F(MetadataStreamTest, BufferImageStream_Write004, TestSize.Level3)
1327 {
1328     BufferMetadataStream stream;
1329     stream.Open();
1330 
1331     byte data[METADATA_STREAM_PAGE_SIZE] = {0};  // Create a 4096-byte data
1332     stream.Write(data, METADATA_STREAM_PAGE_SIZE); // Write 4096 bytes of data
1333     ASSERT_EQ(stream.capacity_,
1334         METADATA_STREAM_PAGE_SIZE); // Check if the buffer capacity is 4096
1335     ASSERT_EQ(stream.Tell(),
1336         METADATA_STREAM_PAGE_SIZE); // Check if the write position is correct
1337 }
1338 
1339 /**
1340  * @tc.name: BufferImageStream_Write005
1341  * @tc.desc: Test the Write function of BufferImageStream, checking if it can
1342  * correctly handle fixed buffer size
1343  * @tc.type: FUNC
1344  */
1345 HWTEST_F(MetadataStreamTest, BufferImageStream_Write005, TestSize.Level3)
1346 {
1347     char text[] = "Hello, world!";
1348     BufferMetadataStream stream((byte *)text, sizeof(text), BufferMetadataStream::Fix);
1349     ASSERT_TRUE(stream.Open());
1350     ASSERT_EQ(stream.Write((byte *)"Hi", 2), 2);
1351     ASSERT_EQ(stream.Tell(), 2);
1352     ASSERT_STREQ(text, "Hillo, world!");
1353     ASSERT_EQ(stream.Write((byte *)"this is a very long text", 24), -1);
1354     ASSERT_STREQ(text, "Hillo, world!");
1355 }
1356 
1357 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write006, TestSize.Level3)
1358 {
1359     for (ssize_t size : testSize) {
1360         BufferMetadataStream stream;
1361         ASSERT_TRUE(stream.Open());
1362         byte *buf = new byte[size](); // Dynamically allocate the buffer with the current test size
1363         ASSERT_EQ(stream.Write(buf, size), size);
1364         ASSERT_EQ(stream.GetSize(), size);
1365 
1366         delete[] buf; // Don't forget to delete the dynamically allocated buffer
1367     }
1368 }
1369 
1370 /**
1371  * @tc.name: BufferImageStream_Write006
1372  * @tc.desc: Test the Write function of BufferImageStream, checking if it can
1373  * correctly handle dynamic buffer size
1374  * @tc.type: FUNC
1375  */
1376 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write007, TestSize.Level3)
1377 {
1378     char text[] = "Hello, world!";
1379     BufferMetadataStream stream((byte *)text, sizeof(text), BufferMetadataStream::Dynamic);
1380     ASSERT_TRUE(stream.Open());
1381     ASSERT_EQ(stream.Write((byte *)"Hi", 2), 2);
1382     ASSERT_EQ(stream.Tell(), 2);
1383     ASSERT_STREQ(text, "Hillo, world!");
1384     stream.Seek(0, SeekPos::BEGIN);
1385     ASSERT_EQ(stream.Write((byte *)"this is a very long text", 25), 25);
1386     ASSERT_STREQ((char *)stream.GetAddr(false), "this is a very long text");
1387 }
1388 
1389 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write008, TestSize.Level3)
1390 {
1391     BufferMetadataStream stream;
1392     byte *buf = new byte[13];
1393     ASSERT_TRUE(stream.Open());
1394     stream.Write((uint8_t *)"Hello, world!", 13);
1395     stream.Seek(4, SeekPos::BEGIN);
1396     stream.Write((uint8_t *)"a", 1);
1397     stream.Write((uint8_t *)"b", 1);
1398     stream.Seek(0, SeekPos::BEGIN);
1399     stream.Read(buf, 13);
1400     ASSERT_STREQ((char *)buf, "Hellab world!");
1401     delete[] buf;
1402 }
1403 
1404 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Write009, TestSize.Level3)
1405 {
1406     BufferMetadataStream stream;
1407     byte *buf = new byte[2000];
1408     byte *buf2 = new byte[500];
1409     ASSERT_TRUE(stream.Open());
1410     stream.Write(buf, 2000);
1411     stream.Write(buf2, 500);
1412     stream.Write(buf2, 500);
1413     ASSERT_EQ(stream.GetSize(), 3000);
1414     ASSERT_EQ(stream.capacity_, 32768);
1415     delete[] buf;
1416     delete[] buf2;
1417 }
1418 
1419 /**
1420  * @tc.name: BufferMetadataStream_Close001
1421  * @tc.desc: Test the Close function of BufferMetadataStream with an empty stream
1422  * @tc.type: FUNC
1423  */
1424 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Close001, TestSize.Level3)
1425 {
1426     BufferMetadataStream stream;
1427 }
1428 
1429 /**
1430  * @tc.name: BufferMetadataStream_Close002
1431  * @tc.desc: Test the Close function of BufferMetadataStream after writing to the
1432  * stream
1433  * @tc.type: FUNC
1434  */
1435 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Close002, TestSize.Level3)
1436 {
1437     BufferMetadataStream stream;
1438     stream.Write((byte *)"Hello, world!", 13);
1439 }
1440 
1441 /**
1442  * @tc.name: BufferImageStream_Close003
1443  * @tc.desc: Test the Close function of BufferImageStream after releasing the
1444  * stream
1445  * @tc.type: FUNC
1446  */
1447 HWTEST_F(MetadataStreamTest, BufferImageStream_Close003, TestSize.Level3)
1448 {
1449     BufferMetadataStream stream;
1450     stream.Write((byte *)"Hello, world!", 13);
1451     delete[] stream.Release();
1452 }
1453 
1454 /**
1455  * @tc.name: BufferMetadataStream_Close004
1456  * @tc.desc: Test the Close function of BufferMetadataStream after closing the
1457  * stream
1458  * @tc.type: FUNC
1459  */
1460 HWTEST_F(MetadataStreamTest, BufferMetadataStream_Close004, TestSize.Level3)
1461 {
1462     BufferMetadataStream stream;
1463     stream.Write((byte *)"Hello, world!", 13);
1464     stream.Close();
1465 }
1466 
1467 /**
1468  * @tc.name: BufferImageStream_Close005
1469  * @tc.desc: Test the Close function of BufferImageStream with a fixed size
1470  * buffer
1471  * @tc.type: FUNC
1472  */
1473 HWTEST_F(MetadataStreamTest, BufferImageStream_Close005, TestSize.Level3)
1474 {
1475     char text[] = "Hello, world!";
1476     BufferMetadataStream stream((byte *)text, sizeof(text), BufferMetadataStream::Fix);
1477 }
1478 
1479 /**
1480  * @tc.name: BufferImageStream_Close006
1481  * @tc.desc: Test the Close function of BufferImageStream with a fixed size
1482  * buffer after releasing the stream
1483  * @tc.type: FUNC
1484  */
1485 HWTEST_F(MetadataStreamTest, BufferImageStream_Close006, TestSize.Level3)
1486 {
1487     char text[] = "Hello, world!";
1488     BufferMetadataStream stream((byte *)text, sizeof(text), BufferMetadataStream::Fix);
1489     stream.Release();
1490 }
1491 
1492 /**
1493  * @tc.name: BufferImageStream_Close007
1494  * @tc.desc: Test the Close function of BufferImageStream with a dynamic size
1495  * buffer after writing and releasing the stream
1496  * @tc.type: FUNC
1497  */
1498 HWTEST_F(MetadataStreamTest, BufferImageStream_Close007, TestSize.Level3)
1499 {
1500     char text[] = "Hello, world!";
1501     BufferMetadataStream stream((byte *)text, sizeof(text), BufferMetadataStream::Dynamic);
1502     stream.Write((byte *)"this is a very very long text", 28);
1503     delete[] stream.Release();
1504 
1505     DataBuf dataBuf(10);
1506     dataBuf.WriteUInt8(0, 123);
1507     EXPECT_EQ(dataBuf.ReadUInt8(0), 123);
1508 }
1509 
1510 HWTEST_F(MetadataStreamTest, BufferMetadataStream_CopyFrom001, TestSize.Level3)
1511 {
1512     FileMetadataStream src(filePathSource);
1513     BufferMetadataStream dest;
1514     src.Open();
1515     dest.Open();
1516     ASSERT_TRUE(dest.CopyFrom(src));
1517     ASSERT_EQ(src.GetSize(), dest.GetSize());
1518     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
1519 }
1520 
1521 HWTEST_F(MetadataStreamTest, BufferMetadataStream_CopyFrom002, TestSize.Level3)
1522 {
1523     BufferMetadataStream src;
1524     BufferMetadataStream dest;
1525     src.Open();
1526     dest.Open();
1527     src.Write((byte *)"Hello, world!", 13);
1528     ASSERT_TRUE(dest.CopyFrom(src));
1529     ASSERT_EQ(src.GetSize(), dest.GetSize());
1530     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
1531 }
1532 
1533 HWTEST_F(MetadataStreamTest, BufferMetadataStream_CopyFrom003, TestSize.Level3)
1534 {
1535     BufferMetadataStream src;
1536     BufferMetadataStream dest;
1537     src.Open();
1538     dest.Open();
1539     char buff[METADATA_STREAM_PAGE_SIZE + 1] = {0};
1540     src.Write((byte *)buff, METADATA_STREAM_PAGE_SIZE + 1);
1541     ASSERT_TRUE(dest.CopyFrom(src));
1542     ASSERT_EQ(src.GetSize(), dest.GetSize());
1543     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
1544 }
1545 
1546 HWTEST_F(MetadataStreamTest, BufferMetadataStream_CopyFrom004, TestSize.Level3)
1547 {
1548     BufferMetadataStream src;
1549     BufferMetadataStream dest;
1550     src.Open();
1551     dest.Open();
1552     char buff[METADATA_STREAM_PAGE_SIZE - 1] = {0};
1553     src.Write((byte *)buff, METADATA_STREAM_PAGE_SIZE - 1);
1554     ASSERT_TRUE(dest.CopyFrom(src));
1555     ASSERT_EQ(src.GetSize(), dest.GetSize());
1556     ASSERT_EQ(memcmp(src.GetAddr(), dest.GetAddr(), src.GetSize()), 0);
1557 }
1558 
1559 HWTEST_F(MetadataStreamTest, BufferMetadataStream_CopyFrom005, TestSize.Level3)
1560 {
1561     BufferMetadataStream temp;
1562     temp.Open();
1563     temp.Write((uint8_t*)"Hello, world", 13);
1564     BufferMetadataStream src(temp.GetAddr(), temp.GetSize(), BufferMetadataStream::Dynamic);
1565     FileMetadataStream dest(filePathSource);
1566     src.Open();
1567     dest.Open();
1568     src.CopyFrom(dest);
1569 }
1570 
1571 } // namespace Media
1572 } // namespace OHOS