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