1 /*
2  * Copyright (C) 2022 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 "medialibrary_unittest_utils.h"
17 
18 #include <cerrno>
19 #include <fstream>
20 #include <sys/stat.h>
21 
22 #include "ability_context_impl.h"
23 #include "fetch_result.h"
24 #include "media_log.h"
25 #include "media_file_utils.h"
26 #include "media_smart_map_column.h"
27 #include "medialibrary_data_manager.h"
28 #include "medialibrary_unistore_manager.h"
29 #include "mimetype_utils.h"
30 #include "result_set_utils.h"
31 #include "scanner_utils.h"
32 
33 using namespace std;
34 using namespace OHOS::DataShare;
35 using namespace OHOS::AppExecFwk;
36 namespace OHOS {
37 namespace Media {
IsValid()38 bool MediaLibraryUnitTestUtils::IsValid()
39 {
40     return isValid_;
41 }
42 
Init()43 void MediaLibraryUnitTestUtils::Init()
44 {
45     auto stageContext = std::make_shared<AbilityRuntime::ContextImpl>();
46     auto abilityContextImpl = std::make_shared<OHOS::AbilityRuntime::AbilityContextImpl>();
47     abilityContextImpl->SetStageContext(stageContext);
48     int32_t sceneCode = 0;
49     MediaLibraryDataManager::GetInstance()->InitMediaLibraryMgr(abilityContextImpl, abilityContextImpl, sceneCode);
50     auto ret = MediaLibraryDataManager::GetInstance()->InitMediaLibraryMgr(abilityContextImpl, abilityContextImpl,
51         sceneCode);
52     CHECK_AND_RETURN_LOG(ret == E_OK, "InitMediaLibraryMgr failed, ret: %{public}d", ret);
53     isValid_ = true;
54 }
55 
InitUnistore()56 int32_t MediaLibraryUnitTestUtils::InitUnistore()
57 {
58     auto stageContext = std::make_shared<AbilityRuntime::ContextImpl>();
59     auto abilityContextImpl = std::make_shared<OHOS::AbilityRuntime::AbilityContextImpl>();
60     abilityContextImpl -> SetStageContext(stageContext);
61     int32_t ret = MediaLibraryUnistoreManager::GetInstance().Init(abilityContextImpl);
62     if (ret != E_OK) {
63         MEDIA_ERR_LOG("init MediaLibraryUnistoreManager failed");
64     }
65     return ret;
66 }
67 
InitUnistore(const NativeRdb::RdbStoreConfig & config,int version,NativeRdb::RdbOpenCallback & openCallback)68 int32_t MediaLibraryUnitTestUtils::InitUnistore(const NativeRdb::RdbStoreConfig &config, int version,
69     NativeRdb::RdbOpenCallback &openCallback)
70 {
71     auto stageContext = std::make_shared<AbilityRuntime::ContextImpl>();
72     auto abilityContextImpl = std::make_shared<OHOS::AbilityRuntime::AbilityContextImpl>();
73     abilityContextImpl->SetStageContext(stageContext);
74     int32_t ret = MediaLibraryUnistoreManager::GetInstance().Init(abilityContextImpl, config, version, openCallback);
75     MediaLibraryDataManager::GetInstance()->rdbStore_ = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
76     if (ret != E_OK) {
77         MEDIA_ERR_LOG("init MediaLibraryUnistoreManager with config failed");
78     }
79     return ret;
80 }
81 
StopUnistore()82 void MediaLibraryUnitTestUtils::StopUnistore()
83 {
84     MediaLibraryDataManager::GetInstance()->rdbStore_ = nullptr;
85     MediaLibraryUnistoreManager::GetInstance().Stop();
86 }
87 
InitRootDirs()88 void MediaLibraryUnitTestUtils::InitRootDirs()
89 {
90     for (const auto &dir : TEST_ROOT_DIRS) {
91         shared_ptr<FileAsset> dirAsset = nullptr;
92         if (!CreateAlbum(dir, nullptr, dirAsset)) {
93             isValid_ = false;
94             return;
95         }
96         rootDirAssetMap_[dir] = dirAsset;
97     }
98 }
99 
CleanTestFiles()100 void MediaLibraryUnitTestUtils::CleanTestFiles()
101 {
102     system("rm -rf /storage/cloud/files/Audio/*");
103     system("rm -rf /storage/cloud/files/Audios/*");
104     system("rm -rf /storage/cloud/files/Camera/*");
105     system("rm -rf /storage/cloud/files/Docs/Documents/*");
106     system("rm -rf /storage/cloud/files/Docs/Download/*");
107     system("rm -rf /storage/cloud/files/Photo/*");
108     system("rm -rf /storage/cloud/files/Pictures/*");
109     system("rm -rf /storage/cloud/files/Pictures/*");
110     system("rm -rf /storage/cloud/files/Videos/*");
111     system("rm -rf /storage/cloud/files/.*");
112     auto rdbStore = MediaLibraryDataManager::GetInstance()->rdbStore_;
113     NativeRdb::AbsRdbPredicates predicates(MEDIALIBRARY_TABLE);
114     predicates.GreaterThan(MEDIA_DATA_DB_ID, to_string(0));
115     int32_t deletedRows = -1;
116     auto ret = rdbStore->Delete(deletedRows, predicates);
117     MEDIA_INFO_LOG("CleanTestFiles Delete retVal: %{public}d, deletedRows: %{public}d", ret, deletedRows);
118 }
119 
CleanBundlePermission()120 void MediaLibraryUnitTestUtils::CleanBundlePermission()
121 {
122     auto rdbStore = MediaLibraryDataManager::GetInstance()->rdbStore_;
123     NativeRdb::AbsRdbPredicates predicates(BUNDLE_PERMISSION_TABLE);
124     predicates.GreaterThan(MEDIA_DATA_DB_ID, to_string(0));
125     int32_t deletedRows = -1;
126     auto ret = rdbStore->Delete(deletedRows, predicates);
127     MEDIA_INFO_LOG("CleanBundlePermission Delete retVal: %{public}d, deletedRows: %{public}d", ret, deletedRows);
128 }
129 
GetRootAsset(const string & dir)130 shared_ptr<FileAsset> MediaLibraryUnitTestUtils::GetRootAsset(const string &dir)
131 {
132     if (rootDirAssetMap_.find(dir) != rootDirAssetMap_.end()) {
133         return rootDirAssetMap_[dir];
134     }
135     return nullptr;
136 }
137 
IsFileExists(const string filePath)138 bool MediaLibraryUnitTestUtils::IsFileExists(const string filePath)
139 {
140     struct stat statInfo {};
141     int errCode = stat(filePath.c_str(), &statInfo);
142     return (errCode == 0);
143 }
144 
GetFileAsset(const int fileId,shared_ptr<FileAsset> & fileAsset)145 bool MediaLibraryUnitTestUtils::GetFileAsset(const int fileId, shared_ptr<FileAsset> &fileAsset)
146 {
147     if (!MediaLibraryUnitTestUtils::IsValid()) {
148         MEDIA_ERR_LOG("MediaLibraryDataManager invalid");
149         exit(1);
150     }
151     vector<string> columns;
152     DataSharePredicates predicates;
153     string selections = MEDIA_DATA_DB_ID + " = " + to_string(fileId);
154     predicates.SetWhereClause(selections);
155     Uri queryFileUri(MEDIALIBRARY_DATA_URI);
156     int errCode = 0;
157     MediaLibraryCommand cmd(queryFileUri, Media::OperationType::QUERY);
158     auto resultSet = MediaLibraryDataManager::GetInstance()->Query(cmd, columns, predicates, errCode);
159     if (resultSet == nullptr) {
160         MEDIA_ERR_LOG("GetFileAsset::resultSet == nullptr");
161         return false;
162     }
163     auto result = make_shared<DataShareResultSet>(resultSet);
164     shared_ptr<FetchResult<FileAsset>> fetchFileResult = make_unique<FetchResult<FileAsset>>(move(result));
165     if (fetchFileResult->GetCount() <= 0) {
166         MEDIA_ERR_LOG("GetFileAsset::GetCount <= 0");
167         return false;
168     }
169     auto firstAsset = fetchFileResult->GetFirstObject();
170     fileAsset = move(firstAsset);
171     if (fileAsset == nullptr) {
172         MEDIA_ERR_LOG("GetFileAsset::fileAsset = nullptr.");
173         return false;
174     }
175     return true;
176 }
177 
CreateAlbum(string displayName,shared_ptr<FileAsset> parentAlbumAsset,shared_ptr<FileAsset> & albumAsset)178 bool MediaLibraryUnitTestUtils::CreateAlbum(string displayName, shared_ptr<FileAsset> parentAlbumAsset,
179     shared_ptr<FileAsset> &albumAsset)
180 {
181     if (!MediaLibraryUnitTestUtils::IsValid()) {
182         MEDIA_ERR_LOG("MediaLibraryDataManager invalid");
183         exit(1);
184     }
185     Uri createAlbumUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_ALBUMOPRN + "/" + MEDIA_ALBUMOPRN_CREATEALBUM);
186     string dirPath;
187     if (parentAlbumAsset == nullptr) {
188         dirPath = ROOT_MEDIA_DIR + displayName;
189     } else {
190         dirPath = parentAlbumAsset->GetPath() + "/" + displayName;
191     }
192     DataShareValuesBucket valuesBucket;
193     valuesBucket.Put(MEDIA_DATA_DB_FILE_PATH, dirPath);
194     valuesBucket.Put(MEDIA_DATA_DB_NAME, displayName);
195     MediaLibraryCommand cmd(createAlbumUri);
196     auto retVal = MediaLibraryDataManager::GetInstance()->Insert(cmd, valuesBucket);
197     MEDIA_INFO_LOG("CreateAlbum:: %{private}s, retVal: %{public}d", dirPath.c_str(), retVal);
198     if (retVal <= 0) {
199         MEDIA_ERR_LOG("CreateAlbum::create failed, %{private}s", dirPath.c_str());
200         return false;
201     }
202     if (!GetFileAsset(retVal, albumAsset)) {
203         MEDIA_ERR_LOG("CreateAlbum::GetFileAsset failed, %{private}s", dirPath.c_str());
204         return false;
205     }
206     return true;
207 }
208 
CreateFile(string displayName,shared_ptr<FileAsset> parentAlbumAsset,shared_ptr<FileAsset> & fileAsset)209 bool MediaLibraryUnitTestUtils::CreateFile(string displayName, shared_ptr<FileAsset> parentAlbumAsset,
210     shared_ptr<FileAsset> &fileAsset)
211 {
212     if (!MediaLibraryUnitTestUtils::IsValid()) {
213         MEDIA_ERR_LOG("MediaLibraryDataManager invalid");
214         exit(1);
215     }
216     Uri createAssetUri(MEDIALIBRARY_DATA_URI + "/" + Media::MEDIA_FILEOPRN + "/" + Media::MEDIA_FILEOPRN_CREATEASSET);
217     DataShareValuesBucket valuesBucket;
218     string relativePath = MediaFileUtils::AddDocsToRelativePath(parentAlbumAsset->GetRelativePath() +
219         parentAlbumAsset->GetDisplayName() + "/");
220     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(ScannerUtils::GetFileExtension(displayName));
221     MediaType mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
222     valuesBucket.Put(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
223     valuesBucket.Put(MEDIA_DATA_DB_NAME, displayName);
224     valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
225     MediaLibraryCommand cmd(createAssetUri);
226     int32_t retVal = MediaLibraryDataManager::GetInstance()->Insert(cmd, valuesBucket);
227     MEDIA_INFO_LOG("CreateFile:: %{private}s, retVal: %{public}d", (relativePath + displayName).c_str(), retVal);
228     if (retVal <= 0) {
229         MEDIA_ERR_LOG("CreateFile::create failed, %{private}s", (relativePath + displayName).c_str());
230         return false;
231     }
232     if (!GetFileAsset(retVal, fileAsset)) {
233         MEDIA_ERR_LOG("CreateFile::GetFileAsset failed, %{private}s", (relativePath + displayName).c_str());
234         return false;
235     }
236     return true;
237 }
238 
CreateFileFS(const string & filePath)239 bool MediaLibraryUnitTestUtils::CreateFileFS(const string &filePath)
240 {
241     bool errCode = false;
242 
243     if (filePath.empty()) {
244         return errCode;
245     }
246 
247     ofstream file(filePath);
248     if (!file) {
249         MEDIA_ERR_LOG("Output file path could not be created");
250         return errCode;
251     }
252 
253     const mode_t CHOWN_RW_UG = 0660;
254     if (chmod(filePath.c_str(), CHOWN_RW_UG) == 0) {
255         errCode = true;
256     }
257 
258     file.close();
259 
260     return errCode;
261 }
262 
DeleteDir(const string & path,const string & dirId)263 bool MediaLibraryUnitTestUtils::DeleteDir(const string &path, const string &dirId)
264 {
265     string cmd = "rm -rf " + path;
266     system(cmd.c_str());
267 
268     auto rdbStore = MediaLibraryDataManager::GetInstance()->rdbStore_;
269     NativeRdb::AbsRdbPredicates predicates(MEDIALIBRARY_TABLE);
270     predicates.EqualTo(MEDIA_DATA_DB_ID, dirId)->Or()->EqualTo(MEDIA_DATA_DB_PARENT_ID, dirId);
271     int32_t deletedRows = -1;
272     auto ret = rdbStore->Delete(deletedRows, predicates);
273     return ret == 0;
274 }
275 
TrashFile(shared_ptr<FileAsset> & fileAsset)276 void MediaLibraryUnitTestUtils::TrashFile(shared_ptr<FileAsset> &fileAsset)
277 {
278     DataShareValuesBucket valuesBucket;
279     valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
280     valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, fileAsset->GetId());
281     string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/" +
282         MEDIA_SMARTALBUMMAPOPRN_ADDSMARTALBUM;
283     Uri uri(uriString);
284     MediaLibraryCommand cmd(uri);
285     MediaLibraryDataManager::GetInstance()->Insert(cmd, valuesBucket);
286 }
287 
RecoveryFile(shared_ptr<FileAsset> & fileAsset)288 void MediaLibraryUnitTestUtils::RecoveryFile(shared_ptr<FileAsset> &fileAsset)
289 {
290     DataShareValuesBucket valuesBucket;
291     valuesBucket.Put(SMARTALBUMMAP_DB_ALBUM_ID, TRASH_ALBUM_ID_VALUES);
292     valuesBucket.Put(SMARTALBUMMAP_DB_CHILD_ASSET_ID, fileAsset->GetId());
293     string uriString = MEDIALIBRARY_DATA_URI + "/" + MEDIA_SMARTALBUMMAPOPRN + "/" +
294         MEDIA_SMARTALBUMMAPOPRN_REMOVESMARTALBUM;
295     Uri uri(uriString);
296     MediaLibraryCommand cmd(uri);
297     MediaLibraryDataManager::GetInstance()->Insert(cmd, valuesBucket);
298 }
299 
WaitForCallback(shared_ptr<TestScannerCallback> callback)300 void MediaLibraryUnitTestUtils::WaitForCallback(shared_ptr<TestScannerCallback> callback)
301 {
302     std::mutex mutex;
303     std::unique_lock<std::mutex> lock(mutex);
304     const int waitSeconds = 10;
305     callback->condVar_.wait_until(lock, std::chrono::system_clock::now() + std::chrono::seconds(waitSeconds));
306 }
307 
GrantUriPermission(const int32_t fileId,const string & bundleName,const string & mode,const int32_t tableType)308 int32_t MediaLibraryUnitTestUtils::GrantUriPermission(const int32_t fileId, const string &bundleName,
309     const string &mode, const int32_t tableType)
310 {
311     Uri addPermission(MEDIALIBRARY_BUNDLEPERM_URI + "/" + BUNDLE_PERMISSION_INSERT);
312     DataShareValuesBucket values;
313     values.Put(PERMISSION_FILE_ID, fileId);
314     values.Put(PERMISSION_BUNDLE_NAME, bundleName);
315     values.Put(PERMISSION_MODE, mode);
316     values.Put(PERMISSION_TABLE_TYPE, tableType);
317     MediaLibraryCommand cmd(addPermission);
318     return MediaLibraryDataManager::GetInstance()->Insert(cmd, values);
319 }
320 
TestScannerCallback()321 TestScannerCallback::TestScannerCallback() : status_(-1) {}
322 
OnScanFinished(const int32_t status,const std::string & uri,const std::string & path)323 int32_t TestScannerCallback::OnScanFinished(const int32_t status, const std::string &uri, const std::string &path)
324 {
325     status_ = status;
326     condVar_.notify_all();
327     return E_OK;
328 }
329 
writeBytesToFile(size_t numBytes,const char * path,size_t & resultFileSize)330 bool MediaLibraryUnitTestUtils::writeBytesToFile(size_t numBytes, const char* path, size_t& resultFileSize)
331 {
332     int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
333     if (fd == -1) {
334         MEDIA_ERR_LOG("Error: Unable to open file %{public}s for writing, errno: %{public}d", path, errno);
335         return false;
336     }
337 
338     char dummyByte = '\0'; // A dummy byte to be written
339 
340     for (size_t i = 0; i < numBytes; ++i) {
341         if (write(fd, &dummyByte, sizeof(char)) == -1) {
342             MEDIA_ERR_LOG("Error while writing to file %{public}s, errno: %{public}d", path, errno);
343             close(fd);
344             return false;
345         }
346     }
347 
348     close(fd);
349 
350     struct stat statbuf;
351     if (lstat(path, &statbuf) == -1) {
352         MEDIA_ERR_LOG("Failed to get file size of %{public}s, errno is %{public}d", path, errno);
353         return false;
354     }
355 
356     resultFileSize = statbuf.st_size;
357     MEDIA_INFO_LOG("File %{public}s successfully written, File size after writing: %{public}zu", path, resultFileSize);
358 
359     return true;
360 }
361 }
362 }
363