Update test cases

This commit is contained in:
Ming Ming 2024-02-13 19:29:13 +08:00
parent 64b281289b
commit 59a5741c50
5 changed files with 223 additions and 37 deletions

View file

@ -1,7 +1,8 @@
import 'package:nc_photos/db/entity_converter.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/entity/file/data_source2.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util;
import 'package:np_collection/np_collection.dart';
import 'package:np_common/or_null.dart';
import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat;
@ -10,9 +11,13 @@ import 'package:test/test.dart';
import '../../test_util.dart' as util;
void main() {
group("FileSqliteDbDataSource", () {
test("list", _list);
test("listSingle", _listSingle);
group("FileNpDbDataSource", () {
group("getFileDescriptors", () {
test("normal", _getFileDescriptors);
test("multiple account", _getFileDescriptorsMultipleAccount);
test("share folder", _getFileDescriptorsShareFolder);
test("extra share folder", _getFileDescriptorsExtraShareFolder);
});
group("remove", () {
test("file", _removeFile);
test("empty dir", _removeEmptyDir);
@ -28,14 +33,11 @@ void main() {
});
}
/// List a dir
/// Return files of an account
///
/// Files: admin/test1.jpg, admin/test/test2.jpg
/// List: admin
/// Expect: admin/test1.jpg
/// List: admin/test
/// Expect: admin/test/test2.jpg
Future<void> _list() async {
/// Expect: admin/test1.jpg, admin/test/test2.jpg
Future<void> _getFileDescriptors() async {
final account = util.buildAccount();
final files = (util.FilesBuilder()
..addDir("admin")
@ -55,17 +57,77 @@ Future<void> _list() async {
await util.insertDirRelation(c.sqliteDb, account, files[2], [files[3]]);
});
final src = FileSqliteDbDataSource(c);
expect(await src.list(account, files[0]), files.slice(0, 3));
expect(await src.list(account, files[2]), files.slice(2, 4));
final src = FileNpDbDataSource(c.npDb);
expect(
await src
.getFileDescriptors(account, file_util.unstripPath(account, ""))
.last,
[files[3].toDescriptor(), files[1].toDescriptor()],
);
}
/// List a single dir
/// Return files of an account
///
/// Expect: throw UnimplementedError
Future<void> _listSingle() async {
/// Files: admin/test1.jpg, admin/test/test2.jpg, user1/test3.jpg
/// Expect: admin/test1.jpg, admin/test/test2.jpg
Future<void> _getFileDescriptorsMultipleAccount() async {
final account = util.buildAccount();
final files = (util.FilesBuilder()..addDir("admin")).build();
final user1Account = util.buildAccount(userId: "user1");
final files = (util.FilesBuilder()
..addDir("admin")
..addJpeg("admin/test1.jpg")
..addDir("admin/test")
..addJpeg("admin/test/test2.jpg"))
.build();
final user1Files = (util.FilesBuilder(initialFileId: files.length)
..addDir("user1", ownerId: "user1")
..addJpeg("user1/test3.jpg"))
.build();
final c = DiContainer(
npDb: util.buildTestDb(),
);
addTearDown(() => c.sqliteDb.close());
await c.sqliteDb.transaction(() async {
await c.sqliteDb.insertAccounts([account.toDb()]);
await c.sqliteDb.insertAccounts([user1Account.toDb()]);
await util.insertFiles(c.sqliteDb, account, files);
await util.insertDirRelation(
c.sqliteDb, account, files[0], files.slice(1, 3));
await util.insertDirRelation(c.sqliteDb, account, files[2], [files[3]]);
await util.insertFiles(c.sqliteDb, user1Account, user1Files);
await util.insertDirRelation(
c.sqliteDb, user1Account, user1Files[0], [user1Files[1]]);
});
final src = FileNpDbDataSource(c.npDb);
expect(
await src
.getFileDescriptors(account, file_util.unstripPath(account, ""))
.last,
[files[3].toDescriptor(), files[1].toDescriptor()],
);
expect(
await src
.getFileDescriptors(
user1Account, file_util.unstripPath(user1Account, ""))
.last,
[user1Files[1].toDescriptor()],
);
}
/// Return files of an account
///
/// Files: admin/test1/test1.jpg, admin/test2/test2.jpg
/// Expect: admin/test1/test1.jpg
Future<void> _getFileDescriptorsShareFolder() async {
final account = util.buildAccount(roots: ["test1"]);
final files = (util.FilesBuilder()
..addDir("admin")
..addDir("admin/test1")
..addJpeg("admin/test1/test1.jpg")
..addDir("admin/test2")
..addJpeg("admin/test2/test2.jpg"))
.build();
final c = DiContainer(
npDb: util.buildTestDb(),
);
@ -73,12 +135,54 @@ Future<void> _listSingle() async {
await c.sqliteDb.transaction(() async {
await c.sqliteDb.insertAccounts([account.toDb()]);
await util.insertFiles(c.sqliteDb, account, files);
await util.insertDirRelation(c.sqliteDb, account, files[0], const []);
await util
.insertDirRelation(c.sqliteDb, account, files[0], [files[1], files[3]]);
await util.insertDirRelation(c.sqliteDb, account, files[1], [files[2]]);
await util.insertDirRelation(c.sqliteDb, account, files[3], [files[4]]);
});
final src = FileSqliteDbDataSource(c);
expect(() async => await src.listSingle(account, files[0]),
throwsUnimplementedError);
final src = FileNpDbDataSource(c.npDb);
expect(
await src
.getFileDescriptors(account, file_util.unstripPath(account, "test1"))
.last,
[files[2].toDescriptor()],
);
}
/// Return files of an account
///
/// Files: admin/test1/test1.jpg, admin/test2/test2.jpg
/// Expect: admin/test1/test1.jpg, admin/test2/test2.jpg
Future<void> _getFileDescriptorsExtraShareFolder() async {
final account = util.buildAccount(roots: ["test1"]);
final files = (util.FilesBuilder()
..addDir("admin")
..addDir("admin/test1")
..addJpeg("admin/test1/test1.jpg")
..addDir("admin/test2")
..addJpeg("admin/test2/test2.jpg"))
.build();
final c = DiContainer(
npDb: util.buildTestDb(),
);
addTearDown(() => c.sqliteDb.close());
await c.sqliteDb.transaction(() async {
await c.sqliteDb.insertAccounts([account.toDb()]);
await util.insertFiles(c.sqliteDb, account, files);
await util
.insertDirRelation(c.sqliteDb, account, files[0], [files[1], files[3]]);
await util.insertDirRelation(c.sqliteDb, account, files[1], [files[2]]);
await util.insertDirRelation(c.sqliteDb, account, files[3], [files[4]]);
});
final src = FileNpDbDataSource(c.npDb);
expect(
await src
.getFileDescriptors(account, file_util.unstripPath(account, "test2"))
.last,
[files[2].toDescriptor(), files[4].toDescriptor()],
);
}
/// Remove a file
@ -100,7 +204,7 @@ Future<void> _removeFile() async {
await util.insertDirRelation(c.sqliteDb, account, files[0], [files[1]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.remove(account, files[1]);
expect(
await util.listSqliteDbFiles(c.sqliteDb),
@ -128,7 +232,7 @@ Future<void> _removeEmptyDir() async {
await util.insertDirRelation(c.sqliteDb, account, files[1], const []);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.remove(account, files[1]);
// parent dir is not updated, parent dir is only updated when syncing with
// remote
@ -161,7 +265,7 @@ Future<void> _removeDir() async {
await util.insertDirRelation(c.sqliteDb, account, files[1], [files[2]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.remove(account, files[1]);
expect(
await util.listSqliteDbFiles(c.sqliteDb),
@ -192,7 +296,7 @@ Future<void> _removeDirWithSubDir() async {
await util.insertDirRelation(c.sqliteDb, account, files[2], [files[3]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.remove(account, files[1]);
expect(
await util.listSqliteDbDirs(c.sqliteDb),
@ -225,7 +329,7 @@ Future<void> _updateFileProperty() async {
await util.insertDirRelation(c.sqliteDb, account, files[0], [files[1]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.updateProperty(
account,
files[1],
@ -267,7 +371,7 @@ Future<void> _updateMetadata() async {
await util.insertDirRelation(c.sqliteDb, account, files[0], [files[1]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.updateProperty(
account,
files[1],
@ -309,7 +413,7 @@ Future<void> _updateAddMetadata() async {
await util.insertDirRelation(c.sqliteDb, account, files[0], [files[1]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.updateProperty(
account,
files[1],
@ -355,7 +459,7 @@ Future<void> _updateDeleteMetadata() async {
await util.insertDirRelation(c.sqliteDb, account, files[0], [files[1]]);
});
final src = FileSqliteDbDataSource(c);
final src = FileNpDbDataSource(c.npDb);
await src.updateProperty(
account,
files[1],

View file

@ -12,6 +12,7 @@ import 'package:nc_photos/entity/face_recognition_person/repo.dart';
import 'package:nc_photos/entity/favorite.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/entity/file/repo.dart';
import 'package:nc_photos/entity/file_descriptor.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util;
import 'package:nc_photos/entity/share.dart';
@ -303,6 +304,72 @@ class MockFileMemoryRepo extends FileRepo {
}
}
class MockFileDataSource2 implements FileDataSource2 {
@override
Stream<List<FileDescriptor>> getFileDescriptors(
Account account, String shareDirPath) {
throw UnimplementedError();
}
@override
Future<void> remove(Account account, FileDescriptor f) {
throw UnimplementedError();
}
@override
Future<void> updateProperty(
Account account,
FileDescriptor f, {
OrNull<Metadata>? metadata,
OrNull<bool>? isArchived,
OrNull<DateTime>? overrideDateTime,
bool? favorite,
OrNull<ImageLocation>? location,
}) {
throw UnimplementedError();
}
}
class MockFileMemoryDataSource2 extends MockFileDataSource2 {
MockFileMemoryDataSource2([
List<FileDescriptor> initialData = const [],
]) : files = initialData.map((f) => f.copyWith()).toList();
@override
Stream<List<FileDescriptor>> getFileDescriptors(
Account account, String shareDirPath) async* {
yield files.where((f) {
if (account.roots.any((r) => file_util.isOrUnderDirPath(
f.fdPath, file_util.unstripPath(account, r)))) {
return true;
} else if (file_util.isOrUnderDirPath(
f.fdPath, file_util.unstripPath(account, shareDirPath))) {
return true;
} else {
return false;
}
}).toList();
}
@override
Future<void> remove(Account account, FileDescriptor file) async {
files.removeWhere((f) => f.compareServerIdentity(file));
}
final List<FileDescriptor> files;
}
/// [FileRepo2] mock that support some ops with an internal List
class MockFileMemoryRepo2 extends BasicFileRepo {
MockFileMemoryRepo2([
List<FileDescriptor> initialData = const [],
]) : super(MockFileMemoryDataSource2(initialData));
List<FileDescriptor> get files {
return (dataSrc as MockFileMemoryDataSource2).files;
}
}
/// Mock of [ShareRepo] where all methods will throw UnimplementedError
class MockShareRepo implements ShareRepo {
@override
@ -489,6 +556,7 @@ class MockFaceRecognitionPersonMemoryRepo
extension MockDiContainerExtension on DiContainer {
MockAlbumMemoryRepo get albumMemoryRepo => albumRepo as MockAlbumMemoryRepo;
MockFileMemoryRepo get fileMemoryRepo => fileRepo as MockFileMemoryRepo;
MockFileMemoryRepo2 get fileMemoryRepo2 => fileRepo2 as MockFileMemoryRepo2;
MockShareMemoryRepo get shareMemoryRepo => shareRepo as MockShareMemoryRepo;
MockShareeMemoryRepo get shareeMemoryRepo =>
shareeRepo as MockShareeMemoryRepo;

View file

@ -317,7 +317,7 @@ void initLog() {
}
Account buildAccount({
String id = "123456-000000",
String? id,
String scheme = "http",
String address = "example.com",
String userId = "admin",
@ -326,7 +326,7 @@ Account buildAccount({
List<String> roots = const [""],
}) =>
Account(
id: id,
id: id ?? "$userId-000000",
scheme: scheme,
address: address,
userId: userId.toCi(),

View file

@ -2,6 +2,7 @@ import 'package:event_bus/event_bus.dart';
import 'package:kiwi/kiwi.dart';
import 'package:nc_photos/db/entity_converter.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/entity/pref/provider/memory.dart';
import 'package:nc_photos/use_case/album/remove_album.dart';
@ -36,6 +37,7 @@ Future<void> _removeAlbum() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo([album1, album2]),
fileRepo: MockFileMemoryRepo([albumFile1, albumFile2]),
fileRepo2: MockFileMemoryRepo2([albumFile1, albumFile2]),
shareRepo: MockShareRepo(),
npDb: util.buildTestDb(),
pref: Pref.scoped(PrefMemoryProvider()),
@ -44,7 +46,7 @@ Future<void> _removeAlbum() async {
await RemoveAlbum(c)(
account, c.albumMemoryRepo.findAlbumByPath(albumFile1.path));
expect(c.fileMemoryRepo.files, [albumFile2]);
expect(c.fileMemoryRepo2.files, [albumFile2.toDescriptor()]);
}
/// Remove a shared album (admin -> user1)
@ -64,6 +66,7 @@ Future<void> _removeSharedAlbum() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo([album]),
fileRepo: MockFileMemoryRepo([albumFile, ...files]),
fileRepo2: MockFileMemoryRepo2([albumFile, ...files]),
shareRepo: MockShareMemoryRepo([
util.buildShare(id: "0", file: albumFile, shareWith: "user1"),
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
@ -77,7 +80,7 @@ Future<void> _removeSharedAlbum() async {
await RemoveAlbum(c)(
account, c.albumMemoryRepo.findAlbumByPath(albumFile.path));
expect(c.fileMemoryRepo.files, [files[0]]);
expect(c.fileMemoryRepo2.files, [files[0].toDescriptor()]);
expect(c.shareMemoryRepo.shares, const []);
}
@ -105,6 +108,7 @@ Future<void> _removeSharedAlbumFileInOtherAlbum() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo(albums),
fileRepo: MockFileMemoryRepo([...albumFiles, ...files]),
fileRepo2: MockFileMemoryRepo2([...albumFiles, ...files]),
shareRepo: MockShareMemoryRepo([
util.buildShare(id: "0", file: albumFiles[0], shareWith: "user1"),
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
@ -119,7 +123,10 @@ Future<void> _removeSharedAlbumFileInOtherAlbum() async {
await RemoveAlbum(c)(
account, c.albumMemoryRepo.findAlbumByPath(albumFiles[0].path));
expect(c.fileMemoryRepo.files, [albumFiles[1], files[0]]);
expect(
c.fileMemoryRepo2.files,
[albumFiles[1].toDescriptor(), files[0].toDescriptor()],
);
expect(c.shareMemoryRepo.shares, [
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
util.buildShare(id: "2", file: albumFiles[1], shareWith: "user1"),
@ -147,6 +154,7 @@ Future<void> _removeSharedAlbumResyncedFile() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo([album]),
fileRepo: MockFileMemoryRepo([albumFile, ...files, ...user1Files]),
fileRepo2: MockFileMemoryRepo2([albumFile, ...files, ...user1Files]),
shareRepo: MockShareMemoryRepo([
util.buildShare(id: "0", file: albumFile, shareWith: "user1"),
util.buildShare(id: "1", file: files[0], shareWith: "user1"),
@ -167,6 +175,9 @@ Future<void> _removeSharedAlbumResyncedFile() async {
await RemoveAlbum(c)(
account, c.albumMemoryRepo.findAlbumByPath(albumFile.path));
expect(c.fileMemoryRepo.files, [...files, ...user1Files]);
expect(
c.fileMemoryRepo2.files,
[...files, ...user1Files].map((e) => e.toDescriptor()),
);
expect(c.shareMemoryRepo.shares, []);
}

View file

@ -6,6 +6,7 @@ import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/album/cover_provider.dart';
import 'package:nc_photos/entity/album/provider.dart';
import 'package:nc_photos/entity/album/sort_provider.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/entity/pref/provider/memory.dart';
import 'package:nc_photos/use_case/remove.dart';
@ -46,6 +47,7 @@ Future<void> _removeFile() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo(),
fileRepo: MockFileMemoryRepo(files),
fileRepo2: MockFileMemoryRepo2(files),
shareRepo: MockShareMemoryRepo(),
npDb: util.buildTestDb(),
pref: Pref.scoped(PrefMemoryProvider()),
@ -57,7 +59,7 @@ Future<void> _removeFile() async {
});
await Remove(c)(account, [files[0]]);
expect(c.fileMemoryRepo.files, [files[1]]);
expect(c.fileMemoryRepo2.files, [files[1].toDescriptor()]);
}
/// Remove a file, skip clean up
@ -72,6 +74,7 @@ Future<void> _removeFileNoCleanUp() async {
final c = DiContainer(
albumRepo: MockAlbumMemoryRepo(),
fileRepo: MockFileMemoryRepo(files),
fileRepo2: MockFileMemoryRepo2(files),
shareRepo: MockShareMemoryRepo(),
npDb: util.buildTestDb(),
pref: Pref.scoped(PrefMemoryProvider()),
@ -83,7 +86,7 @@ Future<void> _removeFileNoCleanUp() async {
});
await Remove(c)(account, [files[0]], shouldCleanUp: false);
expect(c.fileMemoryRepo.files, [files[1]]);
expect(c.fileMemoryRepo2.files, [files[1].toDescriptor()]);
}
/// Remove a file included in an album