per-containder indexing opt out
This commit is contained in:
@@ -16,6 +16,7 @@ import 'schema_v10.dart' as v10;
|
||||
import 'schema_v11.dart' as v11;
|
||||
import 'schema_v12.dart' as v12;
|
||||
import 'schema_v13.dart' as v13;
|
||||
import 'schema_v14.dart' as v14;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
@@ -45,10 +46,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
return v12.DatabaseAtV12(db);
|
||||
case 13:
|
||||
return v13.DatabaseAtV13(db);
|
||||
case 14:
|
||||
return v14.DatabaseAtV14(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
||||
static const versions = const [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,257 @@
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:weblibre/data/database/functions/lexo_rank_functions.dart';
|
||||
import 'package:weblibre/data/database/functions/url_functions.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.dart';
|
||||
|
||||
void main() {
|
||||
late TabDatabase db;
|
||||
|
||||
setUp(() async {
|
||||
db = TabDatabase(
|
||||
NativeDatabase.memory(
|
||||
setup: (database) {
|
||||
registerLexorankFunctions(database);
|
||||
registerUrlFunctions(database);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
await db.customStatement(
|
||||
'INSERT INTO local_index_setting ("key", value) '
|
||||
"VALUES ('enabled', 1), ('index_private', 0)",
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test(
|
||||
'container exclude flag re-evaluates existing tab history rows',
|
||||
() async {
|
||||
await _insertContainer(db, 'container', excludeFromIndex: false);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'tab',
|
||||
containerId: 'container',
|
||||
url: 'https://example.com/page',
|
||||
title: 'Visible title',
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), ['Visible title']);
|
||||
|
||||
await _updateContainerExclude(db, 'container', excludeFromIndex: true);
|
||||
|
||||
expect(await _historyTitles(db), isEmpty);
|
||||
|
||||
await _updateContainerExclude(db, 'container', excludeFromIndex: false);
|
||||
|
||||
expect(await _historyTitles(db), ['Visible title']);
|
||||
},
|
||||
);
|
||||
|
||||
test('tab container assignment re-evaluates existing history rows', () async {
|
||||
await _insertContainer(db, 'allowed', excludeFromIndex: false);
|
||||
await _insertContainer(db, 'excluded', excludeFromIndex: true);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'tab',
|
||||
containerId: 'excluded',
|
||||
url: 'https://example.com/moved',
|
||||
title: 'Moved title',
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), isEmpty);
|
||||
|
||||
await db.customStatement(
|
||||
"UPDATE tab SET container_id = 'allowed' WHERE id = 'tab'",
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), ['Moved title']);
|
||||
|
||||
await db.customStatement(
|
||||
"UPDATE tab SET container_id = 'excluded' WHERE id = 'tab'",
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), isEmpty);
|
||||
});
|
||||
|
||||
test(
|
||||
'excluding one container preserves duplicate URLs from allowed tabs',
|
||||
() async {
|
||||
await _insertContainer(db, 'allowed', excludeFromIndex: false);
|
||||
await _insertContainer(db, 'excluded', excludeFromIndex: false);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'allowed-tab',
|
||||
containerId: 'allowed',
|
||||
url: 'https://example.com/shared',
|
||||
title: 'Allowed title',
|
||||
timestamp: 1,
|
||||
);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'excluded-tab',
|
||||
containerId: 'excluded',
|
||||
url: 'https://example.com/shared',
|
||||
title: 'Excluded title',
|
||||
timestamp: 2,
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), ['Excluded title']);
|
||||
|
||||
await _updateContainerExclude(db, 'excluded', excludeFromIndex: true);
|
||||
|
||||
expect(await _historyTitles(db), ['Allowed title']);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'container exclude re-evaluation refreshes recency for same-hash duplicate URLs',
|
||||
() async {
|
||||
await _insertContainer(db, 'allowed', excludeFromIndex: false);
|
||||
await _insertContainer(db, 'later-excluded', excludeFromIndex: false);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'later-excluded-tab',
|
||||
containerId: 'later-excluded',
|
||||
url: 'https://example.com/same-hash',
|
||||
title: 'Shared title',
|
||||
timestamp: 1,
|
||||
);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'allowed-tab',
|
||||
containerId: 'allowed',
|
||||
url: 'https://example.com/same-hash',
|
||||
title: 'Shared title',
|
||||
timestamp: 2,
|
||||
);
|
||||
|
||||
await _setAllHistoryObservedAt(db, 1);
|
||||
expect(await _historyObservedAt(db), 1);
|
||||
|
||||
await _updateContainerExclude(
|
||||
db,
|
||||
'later-excluded',
|
||||
excludeFromIndex: true,
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), ['Shared title']);
|
||||
expect(await _historyObservedAt(db), greaterThan(1));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'container move re-evaluation refreshes recency for same-hash duplicate URLs',
|
||||
() async {
|
||||
await _insertContainer(db, 'allowed-a', excludeFromIndex: false);
|
||||
await _insertContainer(db, 'allowed-b', excludeFromIndex: false);
|
||||
await _insertContainer(db, 'excluded', excludeFromIndex: true);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'moving-tab',
|
||||
containerId: 'allowed-a',
|
||||
url: 'https://example.com/move-same-hash',
|
||||
title: 'Shared move title',
|
||||
timestamp: 1,
|
||||
);
|
||||
await _insertTab(
|
||||
db,
|
||||
id: 'fallback-tab',
|
||||
containerId: 'allowed-b',
|
||||
url: 'https://example.com/move-same-hash',
|
||||
title: 'Shared move title',
|
||||
timestamp: 2,
|
||||
);
|
||||
|
||||
await _setAllHistoryObservedAt(db, 1);
|
||||
expect(await _historyObservedAt(db), 1);
|
||||
|
||||
await db.customStatement(
|
||||
"UPDATE tab SET container_id = 'excluded' WHERE id = 'moving-tab'",
|
||||
);
|
||||
|
||||
expect(await _historyTitles(db), ['Shared move title']);
|
||||
expect(await _historyObservedAt(db), greaterThan(1));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _insertContainer(
|
||||
TabDatabase db,
|
||||
String id, {
|
||||
required bool excludeFromIndex,
|
||||
}) {
|
||||
return db.customStatement(
|
||||
'INSERT INTO container (id, color, order_key, is_pinned, metadata) '
|
||||
"VALUES (?, 0, ?, 0, ?)",
|
||||
[id, id, '{"excludeFromIndex":$excludeFromIndex}'],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _updateContainerExclude(
|
||||
TabDatabase db,
|
||||
String id, {
|
||||
required bool excludeFromIndex,
|
||||
}) {
|
||||
return db.customStatement('UPDATE container SET metadata = ? WHERE id = ?', [
|
||||
'{"excludeFromIndex":$excludeFromIndex}',
|
||||
id,
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> _insertTab(
|
||||
TabDatabase db, {
|
||||
required String id,
|
||||
required String containerId,
|
||||
required String url,
|
||||
required String title,
|
||||
int timestamp = 1,
|
||||
}) {
|
||||
return db.customStatement(
|
||||
'INSERT INTO tab (id, source, container_id, order_key, url, title, '
|
||||
'extracted_content_plain, full_content_plain, timestamp) '
|
||||
'VALUES (?, 2, ?, ?, ?, ?, ?, ?, ?)',
|
||||
[
|
||||
id,
|
||||
containerId,
|
||||
id,
|
||||
url,
|
||||
title,
|
||||
'$title extracted content',
|
||||
'$title full content',
|
||||
timestamp,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<String?>> _historyTitles(TabDatabase db) async {
|
||||
final rows = await db
|
||||
.customSelect(
|
||||
'SELECT title FROM history ORDER BY url_canonical',
|
||||
readsFrom: {db.history},
|
||||
)
|
||||
.get();
|
||||
|
||||
return [for (final row in rows) row.read<String?>('title')];
|
||||
}
|
||||
|
||||
Future<void> _setAllHistoryObservedAt(TabDatabase db, int observedAt) {
|
||||
return db.customStatement('UPDATE history SET observed_at = ?', [observedAt]);
|
||||
}
|
||||
|
||||
Future<int?> _historyObservedAt(TabDatabase db) async {
|
||||
final row = await db
|
||||
.customSelect(
|
||||
'SELECT CAST(observed_at AS INTEGER) AS observed_at '
|
||||
'FROM history '
|
||||
'ORDER BY url_canonical '
|
||||
'LIMIT 1',
|
||||
readsFrom: {db.history},
|
||||
)
|
||||
.getSingleOrNull();
|
||||
|
||||
return row?.read<int>('observed_at');
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
// ignore_for_file: unused_local_variable, unused_import
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_dev/api/migrations_native.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:weblibre/data/database/functions/url_functions.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.dart';
|
||||
import 'generated/schema.dart';
|
||||
|
||||
import 'generated/schema_v2.dart' as v2;
|
||||
@@ -14,7 +15,7 @@ void main() {
|
||||
late SchemaVerifier verifier;
|
||||
|
||||
setUpAll(() {
|
||||
verifier = SchemaVerifier(GeneratedHelper());
|
||||
verifier = SchemaVerifier(GeneratedHelper(), setup: registerUrlFunctions);
|
||||
});
|
||||
|
||||
group('simple database migrations', () {
|
||||
|
||||
Reference in New Issue
Block a user