• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "mapped_file.h"
16 
17 #include <fstream>
18 #include <gtest/gtest.h>
19 #include <iostream>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include "common_mapped_file_errors.h"
23 #include "directory_ex.h"
24 #include "errors.h"
25 #include "file_ex.h"
26 
27 using namespace testing::ext;
28 using namespace OHOS::Utils;
29 
30 namespace OHOS {
31 namespace {
32 
33 class UtilsMappedFileTest : public testing::Test {
34 public:
35     static constexpr char BASE_PATH[] = "/data/test/commonlibrary_c_utils/";
36     static constexpr char SUITE_PATH[] = "mapped_file/";
37     static void SetUpTestCase(void);
38     static void TearDownTestCase(void);
39 };
40 
SetUpTestCase()41 void UtilsMappedFileTest::SetUpTestCase()
42 {
43     std::string dir = std::string(BASE_PATH).append(SUITE_PATH);
44     if (ForceCreateDirectory(dir)) {
45         std::cout << "Create test dir:" << dir.c_str() << std::endl;
46     } else {
47         std::cout << "Create test dir Failed:" << dir.c_str() << std::endl;
48     }
49 
50     std::cout << "Page size:" << MappedFile::PageSize() << std::endl;
51 }
52 
TearDownTestCase()53 void UtilsMappedFileTest::TearDownTestCase()
54 {
55     if (ForceRemoveDirectory(std::string(BASE_PATH))) {
56         std::cout << "Remove test dir:" << BASE_PATH << std::endl;
57     }
58 }
59 
PrintStatus(MappedFile & mf)60 void PrintStatus(MappedFile& mf)
61 {
62     std::cout << "Mapped Region Start:" << reinterpret_cast<void*>(mf.RegionStart()) << std::endl <<
63                  "Mapped Region End:" << reinterpret_cast<void*>(mf.RegionEnd()) << std::endl <<
64                  "View start:" << reinterpret_cast<void*>(mf.Begin()) << std::endl <<
65                  "View End:" << reinterpret_cast<void*>(mf.End()) << std::endl <<
66                  "View Size:" << mf.Size() << std::endl <<
67                  "File Offset Start:" << mf.StartOffset() << std::endl <<
68                  "File Offset Start:" << mf.EndOffset() << std::endl;
69 }
70 
CreateTestFile(const std::string & path,const std::string & content)71 bool CreateTestFile(const std::string& path, const std::string& content)
72 {
73     std::ofstream out(path, std::ios_base::out | std::ios_base::trunc);
74     if (out.is_open()) {
75         out << content.c_str();
76         return true;
77     }
78 
79     std::cout << "open file failed!" << path.c_str() << std::endl;
80     return false;
81 }
82 
RemoveTestFile(const std::string & path)83 int RemoveTestFile(const std::string& path)
84 {
85     return unlink(path.c_str());
86 }
87 
SaveStringToFile(const std::string & filePath,const std::string & content,off_t offset,bool truncated)88 bool SaveStringToFile(const std::string& filePath, const std::string& content, off_t offset, bool truncated /*= true*/)
89 {
90     if (content.empty()) {
91         return true;
92     }
93 
94     std::ofstream file;
95     if (truncated) {
96         file.open(filePath.c_str(), std::ios::out | std::ios::trunc);
97     } else {
98         file.open(filePath.c_str(), std::ios::out | std::ios::app);
99     }
100 
101     if (!file.is_open()) {
102         return false;
103     }
104 
105     file.seekp(offset, std::ios::beg);
106 
107     file.write(content.c_str(), content.length());
108     if (file.fail()) {
109         return false;
110     }
111     return true;
112 }
113 
ReCreateFile(std::string & filename,const std::string & content)114 void ReCreateFile(std::string& filename, const std::string& content)
115 {
116     filename.insert(0, UtilsMappedFileTest::SUITE_PATH).insert(0, UtilsMappedFileTest::BASE_PATH);
117     RemoveTestFile(filename);
118 
119     ASSERT_TRUE(CreateTestFile(filename, content));
120 }
121 
TestFileReadAndWrite(const MappedFile & mf,const std::string & content)122 void TestFileReadAndWrite(const MappedFile& mf, const std::string& content)
123 {
124     // read from mapped file
125     std::string readout;
126     for (char* cur = mf.Begin(); cur <= mf.End(); cur++) {
127         readout.push_back(*cur);
128     }
129     EXPECT_EQ(readout, content);
130 
131     // write to mapped file
132     std::string toWrite("Complete.");
133     char* newCur = mf.Begin();
134     for (std::string::size_type i = 0; i < toWrite.length(); i++) {
135         (*newCur) = toWrite[i];
136         newCur++;
137     }
138 }
139 
TestFileStat(MappedFile & mf,const std::string & filename,const std::string & content,struct stat * stb)140 void TestFileStat(MappedFile& mf,
141                   const std::string& filename,
142                   const std::string& content,
143                   struct stat* stb)
144 {
145     ASSERT_NE(stb, nullptr);
146     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
147 
148     // check status after mapping
149     ASSERT_TRUE(mf.IsMapped());
150     ASSERT_TRUE(mf.IsNormed());
151 
152     // check size
153     stat(filename.c_str(), stb);
154     ASSERT_TRUE(stb->st_size == mf.Size() || mf.PageSize() == mf.Size());
155 
156     // read from Mapped File
157     std::string readout;
158     for (char* cur = mf.Begin(); cur <= mf.End(); cur++) {
159         readout.push_back(*cur);
160     }
161     EXPECT_EQ(readout, content);
162 }
163 
TestFileContentEqual(const MappedFile & mf,const std::string & filename,std::string & filename1,std::string & content1,struct stat * stb)164 void TestFileContentEqual(const MappedFile& mf,
165                           const std::string& filename,
166                           std::string& filename1,
167                           std::string& content1,
168                           struct stat* stb)
169 {
170     // check pointer not null
171     ASSERT_NE(stb, nullptr);
172     // check status after remapping
173     EXPECT_TRUE(mf.IsMapped());
174     EXPECT_TRUE(mf.IsNormed());
175 
176     // check size
177     stat(filename1.c_str(), stb);
178     EXPECT_TRUE(stb->st_size == mf.Size());
179 
180     // read from Mapped File
181     std::string readout1;
182     for (char* cur1 = mf.Begin(); cur1 <= mf.End(); cur1++) {
183         readout1.push_back(*cur1);
184     }
185     EXPECT_EQ(readout1, content1);
186 
187     RemoveTestFile(filename);
188     RemoveTestFile(filename1);
189 }
190 
TestFileRegion(MappedFile & mf,const off_t orig)191 void TestFileRegion(MappedFile& mf, const off_t orig)
192 {
193     off_t endOff;
194     // keep turnNext within a page
195     ASSERT_NE(orig, 0);
196     if (orig != 0) {
197         for (unsigned int cnt = 2; cnt < (MappedFile::PageSize() / orig); cnt++) { // 2: start from 2 to take the first
198                                                                                 // TunrNext() calling in consideration.
199             endOff = mf.EndOffset();
200             EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
201             EXPECT_EQ(mf.StartOffset(), endOff + 1);
202             EXPECT_EQ(mf.Size(), orig);
203         }
204     }
205     std::cout << "==Last TurnNext() with The Same Size==" << std::endl;
206     PrintStatus(mf);
207 
208     // this turn will reach the bottom of a page
209     endOff = mf.EndOffset();
210     char* rEnd = mf.RegionEnd();
211     char* end = mf.End();
212     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
213     EXPECT_EQ(mf.StartOffset(), endOff + 1);
214     EXPECT_EQ(mf.Size(), static_cast<off_t>(rEnd - end));
215     std::cout << "==Reached Bottom of A Page==" << std::endl;
216     PrintStatus(mf);
217 }
218 
TestFileWrite(const MappedFile & mfNew,const std::string & filename,const std::string & content)219 void TestFileWrite(const MappedFile& mfNew, const std::string& filename, const std::string& content)
220 {
221     // read from mapped file
222     std::string readout;
223     for (char* cur = mfNew.Begin(); cur <= mfNew.End(); cur++) {
224         readout.push_back(*cur);
225     }
226     EXPECT_EQ(readout, content);
227 
228     // write to mapped file
229     std::string toWrite("Complete.");
230     char* newCur = mfNew.Begin();
231     for (std::string::size_type i = 0; i < toWrite.length(); i++) {
232         (*newCur) = toWrite[i];
233         newCur++;
234     }
235     std::string res;
236     LoadStringFromFile(filename, res);
237     EXPECT_EQ(res, "Complete.move use.");
238 
239     RemoveTestFile(filename);
240 }
241 
TestTwoFileWrite(const MappedFile & mf,const std::string & filename,const std::string & filename1,const std::string & content1)242 void TestTwoFileWrite(const MappedFile& mf,
243                       const std::string& filename,
244                       const std::string& filename1,
245                       const std::string& content1)
246 {
247     std::string readout;
248     for (char* cur = mf.Begin(); cur <= mf.End(); cur++) {
249         readout.push_back(*cur);
250     }
251     EXPECT_EQ(readout, content1);
252 
253     //write to mapped file
254     std::string toWrite("Complete.");
255     char* newCur = mf.Begin();
256     for (std::string::size_type i = 0; i < toWrite.length(); i++) {
257         (*newCur) = toWrite[i];
258         newCur++;
259     }
260     std::string res;
261     LoadStringFromFile(filename1, res);
262     EXPECT_EQ(res, "Complete.move use.");
263 
264     RemoveTestFile(filename);
265     RemoveTestFile(filename1);
266 }
267 
268 /*
269  * @tc.name: testDefaultMapping001
270  * @tc.desc: Test file mapping with default params.
271  */
272 HWTEST_F(UtilsMappedFileTest, testDefaultMapping001, TestSize.Level0)
273 {
274     // 1. Create a new file
275     std::string filename = "test_read_write_1.txt";
276     std::string content = "Test for normal use.";
277     ReCreateFile(filename, content);
278 
279     // 2. map file
280     MappedFile mf(filename);
281     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
282 
283     // check status
284     ASSERT_TRUE(mf.IsMapped());
285     ASSERT_TRUE(mf.IsNormed());
286 
287     // check size
288     struct stat stb = {0};
289     stat(filename.c_str(), &stb);
290     ASSERT_TRUE(stb.st_size == mf.Size() || mf.PageSize() == mf.Size());
291 
292     // check map-mode
293     ASSERT_EQ(MapMode::DEFAULT, mf.GetMode());
294 
295     // check offset
296     ASSERT_EQ(mf.StartOffset(), 0u);
297 
298     // 3. read from mapped file
299     // write to mapped file
300     TestFileReadAndWrite(mf, content);
301 
302     std::string res;
303     LoadStringFromFile(filename, res);
304     EXPECT_EQ(res, "Complete.normal use.");
305 
306     // 5. test default mapping and write to addr which excess End() but not across this memory page.
307     EXPECT_LE(mf.Size(), mf.PageSize());
308     char* trueEnd = mf.RegionEnd();
309     ASSERT_GT(trueEnd, mf.Begin());
310     // write to mapped file
311     (*trueEnd) = 'E'; // It is allowed to write to this address which excess the End()
312 
313     EXPECT_EQ((*trueEnd), 'E'); // and of course it is allowed to read from that same address.
314 
315     std::string res1;
316     LoadStringFromFile(filename, res1);
317     EXPECT_EQ(res1, "Complete.normal use."); // While no changes will be sync in the original file.
318 
319     RemoveTestFile(filename);
320 }
321 
322 /*
323  * @tc.name: testNewSharedMappingDefaultSize001
324  * @tc.desc: Test mapping which will create a new file with default size.
325  */
326 HWTEST_F(UtilsMappedFileTest, testNewSharedMappingDefaultSize001, TestSize.Level0)
327 {
328     // 1. Create a new file
329     std::string filename = "test_read_write_2.txt";
330     filename.insert(0, SUITE_PATH).insert(0, BASE_PATH);
331     RemoveTestFile(filename);
332 
333     // 2. map file
334     MappedFile mf(filename, MapMode::DEFAULT | MapMode::CREATE_IF_ABSENT);
335     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
336 
337     // check if file is created
338     ASSERT_TRUE(FileExists(filename));
339 
340     // check status
341     ASSERT_TRUE(mf.IsMapped());
342     ASSERT_TRUE(mf.IsNormed());
343 
344     // check map-mode
345     ASSERT_EQ(MapMode::DEFAULT | MapMode::CREATE_IF_ABSENT, mf.GetMode());
346 
347     // check default size
348     struct stat stb = {0};
349     if (stat(filename.c_str(), &stb) == 0) {
350         EXPECT_EQ(stb.st_size, mf.PageSize()); // contents will be zero-filled.
351     }
352     ASSERT_EQ(mf.Size(), mf.PageSize());
353 
354     // 3. write to mapped file
355     std::string toWrite("Write to newly created file.");
356     char* newCur = mf.Begin();
357     for (std::string::size_type i = 0; i < toWrite.length(); i++) {
358         (*newCur) = toWrite[i];
359         newCur++;
360     }
361     std::string res;
362     LoadStringFromFile(filename, res);
363     EXPECT_STREQ(res.c_str(), toWrite.c_str()); // note that `res` contains filled '0',
364                                                 // use c_str() to compare conveniently.
365 
366     // 4. read from mapped file
367     std::string toRead("Waiting to be read.");
368     SaveStringToFile(filename, toRead, 0, true);
369     std::string readout;
370     for (char* cur = mf.Begin(); *cur != '\0'; cur++) {
371         readout.push_back(*cur);
372     }
373     EXPECT_EQ(readout, toRead);
374 
375     RemoveTestFile(filename);
376 }
377 
378 /*
379  * @tc.name: testNewSharedMapping001
380  * @tc.desc: Test mapping which will create a new file with specified params.
381  */
382 HWTEST_F(UtilsMappedFileTest, testNewSharedMapping001, TestSize.Level0)
383 {
384     std::string filename = "test_read_write_3.txt";
385     filename.insert(0, SUITE_PATH).insert(0, BASE_PATH);
386     RemoveTestFile(filename);
387 
388     // set params
389     // new mapping region will not guaranteed to be located at `hint`
390     char* hint = reinterpret_cast<char*>(0x80000); // 0x80000: hint(expected address).
391     off_t size = 1024;
392     off_t offset = 4 * 1024;
393 
394     // 1. map a non-existed file
395     MappedFile mf(filename, MapMode::DEFAULT | MapMode::CREATE_IF_ABSENT, offset, size, hint);
396     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
397 
398     // check if file is created
399     ASSERT_TRUE(FileExists(filename));
400 
401     // check status
402     ASSERT_TRUE(mf.IsMapped());
403     ASSERT_TRUE(mf.IsNormed());
404 
405     // check specified size
406     struct stat stb = {0};
407     if (stat(filename.c_str(), &stb) == 0) {
408         // Exact file size should be offset + mapped size, contents will be zero-filled.
409         EXPECT_EQ(stb.st_size, offset + size);
410     }
411     ASSERT_EQ(mf.Size(), size);
412 
413     // check specified offset
414     ASSERT_EQ(mf.StartOffset(), offset);
415 
416     // check hint
417     ASSERT_TRUE(mf.GetHint() == nullptr || mf.GetHint() == hint);
418     std::cout << "Exact addr:" <<
419               reinterpret_cast<void*>(mf.Begin()) << std::endl <<
420               "Input hint:" << reinterpret_cast<void*>(hint) << std::endl;
421 
422     // 2. write to mapped file
423     std::string toWrite("Write to newly created file.");
424     char* newCur = mf.Begin();
425     for (std::string::size_type i = 0; i < toWrite.length(); i++) {
426         (*newCur) = toWrite[i];
427         newCur++;
428     }
429     std::cout << "Write finished" << std::endl;
430     EXPECT_TRUE(StringExistsInFile(filename, toWrite));
431 
432     // 3. read from mapped file
433     std::string toRead("Waiting to be read.");
434     SaveStringToFile(filename, toRead, offset, true);
435     std::string readout;
436     for (char* cur = mf.Begin(); cur <= mf.End() && *cur != '\0'; cur++) {
437         readout.push_back(*cur);
438     }
439     std::cout << "Read finished" << std::endl;
440     EXPECT_EQ(readout, toRead);
441 
442     RemoveTestFile(filename);
443 }
444 
445 /*
446  * @tc.name: testPrivateMapping001
447  * @tc.desc: Test mapping which will create a new file with specified params.
448  */
449 HWTEST_F(UtilsMappedFileTest, testPrivateMapping001, TestSize.Level0)
450 {
451     // 1. create a new file
452     std::string filename = "test_read_write_4.txt";
453     std::string content = "Test for private use.";
454     ReCreateFile(filename, content);
455 
456     // 2. map file
457     MappedFile mf(filename, MapMode::DEFAULT | MapMode::PRIVATE);
458     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
459 
460     // 3. check status
461     ASSERT_TRUE(mf.IsMapped());
462     ASSERT_TRUE(mf.IsNormed());
463 
464     // 4. read from mapped file
465     // write to mapped file
466     TestFileReadAndWrite(mf, content);
467 
468     std::string res;
469     LoadStringFromFile(filename, res);
470     EXPECT_EQ(res, content); // changes to private mapped file will not write back to the original file
471 
472     RemoveTestFile(filename);
473 }
474 
475 /*
476  * @tc.name: testSharedReadOnlyMapping001
477  * @tc.desc: Test mapping which will create a new file with specified params.
478  */
479 HWTEST_F(UtilsMappedFileTest, testSharedReadOnlyMapping001, TestSize.Level0)
480 {
481     // 1. create a new file
482     std::string filename = "test_read_write_5.txt";
483     std::string content = "Test for readonly use.";
484 
485     ReCreateFile(filename, content);
486 
487     // 2. map file
488     MappedFile mf(filename, MapMode::DEFAULT | MapMode::READ_ONLY);
489     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
490 
491     // 3. check status
492     ASSERT_TRUE(mf.IsMapped());
493     ASSERT_TRUE(mf.IsNormed());
494 
495     // 4. read from mapped file
496     std::string readout;
497     for (char* cur = mf.Begin(); cur <= mf.End(); cur++) {
498         readout.push_back(*cur);
499     }
500     EXPECT_EQ(readout, content);
501     // !Note: write operation is not permitted, which will raise a signal 11.
502 
503     RemoveTestFile(filename);
504 }
505 
506 /*
507  * @tc.name: testReMap001
508  * @tc.desc: Test remapping using `Unmap()` and `Map()`
509  */
510 HWTEST_F(UtilsMappedFileTest, testReMap001, TestSize.Level0)
511 {
512     // 1. create a new file
513     std::string filename = "test_remap_1.txt";
514     std::string content = "Test for remapping use.";
515     ReCreateFile(filename, content);
516 
517     // 2. map file
518     MappedFile mf(filename);
519     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
520 
521     // 3. check status after mapping
522     ASSERT_TRUE(mf.IsMapped());
523     ASSERT_TRUE(mf.IsNormed());
524 
525     ASSERT_EQ(mf.Unmap(), MAPPED_FILE_ERR_OK);
526 
527     // 4. check status after unmapping
528     EXPECT_FALSE(mf.IsMapped());
529     EXPECT_TRUE(mf.IsNormed());
530     EXPECT_EQ(mf.Begin(), nullptr);
531 
532     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
533     // 5. check status after remapping
534     EXPECT_TRUE(mf.IsMapped());
535     EXPECT_TRUE(mf.IsNormed());
536 
537     // 6. check default size
538     struct stat stb = {0};
539     stat(filename.c_str(), &stb);
540     EXPECT_TRUE(stb.st_size == mf.Size() || mf.PageSize() == mf.Size());
541 
542     RemoveTestFile(filename);
543 }
544 
545 /*
546  * @tc.name: testReMap002
547  * @tc.desc: Test remapping via changing params.
548  */
549 HWTEST_F(UtilsMappedFileTest, testReMap002, TestSize.Level0)
550 {
551     // 1. create a new file
552     std::string filename = "test_remap.txt";
553     std::string content = "Test for default use.";
554     ReCreateFile(filename, content);
555 
556     std::string filename1 = "test_remap_1.txt";
557     std::string content1 = "Test for remapping use.";
558     ReCreateFile(filename1, content1);
559 
560     MappedFile mf(filename);
561 
562     // Change params when unmapped.
563     ASSERT_TRUE(mf.ChangeSize(mf.Size() + 1024));
564     ASSERT_TRUE(mf.ChangeSize(MappedFile::DEFAULT_LENGTH));
565     ASSERT_TRUE(mf.ChangeOffset(mf.PageSize()));
566     ASSERT_TRUE(mf.ChangeOffset(0));
567     ASSERT_TRUE(mf.ChangePath(filename1));
568     ASSERT_TRUE(mf.ChangePath(filename));
569     ASSERT_TRUE(mf.ChangeHint(reinterpret_cast<char*>(0x89000))); // 0x89000: random address.
570     ASSERT_TRUE(mf.ChangeMode(MapMode::READ_ONLY));
571 
572     struct stat stb = {0};
573 
574     // 3. check status after mapping
575     // check size
576     // read from Mapped File
577     TestFileStat(mf, filename, content, &stb);
578 
579     // 4. change params
580     ASSERT_TRUE(mf.ChangePath(filename1));
581     ASSERT_TRUE(mf.ChangeSize(MappedFile::DEFAULT_LENGTH));
582     ASSERT_TRUE(mf.ChangeHint(reinterpret_cast<char*>(0x80000))); // 0x80000: random address.
583     ASSERT_TRUE(mf.ChangeMode(MapMode::DEFAULT | MapMode::CREATE_IF_ABSENT));
584 
585     // 5. check status after changing
586     EXPECT_FALSE(mf.IsMapped());
587     EXPECT_FALSE(mf.IsNormed());
588 
589     // 6. remap file
590     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
591 
592     TestFileContentEqual(mf, filename, filename1, content1, &stb);
593 }
594 
595 /*
596  * @tc.name: testReMap003
597  * @tc.desc: Test remapping via Resize().
598  */
599 HWTEST_F(UtilsMappedFileTest, testReMap003, TestSize.Level0)
600 {
601     // 1. create a new file
602     std::string filename = "test_remap.txt";
603     std::string content = "Test for default use.";
604 
605     std::string filename1 = "test_remap_1.txt";
606     std::string content1 = "Test for remapping use.";
607     ReCreateFile(filename, content);
608     ReCreateFile(filename1, content1);
609 
610     // 2. map file
611     MappedFile mf(filename);
612 
613     struct stat stb = {0};
614 
615     // 3. check status after mapping
616     // check size
617     // read from Mapped File
618     TestFileStat(mf, filename, content, &stb);
619 
620     // 4. change params
621     mf.ChangePath(filename1);
622     mf.ChangeSize(MappedFile::DEFAULT_LENGTH);
623 
624     // 5. check status after changing
625     EXPECT_FALSE(mf.IsMapped());
626     EXPECT_FALSE(mf.IsNormed());
627 
628     // 6. remap file
629     ASSERT_EQ(mf.Resize(), MAPPED_FILE_ERR_OK);
630     // 7. check status after remapping
631     TestFileContentEqual(mf, filename, filename1, content1, &stb);
632 }
633 
634 /*
635  * @tc.name: testReMap004
636  * @tc.desc: Test remapping only to extend mapped region via Resize(off_t, bool).
637  */
638 HWTEST_F(UtilsMappedFileTest, testReMap004, TestSize.Level0)
639 {
640     // 1. create a new file
641     std::string content = "Test for remapping use.";
642     std::string filename = "test_remap.txt";
643     ReCreateFile(filename, content);
644 
645     // 2. map file
646     MappedFile mf(filename);
647     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
648 
649     // 3. check status after mapping
650     ASSERT_TRUE(mf.IsMapped());
651     ASSERT_TRUE(mf.IsNormed());
652 
653     // 4. check size
654     struct stat stb = {0};
655     stat(filename.c_str(), &stb);
656     ASSERT_TRUE(stb.st_size == mf.Size() || mf.PageSize() == mf.Size());
657 
658     // 5. read from Mapped File
659     std::string readout;
660     char* cur = mf.Begin();
661     for (; cur <= mf.End(); cur++) {
662         readout.push_back(*cur);
663     }
664     EXPECT_EQ(readout, content);
665 
666     // 6. Remap to extend region
667     ASSERT_EQ(mf.Resize(mf.Size() + 10), MAPPED_FILE_ERR_OK);
668     // 7. check status after remapping
669     EXPECT_TRUE(mf.IsMapped());
670     EXPECT_TRUE(mf.IsNormed());
671 
672     // 8. check size after remapping
673     stat(filename.c_str(), &stb);
674     EXPECT_TRUE(stb.st_size < mf.Size());
675 
676     // 9. write to the extended region
677     *(cur) = 'E';
678     EXPECT_EQ((*cur), 'E');
679 
680     std::string res;
681     LoadStringFromFile(filename, res);
682     EXPECT_EQ(res, content); // No changes will be sync in the original file, since mapped region
683                              // is larger than substantial size of the file
684 
685     RemoveTestFile(filename);
686 }
687 
688 /*
689  * @tc.name: testReMap005
690  * @tc.desc: Test remapping to extend mapped region as well as substantial file size via Resize(off_t, bool).
691  */
692 HWTEST_F(UtilsMappedFileTest, testReMap005, TestSize.Level0)
693 {
694     // 1. create a new file
695     std::string filename = "test_remap.txt";
696     std::string content = "Test for remapping use.";
697     ReCreateFile(filename, content);
698 
699     // 2. map file
700     MappedFile mf(filename);
701     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
702 
703     // 3. check status after mapping
704     ASSERT_TRUE(mf.IsNormed());
705     ASSERT_TRUE(mf.IsMapped());
706 
707     // 4. check size
708     struct stat stb = {0};
709     stat(filename.c_str(), &stb);
710     ASSERT_TRUE(mf.PageSize() == mf.Size() || stb.st_size == mf.Size());
711 
712     // 5. read from Mapped File
713     std::string readout;
714     char* cur = mf.Begin();
715     for (; cur <= mf.End(); cur++) {
716         readout.push_back(*cur);
717     }
718     EXPECT_EQ(content, readout);
719 
720     // 6. remap to extend region
721     ASSERT_EQ(mf.Resize(mf.Size() + 10, true), MAPPED_FILE_ERR_OK);
722     // check status after remapping
723     EXPECT_TRUE(mf.IsMapped());
724     EXPECT_TRUE(mf.IsNormed());
725 
726     // 7. check size after remapping
727     stat(filename.c_str(), &stb);
728     EXPECT_TRUE(stb.st_size == mf.Size()); // File size will sync to that of the mapped region.
729 
730     // 8. write to the extended region
731     *(cur) = 'E';
732     EXPECT_EQ((*cur), 'E');
733 
734     std::string res;
735     LoadStringFromFile(filename, res);
736     EXPECT_STREQ(res.c_str(), content.append("E").c_str()); // Changes will be sync in the original file.
737 }
738 
739 /*
740  * @tc.name: testReMap006
741  * @tc.desc: Test remapping to via Resize(off_t, bool).
742  */
743 HWTEST_F(UtilsMappedFileTest, testReMap006, TestSize.Level0)
744 {
745     // 1. create a new file
746     std::string filename = "test_remap.txt";
747     std::string content = "Test for remapping use.";
748 
749     ReCreateFile(filename, content);
750 
751     // 2. map file
752     off_t size = 20;
753     MappedFile mf(filename, MapMode::DEFAULT, 0, size);
754     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
755 
756     // 3. check status after mapping
757     ASSERT_TRUE(mf.IsMapped());
758     ASSERT_TRUE(mf.IsNormed());
759 
760     // 4. check size
761     ASSERT_TRUE(size == mf.Size());
762 
763     // 5. remap to extend region
764     ASSERT_EQ(mf.Resize(MappedFile::DEFAULT_LENGTH, true), MAPPED_FILE_ERR_OK);
765     off_t lessSize = mf.Size() - 8;
766     ASSERT_EQ(mf.Resize(lessSize, true), MAPPED_FILE_ERR_OK);
767     // 6. check status after remapping
768     EXPECT_TRUE(mf.IsMapped());
769     EXPECT_TRUE(mf.IsNormed());
770 
771     // 7. check size after remapping
772     struct stat stb = {0};
773     stat(filename.c_str(), &stb);
774     EXPECT_EQ(lessSize, mf.Size());
775 }
776 
777 /*
778  * @tc.name: testTurnNext001
779  * @tc.desc: Test TurnNext() when `IsMapped()`.
780  */
781 HWTEST_F(UtilsMappedFileTest, testTurnNext001, TestSize.Level0)
782 {
783     // 1. create a new file
784     std::string filename = "test_remap.txt";
785     std::string content = "Test for remapping use.";
786 
787     ReCreateFile(filename, content);
788 
789     struct stat stb = {0};
790     ASSERT_EQ(stat(filename.c_str(), &stb), 0);
791     off_t orig = stb.st_size; // 23 bytes
792 
793     // 2. extend its size
794     int fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
795     ASSERT_NE(fd, -1);
796     ASSERT_EQ(ftruncate(fd, MappedFile::PageSize() + MappedFile::PageSize() / 100LL), 0); // 100: ratio to a page.
797 
798     // 3. map file
799     MappedFile mf(filename, MapMode::DEFAULT, 0, orig);
800     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
801 
802     // 4. check status after mapping
803     ASSERT_TRUE(mf.IsMapped());
804     ASSERT_TRUE(mf.IsNormed());
805 
806     // 5. turn next mapped region with the same size as the file's initial size.
807     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
808     char* cur = mf.Begin();
809     *cur = 'N';
810 
811     std::string res;
812     LoadStringFromFile(filename, res);
813     EXPECT_STREQ(res.c_str(), content.append("N").c_str());
814 
815     // 6. keep turnNext within a page
816     // this turn will reach the bottom of a page
817     TestFileRegion(mf, orig);
818 
819     // 7. this turn will trigger a remapping
820     off_t endOff = mf.EndOffset();
821     off_t curSize = mf.Size();
822     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
823     EXPECT_TRUE(mf.IsMapped());
824     EXPECT_EQ(mf.StartOffset(), endOff + 1);
825     EXPECT_EQ(mf.Size(), curSize);
826     EXPECT_EQ(mf.RegionStart(), mf.Begin());
827     EXPECT_EQ(static_cast<off_t>(mf.RegionEnd() - mf.RegionStart()) + 1LL, mf.PageSize());
828     std::cout << "==Remap A New Page==" << std::endl;
829     PrintStatus(mf);
830 
831     // 8. keep turnNext within a page
832     for (off_t cnt = 1; cnt < (MappedFile::PageSize() / 100LL / curSize); cnt++) {
833         endOff = mf.EndOffset();
834         EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
835         EXPECT_EQ(mf.StartOffset(), endOff + 1);
836         EXPECT_EQ(mf.Size(), curSize);
837     }
838 
839     // 10. this turn will fail since no place remained.
840     EXPECT_NE(mf.TurnNext(), MAPPED_FILE_ERR_OK);
841 
842     RemoveTestFile(filename);
843 }
844 
845 /*
846  * @tc.name: testTurnNext002
847  * @tc.desc: Test TurnNext() when `!IsMapped()`.
848  */
849 HWTEST_F(UtilsMappedFileTest, testTurnNext002, TestSize.Level0)
850 {
851     // 1. create a new file
852     std::string filename = "test_remap.txt";
853     std::string content = "Test for remapping use.";
854 
855     ReCreateFile(filename, content);
856 
857     // 2. map file
858     MappedFile mf(filename);
859     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
860     off_t curSize = mf.Size();
861     off_t curOff = mf.StartOffset();
862 
863     // 3. check status after mapping
864     ASSERT_TRUE(mf.IsMapped());
865     ASSERT_TRUE(mf.IsNormed());
866     // 4. recommand to unmap first before other operations on the file.
867     ASSERT_EQ(mf.Unmap(), MAPPED_FILE_ERR_OK);
868     // 5. enlarge file size to make it possible to `turnNext()`.
869     ASSERT_EQ(ftruncate(mf.GetFd(), MappedFile::PageSize() + MappedFile::PageSize() / 100LL), 0);
870     // 6. turn next page of `PageSize()` and keep the same `size_`
871     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
872     EXPECT_EQ(mf.Size(), curSize);
873     EXPECT_EQ(static_cast<off_t>(mf.StartOffset()), curOff + mf.PageSize());
874 
875     RemoveTestFile(filename);
876 }
877 
878 /*
879  * @tc.name: testTurnNext003
880  * @tc.desc: Test TurnNext() (using internal fd to `ftruncate()`).
881  */
882 HWTEST_F(UtilsMappedFileTest, testTurnNext003, TestSize.Level0)
883 {
884     // 1. create a new file
885     std::string content = "Test for remapping use.";
886     std::string filename = "test_remap.txt";
887 
888     ReCreateFile(filename, content);
889 
890     // 2. map file
891     MappedFile mf(filename);
892     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
893 
894     // 3. check status after mapping
895     ASSERT_TRUE(mf.IsNormed());
896     ASSERT_TRUE(mf.IsMapped());
897 
898     // 4. recommand to unmap first before other operations on the file.
899     ASSERT_EQ(mf.Unmap(), MAPPED_FILE_ERR_OK);
900     // 5. enlarge file size to make it possible to `turnNext()`.
901     ASSERT_EQ(ftruncate(mf.GetFd(), MappedFile::PageSize() + MappedFile::PageSize() / 100LL), 0);
902 
903     // 6. remap
904     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
905 
906     // 7. turn next mapped region with the same size as the file's initial size.
907     ASSERT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
908     char* cur = mf.Begin();
909     *cur = 'N';
910 
911     std::string res;
912     LoadStringFromFile(filename, res);
913     EXPECT_STREQ(res.c_str(), content.append("N").c_str());
914 
915     RemoveTestFile(filename);
916 }
917 
918 /*
919  * @tc.name: testTurnNext004
920  * @tc.desc: Test TurnNext() failed.
921  */
922 HWTEST_F(UtilsMappedFileTest, testTurnNext004, TestSize.Level0)
923 {
924     // 1. create a new file
925     std::string filename = "test_remap.txt";
926     std::string content = "Test for remapping use.";
927 
928     ReCreateFile(filename, content);
929 
930     // 2. map file
931     MappedFile mf(filename);
932     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
933 
934     // 3. check status after mapping
935     ASSERT_TRUE(mf.IsMapped());
936     ASSERT_TRUE(mf.IsNormed());
937 
938     // 4. turn next mapped region with the same size as the file's initial size.
939     EXPECT_EQ(mf.TurnNext(), ERR_INVALID_OPERATION);
940 
941     RemoveTestFile(filename);
942 }
943 
944 /*
945  * @tc.name: testTurnNext005
946  * @tc.desc: Test TurnNext() with file size less than one page.
947  */
948 HWTEST_F(UtilsMappedFileTest, testTurnNext005, TestSize.Level0)
949 {
950     // 1. create a new file
951     std::string filename = "test_remap.txt";
952     std::string content = "Test for remapping use.00";
953 
954     ReCreateFile(filename, content);
955 
956     struct stat stb = {0};
957     ASSERT_EQ(stat(filename.c_str(), &stb), 0);
958     off_t orig = stb.st_size; // 25 bytes
959 
960     // 2. extend its size
961     int fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
962     ASSERT_NE(fd, -1);
963     ASSERT_EQ(ftruncate(fd, MappedFile::PageSize() + 10), 0); // 10: remain contents less than 25bits.
964 
965     // 3. map file
966     MappedFile mf(filename, MapMode::DEFAULT, 0, orig);
967     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
968 
969     // 4. check status after mapping
970     ASSERT_TRUE(mf.IsMapped());
971     ASSERT_TRUE(mf.IsNormed());
972 
973     // 5. turn next mapped region with the same size as the file's initial size.
974     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
975 
976     // 6. keep turnNext within a page
977     // this turn will reach the bottom of a page
978     TestFileRegion(mf, orig);
979 
980     // 7. this turn will trigger a remapping
981     off_t endOff = mf.EndOffset();
982     EXPECT_EQ(mf.TurnNext(), MAPPED_FILE_ERR_OK);
983     EXPECT_TRUE(mf.IsMapped());
984     EXPECT_EQ(mf.StartOffset(), endOff + 1);
985     EXPECT_EQ(mf.Size(), 10);
986     EXPECT_EQ(mf.RegionStart(), mf.Begin());
987     EXPECT_EQ(static_cast<off_t>(mf.RegionEnd() - mf.RegionStart()) + 1LL, mf.PageSize());
988     std::cout << "==Remap A New Page==" << std::endl;
989     PrintStatus(mf);
990 }
991 
992 /*
993  * @tc.name: testInvalidMap001
994  * @tc.desc: Test file mapping with invalid offset.
995  */
996 HWTEST_F(UtilsMappedFileTest, testInvalidMap001, TestSize.Level0)
997 {
998     // 1. create a new file
999     std::string filename = "test_invalid_1.txt";
1000     std::string content = "Test for invalid use.";
1001 
1002     ReCreateFile(filename, content);
1003 
1004     // 2. map file
1005     off_t offset = 100; // Specify offset that is not multiple of page-size.
1006     MappedFile mf(filename, MapMode::DEFAULT, offset);
1007     ASSERT_NE(mf.Map(), MAPPED_FILE_ERR_OK);
1008 
1009     MappedFile mf1(filename, MapMode::DEFAULT, -1);
1010     ASSERT_NE(mf1.Map(), MAPPED_FILE_ERR_OK);
1011 
1012     // 3. check status
1013     EXPECT_FALSE(mf.IsMapped());
1014     EXPECT_FALSE(mf.IsNormed()); // mapping will fail in normalize stage.
1015     EXPECT_FALSE(mf1.IsMapped());
1016     EXPECT_FALSE(mf1.IsNormed()); // mapping will fail in normalize stage.
1017 
1018     RemoveTestFile(filename);
1019 }
1020 
1021 /*
1022  * @tc.name: testInvalidMap002
1023  * @tc.desc: Test file mapping with invalid offset excessing the substantial size of the file.
1024  */
1025 HWTEST_F(UtilsMappedFileTest, testInvalidMap002, TestSize.Level0)
1026 {
1027     // 1. create a new file
1028     std::string filename = "test_invalid_2.txt";
1029     std::string content = "Test for invalid use.";
1030 
1031     ReCreateFile(filename, content);
1032 
1033     // 2. map file
1034     off_t offset = 4 * 1024; // Specify offset excessing the substantial size of the file.
1035     MappedFile mf(filename, MapMode::DEFAULT, offset);
1036     ASSERT_NE(mf.Map(), MAPPED_FILE_ERR_OK);
1037 
1038     // 3. check status
1039     EXPECT_FALSE(mf.IsMapped());
1040     EXPECT_FALSE(mf.IsNormed()); // mapping will fail in normalize stage.
1041 
1042     RemoveTestFile(filename);
1043 }
1044 
1045 /*
1046  * @tc.name: testInvalidMap003
1047  * @tc.desc: Test mapping non-existed file without setting CREAT_IF_ABSENT.
1048  */
1049 HWTEST_F(UtilsMappedFileTest, testInvalidMap003, TestSize.Level0)
1050 {
1051     // 1. create a new file
1052     std::string filename = "test_invalid_3.txt";
1053     filename.insert(0, SUITE_PATH).insert(0, BASE_PATH);
1054     RemoveTestFile(filename);
1055 
1056     // 2. map file
1057     MappedFile mf(filename);
1058     ASSERT_NE(mf.Map(), MAPPED_FILE_ERR_OK);
1059 
1060     // 3. check status
1061     EXPECT_FALSE(mf.IsMapped());
1062     EXPECT_FALSE(mf.IsNormed()); // mapping will fail in normalize stage.
1063 
1064     RemoveTestFile(filename);
1065 }
1066 
1067 /*
1068  * @tc.name: testInvalidMap004
1069  * @tc.desc: Test mapping with invalid size.
1070  */
1071 HWTEST_F(UtilsMappedFileTest, testInvalidMap004, TestSize.Level0)
1072 {
1073     // 1. create a new file
1074     std::string filename = "test_invalid_4.txt";
1075     std::string content = "Test for invalid use.";
1076 
1077     ReCreateFile(filename, content);
1078 
1079     // 2. map file
1080     MappedFile mf(filename, MapMode::DEFAULT, 0, -2); // -2: less than DEFAULT_LENGTH(-1)
1081     ASSERT_EQ(mf.Map(), ERR_INVALID_VALUE);
1082 
1083     // 3. map again with another invalid param.
1084     MappedFile mf1(filename, MapMode::DEFAULT, 0, 0);
1085     ASSERT_EQ(mf1.Map(), ERR_INVALID_VALUE);
1086 
1087     // 4. check status
1088     EXPECT_FALSE(mf.IsMapped());
1089     EXPECT_FALSE(mf.IsNormed()); // mapping will fail in normalize stage.
1090     EXPECT_FALSE(mf1.IsMapped());
1091     EXPECT_FALSE(mf1.IsNormed()); // mapping will fail in normalize stage.
1092 
1093     RemoveTestFile(filename);
1094 }
1095 
1096 /*
1097  * @tc.name: testInvalidMap005
1098  * @tc.desc: Test mapping an already mapped file.
1099  */
1100 HWTEST_F(UtilsMappedFileTest, testInvalidMap005, TestSize.Level0)
1101 {
1102     // 1. create a new file
1103     std::string filename = "test_invalid_6.txt";
1104     std::string content = "Test for invalid use.";
1105 
1106     ReCreateFile(filename, content);
1107 
1108     // 2. map file
1109     MappedFile mf(filename);
1110     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1111     ASSERT_EQ(mf.Map(), ERR_INVALID_OPERATION); // Map again.
1112 
1113     // 3. check status
1114     EXPECT_TRUE(mf.IsMapped());
1115     EXPECT_TRUE(mf.IsNormed());
1116 
1117     RemoveTestFile(filename);
1118 }
1119 
1120 /*
1121  * @tc.name: testInvalidMap006
1122  * @tc.desc: Test resize with invalid params.
1123  */
1124 HWTEST_F(UtilsMappedFileTest, testInvalidMap006, TestSize.Level0)
1125 {
1126     // 1. create a new file
1127     std::string filename = "test_invalid_7.txt";
1128     std::string content = "Test for invalid use.";
1129 
1130     ReCreateFile(filename, content);
1131 
1132     // 2. map file
1133     MappedFile mf(filename);
1134     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1135 
1136     // 3. check status
1137     ASSERT_TRUE(mf.IsMapped());
1138     ASSERT_TRUE(mf.IsNormed());
1139 
1140     // 4. resize
1141     EXPECT_EQ(mf.Resize(0), ERR_INVALID_OPERATION);
1142     EXPECT_EQ(mf.Resize(-2), ERR_INVALID_OPERATION); // -2: less than DEFAULT_LENGTH(-1).
1143     EXPECT_EQ(mf.Resize(mf.Size()), ERR_INVALID_OPERATION);
1144 
1145     // 5. Unmap first then resize.
1146     ASSERT_EQ(mf.Unmap(), MAPPED_FILE_ERR_OK);
1147     EXPECT_EQ(mf.Resize(mf.Size() + 8), ERR_INVALID_OPERATION);
1148 
1149     RemoveTestFile(filename);
1150 }
1151 
1152 /*
1153  * @tc.name: testInvalidMap007
1154  * @tc.desc: Test resize with no param changed.
1155  */
1156 HWTEST_F(UtilsMappedFileTest, testInvalidMap007, TestSize.Level0)
1157 {
1158     // 1. create a new file
1159     std::string filename = "test_invalid_8.txt";
1160     std::string content = "Test for invalid use.";
1161 
1162     ReCreateFile(filename, content);
1163 
1164     // 2. map file
1165     MappedFile mf(filename);
1166     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1167 
1168     // 3. check status
1169     ASSERT_TRUE(mf.IsMapped());
1170     ASSERT_TRUE(mf.IsNormed());
1171 
1172     // 4. resize
1173     EXPECT_EQ(mf.Resize(), ERR_INVALID_OPERATION);
1174 
1175     RemoveTestFile(filename);
1176 }
1177 
1178 /*
1179  * @tc.name: testInvalidMap008
1180  * @tc.desc: Test TurnNext() with params changed.
1181  */
1182 HWTEST_F(UtilsMappedFileTest, testInvalidMap008, TestSize.Level0)
1183 {
1184     // 1. create a new file
1185     std::string filename = "test_invalid_9.txt";
1186     std::string content = "Test for invalid use.";
1187 
1188     ReCreateFile(filename, content);
1189 
1190     // 2. map file
1191     MappedFile mf(filename);
1192     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1193 
1194     // 3. check status
1195     ASSERT_TRUE(mf.IsMapped());
1196     ASSERT_TRUE(mf.IsNormed());
1197 
1198     // 4. Change params
1199     ASSERT_TRUE(mf.ChangeSize(mf.Size() + 1));
1200 
1201     // 5. check status
1202     ASSERT_FALSE(mf.IsMapped());
1203     ASSERT_FALSE(mf.IsNormed());
1204 
1205     // 6. turn next.
1206     EXPECT_EQ(mf.TurnNext(), ERR_INVALID_OPERATION);
1207 
1208     RemoveTestFile(filename);
1209 }
1210 
1211 /*
1212  * @tc.name: testInvalidMap009
1213  * @tc.desc: Test ChangeXX() with invalid params.
1214  */
1215 HWTEST_F(UtilsMappedFileTest, testInvalidMap009, TestSize.Level0)
1216 {
1217     // 1. create a new file
1218     std::string filename = "test_invalid_10.txt";
1219     std::string content = "Test for invalid use.";
1220 
1221     ReCreateFile(filename, content);
1222 
1223     // 2. create MappedFile
1224     MappedFile mf(filename);
1225 
1226     // 3. map file
1227     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1228 
1229     // 4. check status
1230     ASSERT_TRUE(mf.IsMapped());
1231     ASSERT_TRUE(mf.IsNormed());
1232 
1233     // 5. Change params
1234     ASSERT_FALSE(mf.ChangeOffset(mf.StartOffset()));
1235     ASSERT_FALSE(mf.ChangeSize(mf.Size()));
1236     ASSERT_FALSE(mf.ChangeHint(mf.GetHint()));
1237     ASSERT_FALSE(mf.ChangeMode(mf.GetMode()));
1238     ASSERT_FALSE(mf.ChangePath(mf.GetPath()));
1239 
1240     RemoveTestFile(filename);
1241 }
1242 
1243 /*
1244  * @tc.name: testAutoAdjustedMode001
1245  * @tc.desc: Test mapping file with invalid mapping mode, but can be auto adjusted.
1246  */
1247 HWTEST_F(UtilsMappedFileTest, testAutoAdjustedMode001, TestSize.Level0)
1248 {
1249     // 1. create a new file
1250     std::string filename = "test_adjmod_1.txt";
1251     std::string content = "Test for auto adj use.";
1252 
1253     ReCreateFile(filename, content);
1254 
1255     // 2. map file
1256     MapMode mode = static_cast<MapMode>(1) | static_cast<MapMode>(16) |
1257                    MapMode::PRIVATE | MapMode::READ_ONLY; // bits out of the scope will be ignored.
1258     MappedFile mf(filename, mode);
1259     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1260 
1261     // 3. check status
1262     EXPECT_TRUE(mf.IsMapped());
1263     EXPECT_TRUE(mf.IsNormed());
1264 
1265     // 4. check map-mode
1266     ASSERT_EQ(MapMode::PRIVATE | MapMode::READ_ONLY, mf.GetMode());
1267 
1268     RemoveTestFile(filename);
1269 }
1270 
1271 /*
1272  * @tc.name: testAutoAdjustedSize001
1273  * @tc.desc: Test file mapping with size excessing the last page of the file.
1274  */
1275 HWTEST_F(UtilsMappedFileTest, testAutoAdjustedSize001, TestSize.Level0)
1276 {
1277     // 1. create a new file
1278     std::string filename = "test_adjsize_1.txt";
1279     std::string content = "Test for auto adj use.";
1280 
1281     ReCreateFile(filename, content);
1282 
1283     // 2. map file
1284     off_t size = 5 * 1024; // Specified size excessing the last page of the file.
1285     MappedFile mf(filename, MapMode::DEFAULT, 0, size);
1286     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1287 
1288     // 3. check status
1289     EXPECT_TRUE(mf.IsMapped());
1290     EXPECT_TRUE(mf.IsNormed());
1291 
1292     // 4. check size
1293     struct stat stb = {0};
1294     stat(filename.c_str(), &stb);
1295     off_t max = (stb.st_size / mf.PageSize() + 1LL) * mf.PageSize() - 0LL;
1296     EXPECT_EQ(mf.Size(), max); // Size will be automatically adjusted, due to safe-concern.
1297 
1298     RemoveTestFile(filename);
1299 }
1300 
1301 /*
1302  * @tc.name: testAutoAdjustedSize002
1303  * @tc.desc: Test file mapping with size excessing the last page of the file.
1304  */
1305 HWTEST_F(UtilsMappedFileTest, testAutoAdjustedSize002, TestSize.Level0)
1306 {
1307     // 1. create a new file
1308     std::string filename = "test_adjsize_2.txt";
1309     std::string content = "Test for auto adj use.";
1310 
1311     ReCreateFile(filename, content);
1312 
1313     // 2. Extend size manually
1314     int fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
1315     if (fd != -1) {
1316         std::cout << "open success." << std::endl;
1317         ftruncate(fd, 7 * 1024);
1318 
1319         // 3. map file
1320         off_t offset = 4 * 1024;
1321         off_t size = 5 * 1024; // Specified size excessing the last page of the file.
1322         MappedFile mf(filename, MapMode::DEFAULT, offset, size);
1323         ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1324 
1325         // 4. check status
1326         EXPECT_TRUE(mf.IsMapped());
1327         EXPECT_TRUE(mf.IsNormed());
1328 
1329         // 5. check size
1330         struct stat stb = {0};
1331         stat(filename.c_str(), &stb);
1332         off_t max = (stb.st_size / mf.PageSize() + 1LL) * mf.PageSize() - offset;
1333         EXPECT_EQ(mf.Size(), max); // Size will be automatically adjusted, due to safe-concern.
1334 
1335         close(fd);
1336     }
1337 
1338     RemoveTestFile(filename);
1339 }
1340 
1341 /*
1342  * @tc.name: testMoveMappedFile001
1343  * @tc.desc: Test move constructor.
1344  */
1345 HWTEST_F(UtilsMappedFileTest, testMoveMappedFile001, TestSize.Level0)
1346 {
1347     // 1. create a new file
1348     std::string filename = "test_move_1.txt";
1349     std::string content = "Test for move use.";
1350 
1351     ReCreateFile(filename, content);
1352 
1353     // 2. map file
1354     MappedFile mf(filename);
1355     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1356 
1357     off_t size = mf.Size();
1358     off_t offset = mf.StartOffset();
1359     char* data = mf.Begin();
1360     MapMode mode = mf.GetMode();
1361     const char* hint = mf.GetHint();
1362 
1363     // 3. move to a new object
1364     MappedFile mfNew(std::move(mf));
1365 
1366     // 4. check status and params after move
1367     EXPECT_FALSE(mf.IsMapped());
1368     EXPECT_FALSE(mf.IsNormed());
1369     EXPECT_EQ(mf.Begin(), nullptr);
1370     EXPECT_EQ(mf.Size(), MappedFile::DEFAULT_LENGTH);
1371     EXPECT_EQ(mf.StartOffset(), 0);
1372     EXPECT_EQ(mf.GetMode(), MapMode::DEFAULT);
1373     EXPECT_EQ(mf.GetHint(), nullptr);
1374     EXPECT_EQ(mf.GetPath(), "");
1375 
1376     EXPECT_TRUE(mfNew.IsMapped());
1377     EXPECT_TRUE(mfNew.IsNormed());
1378     EXPECT_EQ(mfNew.Begin(), data);
1379     EXPECT_EQ(mfNew.Size(), size);
1380     EXPECT_EQ(mfNew.StartOffset(), offset);
1381     EXPECT_EQ(mfNew.GetMode(), mode);
1382     EXPECT_EQ(mfNew.GetHint(), hint);
1383     EXPECT_EQ(mfNew.GetPath(), filename);
1384 
1385     // 5. read from mapped file
1386     // write to mapped file
1387     TestFileWrite(mfNew, filename, content);
1388 }
1389 
1390 /*
1391  * @tc.name: testMoveMappedFile002
1392  * @tc.desc: Test move constructor with ummapped region.
1393  */
1394 HWTEST_F(UtilsMappedFileTest, testMoveMappedFile002, TestSize.Level0)
1395 {
1396     // 1. create a new file
1397     std::string filename = "test_move_2.txt";
1398     std::string content = "Test for move use.";
1399 
1400     ReCreateFile(filename, content);
1401 
1402     // 2. map file
1403     MappedFile mf(filename);
1404     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1405 
1406     off_t size = mf.Size();
1407     off_t offset = mf.StartOffset();
1408     MapMode mode = mf.GetMode();
1409     const char* hint = mf.GetHint();
1410 
1411     ASSERT_EQ(mf.Unmap(), MAPPED_FILE_ERR_OK);
1412     // 3. move to a new object
1413     MappedFile mfNew(std::move(mf));
1414 
1415     // 4. check status and params after move
1416     EXPECT_FALSE(mf.IsMapped());
1417     EXPECT_FALSE(mf.IsNormed());
1418     EXPECT_EQ(mf.Begin(), nullptr);
1419     EXPECT_EQ(mf.Size(), MappedFile::DEFAULT_LENGTH);
1420     EXPECT_EQ(mf.StartOffset(), 0);
1421     EXPECT_EQ(mf.GetMode(), MapMode::DEFAULT);
1422     EXPECT_EQ(mf.GetHint(), nullptr);
1423     EXPECT_EQ(mf.GetPath(), "");
1424 
1425     EXPECT_FALSE(mfNew.IsMapped());
1426     EXPECT_TRUE(mfNew.IsNormed());
1427     EXPECT_EQ(mfNew.Begin(), nullptr);
1428     EXPECT_EQ(mfNew.Size(), size);
1429     EXPECT_EQ(mfNew.StartOffset(), offset);
1430     EXPECT_EQ(mfNew.GetMode(), mode);
1431     EXPECT_EQ(mfNew.GetHint(), hint);
1432     EXPECT_EQ(mfNew.GetPath(), filename);
1433 
1434     // 5. Map again
1435     ASSERT_EQ(mfNew.Map(), MAPPED_FILE_ERR_OK);
1436     // 6. read from mapped file
1437     // write to mapped file
1438     TestFileWrite(mfNew, filename, content);
1439 }
1440 
1441 /*
1442  * @tc.name: testMoveMappedFile003
1443  * @tc.desc: Test move assignment operator overload.
1444  */
1445 HWTEST_F(UtilsMappedFileTest, testMoveMappedFile003, TestSize.Level0)
1446 {
1447     // 1. create a new file
1448     std::string filename = "test_move_3.txt";
1449     std::string content = "Test for move use.";
1450 
1451     std::string filename1 = "test_move_4.txt";
1452     std::string content1 = "Test for move use.";
1453 
1454     ReCreateFile(filename, content);
1455     ReCreateFile(filename1, content1);
1456 
1457     // 2. map file
1458     MappedFile mf(filename);
1459     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1460     MappedFile mf1(filename1);
1461     ASSERT_EQ(mf1.Map(), MAPPED_FILE_ERR_OK);
1462 
1463     off_t size = mf1.Size();
1464     off_t offset = mf1.StartOffset();
1465     MapMode mode = mf1.GetMode();
1466     char* data = mf1.Begin();
1467     const char* hint = mf1.GetHint();
1468 
1469     // 3. move assignment
1470     mf = std::move(mf1);
1471 
1472     // 4. check status and params after move
1473     EXPECT_TRUE(mf.IsMapped());
1474     EXPECT_TRUE(mf.IsNormed());
1475     EXPECT_EQ(mf.Begin(), data);
1476     EXPECT_EQ(mf.Size(), size);
1477     EXPECT_EQ(mf.StartOffset(), offset);
1478     EXPECT_EQ(mf.GetMode(), mode);
1479     EXPECT_EQ(mf.GetHint(), hint);
1480     EXPECT_EQ(mf.GetPath(), filename1);
1481 
1482     // 5. read from mapped file
1483     // write to mapped file
1484     TestTwoFileWrite(mf, filename, filename1, content1);
1485 }
1486 
1487 /*
1488  * @tc.name: testMoveMappedFile004
1489  * @tc.desc: Test move assignment operator overload with ummapped region.
1490  */
1491 HWTEST_F(UtilsMappedFileTest, testMoveMappedFile004, TestSize.Level0)
1492 {
1493     // 1. create a new file
1494     std::string filename = "test_move_4.txt";
1495     std::string content = "Test for move use.";
1496     ReCreateFile(filename, content);
1497 
1498     std::string filename1 = "test_move_5.txt";
1499     std::string content1 = "Test for move use.";
1500     ReCreateFile(filename1, content1);
1501 
1502     // 2. map file
1503     MappedFile mf(filename);
1504     MappedFile mf1(filename1);
1505     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1506     ASSERT_EQ(mf1.Map(), MAPPED_FILE_ERR_OK);
1507 
1508     off_t size = mf1.Size();
1509     off_t offset = mf1.StartOffset();
1510     MapMode mode = mf1.GetMode();
1511     const char* hint = mf1.GetHint();
1512 
1513     // 3. ummap mf1
1514     ASSERT_EQ(mf1.Unmap(), MAPPED_FILE_ERR_OK);
1515     // 4. move assignment
1516     mf = std::move(mf1);
1517     // 5. check status and params after move
1518     EXPECT_FALSE(mf.IsMapped());
1519     EXPECT_TRUE(mf.IsNormed());
1520     EXPECT_EQ(mf.Begin(), nullptr); // since mf1 is unmapped, its `data_` are set to `nullptr`
1521     EXPECT_EQ(mf.Size(), size);
1522     EXPECT_EQ(mf.StartOffset(), offset);
1523     EXPECT_EQ(mf.GetMode(), mode);
1524     EXPECT_EQ(mf.GetHint(), hint);
1525     EXPECT_EQ(mf.GetPath(), filename1);
1526 
1527     ASSERT_EQ(mf.Map(), MAPPED_FILE_ERR_OK);
1528     // 6. read from mapped file
1529     // write to mapped file
1530     TestTwoFileWrite(mf, filename, filename1, content1);
1531 }
1532 
1533 }  // namespace
1534 }  // namespace OHOS