From 60edf1a13aeb181389ce7c5cd48154968b412ffc Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Wed, 7 Aug 2019 15:49:41 +0200 Subject: [PATCH] Migrate listing tests. --- app/lib/search/updater.dart | 14 ++ app/test/frontend/handlers/listing_test.dart | 97 +++----- app/test/frontend/mocks.dart | 238 ------------------- app/test/shared/test_services.dart | 11 +- 4 files changed, 54 insertions(+), 306 deletions(-) diff --git a/app/lib/search/updater.dart b/app/lib/search/updater.dart index d7a15c1596..67a4095372 100644 --- a/app/lib/search/updater.dart +++ b/app/lib/search/updater.dart @@ -9,8 +9,10 @@ import 'package:_discoveryapis_commons/_discoveryapis_commons.dart' import 'package:gcloud/db.dart'; import 'package:gcloud/service_scope.dart' as ss; import 'package:logging/logging.dart'; +import 'package:meta/meta.dart'; import '../dartdoc/backend.dart'; +import '../frontend/models.dart' show Package; import '../shared/exceptions.dart'; import '../shared/scheduler_stats.dart'; import '../shared/task_scheduler.dart'; @@ -57,6 +59,18 @@ class IndexUpdater implements TaskRunner { } } + /// Updates all packages in the index. + /// It is slower than searchBackend.loadMinimumPackageIndex, but provides a + /// complete document for the index. + @visibleForTesting + Future updateAllPackages() async { + await for (final p in _db.query().run()) { + final doc = await searchBackend.loadDocument(p.name); + await packageIndex.addPackage(doc); + } + await packageIndex.merge(); + } + Future _initSnapshot() async { if (_snapshot != null) return; try { diff --git a/app/test/frontend/handlers/listing_test.dart b/app/test/frontend/handlers/listing_test.dart index 9bb105bf56..c21f269c46 100644 --- a/app/test/frontend/handlers/listing_test.dart +++ b/app/test/frontend/handlers/listing_test.dart @@ -2,22 +2,19 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:gcloud/db.dart'; import 'package:http/testing.dart'; import 'package:test/test.dart'; import 'package:pub_dartlang_org/frontend/backend.dart'; -import 'package:pub_dartlang_org/frontend/models.dart'; import 'package:pub_dartlang_org/frontend/name_tracker.dart'; -import 'package:pub_dartlang_org/frontend/search_service.dart'; import 'package:pub_dartlang_org/frontend/static_files.dart'; -import 'package:pub_dartlang_org/shared/analyzer_client.dart'; -import 'package:pub_dartlang_org/shared/search_service.dart'; import 'package:pub_dartlang_org/shared/search_client.dart'; +import 'package:pub_dartlang_org/search/updater.dart'; import '../../shared/handlers_test_utils.dart'; import '../../shared/test_models.dart'; import '../../shared/test_services.dart'; -import '../mocks.dart'; import '_utils.dart'; @@ -89,34 +86,21 @@ void main() { expect(content, contains('helium is a Dart package')); }); - tScopedTest('/packages?page=2', () async { - registerSearchService(SearchServiceMock( - (SearchQuery query) { - expect(query.offset, 10); - expect(query.limit, pageSize); - expect(query.platform, isNull); - expect(query.isAd, isFalse); - return SearchResultPage(query, 1, [ - PackageView.fromModel( - package: foobarPackage, - version: foobarStablePV, - scoreCard: null) - ]); - }, - )); - final backend = BackendMock( - lookupPackageFun: (packageName) { - return packageName == foobarPackage.name ? foobarPackage : null; - }, - lookupLatestVersionsFun: (List packages) { - expect(packages.length, 1); - expect(packages.first, foobarPackage); - return [foobarStablePV]; - }, + testWithServices('/packages?page=2', () async { + for (int i = 0; i < 15; i++) { + final bundle = generateBundle('pkg$i', ['1.0.0']); + await dbService.commit(inserts: [bundle.package, ...bundle.versions]); + } + await indexUpdater.updateAllPackages(); + + final names = ['pkg0', 'pkg3', 'pkg10']; + final list = await backend.latestPackageVersions(offset: 10); + expect(list.map((p) => p.package).toList(), containsAll(names)); + + await expectHtmlResponse( + await issueGet('/packages?page=2'), + present: names.map((name) => '/packages/$name').toList(), ); - registerBackend(backend); - registerAnalyzerClient(AnalyzerClientMock()); - await expectHtmlResponse(await issueGet('/packages?page=2')); }); testWithServices('/flutter/packages', () async { @@ -135,34 +119,29 @@ void main() { ); }); - tScopedTest('/flutter/packages&page=2', () async { - registerSearchService(SearchServiceMock( - (SearchQuery query) { - expect(query.offset, 10); - expect(query.limit, pageSize); - expect(query.platform, 'flutter'); - expect(query.isAd, isFalse); - return SearchResultPage(query, 1, [ - PackageView.fromModel( - package: foobarPackage, - version: foobarStablePV, - scoreCard: null) - ]); - }, + testWithServices('/flutter/packages&page=2', () async { + for (int i = 0; i < 15; i++) { + final bundle = generateBundle( + 'pkg$i', + ['1.0.0'], + pubspecExtraContent: ''' +flutter: + plugin: + class: SomeClass +''', + ); + await dbService.commit(inserts: [bundle.package, ...bundle.versions]); + } + await indexUpdater.updateAllPackages(); + + final names = ['pkg0', 'pkg3', 'pkg10']; + final list = await backend.latestPackageVersions(offset: 10); + expect(list.map((p) => p.package).toList(), containsAll(names)); + + print(await expectHtmlResponse( + await issueGet('/packages?page=2'), + present: names.map((name) => '/packages/$name').toList(), )); - final backend = BackendMock( - lookupPackageFun: (packageName) { - return packageName == foobarPackage.name ? foobarPackage : null; - }, - lookupLatestVersionsFun: (List packages) { - expect(packages.length, 1); - expect(packages.first, foobarPackage); - return [foobarStablePV]; - }, - ); - registerBackend(backend); - registerAnalyzerClient(AnalyzerClientMock()); - await expectHtmlResponse(await issueGet('/flutter/packages?page=2')); }); }); } diff --git a/app/test/frontend/mocks.dart b/app/test/frontend/mocks.dart index beebaf2446..2b220c5fb8 100644 --- a/app/test/frontend/mocks.dart +++ b/app/test/frontend/mocks.dart @@ -2,232 +2,9 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:client_data/package_api.dart'; import 'package:pub_dartlang_org/dartdoc/models.dart'; -import 'package:pub_dartlang_org/frontend/backend.dart'; -import 'package:pub_dartlang_org/frontend/models.dart'; -import 'package:pub_dartlang_org/frontend/search_service.dart'; -import 'package:pub_dartlang_org/scorecard/backend.dart'; -import 'package:pub_dartlang_org/scorecard/models.dart'; import 'package:pub_dartlang_org/shared/analyzer_client.dart'; import 'package:pub_dartlang_org/shared/dartdoc_client.dart'; -import 'package:pub_dartlang_org/shared/search_service.dart'; -import 'package:pub_server/shelf_pubserver.dart' show ShelfPubServer; - -class BackendMock implements Backend { - final Function newestPackagesFun; - final Function latestPackageVersionsFun; - final Function latestPackagesFun; - final Function lookupLatestVersionsFun; - final Function lookupPackageFun; - final Function lookupPackageVersionFun; - final Function versionsOfPackageFun; - final Function downloadUrlFun; - final Function updatePackageInviteFn; - - BackendMock({ - this.newestPackagesFun, - this.latestPackageVersionsFun, - this.latestPackagesFun, - this.lookupLatestVersionsFun, - this.lookupPackageFun, - this.lookupPackageVersionFun, - this.versionsOfPackageFun, - this.downloadUrlFun, - this.updatePackageInviteFn, - }); - - @override - ShelfPubServer get pubServer => - throw Exception('unexpected pubServer access'); - - @override - // ignore: always_declare_return_types - get db => throw Exception('unexpected db access'); - - @override - // ignore: always_declare_return_types - get repository => throw Exception('unexpected repository access'); - - @override - Future> newestPackages({int offset, int limit}) async { - if (newestPackagesFun == null) { - throw Exception('no newestPackagesFun'); - } - return ((await newestPackagesFun(offset: offset, limit: limit)) as List) - .cast(); - } - - @override - Stream allPackageNames( - {DateTime updatedSince, bool excludeDiscontinued = false}) { - throw UnsupportedError('sorry!'); - } - - @override - Future> latestPackageVersions( - {int offset, int limit}) async { - if (latestPackageVersionsFun == null) { - throw Exception('no latestPackageVersionsFun'); - } - return ((await latestPackageVersionsFun(offset: offset, limit: limit)) - as List) - .cast(); - } - - @override - Future> latestPackages( - {int offset, int limit, String detectedType}) async { - if (latestPackagesFun == null) { - throw Exception('no latestPackagesFun'); - } - return ((await latestPackagesFun( - offset: offset, limit: limit, detectedType: detectedType)) as List) - .cast(); - } - - @override - Future> lookupLatestVersions( - List packages) async { - if (lookupLatestVersionsFun == null) { - throw Exception('no lookupLatestVersionsFun'); - } - return ((await lookupLatestVersionsFun(packages)) as List) - .cast(); - } - - @override - Future lookupPackage(String packageName) async { - if (lookupPackageFun == null) { - throw Exception('no lookupPackageFun'); - } - return (await lookupPackageFun(packageName)) as Package; - } - - @override - Future> lookupPackages(Iterable packageNames) async { - return (await Future.wait(packageNames.map(lookupPackage))).toList(); - } - - @override - Future lookupPackageVersion( - String package, String version) async { - if (lookupPackageVersionFun == null) { - throw Exception('no lookupPackageVersionFun'); - } - return (await lookupPackageVersionFun(package, version)) as PackageVersion; - } - - @override - Future> versionsOfPackage(String packageName) async { - if (versionsOfPackageFun == null) { - throw Exception('no versionsOfPackageFun'); - } - return ((await versionsOfPackageFun(packageName)) as List) - .cast(); - } - - @override - Future downloadUrl(String package, String version) async { - if (downloadUrlFun == null) { - throw Exception('no downloadUrlFun'); - } - return (await downloadUrlFun(package, version)) as Uri; - } - - @override - Future getPackageInvite({ - String packageName, - String type, - String recipientEmail, - String urlNonce, - }) { - throw UnimplementedError(); - } - - @override - Future confirmPackageInvite(PackageInvite invite) { - throw UnimplementedError(); - } - - @override - Future updatePackageInvite({ - String packageName, - String type, - String recipientEmail, - String fromUserId, - String fromEmail, - }) async { - if (updatePackageInviteFn == null) { - throw Exception('no downloadUrlFun'); - } - return (await updatePackageInviteFn( - packageName: packageName, - type: type, - recipientEmail: recipientEmail, - fromUserId: fromUserId, - fromEmail: fromEmail, - )) as InviteStatus; - } - - @override - Future deleteObsoleteInvites() { - throw UnimplementedError(); - } - - @override - Future updateOptions(String package, PkgOptions options) { - throw UnimplementedError(); - } -} - -class ScoreCardBackendMock implements ScoreCardBackend { - @override - Future getScoreCardData( - String packageName, String packageVersion, - {bool onlyCurrent = false}) async { - return null; - } - - @override - Future getPackageStatus(String package, String version) { - throw UnimplementedError(); - } - - @override - Future deleteOldEntries() { - throw UnimplementedError(); - } - - @override - Future> loadReports( - String packageName, String packageVersion, - {List reportTypes, String runtimeVersion}) { - throw UnimplementedError(); - } - - @override - Future shouldUpdateReport( - String packageName, String packageVersion, String reportType, - {bool includeDiscontinued = false, - bool includeObsolete = false, - Duration successThreshold = const Duration(days: 30), - Duration failureThreshold = const Duration(days: 1), - DateTime updatedAfter}) { - throw UnimplementedError(); - } - - @override - Future updateReport( - String packageName, String packageVersion, ReportData data) { - throw UnimplementedError(); - } - - @override - Future updateScoreCard(String packageName, String packageVersion) { - throw UnimplementedError(); - } -} class AnalyzerClientMock implements AnalyzerClient { AnalysisView mockAnalysisView; @@ -267,18 +44,3 @@ class DartdocClientMock implements DartdocClient { return null; } } - -class SearchServiceMock implements SearchService { - final Function searchFun; - - SearchServiceMock(this.searchFun); - - @override - Future search(SearchQuery query, - {bool fallbackToNames = true}) async { - return (await searchFun(query)) as SearchResultPage; - } - - @override - Future close() async => null; -} diff --git a/app/test/shared/test_services.dart b/app/test/shared/test_services.dart index d87a12fcd1..4630d1b5be 100644 --- a/app/test/shared/test_services.dart +++ b/app/test/shared/test_services.dart @@ -17,9 +17,9 @@ import 'package:pub_dartlang_org/account/testing/fake_auth_provider.dart'; import 'package:pub_dartlang_org/frontend/handlers.dart'; import 'package:pub_dartlang_org/frontend/handlers/pubapi.client.dart'; import 'package:pub_dartlang_org/scorecard/backend.dart'; -import 'package:pub_dartlang_org/search/backend.dart'; import 'package:pub_dartlang_org/search/handlers.dart'; import 'package:pub_dartlang_org/search/index_simple.dart'; +import 'package:pub_dartlang_org/search/updater.dart'; import 'package:pub_dartlang_org/shared/configuration.dart'; import 'package:pub_dartlang_org/shared/handler_helpers.dart'; import 'package:pub_dartlang_org/shared/popularity_storage.dart'; @@ -80,14 +80,7 @@ void testWithServices(String name, Future fn()) { AccountBackend(db, authProvider: FakeAuthProvider())); await dartSdkIndex.merge(); - - packageIndex.addPackage( - await searchBackend.loadDocument(hydrogen.package.name)); - packageIndex.addPackage( - await searchBackend.loadDocument(helium.package.name)); - packageIndex.addPackage( - await searchBackend.loadDocument(lithium.package.name)); - await packageIndex.merge(); + await indexUpdater.updateAllPackages(); registerSearchClient( SearchClient(_httpClient(handler: searchServiceHandler)));