diff --git a/analysis_options.yaml b/analysis_options.yaml index c2c9d51e3f..d809773723 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -12,6 +12,7 @@ analyzer: avoid_dynamic_calls: ignore comment_references: ignore deprecated_member_use_from_same_package: ignore + duplicate_ignore: ignore lines_longer_than_80_chars: ignore only_throw_errors: ignore exclude: diff --git a/app_dart/bin/gae_server.dart b/app_dart/bin/gae_server.dart index 28575c5ab7..ac93aac6de 100644 --- a/app_dart/bin/gae_server.dart +++ b/app_dart/bin/gae_server.dart @@ -9,7 +9,8 @@ import 'package:cocoon_server/google_auth_provider.dart'; import 'package:cocoon_server/secret_manager.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/server.dart'; -import 'package:cocoon_service/src/request_handling/dashboard_authentication.dart'; +import 'package:cocoon_service/src/foundation/appengine_utils.dart'; +import 'package:cocoon_service/src/foundation/providers.dart'; import 'package:cocoon_service/src/service/big_query.dart'; import 'package:cocoon_service/src/service/build_status_service.dart'; import 'package:cocoon_service/src/service/commit_service.dart'; @@ -24,6 +25,8 @@ Future main() async { await withAppEngineServices(() async { useLoggingPackageAdaptor(); + Providers.contextProvider = () => AppEngineClientContext(context); + // This is bad, and I should feel bad, but I won't because the logging system // is inherently bad. We're allocating the logger (or getting back one) and // then turning it off - there is no way to "filter". Luckily; the library diff --git a/app_dart/lib/cocoon_service.dart b/app_dart/lib/cocoon_service.dart index 245ddd83c4..27214df51c 100644 --- a/app_dart/lib/cocoon_service.dart +++ b/app_dart/lib/cocoon_service.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +export 'src/foundation/context.dart'; export 'src/foundation/utils.dart'; export 'src/request_handlers/check_flaky_builders.dart'; export 'src/request_handlers/create_branch.dart'; @@ -32,6 +33,8 @@ export 'src/request_handlers/update_existing_flaky_issues.dart'; export 'src/request_handlers/vacuum_github_commits.dart'; export 'src/request_handling/authentication.dart'; export 'src/request_handling/cache_request_handler.dart'; +export 'src/request_handling/checkrun_authentication.dart'; +export 'src/request_handling/dashboard_authentication.dart'; export 'src/request_handling/pubsub.dart'; export 'src/request_handling/pubsub_authentication.dart'; export 'src/request_handling/request_handler.dart'; diff --git a/app_dart/lib/src/foundation/appengine_utils.dart b/app_dart/lib/src/foundation/appengine_utils.dart new file mode 100644 index 0000000000..5c0370c15a --- /dev/null +++ b/app_dart/lib/src/foundation/appengine_utils.dart @@ -0,0 +1,15 @@ +// Copyright 2026 The Flutter Authors. 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:appengine/appengine.dart' as gae; + +import 'context.dart'; + +class AppEngineClientContext implements ClientContext { + final gae.ClientContext _context; + AppEngineClientContext(this._context); + + @override + bool get isDevelopmentEnvironment => _context.isDevelopmentEnvironment; +} diff --git a/app_dart/lib/src/foundation/context.dart b/app_dart/lib/src/foundation/context.dart new file mode 100644 index 0000000000..83d080d131 --- /dev/null +++ b/app_dart/lib/src/foundation/context.dart @@ -0,0 +1,12 @@ +// Copyright 2026 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// A context for the current request. +/// +/// This abstracts the underlying App Engine context to avoid direct dependencies +/// on package:appengine in core logic. +abstract class ClientContext { + /// Whether the application is running in the development environment. + bool get isDevelopmentEnvironment; +} diff --git a/app_dart/lib/src/foundation/providers.dart b/app_dart/lib/src/foundation/providers.dart index 3c2831899c..6f69d6799f 100644 --- a/app_dart/lib/src/foundation/providers.dart +++ b/app_dart/lib/src/foundation/providers.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:appengine/appengine.dart' as gae; import 'package:http/http.dart' as http; +import 'context.dart'; import 'typedefs.dart'; /// Class that holds static default providers. @@ -18,17 +18,16 @@ class Providers { /// * [HttpClientProvider], which defines this interface. static http.Client freshHttpClient() => http.Client(); - /// Default [gae.Logging] provider. + /// Initializes the [ClientContext] provider. /// - /// See also: - /// - /// * [LoggingProvider], which defines this interface. - static gae.Logging serviceScopeLogger() => gae.loggingService; + /// This must be called before [serviceScopeContext] is used. + static ClientContextProvider contextProvider = () => + throw UnimplementedError('ClientContext provider not initialized'); - /// Default [gae.ClientContext] provider. + /// Default [ClientContext] provider. /// /// See also: /// /// * [ClientContextProvider], which defines this interface. - static gae.ClientContext serviceScopeContext() => gae.context; + static ClientContext serviceScopeContext() => contextProvider(); } diff --git a/app_dart/lib/src/foundation/typedefs.dart b/app_dart/lib/src/foundation/typedefs.dart index fe0ddc51dd..b027fbf83e 100644 --- a/app_dart/lib/src/foundation/typedefs.dart +++ b/app_dart/lib/src/foundation/typedefs.dart @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:appengine/appengine.dart'; import 'package:http/http.dart' as http; +import 'context.dart'; + /// Signature for a function that returns an App Engine [ClientContext]. /// /// This is used in [AuthenticationProvider] to provide the client context diff --git a/app_dart/lib/src/request_handling/authentication.dart b/app_dart/lib/src/request_handling/authentication.dart index 3a970f68cc..218ec07a5d 100644 --- a/app_dart/lib/src/request_handling/authentication.dart +++ b/app_dart/lib/src/request_handling/authentication.dart @@ -5,9 +5,9 @@ import 'dart:async'; import 'dart:io'; -import 'package:appengine/appengine.dart'; import 'package:meta/meta.dart'; +import '../foundation/context.dart'; import 'exceptions.dart'; @immutable diff --git a/app_dart/lib/src/request_handling/checkrun_authentication.dart b/app_dart/lib/src/request_handling/checkrun_authentication.dart index 730abd538f..10350d1e17 100644 --- a/app_dart/lib/src/request_handling/checkrun_authentication.dart +++ b/app_dart/lib/src/request_handling/checkrun_authentication.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:appengine/appengine.dart'; import 'package:cocoon_server/logging.dart'; import 'package:github/github.dart'; import 'package:meta/meta.dart'; @@ -15,7 +14,6 @@ import '../foundation/providers.dart'; import '../foundation/typedefs.dart'; import '../model/google/token_info.dart'; import '../service/firebase_jwt_validator.dart'; -import 'dashboard_authentication.dart'; import 'exceptions.dart'; /// Class capable of authenticating [HttpRequest]s from the Checkrun page. diff --git a/app_dart/lib/src/request_handling/dashboard_authentication.dart b/app_dart/lib/src/request_handling/dashboard_authentication.dart index f492e289fc..62139ec424 100644 --- a/app_dart/lib/src/request_handling/dashboard_authentication.dart +++ b/app_dart/lib/src/request_handling/dashboard_authentication.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:appengine/appengine.dart'; import 'package:cocoon_server/logging.dart'; import 'package:meta/meta.dart'; diff --git a/app_dart/lib/src/request_handling/pubsub_authentication.dart b/app_dart/lib/src/request_handling/pubsub_authentication.dart index fc7e7ac89f..eb6a290daa 100644 --- a/app_dart/lib/src/request_handling/pubsub_authentication.dart +++ b/app_dart/lib/src/request_handling/pubsub_authentication.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:appengine/appengine.dart'; import 'package:cocoon_server/logging.dart'; import 'package:googleapis/oauth2/v2.dart'; import 'package:meta/meta.dart'; diff --git a/app_dart/lib/src/request_handling/swarming_authentication.dart b/app_dart/lib/src/request_handling/swarming_authentication.dart index 57d1324e55..f2a1b02284 100644 --- a/app_dart/lib/src/request_handling/swarming_authentication.dart +++ b/app_dart/lib/src/request_handling/swarming_authentication.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:appengine/appengine.dart'; import 'package:cocoon_server/logging.dart'; import 'package:meta/meta.dart'; diff --git a/app_dart/pubspec.yaml b/app_dart/pubspec.yaml index 30f06bf6ab..9acaaa86df 100644 --- a/app_dart/pubspec.yaml +++ b/app_dart/pubspec.yaml @@ -57,6 +57,8 @@ dev_dependencies: build_runner: ^2.4.15 cocoon_common_test: path: ../packages/cocoon_common_test + cocoon_integration_test: + path: ../packages/cocoon_integration_test cocoon_server_test: path: ../packages/cocoon_server_test dart_flutter_team_lints: 3.5.2 diff --git a/app_dart/test/foundation/utils_test.dart b/app_dart/test/foundation/utils_test.dart index c4bd9ef5c2..49a69b2b6a 100644 --- a/app_dart/test/foundation/utils_test.dart +++ b/app_dart/test/foundation/utils_test.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:cocoon_common/cocoon_common.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/foundation/utils.dart'; @@ -18,9 +19,6 @@ import 'package:http/testing.dart'; import 'package:retry/retry.dart'; import 'package:test/test.dart'; -import '../src/bigquery/fake_tabledata_resource.dart'; -import '../src/utilities/entity_generators.dart'; - const String branchRegExp = ''' master flutter-1.1-candidate.1 diff --git a/app_dart/test/model/ci_yaml/ci_yaml_test.dart b/app_dart/test/model/ci_yaml/ci_yaml_test.dart index 32780417bb..bffd545a6b 100644 --- a/app_dart/test/model/ci_yaml/ci_yaml_test.dart +++ b/app_dart/test/model/ci_yaml/ci_yaml_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/protos.dart' as pb; import 'package:cocoon_service/src/model/ci_yaml/ci_yaml.dart'; @@ -10,9 +11,6 @@ import 'package:cocoon_service/src/service/config.dart'; import 'package:cocoon_service/src/service/flags/ci_yaml_flags.dart'; import 'package:test/test.dart'; -import '../../src/model/ci_yaml_matcher.dart'; -import '../../src/service/fake_scheduler.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/ci_yaml/target_test.dart b/app_dart/test/model/ci_yaml/target_test.dart index 487ccf45aa..68dc82bbc3 100644 --- a/app_dart/test/model/ci_yaml/target_test.dart +++ b/app_dart/test/model/ci_yaml/target_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/proto/internal/scheduler.pbenum.dart'; import 'package:cocoon_service/src/model/proto/protos.dart' as pb; @@ -10,9 +11,6 @@ import 'package:cocoon_service/src/service/scheduler/policy.dart'; import 'package:github/github.dart' as github; import 'package:test/test.dart'; -import '../../src/model/ci_yaml_matcher.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/ci_staging_test.dart b/app_dart/test/model/firestore/ci_staging_test.dart index 11c4169b66..60f926f9ee 100644 --- a/app_dart/test/model/firestore/ci_staging_test.dart +++ b/app_dart/test/model/firestore/ci_staging_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/common/presubmit_guard_conclusion.dart'; import 'package:cocoon_service/src/model/firestore/base.dart'; @@ -11,8 +12,6 @@ import 'package:github/github.dart'; import 'package:googleapis/firestore/v1.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/commit_test.dart b/app_dart/test/model/firestore/commit_test.dart index c2b05ff1af..91985ccc42 100644 --- a/app_dart/test/model/firestore/commit_test.dart +++ b/app_dart/test/model/firestore/commit_test.dart @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/commit.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/github_build_status_test.dart b/app_dart/test/model/firestore/github_build_status_test.dart index 2a6bf267d5..db4b962921 100644 --- a/app_dart/test/model/firestore/github_build_status_test.dart +++ b/app_dart/test/model/firestore/github_build_status_test.dart @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/github_build_status.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/github_gold_status_test.dart b/app_dart/test/model/firestore/github_gold_status_test.dart index 48c3fb3863..3c75fb8fc8 100644 --- a/app_dart/test/model/firestore/github_gold_status_test.dart +++ b/app_dart/test/model/firestore/github_gold_status_test.dart @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/github_gold_status.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/pr_check_runs_test.dart b/app_dart/test/model/firestore/pr_check_runs_test.dart index 308ca9f679..766f101de9 100644 --- a/app_dart/test/model/firestore/pr_check_runs_test.dart +++ b/app_dart/test/model/firestore/pr_check_runs_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/common/firestore_extensions.dart'; import 'package:cocoon_service/src/model/firestore/pr_check_runs.dart'; @@ -11,9 +12,6 @@ import 'package:github/github.dart'; import 'package:googleapis/firestore/v1.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/presubmit_check_test.dart b/app_dart/test/model/firestore/presubmit_check_test.dart index 8548f209a4..db89b824a4 100644 --- a/app_dart/test/model/firestore/presubmit_check_test.dart +++ b/app_dart/test/model/firestore/presubmit_check_test.dart @@ -4,14 +4,13 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/presubmit_check.dart'; import 'package:fixnum/fixnum.dart'; import 'package:googleapis/firestore/v1.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/firestore/task_test.dart b/app_dart/test/model/firestore/task_test.dart index f4588e7a32..da99b08350 100644 --- a/app_dart/test/model/firestore/task_test.dart +++ b/app_dart/test/model/firestore/task_test.dart @@ -6,13 +6,11 @@ import 'dart:convert'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/task.dart'; import 'package:test/test.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/model/ref_test.dart b/app_dart/test/model/ref_test.dart index f735749c7e..fb4695f76d 100644 --- a/app_dart/test/model/ref_test.dart +++ b/app_dart/test/model/ref_test.dart @@ -3,14 +3,13 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; import 'package:cocoon_service/src/model/task_ref.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/model/ref_matcher.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/check_flaky_builders_test.dart b/app_dart/test/request_handlers/check_flaky_builders_test.dart index f1b701d6ef..401bc8431d 100644 --- a/app_dart/test/request_handlers/check_flaky_builders_test.dart +++ b/app_dart/test/request_handlers/check_flaky_builders_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'dart:io' as io; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/ci_yaml.dart'; @@ -20,11 +21,7 @@ import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/utilities/mocks.dart'; import 'check_flaky_builders_test_data.dart'; const String kThreshold = '0.02'; diff --git a/app_dart/test/request_handlers/create_branch_test.dart b/app_dart/test/request_handlers/create_branch_test.dart index 9c04411e0c..acb73e77ad 100644 --- a/app_dart/test/request_handlers/create_branch_test.dart +++ b/app_dart/test/request_handlers/create_branch_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handlers/create_branch.dart'; import 'package:cocoon_service/src/request_handling/request_handler.dart'; @@ -9,11 +10,7 @@ import 'package:cocoon_service/src/service/branch_service.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/dart_internal_subscription_test.dart b/app_dart/test/request_handlers/dart_internal_subscription_test.dart index 78334d66c3..0765e48972 100644 --- a/app_dart/test/request_handlers/dart_internal_subscription_test.dart +++ b/app_dart/test/request_handlers/dart_internal_subscription_test.dart @@ -6,6 +6,7 @@ import 'dart:convert'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/task.dart' as fs; @@ -13,13 +14,7 @@ import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/subscription_tester.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart b/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart index 7f2f558e17..171cbf65ba 100644 --- a/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart +++ b/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/ci_yaml.dart'; @@ -19,11 +20,7 @@ import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/utilities/mocks.dart'; import 'file_flaky_issue_and_pr_test_data.dart'; const String kThreshold = '0.02'; diff --git a/app_dart/test/request_handlers/flaky_handler_utiles_test.dart b/app_dart/test/request_handlers/flaky_handler_utiles_test.dart index f8b6228f1a..5532cc9b33 100644 --- a/app_dart/test/request_handlers/flaky_handler_utiles_test.dart +++ b/app_dart/test/request_handlers/flaky_handler_utiles_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/protos.dart' as pb; @@ -12,8 +13,6 @@ import 'package:github/github.dart' hide Team; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/flush_cache_test.dart b/app_dart/test/request_handlers/flush_cache_test.dart index ac6e463a2d..2ad8ab4c97 100644 --- a/app_dart/test/request_handlers/flush_cache_test.dart +++ b/app_dart/test/request_handlers/flush_cache_test.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handlers/flush_cache.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; @@ -11,10 +12,7 @@ import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:cocoon_service/src/service/config.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_build_status_badge_test.dart b/app_dart/test/request_handlers/get_build_status_badge_test.dart index a9547f7d24..55dffbe7fb 100644 --- a/app_dart/test/request_handlers/get_build_status_badge_test.dart +++ b/app_dart/test/request_handlers/get_build_status_badge_test.dart @@ -3,14 +3,12 @@ // found in the LICENSE file. import 'package:cocoon_common/rpc_model.dart' as rpc_model; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handlers/get_build_status_badge.dart'; import 'package:cocoon_service/src/service/build_status_service.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/service/fake_firestore_service.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_build_status_test.dart b/app_dart/test/request_handlers/get_build_status_test.dart index 815e4d9c1e..a3c48d0dc8 100644 --- a/app_dart/test/request_handlers/get_build_status_test.dart +++ b/app_dart/test/request_handlers/get_build_status_test.dart @@ -5,15 +5,13 @@ import 'dart:convert'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/service/build_status_service.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_engine_artifacts_ready_test.dart b/app_dart/test/request_handlers/get_engine_artifacts_ready_test.dart index 9d2484c506..8e53b1549e 100644 --- a/app_dart/test/request_handlers/get_engine_artifacts_ready_test.dart +++ b/app_dart/test/request_handlers/get_engine_artifacts_ready_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/common/firestore_extensions.dart'; import 'package:cocoon_service/src/model/firestore/base.dart'; @@ -14,9 +15,7 @@ import 'package:cocoon_service/src/service/config.dart'; import 'package:googleapis/firestore/v1.dart' as g; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_green_commits_test.dart b/app_dart/test/request_handlers/get_green_commits_test.dart index 9838230b93..a27a374785 100644 --- a/app_dart/test/request_handlers/get_green_commits_test.dart +++ b/app_dart/test/request_handlers/get_green_commits_test.dart @@ -5,16 +5,13 @@ import 'dart:convert'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/service/build_status_provider/commit_tasks_status.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_build_status_service.dart'; -import '../src/utilities/entity_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_presubmit_checks_test.dart b/app_dart/test/request_handlers/get_presubmit_checks_test.dart index ffc39bdeb5..fd6cc77f9c 100644 --- a/app_dart/test/request_handlers/get_presubmit_checks_test.dart +++ b/app_dart/test/request_handlers/get_presubmit_checks_test.dart @@ -7,17 +7,14 @@ import 'dart:io'; import 'package:cocoon_common/rpc_model.dart'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/presubmit_check.dart' as fs; import 'package:cocoon_service/src/request_handlers/get_presubmit_checks.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { group('GetPresubmitChecks', () { diff --git a/app_dart/test/request_handlers/get_presubmit_guard_test.dart b/app_dart/test/request_handlers/get_presubmit_guard_test.dart index 65e74e3e2f..87b6f2c778 100644 --- a/app_dart/test/request_handlers/get_presubmit_guard_test.dart +++ b/app_dart/test/request_handlers/get_presubmit_guard_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:cocoon_common/guard_status.dart'; import 'package:cocoon_common/src/rpc_model/presubmit_guard.dart'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/base.dart'; import 'package:cocoon_service/src/request_handlers/get_presubmit_guard.dart'; @@ -15,12 +16,7 @@ import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_status_test.dart b/app_dart/test/request_handlers/get_status_test.dart index 28dafc6b86..ddaae72a4c 100644 --- a/app_dart/test/request_handlers/get_status_test.dart +++ b/app_dart/test/request_handlers/get_status_test.dart @@ -5,17 +5,13 @@ import 'dart:convert'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handlers/get_status.dart'; import 'package:cocoon_service/src/service/build_status_provider/commit_tasks_status.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_build_status_service.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_suppressed_tests_test.dart b/app_dart/test/request_handlers/get_suppressed_tests_test.dart index 79f0ee13a8..d10cc6a2aa 100644 --- a/app_dart/test/request_handlers/get_suppressed_tests_test.dart +++ b/app_dart/test/request_handlers/get_suppressed_tests_test.dart @@ -4,17 +4,14 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/suppressed_test.dart'; - import 'package:cocoon_service/src/service/flags/dynamic_config.dart'; - import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/get_tree_status_test.dart b/app_dart/test/request_handlers/get_tree_status_test.dart index dd1a164d52..25570e9d09 100644 --- a/app_dart/test/request_handlers/get_tree_status_test.dart +++ b/app_dart/test/request_handlers/get_tree_status_test.dart @@ -4,6 +4,7 @@ import 'package:cocoon_common/core_extensions.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/tree_status_change.dart'; import 'package:cocoon_service/src/request_handlers/get_tree_status_changes.dart'; @@ -11,10 +12,7 @@ import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/github/webhook_subscription_test.dart b/app_dart/test/request_handlers/github/webhook_subscription_test.dart index bd11cbfb81..d5fb711fd0 100644 --- a/app_dart/test/request_handlers/github/webhook_subscription_test.dart +++ b/app_dart/test/request_handlers/github/webhook_subscription_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/core_extensions.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; @@ -29,17 +30,7 @@ import 'package:googleapis/bigquery/v2.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_http.dart'; import '../../src/request_handling/subscription_tester.dart'; -import '../../src/service/fake_build_bucket_client.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/service/fake_github_service.dart'; -import '../../src/service/fake_scheduler.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.dart'; -import '../../src/utilities/webhook_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/github_webhook_replay_test.dart b/app_dart/test/request_handlers/github_webhook_replay_test.dart index 0e22636f14..7c603637a1 100644 --- a/app_dart/test/request_handlers/github_webhook_replay_test.dart +++ b/app_dart/test/request_handlers/github_webhook_replay_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/github_webhook_message.dart'; @@ -9,11 +10,7 @@ import 'package:cocoon_service/src/request_handlers/github_webhook_replay.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_pubsub.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/github_webhook_test.dart b/app_dart/test/request_handlers/github_webhook_test.dart index 70744b1d72..add8bf63d1 100644 --- a/app_dart/test/request_handlers/github_webhook_test.dart +++ b/app_dart/test/request_handlers/github_webhook_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/protos.dart'; @@ -14,11 +15,7 @@ import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:crypto/crypto.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/request_handling/fake_pubsub.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/lookup_hash_test.dart b/app_dart/test/request_handlers/lookup_hash_test.dart index d450202802..737d3a4c92 100644 --- a/app_dart/test/request_handlers/lookup_hash_test.dart +++ b/app_dart/test/request_handlers/lookup_hash_test.dart @@ -5,15 +5,13 @@ import 'dart:convert'; import 'package:cocoon_common/rpc_model.dart' show ContentHashLookup; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/content_aware_hash_builds.dart'; import 'package:cocoon_service/src/request_handlers/lookup_hash.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_content_aware_hash_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/merge_queue_hooks_test.dart b/app_dart/test/request_handlers/merge_queue_hooks_test.dart index 127289b91a..bfdbae8a20 100644 --- a/app_dart/test/request_handlers/merge_queue_hooks_test.dart +++ b/app_dart/test/request_handlers/merge_queue_hooks_test.dart @@ -5,16 +5,14 @@ import 'dart:convert'; import 'package:cocoon_common/rpc_model.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/github_webhook_message.dart'; import 'package:cocoon_service/src/request_handlers/merge_queue_hooks.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/postsubmit_luci_subscription_test.dart b/app_dart/test/request_handlers/postsubmit_luci_subscription_test.dart index 27757a3141..fcd3e5fd42 100644 --- a/app_dart/test/request_handlers/postsubmit_luci_subscription_test.dart +++ b/app_dart/test/request_handlers/postsubmit_luci_subscription_test.dart @@ -5,6 +5,7 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -14,17 +15,7 @@ import 'package:fixnum/fixnum.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/subscription_tester.dart'; -import '../src/service/fake_ci_yaml_fetcher.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_luci_build_service.dart'; -import '../src/service/fake_scheduler.dart'; -import '../src/utilities/build_bucket_messages.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart b/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart index 300bbaef7e..3432b2de45 100644 --- a/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart +++ b/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart @@ -4,6 +4,7 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -19,16 +20,7 @@ import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; import '../src/request_handling/subscription_tester.dart'; -import '../src/service/fake_ci_yaml_fetcher.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_luci_build_service.dart'; -import '../src/service/fake_scheduler.dart'; -import '../src/utilities/build_bucket_messages.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/push_build_status_to_github_test.dart b/app_dart/test/request_handlers/push_build_status_to_github_test.dart index cf0660508f..02f94672b4 100644 --- a/app_dart/test/request_handlers/push_build_status_to_github_test.dart +++ b/app_dart/test/request_handlers/push_build_status_to_github_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/github_build_status.dart'; @@ -14,15 +15,7 @@ import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/bigquery/fake_tabledata_resource.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_build_status_service.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_github_service.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/push_gold_status_to_github_test.dart b/app_dart/test/request_handlers/push_gold_status_to_github_test.dart index 0a13e6e4c9..097fc64071 100644 --- a/app_dart/test/request_handlers/push_gold_status_to_github_test.dart +++ b/app_dart/test/request_handlers/push_gold_status_to_github_test.dart @@ -6,12 +6,13 @@ import 'dart:async'; import 'dart:io'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; -import 'package:cocoon_service/src/model/firestore/github_gold_status.dart'; import 'package:cocoon_service/src/model/firestore/github_gold_status.dart' as fs; +import 'package:cocoon_service/src/model/firestore/github_gold_status.dart'; import 'package:cocoon_service/src/request_handlers/push_gold_status_to_github.dart'; import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:github/github.dart'; @@ -21,13 +22,7 @@ import 'package:http/testing.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_graphql_client.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/rerun_prod_task_test.dart b/app_dart/test/request_handlers/rerun_prod_task_test.dart index 09ace3d7c2..fc518d34ec 100644 --- a/app_dart/test/request_handlers/rerun_prod_task_test.dart +++ b/app_dart/test/request_handlers/rerun_prod_task_test.dart @@ -4,6 +4,7 @@ import 'package:cocoon_common/task_status.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -13,14 +14,7 @@ import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_ci_yaml_fetcher.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_scheduler.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/reset_try_task_test.dart b/app_dart/test/request_handlers/reset_try_task_test.dart index b48d281be1..e1f6cb0346 100644 --- a/app_dart/test/request_handlers/reset_try_task_test.dart +++ b/app_dart/test/request_handlers/reset_try_task_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handlers/reset_try_task.dart'; @@ -11,15 +12,7 @@ import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_github_service.dart'; -import '../src/service/fake_scheduler.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/scheduler/backfill_grid_test.dart b/app_dart/test/request_handlers/scheduler/backfill_grid_test.dart index 57e011011c..1178d2b48e 100644 --- a/app_dart/test/request_handlers/scheduler/backfill_grid_test.dart +++ b/app_dart/test/request_handlers/scheduler/backfill_grid_test.dart @@ -3,13 +3,12 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/protos.dart'; import 'package:cocoon_service/src/request_handlers/scheduler/backfill_grid.dart'; import 'package:test/test.dart'; -import '../../src/model/ci_yaml_matcher.dart'; -import '../../src/utilities/entity_generators.dart'; import 'backfill_matcher.dart'; void main() { diff --git a/app_dart/test/request_handlers/scheduler/backfill_matcher.dart b/app_dart/test/request_handlers/scheduler/backfill_matcher.dart index 67e52afc8e..081e15069a 100644 --- a/app_dart/test/request_handlers/scheduler/backfill_matcher.dart +++ b/app_dart/test/request_handlers/scheduler/backfill_matcher.dart @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; import 'package:cocoon_service/src/model/task_ref.dart'; import 'package:cocoon_service/src/request_handlers/scheduler/backfill_grid.dart'; import 'package:test/expect.dart'; -import '../../src/model/ci_yaml_matcher.dart'; - /// Returns a matcher that asserts the state of [BackfillGrid.eligibleTasks]. Matcher hasGridTargetsMatching( Iterable<(TargetMatcher, List)> targets, diff --git a/app_dart/test/request_handlers/scheduler/backfill_strategy_test.dart b/app_dart/test/request_handlers/scheduler/backfill_strategy_test.dart index 564ef9ff49..af57ed859f 100644 --- a/app_dart/test/request_handlers/scheduler/backfill_strategy_test.dart +++ b/app_dart/test/request_handlers/scheduler/backfill_strategy_test.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/task_ref.dart'; import 'package:cocoon_service/src/request_handlers/scheduler/backfill_grid.dart'; @@ -13,7 +14,6 @@ import 'package:cocoon_service/src/service/luci_build_service.dart'; import 'package:test/fake.dart'; import 'package:test/test.dart'; -import '../../src/utilities/entity_generators.dart'; import 'backfill_matcher.dart'; void main() { diff --git a/app_dart/test/request_handlers/scheduler/batch_backfiller_test.dart b/app_dart/test/request_handlers/scheduler/batch_backfiller_test.dart index 0e9a9f2808..a44dd5b74f 100644 --- a/app_dart/test/request_handlers/scheduler/batch_backfiller_test.dart +++ b/app_dart/test/request_handlers/scheduler/batch_backfiller_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; import 'package:cocoon_service/src/request_handlers/scheduler/backfill_grid.dart'; @@ -16,11 +17,7 @@ import 'package:collection/collection.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; import '../../src/request_handling/request_handler_tester.dart'; -import '../../src/service/fake_ci_yaml_fetcher.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/scheduler/scheduler_request_subscription_test.dart b/app_dart/test/request_handlers/scheduler/scheduler_request_subscription_test.dart index b259f08539..8c79f703a9 100644 --- a/app_dart/test/request_handlers/scheduler/scheduler_request_subscription_test.dart +++ b/app_dart/test/request_handlers/scheduler/scheduler_request_subscription_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; @@ -15,12 +16,7 @@ import 'package:mockito/mockito.dart'; import 'package:retry/retry.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_dashboard_authentication.dart'; -import '../../src/request_handling/fake_http.dart'; import '../../src/request_handling/subscription_tester.dart'; -import '../../src/service/fake_github_service.dart'; -import '../../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/scheduler/vacuum_stale_tasks_test.dart b/app_dart/test/request_handlers/scheduler/vacuum_stale_tasks_test.dart index d475582753..52c7bc17e3 100644 --- a/app_dart/test/request_handlers/scheduler/vacuum_stale_tasks_test.dart +++ b/app_dart/test/request_handlers/scheduler/vacuum_stale_tasks_test.dart @@ -5,6 +5,7 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/rpc_model.dart' as rpc; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/task.dart' as fs; @@ -12,11 +13,7 @@ import 'package:fixnum/fixnum.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; import '../../src/request_handling/request_handler_tester.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/update_discord_status_test.dart b/app_dart/test/request_handlers/update_discord_status_test.dart index 18e3f0af7e..19ef72a8de 100644 --- a/app_dart/test/request_handlers/update_discord_status_test.dart +++ b/app_dart/test/request_handlers/update_discord_status_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/build_status_snapshot.dart'; import 'package:cocoon_service/src/request_handlers/update_discord_status.dart'; @@ -14,13 +15,7 @@ import 'package:cocoon_service/src/service/discord_service.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/model/firestore_matcher.dart'; import '../src/request_handling/request_handler_tester.dart'; -import '../src/service/fake_firestore_service.dart' - show FakeFirestoreService, existsInStorage; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/update_existing_flaky_issues_test.dart b/app_dart/test/request_handlers/update_existing_flaky_issues_test.dart index f3368d68a7..2a53c0646c 100644 --- a/app_dart/test/request_handlers/update_existing_flaky_issues_test.dart +++ b/app_dart/test/request_handlers/update_existing_flaky_issues_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -15,12 +16,7 @@ import 'package:http/http.dart' as http; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/service/fake_ci_yaml_fetcher.dart'; -import '../src/utilities/mocks.dart'; import 'update_existing_flaky_issues_test_data.dart'; const String kThreshold = '0.02'; diff --git a/app_dart/test/request_handlers/update_suppressed_test_test.dart b/app_dart/test/request_handlers/update_suppressed_test_test.dart index 78cf2717f1..feae6971a8 100644 --- a/app_dart/test/request_handlers/update_suppressed_test_test.dart +++ b/app_dart/test/request_handlers/update_suppressed_test_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/suppressed_test.dart'; import 'package:cocoon_service/src/request_handlers/update_suppressed_test.dart'; @@ -13,11 +14,7 @@ import 'package:cocoon_service/src/service/flags/dynamic_config.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_github_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/update_tree_status_test.dart b/app_dart/test/request_handlers/update_tree_status_test.dart index 23890eee91..4e03261d61 100644 --- a/app_dart/test/request_handlers/update_tree_status_test.dart +++ b/app_dart/test/request_handlers/update_tree_status_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/tree_status_change.dart'; import 'package:cocoon_service/src/request_handlers/update_tree_status.dart'; @@ -11,10 +12,7 @@ import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:cocoon_service/src/service/config.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handlers/vacuum_github_commits_test.dart b/app_dart/test/request_handlers/vacuum_github_commits_test.dart index cc81f5b898..5b6cdae2c3 100644 --- a/app_dart/test/request_handlers/vacuum_github_commits_test.dart +++ b/app_dart/test/request_handlers/vacuum_github_commits_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/commit.dart' as fs; @@ -13,13 +14,7 @@ import 'package:googleapis/bigquery/v2.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/api_request_handler_tester.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_github_service.dart'; -import '../src/service/fake_scheduler.dart'; -import '../src/utilities/mocks.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/api_request_handler_test.dart b/app_dart/test/request_handling/api_request_handler_test.dart index bb84668026..da367846b2 100644 --- a/app_dart/test/request_handling/api_request_handler_test.dart +++ b/app_dart/test/request_handling/api_request_handler_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:cocoon_common/core_extensions.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/api_request_handler.dart'; @@ -16,9 +17,6 @@ import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:gcloud/service_scope.dart' as ss; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/cache_request_handler_test.dart b/app_dart/test/request_handling/cache_request_handler_test.dart index d0e24198d9..146bb5a4b0 100644 --- a/app_dart/test/request_handling/cache_request_handler_test.dart +++ b/app_dart/test/request_handling/cache_request_handler_test.dart @@ -5,15 +5,13 @@ import 'dart:convert'; import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/cache_request_handler.dart'; import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/request_handling/fake_request_handler.dart'; import '../src/request_handling/request_handler_tester.dart'; void main() { diff --git a/app_dart/test/request_handling/checkrun_authentication_test.dart b/app_dart/test/request_handling/checkrun_authentication_test.dart index 601521384a..7ba78a78aa 100644 --- a/app_dart/test/request_handling/checkrun_authentication_test.dart +++ b/app_dart/test/request_handling/checkrun_authentication_test.dart @@ -5,12 +5,12 @@ import 'dart:convert'; import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/google/firebase_jwt_claim.dart'; import 'package:cocoon_service/src/model/google/token_info.dart'; -import 'package:cocoon_service/src/request_handling/checkrun_authentication.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:cocoon_service/src/service/github_service.dart'; import 'package:github/github.dart'; @@ -18,12 +18,6 @@ import 'package:http/http.dart' as http; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -import '../src/service/fake_firebase_jwt_validator.dart'; -import '../src/utilities/mocks.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/dashboard_authentication_test.dart b/app_dart/test/request_handling/dashboard_authentication_test.dart index 122ea5f116..83fae7fb50 100644 --- a/app_dart/test/request_handling/dashboard_authentication_test.dart +++ b/app_dart/test/request_handling/dashboard_authentication_test.dart @@ -2,20 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/account.dart'; import 'package:cocoon_service/src/model/google/token_info.dart'; -import 'package:cocoon_service/src/request_handling/dashboard_authentication.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:test/test.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; -// import '../src/service/fake_firebase_jwt_validator.dart'; -import '../src/service/fake_firebase_jwt_validator.dart'; -import '../src/service/fake_firestore_service.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/pubsub_authentication_test.dart b/app_dart/test/request_handling/pubsub_authentication_test.dart index 1bdb501463..0d8a6da2a1 100644 --- a/app_dart/test/request_handling/pubsub_authentication_test.dart +++ b/app_dart/test/request_handling/pubsub_authentication_test.dart @@ -4,6 +4,7 @@ import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:cocoon_service/src/request_handling/pubsub_authentication.dart'; @@ -12,10 +13,6 @@ import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/request_handler_test.dart b/app_dart/test/request_handling/request_handler_test.dart index 646b01c441..711b7515db 100644 --- a/app_dart/test/request_handling/request_handler_test.dart +++ b/app_dart/test/request_handling/request_handler_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:cocoon_common/core_extensions.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; @@ -16,8 +17,6 @@ import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:gcloud/service_scope.dart' as ss; import 'package:test/test.dart'; -import '../src/fake_config.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/static_file_handler_test.dart b/app_dart/test/request_handling/static_file_handler_test.dart index 69b54aafd1..b209d689df 100644 --- a/app_dart/test/request_handling/static_file_handler_test.dart +++ b/app_dart/test/request_handling/static_file_handler_test.dart @@ -4,6 +4,7 @@ import 'dart:convert' show utf8; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; @@ -11,7 +12,6 @@ import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; import '../src/request_handling/request_handler_tester.dart'; void main() { diff --git a/app_dart/test/request_handling/subscription_handler_test.dart b/app_dart/test/request_handling/subscription_handler_test.dart index 7ab8e986bd..e0f47a2585 100644 --- a/app_dart/test/request_handling/subscription_handler_test.dart +++ b/app_dart/test/request_handling/subscription_handler_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; @@ -15,9 +16,6 @@ import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:gcloud/service_scope.dart' as ss; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/request_handling/swarming_authentication_test.dart b/app_dart/test/request_handling/swarming_authentication_test.dart index 2cc29d6c6b..8556725acf 100644 --- a/app_dart/test/request_handling/swarming_authentication_test.dart +++ b/app_dart/test/request_handling/swarming_authentication_test.dart @@ -4,6 +4,7 @@ import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:cocoon_service/src/request_handling/swarming_authentication.dart'; @@ -12,10 +13,6 @@ import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_dashboard_authentication.dart'; -import '../src/request_handling/fake_http.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/server_test.dart b/app_dart/test/server_test.dart index 768eb52729..28845258ba 100644 --- a/app_dart/test/server_test.dart +++ b/app_dart/test/server_test.dart @@ -2,23 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/server.dart'; import 'package:cocoon_service/src/service/commit_service.dart'; import 'package:test/test.dart'; -import 'src/fake_config.dart'; -import 'src/request_handling/fake_dashboard_authentication.dart'; -import 'src/service/fake_build_bucket_client.dart'; -import 'src/service/fake_build_status_service.dart'; -import 'src/service/fake_ci_yaml_fetcher.dart'; -import 'src/service/fake_content_aware_hash_service.dart'; -import 'src/service/fake_firestore_service.dart'; -import 'src/service/fake_gerrit_service.dart'; -import 'src/service/fake_luci_build_service.dart'; -import 'src/service/fake_scheduler.dart'; -import 'src/utilities/mocks.dart'; - void main() { test('verify server can be created', () { final firestore = FakeFirestoreService(); diff --git a/app_dart/test/service/bigquery_test.dart b/app_dart/test/service/bigquery_test.dart index e61c2e1516..633277dd4d 100644 --- a/app_dart/test/service/bigquery_test.dart +++ b/app_dart/test/service/bigquery_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/big_query.dart'; @@ -11,8 +12,6 @@ import 'package:googleapis/bigquery/v2.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/utilities/mocks.dart'; - const String semanticsIntegrationTestResponse = ''' { "jobComplete" : true, diff --git a/app_dart/test/service/branch_service_test.dart b/app_dart/test/service/branch_service_test.dart index 716aad0676..9d5cb9c02e 100644 --- a/app_dart/test/service/branch_service_test.dart +++ b/app_dart/test/service/branch_service_test.dart @@ -4,6 +4,7 @@ import 'package:cocoon_common/rpc_model.dart' as rpc_model; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; @@ -18,11 +19,6 @@ import 'package:mockito/mockito.dart'; import 'package:retry/retry.dart'; import 'package:test/test.dart'; -import '../src/service/fake_gerrit_service.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/matchers.dart'; -import '../src/utilities/mocks.mocks.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/build_bucket_client_test.dart b/app_dart/test/service/build_bucket_client_test.dart index 9a751c55d4..b81c77acf3 100644 --- a/app_dart/test/service/build_bucket_client_test.dart +++ b/app_dart/test/service/build_bucket_client_test.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/build_bucket_client.dart'; import 'package:fixnum/fixnum.dart'; @@ -16,8 +17,6 @@ import 'package:http/testing.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/utilities/mocks.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/build_status_service_test.dart b/app_dart/test/service/build_status_service_test.dart index 769c6daf9b..fccaa0d933 100644 --- a/app_dart/test/service/build_status_service_test.dart +++ b/app_dart/test/service/build_status_service_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/tree_status_change.dart'; import 'package:cocoon_service/src/service/build_status_service.dart'; @@ -10,10 +11,6 @@ import 'package:cocoon_service/src/service/flags/dynamic_config.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/cache_service_test.dart b/app_dart/test/service/cache_service_test.dart index 19f1672d08..41c8cc1c01 100644 --- a/app_dart/test/service/cache_service_test.dart +++ b/app_dart/test/service/cache_service_test.dart @@ -5,14 +5,13 @@ import 'dart:async'; import 'dart:typed_data'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:mockito/mockito.dart'; import 'package:neat_cache/neat_cache.dart'; import 'package:test/test.dart'; -import '../src/utilities/mocks.dart'; - void main() { useTestLoggerPerTest(); @@ -294,23 +293,3 @@ void main() { }); }); } - -class FakeEntry extends Entry { - Uint8List value = Uint8List.fromList('abc123'.codeUnits); - - @override - Future get([ - Future Function()? create, - Duration? ttl, - ]) async => value; - - @override - Future purge({int retries = 0}) => throw UnimplementedError(); - - @override - Future set(Uint8List? value, [Duration? ttl]) async { - value = value; - - return value; - } -} diff --git a/app_dart/test/service/commit_service_test.dart b/app_dart/test/service/commit_service_test.dart index b90e21c122..4c1a058e91 100644 --- a/app_dart/test/service/commit_service_test.dart +++ b/app_dart/test/service/commit_service_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/commit.dart' as fs; @@ -10,12 +11,6 @@ import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.mocks.dart'; -import '../src/utilities/webhook_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/commit_tasks_status_test.dart b/app_dart/test/service/commit_tasks_status_test.dart index 5108e45a88..80f152b372 100644 --- a/app_dart/test/service/commit_tasks_status_test.dart +++ b/app_dart/test/service/commit_tasks_status_test.dart @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/build_status_provider/commit_tasks_status.dart'; import 'package:test/test.dart'; -import '../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/content_aware_hash_service_test.dart b/app_dart/test/service/content_aware_hash_service_test.dart index aabfd016cb..4c6187fd6f 100644 --- a/app_dart/test/service/content_aware_hash_service_test.dart +++ b/app_dart/test/service/content_aware_hash_service_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; @@ -17,9 +18,6 @@ import 'package:retry/retry.dart'; import 'package:test/test.dart'; import '../model/github/workflow_job_data.dart'; -import '../src/fake_config.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_github_service.dart'; void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/firestore/unified_check_run_test.dart b/app_dart/test/service/firestore/unified_check_run_test.dart index 960793646d..7db68690d1 100644 --- a/app_dart/test/service/firestore/unified_check_run_test.dart +++ b/app_dart/test/service/firestore/unified_check_run_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/common/presubmit_check_state.dart'; import 'package:cocoon_service/src/model/common/presubmit_guard_conclusion.dart'; @@ -16,10 +17,6 @@ import 'package:github/github.dart'; import 'package:googleapis/firestore/v1.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/firestore_test.dart b/app_dart/test/service/firestore_test.dart index 923e2b3c77..160e4bb3eb 100644 --- a/app_dart/test/service/firestore_test.dart +++ b/app_dart/test/service/firestore_test.dart @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/firestore.dart'; import 'package:cocoon_service/src/service/firestore/commit_and_tasks.dart'; import 'package:googleapis/firestore/v1.dart'; import 'package:test/test.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/gerrit_service_test.dart b/app_dart/test/service/gerrit_service_test.dart index dbe206f63b..9302e0b275 100644 --- a/app_dart/test/service/gerrit_service_test.dart +++ b/app_dart/test/service/gerrit_service_test.dart @@ -4,6 +4,7 @@ import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; import 'package:cocoon_service/src/service/config.dart'; @@ -14,10 +15,6 @@ import 'package:http/http.dart'; import 'package:http/testing.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/service/fake_auth_client.dart'; -import '../src/utilities/matchers.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/github_checks_service_test.dart b/app_dart/test/service/github_checks_service_test.dart index 734108f4dc..f0511621c2 100644 --- a/app_dart/test/service/github_checks_service_test.dart +++ b/app_dart/test/service/github_checks_service_test.dart @@ -5,20 +5,17 @@ import 'dart:convert'; import 'package:buildbucket/buildbucket_pb.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; import 'package:cocoon_service/src/service/github_checks_service.dart'; import 'package:cocoon_service/src/service/luci_build_service/user_data.dart'; import 'package:fixnum/fixnum.dart'; - import 'package:github/github.dart' as github; import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/fake_config.dart'; -import '../src/utilities/mocks.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/github_service_test.dart b/app_dart/test/service/github_service_test.dart index c01df81694..3cdd788f78 100644 --- a/app_dart/test/service/github_service_test.dart +++ b/app_dart/test/service/github_service_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/github_service.dart'; @@ -13,8 +14,6 @@ import 'package:http/http.dart' as http; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../src/utilities/mocks.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/luci_build_service/cancel_builds_test.dart b/app_dart/test/service/luci_build_service/cancel_builds_test.dart index 77bc2bcba1..c792fcdb31 100644 --- a/app_dart/test/service/luci_build_service/cancel_builds_test.dart +++ b/app_dart/test/service/luci_build_service/cancel_builds_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:cocoon_service/src/service/luci_build_service.dart'; @@ -10,13 +11,6 @@ import 'package:fixnum/fixnum.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to fetching prod-bot builds. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/check_rerun_builder_test.dart b/app_dart/test/service/luci_build_service/check_rerun_builder_test.dart index c0b358288c..a1daa8bc2a 100644 --- a/app_dart/test/service/luci_build_service/check_rerun_builder_test.dart +++ b/app_dart/test/service/luci_build_service/check_rerun_builder_test.dart @@ -4,18 +4,12 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/model/firestore/task.dart' as fs; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to rerunning TOT test failures. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/find_or_get_builds_test.dart b/app_dart/test/service/luci_build_service/find_or_get_builds_test.dart index 681bd8b81b..b2416518b3 100644 --- a/app_dart/test/service/luci_build_service/find_or_get_builds_test.dart +++ b/app_dart/test/service/luci_build_service/find_or_get_builds_test.dart @@ -5,6 +5,7 @@ import 'dart:typed_data'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:cocoon_service/src/service/luci_build_service.dart'; @@ -13,13 +14,6 @@ import 'package:github/github.dart' as gh; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to fetching [bbv2.Build]s. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/rerun_dart_internal_test.dart b/app_dart/test/service/luci_build_service/rerun_dart_internal_test.dart index e7ce64aa0f..6171c23f82 100644 --- a/app_dart/test/service/luci_build_service/rerun_dart_internal_test.dart +++ b/app_dart/test/service/luci_build_service/rerun_dart_internal_test.dart @@ -5,6 +5,7 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -14,13 +15,6 @@ import 'package:fixnum/fixnum.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to `dart-internal` builds. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/schedule_merge_group_builds_test.dart b/app_dart/test/service/luci_build_service/schedule_merge_group_builds_test.dart index f7540fef5a..9403ee0624 100644 --- a/app_dart/test/service/luci_build_service/schedule_merge_group_builds_test.dart +++ b/app_dart/test/service/luci_build_service/schedule_merge_group_builds_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; import 'package:cocoon_service/src/service/cache_service.dart'; @@ -14,13 +15,6 @@ import 'package:mockito/mockito.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to scheduling for a merge group. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/schedule_prod_builds_test.dart b/app_dart/test/service/luci_build_service/schedule_prod_builds_test.dart index dff48ca435..8a3cc366bc 100644 --- a/app_dart/test/service/luci_build_service/schedule_prod_builds_test.dart +++ b/app_dart/test/service/luci_build_service/schedule_prod_builds_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/task.dart' as fs; import 'package:cocoon_service/src/model/github/checks.dart'; @@ -19,14 +20,6 @@ import 'package:fixnum/fixnum.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; -import '../../src/utilities/webhook_generators.dart'; - /// Tests [LuciBuildService] public API related to fetching prod-bot builds. /// /// Specifically: diff --git a/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart b/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart index 8665f4a87c..e09bcfd2f6 100644 --- a/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart +++ b/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart @@ -4,6 +4,7 @@ import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/commit_ref.dart'; @@ -21,14 +22,6 @@ import 'package:github/github.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/model/ci_yaml_matcher.dart'; -import '../../src/request_handling/fake_pubsub.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_gerrit_service.dart'; -import '../../src/utilities/entity_generators.dart'; -import '../../src/utilities/mocks.mocks.dart'; - /// Tests [LuciBuildService] public API related to fetching try-bot builds. /// /// Specifically: diff --git a/app_dart/test/service/presubmit_guard_query_test.dart b/app_dart/test/service/presubmit_guard_query_test.dart index 884d601d1a..33900d3b7d 100644 --- a/app_dart/test/service/presubmit_guard_query_test.dart +++ b/app_dart/test/service/presubmit_guard_query_test.dart @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/base.dart'; import 'package:cocoon_service/src/service/firestore/unified_check_run.dart'; import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/scheduler/ci_yaml_fetcher_test.dart b/app_dart/test/service/scheduler/ci_yaml_fetcher_test.dart index f6eab7aa20..6ec741067d 100644 --- a/app_dart/test/service/scheduler/ci_yaml_fetcher_test.dart +++ b/app_dart/test/service/scheduler/ci_yaml_fetcher_test.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/ci_yaml.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -17,10 +18,6 @@ import 'package:path/path.dart' as p; import 'package:retry/retry.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/scheduler/files_changed_optimization_test.dart b/app_dart/test/service/scheduler/files_changed_optimization_test.dart index 4006284b86..f917f047b8 100644 --- a/app_dart/test/service/scheduler/files_changed_optimization_test.dart +++ b/app_dart/test/service/scheduler/files_changed_optimization_test.dart @@ -4,6 +4,7 @@ import 'package:cocoon_common/cocoon_common.dart'; import 'package:cocoon_common_test/cocoon_common_test.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/logging.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/protos.dart' as pb; @@ -15,11 +16,6 @@ import 'package:cocoon_service/src/service/scheduler/files_changed_optimization. import 'package:github/github.dart'; import 'package:test/test.dart'; -import '../../src/fake_config.dart'; -import '../../src/service/fake_ci_yaml_fetcher.dart'; -import '../../src/service/fake_get_files_changed.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/scheduler/hash_workflow_test.dart b/app_dart/test/service/scheduler/hash_workflow_test.dart index 7bee9f98ec..61be590630 100644 --- a/app_dart/test/service/scheduler/hash_workflow_test.dart +++ b/app_dart/test/service/scheduler/hash_workflow_test.dart @@ -4,6 +4,7 @@ import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart' hide Response; @@ -18,12 +19,6 @@ import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import '../../model/github/workflow_job_data.dart'; -import '../../src/fake_config.dart'; -import '../../src/service/fake_ci_yaml_fetcher.dart'; -import '../../src/service/fake_firestore_service.dart'; -import '../../src/service/fake_get_files_changed.dart'; -import '../../src/service/fake_github_service.dart'; -import '../../src/utilities/mocks.mocks.dart'; import '../content_aware_hash_service_test.dart' show goodAnnotation; import 'ci_yaml_strings.dart'; import 'create_check_run.dart'; diff --git a/app_dart/test/service/scheduler/policy_test.dart b/app_dart/test/service/scheduler/policy_test.dart index 7b705965df..32740ddcc8 100644 --- a/app_dart/test/service/scheduler/policy_test.dart +++ b/app_dart/test/service/scheduler/policy_test.dart @@ -3,14 +3,13 @@ // found in the LICENSE file. import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/model/firestore/task.dart'; import 'package:cocoon_service/src/service/luci_build_service.dart'; import 'package:cocoon_service/src/service/scheduler/policy.dart'; import 'package:test/test.dart'; -import '../../src/utilities/entity_generators.dart'; - void main() { useTestLoggerPerTest(); diff --git a/app_dart/test/service/scheduler_test.dart b/app_dart/test/service/scheduler_test.dart index f0bdd30270..837ad9a8b6 100644 --- a/app_dart/test/service/scheduler_test.dart +++ b/app_dart/test/service/scheduler_test.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:buildbucket/buildbucket_pb.dart' as bbv2; import 'package:cocoon_common/task_status.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/mocks.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/cocoon_service.dart'; @@ -37,19 +38,6 @@ import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import '../model/github/checks_test_data.dart'; -import '../src/fake_config.dart'; -import '../src/request_handling/fake_pubsub.dart'; -import '../src/service/fake_build_bucket_client.dart'; -import '../src/service/fake_ci_yaml_fetcher.dart'; -import '../src/service/fake_content_aware_hash_service.dart'; -import '../src/service/fake_firestore_service.dart'; -import '../src/service/fake_gerrit_service.dart'; -import '../src/service/fake_get_files_changed.dart'; -import '../src/service/fake_github_service.dart'; -import '../src/service/fake_luci_build_service.dart'; -import '../src/utilities/entity_generators.dart'; -import '../src/utilities/mocks.dart'; -import '../src/utilities/webhook_generators.dart'; import 'scheduler/ci_yaml_strings.dart'; import 'scheduler/create_check_run.dart'; diff --git a/app_dart/test/src/request_handling/api_request_handler_tester.dart b/app_dart/test/src/request_handling/api_request_handler_tester.dart index d0c968d19e..02f0832ea0 100644 --- a/app_dart/test/src/request_handling/api_request_handler_tester.dart +++ b/app_dart/test/src/request_handling/api_request_handler_tester.dart @@ -5,12 +5,12 @@ import 'dart:async'; import 'dart:convert'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_service/src/request_handling/api_request_handler.dart'; import 'package:cocoon_service/src/request_handling/request_handler.dart'; import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:meta/meta.dart'; -import 'fake_dashboard_authentication.dart'; import 'request_handler_tester.dart'; class ApiRequestHandlerTester extends RequestHandlerTester { diff --git a/app_dart/test/src/request_handling/request_handler_tester.dart b/app_dart/test/src/request_handling/request_handler_tester.dart index e881f8e2b2..b3ba131274 100644 --- a/app_dart/test/src/request_handling/request_handler_tester.dart +++ b/app_dart/test/src/request_handling/request_handler_tester.dart @@ -4,12 +4,11 @@ import 'dart:async'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_service/src/request_handling/request_handler.dart'; import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:meta/meta.dart'; -import 'fake_http.dart'; - class RequestHandlerTester { RequestHandlerTester({FakeHttpRequest? request}) : request = request ?? FakeHttpRequest(); diff --git a/app_dart/test/src/request_handling/subscription_tester.dart b/app_dart/test/src/request_handling/subscription_tester.dart index f1a91d6793..87b20235e8 100644 --- a/app_dart/test/src/request_handling/subscription_tester.dart +++ b/app_dart/test/src/request_handling/subscription_tester.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; import 'package:cocoon_service/src/request_handling/api_request_handler.dart'; import 'package:cocoon_service/src/request_handling/request_handler.dart'; @@ -11,7 +12,6 @@ import 'package:cocoon_service/src/request_handling/response.dart'; import 'package:cocoon_service/src/request_handling/subscription_handler.dart'; import 'package:meta/meta.dart'; -import 'fake_dashboard_authentication.dart'; import 'request_handler_tester.dart'; class SubscriptionTester extends RequestHandlerTester { diff --git a/app_dart/tool/local_server.dart b/app_dart/tool/local_server.dart index 49d00cf952..04a4c270de 100644 --- a/app_dart/tool/local_server.dart +++ b/app_dart/tool/local_server.dart @@ -5,12 +5,12 @@ import 'dart:io'; import 'package:appengine/appengine.dart'; +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server/google_auth_provider.dart'; import 'package:cocoon_server_test/fake_secret_manager.dart'; import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/server.dart'; import 'package:cocoon_service/src/foundation/providers.dart'; -import 'package:cocoon_service/src/request_handling/dashboard_authentication.dart'; import 'package:cocoon_service/src/service/big_query.dart'; import 'package:cocoon_service/src/service/build_status_service.dart'; import 'package:cocoon_service/src/service/commit_service.dart'; @@ -19,9 +19,6 @@ import 'package:cocoon_service/src/service/flags/dynamic_config.dart'; import 'package:cocoon_service/src/service/get_files_changed.dart'; import 'package:cocoon_service/src/service/scheduler/ci_yaml_fetcher.dart'; -import '../test/src/service/fake_content_aware_hash_service.dart'; -import '../test/src/service/fake_firestore_service.dart'; - Future main() async { final cache = CacheService(inMemory: false); final config = Config( diff --git a/conductor/product.md b/conductor/product.md index 93b76087b9..8411b2b2b3 100644 --- a/conductor/product.md +++ b/conductor/product.md @@ -15,7 +15,7 @@ Cocoon is the CI coordination and orchestration system for the Flutter project. * **Reliable Integration:** Seamlessly coordinate between GitHub webhooks, LUCI build bots, and Google Cloud services. ## Key Features -* **CI Orchestration:** Automates the scheduling and tracking of LUCI builds for the Flutter framework and engine. +* **Offline Integration Testing:** A dedicated testing environment that simulates all backend services (GitHub, Firestore, BigQuery, LUCI) with functional fakes, enabling deterministic, offline verification of frontend and backend logic. * **Tree Status Dashboard:** A Flutter-based web application that provides a visual overview of build health across various commits and branches. * **Presubmit Check Details:** APIs to retrieve detailed attempt history and status for specific presubmit checks, aiding in debugging and visibility. * **Merge Queue Visibility:** APIs for querying and inspecting recent GitHub Merge Queue webhook events to diagnose integration issues. diff --git a/conductor/tech-stack.md b/conductor/tech-stack.md index 866f7383bc..d8aa022e20 100644 --- a/conductor/tech-stack.md +++ b/conductor/tech-stack.md @@ -26,7 +26,9 @@ * `app_dart/`: Main CI orchestrator and backend API. * `auto_submit/`: Automated PR management bot. * `dashboard/`: Flutter Web frontend. - * `packages/`: Shared libraries and internal SDKs (`cocoon_common`, `buildbucket-dart`). + * `packages/`: Shared libraries and internal SDKs (`cocoon_common`, `buildbucket-dart`, `cocoon_integration_test`). +* **Testing Infrastructure:** + * **Integration Testing:** `packages/cocoon_integration_test` provides an offline environment with functional fakes for all GCP and external services, allowing full-stack integration testing without live connections. * **Code Generation:** * `build_runner` for `json_serializable` (DTOs/Database models). * `package:protobuf` for internal configuration (`.ci.yaml`) and BuildBucket interactions. \ No newline at end of file diff --git a/conductor/tracks.md b/conductor/tracks.md index 39602a5806..6ee7e79680 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -2,5 +2,11 @@ --- -- [x] **Track: Implement get presubmit check api to show check details on dashboard** -*Link: [./tracks/get_presubmit_checks_20260205/](./tracks/get_presubmit_checks_20260205/)* +- [~] **Track: Cocoon Integration Test Environment** +*Link: [./tracks/cocoon_integration_test_20260206/](./tracks/cocoon_integration_test_20260206/)* + +--- + +- [~] **Track: Build a Merge Queue Dashboard** +*Link: [./tracks/merge_queue_dashboard_20260205/](./tracks/merge_queue_dashboard_20260205/)* + diff --git a/conductor/tracks/cocoon_integration_test_20260206/plan.md b/conductor/tracks/cocoon_integration_test_20260206/plan.md new file mode 100644 index 0000000000..491b41efcc --- /dev/null +++ b/conductor/tracks/cocoon_integration_test_20260206/plan.md @@ -0,0 +1,25 @@ +# Implementation Plan: Cocoon Integration Test + +## Phase 1: Package Setup & Fake Consolidation +- [x] Task: Create `packages/cocoon_integration_test` structure. + - [x] Create directory and `pubspec.yaml`. + - [x] Add dependencies: `cocoon_service` (app_dart), `cocoon_server_test`, `test`, `http`, etc. +- [x] Task: Consolidate Fakes into `packages/cocoon_integration_test`. + - [x] Identify `FakeConfig`, `FakeDashboardAuthentication`, `FakeBuildBucketClient`, `FakeLuciBuildService`, `FakeGerritService`, `FakeScheduler`, `FakeCiYamlFetcher`, `FakeBuildStatusService`, `FakeContentAwareHashService`. + - [x] Move these from `app_dart/test/src/` (or wherever they are) to `packages/cocoon_integration_test/lib/src/fakes/`. + - [x] Export them from `packages/cocoon_integration_test/lib/testing.dart`. + - [x] Update `app_dart` to depend on `cocoon_integration_test` for these fakes (refactor existing tests). + +## Phase 2: Implementation of Integration Server +- [x] Task: Implement `IntegrationServer` class. + - [x] Create `packages/cocoon_integration_test/lib/src/server.dart`. + - [x] Implement `startServer({Config? config, ...})` which sets up the `CocoonService` (from `app_dart`) with the Fakes. + - [x] Ensure `CacheService` is `inMemory: true`. +- [x] Task: Implement Test Helpers. + - [x] Create helper methods to seed the Fakes (e.g., `populateFirestore`, `setConfigs`). + +## Phase 3: Verification +- [x] Task: Write a "Smoke Test". + - [x] Create `packages/cocoon_integration_test/test/server_test.dart`. + - [x] Verify the server starts and responds to a simple health check or API call. +- [ ] Task: Conductor - User Manual Verification (Protocol in workflow.md) diff --git a/conductor/tracks/cocoon_integration_test_20260206/spec.md b/conductor/tracks/cocoon_integration_test_20260206/spec.md new file mode 100644 index 0000000000..7176174956 --- /dev/null +++ b/conductor/tracks/cocoon_integration_test_20260206/spec.md @@ -0,0 +1,33 @@ +# Specification: Cocoon Integration Test + +## Goal +Create a new package `packages/cocoon_integration_test` to facilitate offline integration testing of the Cocoon backend and frontend. + +## Background +Currently, testing the Cocoon server (`app_dart`) involves unit tests or live integration tests. There is a need for a "fake server" environment that can run offline, simulating all external dependencies (GitHub, Gerrit, BuildBucket, etc.) with in-memory fakes. This will allow for robust, deterministic integration testing of the dashboard and other clients against a running (fake) server. + +## Requirements +1. **New Package:** `packages/cocoon_integration_test`. +2. **Fake Server Factory:** Provide a method to start the `app_dart` server with injected fakes. +3. **Fakes over Mocks:** Prefer using Fakes (functional implementations) over Mocks (record/replay) where possible. +4. **Components to Fake:** + - `Config` (`FakeConfig` with `webhookKeyValue`) + - `CacheService` (In-memory) + - `Authentication` (`FakeDashboardAuthentication` for both standard and swarming) + - `BranchService` + - `BuildBucketClient` + - `LuciBuildService` + - `GithubChecksService` + - `CommitService` + - `GerritService` + - `Scheduler` + - `CiYamlFetcher` + - `BuildStatusService` + - `ContentAwareHashService` +5. **External Dependencies:** The package should depend on `app_dart` (likely via path or git dependency if strict package separation isn't enforced yet, or by moving shared types to `cocoon_common`). *Note: For this iteration, we will assume `app_dart` is accessible.* + +## Deliverables +- `packages/cocoon_integration_test/pubspec.yaml` +- `packages/cocoon_integration_test/lib/cocoon_integration_test.dart` (Entry point) +- `packages/cocoon_integration_test/lib/src/server.dart` (Server setup logic) +- Basic test to verify the fake server starts. diff --git a/conductor/tracks/merge_queue_dashboard_20260205/index.md b/conductor/tracks/merge_queue_dashboard_20260205/index.md new file mode 100644 index 0000000000..d8c1a82ca8 --- /dev/null +++ b/conductor/tracks/merge_queue_dashboard_20260205/index.md @@ -0,0 +1,5 @@ +# Track merge_queue_dashboard_20260205 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/tracks/merge_queue_dashboard_20260205/metadata.json b/conductor/tracks/merge_queue_dashboard_20260205/metadata.json new file mode 100644 index 0000000000..8009d6d0be --- /dev/null +++ b/conductor/tracks/merge_queue_dashboard_20260205/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "merge_queue_dashboard_20260205", + "type": "feature", + "status": "new", + "created_at": "2026-02-05T10:00:00Z", + "updated_at": "2026-02-05T10:00:00Z", + "description": "Build a Merge Queue Dashboard for rendering the @app_dart/lib/src/request_handlers/merge_queue_hooks.dart and providing an ability to resend merge queue events using the `/api/github-webhook-replay` API." +} diff --git a/conductor/tracks/merge_queue_dashboard_20260205/plan.md b/conductor/tracks/merge_queue_dashboard_20260205/plan.md new file mode 100644 index 0000000000..718178263b --- /dev/null +++ b/conductor/tracks/merge_queue_dashboard_20260205/plan.md @@ -0,0 +1,51 @@ +# Implementation Plan: Merge Queue Dashboard + +## Phase 1: Service Layer Integration +- [x] Task: Write Tests for `fetchMergeQueueHooks` and `replayGitHubWebhook` in `CocoonService`. + - [x] Add tests to `dashboard/test/service/appengine_cocoon_test.dart` (or create a new test file). + - [x] Define expected behavior for successful fetches (List of `MergeGroupHook`) and successful replays (POST request). + - [x] Define expected behavior for access denied (403) and other API errors. +- [x] Task: Update `CocoonService` interface and implement in `AppEngineCocoonService`. + - [x] Add `fetchMergeQueueHooks` to `CocoonService` in `dashboard/lib/service/cocoon.dart`. + - [x] Add `replayGitHubWebhook` to `CocoonService` in `dashboard/lib/service/cocoon.dart`. + - [x] Implement `fetchMergeQueueHooks` (GET `/api/merge_queue_hooks`) in `AppEngineCocoonService`. + - [x] Implement `replayGitHubWebhook` (POST `/api/github-webhook-replay?id=...`) in `AppEngineCocoonService`. + - [x] Ensure the `idToken` is included in the headers for both requests. +- [x] Task: Conductor - User Manual Verification 'Phase 1: Service Layer Integration' (Protocol in workflow.md) +[checkpoint: ea18514] + +## Phase 2: State Management +- [ ] Task: Write Tests for `MergeQueueState`. + - [ ] Create `dashboard/test/state/merge_queue_test.dart`. + - [ ] Test initial state, successful data fetching, and handling of 403 Forbidden errors. + - [ ] Test searching/filtering logic by commit hash, ref, and message. + - [ ] Test auto-refresh timer logic and debounce logic for the "Resend" action. +- [ ] Task: Implement `MergeQueueState`. + - [ ] Create `dashboard/lib/state/merge_queue.dart` extending `ChangeNotifier`. + - [ ] Integrate `CocoonService` and `FirebaseAuthService`. + - [ ] Implement the `fetch` logic with state variables for loading, error, and filtered data. + - [ ] Implement the 3-second debounce logic for the `replay` action. + - [ ] Implement auto-refresh logic based on a user-selectable interval. +- [ ] Task: Conductor - User Manual Verification 'Phase 2: State Management' (Protocol in workflow.md) + +## Phase 3: Dashboard View & UI +- [ ] Task: Write Widget and Golden Tests for `MergeQueueDashboard`. + - [ ] Create `dashboard/test/views/merge_queue_dashboard_test.dart`. + - [ ] Verify that the dashboard displays an error message when access is denied. + - [ ] Verify that the search bar correctly triggers filtering. + - [ ] Verify that the "Resend" button is disabled during the debounce period. + - [ ] **Golden Test:** Create a golden image test to ensure the UI renders correctly (data table, search bar, buttons) across different screen sizes. +- [ ] Task: Implement `MergeQueueDashboard` view. + - [ ] Create `dashboard/lib/views/merge_queue_dashboard_page.dart`. + - [ ] Implement the UI layout using a `Scaffold` with a header for Search and Auto-Refresh controls. + - [ ] Implement the data table to display Merge Queue event details. + - [ ] Connect the UI to `MergeQueueState` and provide visual feedback for resend actions. +- [ ] Task: Conductor - User Manual Verification 'Phase 3: Dashboard View & UI' (Protocol in workflow.md) + +## Phase 4: Navigation & Integration +- [ ] Task: Write Tests for navigation and routing. + - [ ] Update `dashboard/test/main_test.dart` or similar to verify the new route. +- [ ] Task: Register the new route and add navigation. + - [ ] Update `dashboard/lib/main.dart` to include the `/merge-queue` route in `onGenerateRoute`. + - [ ] Update `dashboard/lib/logic/links.dart` to add the "Merge Queue" link to the navigation drawer. +- [ ] Task: Conductor - User Manual Verification 'Phase 4: Navigation & Integration' (Protocol in workflow.md) diff --git a/conductor/tracks/merge_queue_dashboard_20260205/spec.md b/conductor/tracks/merge_queue_dashboard_20260205/spec.md new file mode 100644 index 0000000000..1c7c42d219 --- /dev/null +++ b/conductor/tracks/merge_queue_dashboard_20260205/spec.md @@ -0,0 +1,47 @@ +# Specification: Merge Queue Dashboard + +## Overview +Create a new standalone dashboard page in the Flutter-based Cocoon dashboard to visualize and manage GitHub Merge Queue events. This tool will allow Flutter EngProd and Release Engineers to monitor merge queue activity, search for specific events, and manually trigger event replays to diagnose and fix integration issues. + +## Functional Requirements +- **Standalone Page:** A new route (e.g., `/merge-queue`) in the dashboard application. +- **Data Table:** A scrollable list of merge queue events with the following columns: + - Document ID (Firestore ID) + - Date/Time + - Event/Action (e.g., `dequeued`, `merged`) + - Base Ref + - Commit Message + - Git Hash (Head Commit ID) +- **Search/Filter:** A search bar to filter the displayed list by: + - Git Hash + - Base Ref + - Commit Message +- **Individual Resend Action:** A "Resend" button on each row that calls the `/api/github-webhook-replay` API. + - **Debouncing:** Disable the "Resend" button for 3 seconds after a click to prevent accidental double-deliveries. +- **Interactive Feedback:** + - Visual indicator on the row showing the status of the replay attempt (Success/Failure) after the action is triggered. +- **Access Control & Error Handling:** + - If the fetch from `/api/merge_queue_hooks` fails (e.g., 403 Forbidden for non-Google users), display a clear error message on the screen (e.g., "Access Denied: You must be logged in with a @google.com account"). +- **Auto-Refresh:** + - A dropdown menu to select an auto-refresh interval (e.g., Off, 30s, 1m, 5m). + - When enabled, the dashboard periodically calls `/api/merge_queue_hooks` to update the event list. +- **Data Source:** Integration with the existing `MergeQueueHooks` API endpoint. + +## Non-Functional Requirements +- **Consistency:** Follow Material Design 3 principles as defined in the project's tech stack and product guidelines. +- **Performance:** Efficient rendering of the scrollable list using `ListView.builder` or a Data Table. +- **Responsive Design:** Ensure the table layout is usable on desktop and larger tablet screens. + +## Acceptance Criteria +- [ ] Users can navigate to the Merge Queue Dashboard via the navigation menu. +- [ ] The list displays real-time data from the `MergeQueueHooks` endpoint. +- [ ] Users see a clear error message if they lack permission to view the data. +- [ ] Users can search for a specific commit hash and see matching rows. +- [ ] Clicking "Resend" triggers the replay API and disables the button for 3 seconds. +- [ ] The UI visually confirms when a replay request succeeds or fails on the corresponding row. +- [ ] Selecting an auto-refresh interval correctly updates the data periodically. + +## Out of Scope +- Bulk resending of events. +- Advanced date-range filtering. +- Editing event data. diff --git a/dashboard/lib/service/appengine_cocoon.dart b/dashboard/lib/service/appengine_cocoon.dart index bd5c017c20..15d9cc3faf 100644 --- a/dashboard/lib/service/appengine_cocoon.dart +++ b/dashboard/lib/service/appengine_cocoon.dart @@ -395,6 +395,68 @@ class AppEngineCocoonService implements CocoonService { ); } + @override + Future>> fetchMergeQueueHooks({ + required String idToken, + }) async { + final getMergeQueueHooksUrl = apiEndpoint('/api/merge_queue_hooks'); + + final response = await _client.get( + getMergeQueueHooksUrl, + headers: {'X-Flutter-IdToken': idToken}, + ); + + if (response.statusCode != HttpStatus.ok) { + return CocoonResponse.error( + '/api/merge_queue_hooks returned ${response.statusCode}', + statusCode: response.statusCode, + ); + } + + try { + final jsonResponse = jsonDecode(response.body) as Map; + final hooks = MergeGroupHooks.fromJson(jsonResponse); + return CocoonResponse.data(hooks.hooks); + } catch (error) { + return CocoonResponse.error( + error.toString(), + statusCode: response.statusCode, + ); + } + } + + @override + Future> replayGitHubWebhook({ + required String idToken, + required String id, + }) async { + if (idToken.isEmpty) { + return const CocoonResponse.error( + 'Sign in to replay events', + statusCode: 401, + ); + } + + final replayUrl = apiEndpoint( + '/api/github-webhook-replay', + queryParameters: {'id': id}, + ); + + final response = await _client.post( + replayUrl, + headers: {'X-Flutter-IdToken': idToken}, + ); + + if (response.statusCode == HttpStatus.ok) { + return const CocoonResponse.data(null); + } + + return CocoonResponse.error( + 'HTTP Code: ${response.statusCode}, ${response.body}', + statusCode: response.statusCode, + ); + } + /// Construct the API endpoint based on the priority of using a local endpoint /// before falling back to the production endpoint. /// diff --git a/dashboard/lib/service/cocoon.dart b/dashboard/lib/service/cocoon.dart index 6c02b834f5..fe20aaf24d 100644 --- a/dashboard/lib/service/cocoon.dart +++ b/dashboard/lib/service/cocoon.dart @@ -106,6 +106,17 @@ abstract class CocoonService { String? issueLink, String? note, }); + + /// Get the current list of merge queue hooks. + Future>> fetchMergeQueueHooks({ + required String idToken, + }); + + /// Replay a GitHub webhook. + Future> replayGitHubWebhook({ + required String idToken, + required String id, + }); } /// Wrapper class for data this state serves. diff --git a/dashboard/lib/service/dev_cocoon.dart b/dashboard/lib/service/dev_cocoon.dart index 93454ceeb0..4158dd888b 100644 --- a/dashboard/lib/service/dev_cocoon.dart +++ b/dashboard/lib/service/dev_cocoon.dart @@ -275,6 +275,21 @@ class DevelopmentCocoonService implements CocoonService { ); } + @override + Future>> fetchMergeQueueHooks({ + required String idToken, + }) async { + return const CocoonResponse>.data([]); + } + + @override + Future> replayGitHubWebhook({ + required String idToken, + required String id, + }) async { + return const CocoonResponse.data(null); + } + static const int _commitGap = 2 * 60 * 1000; // 2 minutes between commits List _createFakeCommitStatuses( diff --git a/dashboard/merge_queue_dashboard_modal.png b/dashboard/merge_queue_dashboard_modal.png new file mode 100644 index 0000000000..35db25af90 Binary files /dev/null and b/dashboard/merge_queue_dashboard_modal.png differ diff --git a/dashboard/pubspec.yaml b/dashboard/pubspec.yaml index e857016531..a1aeb2c4a3 100644 --- a/dashboard/pubspec.yaml +++ b/dashboard/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: cached_network_image_platform_interface: ^4.1.1 cocoon_common: path: ../packages/cocoon_common + cocoon_service: ^0.0.0 collection: any # Match Flutter SDK firebase_auth: ^6.0.0 firebase_core: 4.4.0 # Rolled by dependabot @@ -24,6 +25,7 @@ dependencies: flutter: sdk: flutter flutter_app_icons: 0.1.1 # Rolled by dependabot + github: ^9.25.0 google_sign_in: ^7.0.0 google_sign_in_platform_interface: ^3.0.0 google_sign_in_web: ^1.0.0 @@ -39,6 +41,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.15 # Rolled by dependabot + cocoon_integration_test: + path: ../packages/cocoon_integration_test dart_flutter_team_lints: 3.5.2 flutter_test: sdk: flutter diff --git a/dashboard/test/integration/update_test_suppression_test.dart b/dashboard/test/integration/update_test_suppression_test.dart new file mode 100644 index 0000000000..7db29fab1d --- /dev/null +++ b/dashboard/test/integration/update_test_suppression_test.dart @@ -0,0 +1,77 @@ +// Copyright 2026 The Flutter Authors. 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:cocoon_integration_test/cocoon_integration_test.dart'; +import 'package:cocoon_service/src/service/flags/dynamic_config.dart'; +import 'package:flutter_dashboard/service/appengine_cocoon.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:github/github.dart'; + +void main() { + group('Integration: Update Test Suppression', () { + late IntegrationServer server; + late IntegrationHttpClient client; + late AppEngineCocoonService service; + + setUp(() async { + final githubService = FakeGithubService(); + githubService.getIssueMock = (slug, {issueNumber}) { + if (issueNumber == 123) { + return Future.value(Issue(state: 'open', id: 123, number: 123)); + } + return null; + }; + + server = IntegrationServer( + config: FakeConfig( + webhookKeyValue: 'fake-secret', + dynamicConfig: DynamicConfig(dynamicTestSuppression: true), + githubService: githubService, + ), + ); + + client = IntegrationHttpClient(server); + service = AppEngineCocoonService(client: client); + }); + + test('suppress and unsuppress a test', () async { + const repo = 'flutter/flutter'; + const testName = 'linux_android'; + const idToken = 'fake-token'; + + // 1. Verify initially empty + var suppressedTests = await service.fetchSuppressedTests(repo: repo); + expect(suppressedTests.data, isEmpty); + + // 2. Suppress the test + final suppressResponse = await service.updateTestSuppression( + idToken: idToken, + repo: repo, + testName: testName, + suppress: true, + issueLink: 'https://github.com/flutter/flutter/issues/123', + note: 'Flaky', + ); + expect(suppressResponse.error, isNull); + + // 3. Verify it is suppressed + suppressedTests = await service.fetchSuppressedTests(repo: repo); + expect(suppressedTests.data, hasLength(1)); + expect(suppressedTests.data!.first.name, testName); + + // 4. Unsuppress the test + final unsuppressResponse = await service.updateTestSuppression( + idToken: idToken, + repo: repo, + testName: testName, + suppress: false, + ); + expect(unsuppressResponse.error, isNull); + + // 5. Verify it is gone + suppressedTests = await service.fetchSuppressedTests(repo: repo); + expect(suppressedTests.data, isEmpty); + }); + }); +} diff --git a/dashboard/test/service/appengine_cocoon_test.dart b/dashboard/test/service/appengine_cocoon_test.dart index 287b239920..4c0d5a7f1b 100644 --- a/dashboard/test/service/appengine_cocoon_test.dart +++ b/dashboard/test/service/appengine_cocoon_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:convert'; + import 'package:cocoon_common/rpc_model.dart'; import 'package:cocoon_common/task_status.dart'; import 'package:flutter/foundation.dart' show kIsWeb; @@ -537,4 +539,90 @@ void main() { } }); }); + + group('AppEngine CocoonService fetchMergeQueueHooks', () { + late AppEngineCocoonService service; + + test('should return list of MergeGroupHook', () async { + final expectedHooks = MergeGroupHooks( + hooks: [ + MergeGroupHook( + id: '1', + timestamp: 123, + action: 'dequeued', + headRef: 'refs/heads/main', + headCommitId: 'sha', + headCommitMessage: 'msg', + ), + ], + ); + + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response(jsonEncode(expectedHooks.toJson()), 200); + }), + ); + + final response = await service.fetchMergeQueueHooks(idToken: 'token'); + expect(response.error, isNull); + expect(response.data!.length, 1); + expect(response.data!.first.id, '1'); + }); + + test('should return error on failure', () async { + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response('Internal Server Error', 500); + }), + ); + + final response = await service.fetchMergeQueueHooks(idToken: 'token'); + expect(response.error, isNotNull); + }); + }); + + group('AppEngine CocoonService replayGitHubWebhook', () { + late AppEngineCocoonService service; + + test('should return true if request succeeds', () async { + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response('', 200); + }), + ); + + final response = await service.replayGitHubWebhook( + idToken: 'token', + id: '1', + ); + expect(response.error, isNull); + }); + + test('should set error in response if ID token is null', () async { + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response('', 200); + }), + ); + final response = await service.replayGitHubWebhook(idToken: '', id: '1'); + expect( + response.error, + allOf([isNotNull, contains('Sign in to replay events')]), + ); + }); + + test('should return error on failure', () async { + service = AppEngineCocoonService( + client: MockClient((Request request) async { + return Response('Internal Server Error', 500); + }), + ); + + final response = await service.replayGitHubWebhook( + idToken: 'token', + id: '1', + ); + expect(response.error, isNotNull); + }); + }); } diff --git a/dashboard/test/service/dev_cocoon_test.dart b/dashboard/test/service/dev_cocoon_test.dart new file mode 100644 index 0000000000..232e652bed --- /dev/null +++ b/dashboard/test/service/dev_cocoon_test.dart @@ -0,0 +1,30 @@ +// Copyright 2019 The Flutter Authors. 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:flutter_dashboard/service/dev_cocoon.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('DevelopmentCocoonService', () { + late DevelopmentCocoonService service; + + setUp(() { + service = DevelopmentCocoonService(DateTime.now()); + }); + + test('fetchMergeQueueHooks returns empty list', () async { + final response = await service.fetchMergeQueueHooks(idToken: 'token'); + expect(response.error, isNull); + expect(response.data, isEmpty); + }); + + test('replayGitHubWebhook returns success', () async { + final response = await service.replayGitHubWebhook( + idToken: 'token', + id: '1', + ); + expect(response.error, isNull); + }); + }); +} diff --git a/dashboard/test/utils/mocks.mocks.dart b/dashboard/test/utils/mocks.mocks.dart index 9c8b71f822..e1a77d00c6 100644 --- a/dashboard/test/utils/mocks.mocks.dart +++ b/dashboard/test/utils/mocks.mocks.dart @@ -547,6 +547,45 @@ class MockCocoonService extends _i1.Mock implements _i3.CocoonService { ), ) as _i8.Future<_i3.CocoonResponse>); + + @override + _i8.Future<_i3.CocoonResponse>> + fetchMergeQueueHooks({required String? idToken}) => + (super.noSuchMethod( + Invocation.method(#fetchMergeQueueHooks, [], {#idToken: idToken}), + returnValue: + _i8.Future<_i3.CocoonResponse>>.value( + _FakeCocoonResponse_2>( + this, + Invocation.method(#fetchMergeQueueHooks, [], { + #idToken: idToken, + }), + ), + ), + ) + as _i8.Future<_i3.CocoonResponse>>); + + @override + _i8.Future<_i3.CocoonResponse> replayGitHubWebhook({ + required String? idToken, + required String? id, + }) => + (super.noSuchMethod( + Invocation.method(#replayGitHubWebhook, [], { + #idToken: idToken, + #id: id, + }), + returnValue: _i8.Future<_i3.CocoonResponse>.value( + _FakeCocoonResponse_2( + this, + Invocation.method(#replayGitHubWebhook, [], { + #idToken: idToken, + #id: id, + }), + ), + ), + ) + as _i8.Future<_i3.CocoonResponse>); } /// A class which mocks [BuildState]. diff --git a/packages/cocoon_integration_test/.gitignore b/packages/cocoon_integration_test/.gitignore new file mode 100644 index 0000000000..3cceda5578 --- /dev/null +++ b/packages/cocoon_integration_test/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/packages/cocoon_integration_test/CHANGELOG.md b/packages/cocoon_integration_test/CHANGELOG.md new file mode 100644 index 0000000000..effe43c82c --- /dev/null +++ b/packages/cocoon_integration_test/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/packages/cocoon_integration_test/README.md b/packages/cocoon_integration_test/README.md new file mode 100644 index 0000000000..8831761b89 --- /dev/null +++ b/packages/cocoon_integration_test/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/packages/cocoon_integration_test/analysis_options.yaml b/packages/cocoon_integration_test/analysis_options.yaml new file mode 100644 index 0000000000..6ea6759dd7 --- /dev/null +++ b/packages/cocoon_integration_test/analysis_options.yaml @@ -0,0 +1,8 @@ +include: ../../analysis_options.yaml + +analyzer: + errors: + duplicate_ignore: ignore + implementation_imports: ignore + invalid_use_of_internal_member: ignore + invalid_use_of_visible_for_testing_member: ignore \ No newline at end of file diff --git a/packages/cocoon_integration_test/build.yaml b/packages/cocoon_integration_test/build.yaml new file mode 100644 index 0000000000..4b55d7f6f7 --- /dev/null +++ b/packages/cocoon_integration_test/build.yaml @@ -0,0 +1,6 @@ +targets: + $default: + builders: + mockito:mockBuilder: + generate_for: + - lib/src/utilities/mocks.dart diff --git a/packages/cocoon_integration_test/lib/cocoon_integration_test.dart b/packages/cocoon_integration_test/lib/cocoon_integration_test.dart new file mode 100644 index 0000000000..347125dbf6 --- /dev/null +++ b/packages/cocoon_integration_test/lib/cocoon_integration_test.dart @@ -0,0 +1,6 @@ +// Copyright 2026 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/server.dart'; +export 'testing.dart'; diff --git a/app_dart/test/src/delegate_matcher.dart b/packages/cocoon_integration_test/lib/src/delegate_matcher.dart similarity index 100% rename from app_dart/test/src/delegate_matcher.dart rename to packages/cocoon_integration_test/lib/src/delegate_matcher.dart diff --git a/app_dart/test/src/service/fake_auth_client.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_auth_client.dart similarity index 100% rename from app_dart/test/src/service/fake_auth_client.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_auth_client.dart diff --git a/packages/cocoon_integration_test/lib/src/fakes/fake_big_query_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_big_query_service.dart new file mode 100644 index 0000000000..eed8f419fd --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_big_query_service.dart @@ -0,0 +1,13 @@ +// Copyright 2020 The Flutter Authors. 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:cocoon_server_test/mocks.dart'; +import 'package:cocoon_service/src/service/big_query.dart'; + +import 'fake_tabledata_resource.dart'; + +class FakeBigQueryService extends BigQueryService { + FakeBigQueryService() + : super.forTesting(FakeTabledataResource(), MockJobsResource()); +} diff --git a/app_dart/test/src/service/fake_build_bucket_client.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_build_bucket_client.dart similarity index 100% rename from app_dart/test/src/service/fake_build_bucket_client.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_build_bucket_client.dart diff --git a/app_dart/test/src/service/fake_build_status_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_build_status_service.dart similarity index 100% rename from app_dart/test/src/service/fake_build_status_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_build_status_service.dart diff --git a/packages/cocoon_integration_test/lib/src/fakes/fake_cache_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_cache_service.dart new file mode 100644 index 0000000000..d8c8f23e36 --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_cache_service.dart @@ -0,0 +1,55 @@ +// Copyright 2026 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:cocoon_service/src/service/cache_service.dart'; + +/// A [CacheService] that doesn't actually cache anything. +class FakeCacheService extends CacheService { + FakeCacheService() : super(inMemory: true); + + @override + Future getOrCreate( + String subcacheName, + String key, { + required Future Function()? createFn, + Duration ttl = const Duration(minutes: 1), + }) async { + return createFn?.call(); + } + + @override + Future getOrCreateWithLocking( + String subcacheName, + String key, { + required Future Function()? createFn, + Duration ttl = const Duration(minutes: 1), + }) async { + return createFn?.call(); + } + + @override + Future set( + String subcacheName, + String key, + Uint8List? value, { + Duration ttl = const Duration(minutes: 1), + }) async { + return value; + } + + @override + Future setWithLocking( + String subcacheName, + String key, + Uint8List? value, { + Duration ttl = const Duration(minutes: 1), + }) async { + return value; + } + + @override + Future purge(String subcacheName, String key) async {} +} diff --git a/app_dart/test/src/service/fake_ci_yaml_fetcher.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_ci_yaml_fetcher.dart similarity index 100% rename from app_dart/test/src/service/fake_ci_yaml_fetcher.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_ci_yaml_fetcher.dart diff --git a/app_dart/test/src/fake_config.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_config.dart similarity index 99% rename from app_dart/test/src/fake_config.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_config.dart index cb6fa73efe..c3dca0682f 100644 --- a/app_dart/test/src/fake_config.dart +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_config.dart @@ -11,7 +11,7 @@ import 'package:cocoon_service/src/service/luci_build_service/cipd_version.dart' import 'package:github/github.dart' as gh; import 'package:graphql/client.dart'; -import 'service/fake_github_service.dart'; +import 'fake_github_service.dart'; // ignore: must_be_immutable // TODO(matanlurey): Make this *not* a mess. See https://github.com/flutter/flutter/issues/164646. diff --git a/app_dart/test/src/service/fake_content_aware_hash_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_content_aware_hash_service.dart similarity index 100% rename from app_dart/test/src/service/fake_content_aware_hash_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_content_aware_hash_service.dart diff --git a/app_dart/test/src/request_handling/fake_dashboard_authentication.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_dashboard_authentication.dart similarity index 55% rename from app_dart/test/src/request_handling/fake_dashboard_authentication.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_dashboard_authentication.dart index 501bab52b5..38d8721273 100644 --- a/app_dart/test/src/request_handling/fake_dashboard_authentication.dart +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_dashboard_authentication.dart @@ -4,9 +4,7 @@ import 'dart:io'; -import 'package:appengine/appengine.dart'; -import 'package:cocoon_service/src/request_handling/authentication.dart'; -import 'package:cocoon_service/src/request_handling/dashboard_authentication.dart'; +import 'package:cocoon_service/cocoon_service.dart'; import 'package:cocoon_service/src/request_handling/exceptions.dart'; // ignore: must_be_immutable @@ -42,50 +40,8 @@ class FakeAuthenticatedContext implements AuthenticatedContext { } class FakeClientContext implements ClientContext { - FakeClientContext({ - this.isDevelopmentEnvironment = true, - this.isProductionEnvironment = false, - FakeAppEngineContext? applicationContext, - }) : applicationContext = applicationContext ?? FakeAppEngineContext(); - - @override - FakeAppEngineContext applicationContext; + FakeClientContext({this.isDevelopmentEnvironment = true}); @override bool isDevelopmentEnvironment; - - @override - bool isProductionEnvironment; - - @override - late Services services; - - @override - String? traceId; -} - -class FakeAppEngineContext implements AppEngineContext { - @override - String applicationID = 'flutter-dashboard'; - - @override - late String fullQualifiedApplicationId; - - @override - late String instance; - - @override - String? instanceId; - - @override - late bool isDevelopmentEnvironment; - - @override - late String module; - - @override - String partition = '[default]'; - - @override - late String version; } diff --git a/packages/cocoon_integration_test/lib/src/fakes/fake_entry.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_entry.dart new file mode 100644 index 0000000000..600d06f63f --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_entry.dart @@ -0,0 +1,28 @@ +// Copyright 2019 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:neat_cache/neat_cache.dart'; + +class FakeEntry extends Entry { + Uint8List value = Uint8List.fromList('abc123'.codeUnits); + + @override + Future get([ + Future Function()? create, + Duration? ttl, + ]) async => value; + + @override + Future purge({int retries = 0}) => throw UnimplementedError(); + + @override + Future set(Uint8List? value, [Duration? ttl]) async { + value = value; + + return value; + } +} diff --git a/app_dart/test/src/service/fake_firebase_jwt_validator.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_firebase_jwt_validator.dart similarity index 100% rename from app_dart/test/src/service/fake_firebase_jwt_validator.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_firebase_jwt_validator.dart diff --git a/app_dart/test/src/service/fake_firestore_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart similarity index 100% rename from app_dart/test/src/service/fake_firestore_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart diff --git a/app_dart/test/src/service/fake_gerrit_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_gerrit_service.dart similarity index 100% rename from app_dart/test/src/service/fake_gerrit_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_gerrit_service.dart diff --git a/app_dart/test/src/service/fake_get_files_changed.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_get_files_changed.dart similarity index 100% rename from app_dart/test/src/service/fake_get_files_changed.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_get_files_changed.dart diff --git a/app_dart/test/src/service/fake_github_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_github_service.dart similarity index 97% rename from app_dart/test/src/service/fake_github_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_github_service.dart index cc4128d2bd..bc76297603 100644 --- a/app_dart/test/src/service/fake_github_service.dart +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_github_service.dart @@ -143,8 +143,13 @@ class FakeGithubService implements GithubService { return []; } + Future? Function(RepositorySlug, {int? issueNumber})? getIssueMock; + @override Future? getIssue(RepositorySlug slug, {int? issueNumber}) { + if (getIssueMock != null) { + return getIssueMock!(slug, issueNumber: issueNumber); + } return null; } diff --git a/app_dart/test/src/service/fake_graphql_client.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_graphql_client.dart similarity index 100% rename from app_dart/test/src/service/fake_graphql_client.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_graphql_client.dart diff --git a/app_dart/test/src/request_handling/fake_http.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_http.dart similarity index 100% rename from app_dart/test/src/request_handling/fake_http.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_http.dart diff --git a/app_dart/test/src/service/fake_luci_build_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_luci_build_service.dart similarity index 96% rename from app_dart/test/src/service/fake_luci_build_service.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_luci_build_service.dart index 50b87046dc..9c6e628ae6 100644 --- a/app_dart/test/src/service/fake_luci_build_service.dart +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_luci_build_service.dart @@ -9,10 +9,10 @@ import 'package:cocoon_service/src/service/cache_service.dart'; import 'package:cocoon_service/src/service/gerrit_service.dart'; import 'package:cocoon_service/src/service/luci_build_service.dart'; -import '../request_handling/fake_pubsub.dart'; import '../utilities/mocks.dart'; import 'fake_build_bucket_client.dart'; import 'fake_gerrit_service.dart'; +import 'fake_pubsub.dart'; /// Fake [LuciBuildService] for use in tests. class FakeLuciBuildService extends LuciBuildService { diff --git a/app_dart/test/src/request_handling/fake_pubsub.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_pubsub.dart similarity index 89% rename from app_dart/test/src/request_handling/fake_pubsub.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_pubsub.dart index 1810a74193..8d44afd32a 100644 --- a/app_dart/test/src/request_handling/fake_pubsub.dart +++ b/packages/cocoon_integration_test/lib/src/fakes/fake_pubsub.dart @@ -11,7 +11,7 @@ class FakePubSub extends PubSub { int exceptionRepetition = 1; @override - Future> publish(String topicName, dynamic json) async { + Future> publish(String topic, dynamic json) async { if (exceptionFlag && exceptionRepetition > 0) { exceptionRepetition--; throw DetailedApiRequestError(500, 'test api error'); diff --git a/app_dart/test/src/request_handling/fake_request_handler.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_request_handler.dart similarity index 100% rename from app_dart/test/src/request_handling/fake_request_handler.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_request_handler.dart diff --git a/app_dart/test/src/service/fake_scheduler.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_scheduler.dart similarity index 100% rename from app_dart/test/src/service/fake_scheduler.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_scheduler.dart diff --git a/app_dart/test/src/bigquery/fake_tabledata_resource.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_tabledata_resource.dart similarity index 100% rename from app_dart/test/src/bigquery/fake_tabledata_resource.dart rename to packages/cocoon_integration_test/lib/src/fakes/fake_tabledata_resource.dart diff --git a/packages/cocoon_integration_test/lib/src/integration_http_client.dart b/packages/cocoon_integration_test/lib/src/integration_http_client.dart new file mode 100644 index 0000000000..cf0373f31c --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/integration_http_client.dart @@ -0,0 +1,49 @@ +// Copyright 2026 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +import '../testing.dart'; +import 'server.dart'; + +class IntegrationHttpClient extends http.BaseClient { + IntegrationHttpClient(this.server); + + final IntegrationServer server; + + @override + Future send(http.BaseRequest request) async { + final bodyBytes = await request.finalize().toBytes(); + final body = utf8.decode(bodyBytes); + + final fakeResponse = FakeHttpResponse(); + final fakeRequest = FakeHttpRequest( + method: request.method, + body: body, + path: request.url.path, + queryParametersValue: request.url.queryParameters, + response: fakeResponse, + ); + + request.headers.forEach((key, value) { + fakeRequest.headers.add(key, value); + }); + + await server.server(fakeRequest); + + final responseHeaders = {}; + fakeResponse.headers.forEach((name, values) { + responseHeaders[name] = values.join(','); + }); + + return http.StreamedResponse( + Stream.value(utf8.encode(fakeResponse.body)), + fakeResponse.statusCode, + contentLength: fakeResponse.body.length, + headers: responseHeaders, + ); + } +} diff --git a/app_dart/test/src/model/_build_status_snapshot.dart b/packages/cocoon_integration_test/lib/src/model/_build_status_snapshot.dart similarity index 100% rename from app_dart/test/src/model/_build_status_snapshot.dart rename to packages/cocoon_integration_test/lib/src/model/_build_status_snapshot.dart diff --git a/app_dart/test/src/model/_ci_staging.dart b/packages/cocoon_integration_test/lib/src/model/_ci_staging.dart similarity index 100% rename from app_dart/test/src/model/_ci_staging.dart rename to packages/cocoon_integration_test/lib/src/model/_ci_staging.dart diff --git a/app_dart/test/src/model/_commit.dart b/packages/cocoon_integration_test/lib/src/model/_commit.dart similarity index 100% rename from app_dart/test/src/model/_commit.dart rename to packages/cocoon_integration_test/lib/src/model/_commit.dart diff --git a/app_dart/test/src/model/_content_aware_hash_builds.dart b/packages/cocoon_integration_test/lib/src/model/_content_aware_hash_builds.dart similarity index 100% rename from app_dart/test/src/model/_content_aware_hash_builds.dart rename to packages/cocoon_integration_test/lib/src/model/_content_aware_hash_builds.dart diff --git a/app_dart/test/src/model/_github_build_status.dart b/packages/cocoon_integration_test/lib/src/model/_github_build_status.dart similarity index 100% rename from app_dart/test/src/model/_github_build_status.dart rename to packages/cocoon_integration_test/lib/src/model/_github_build_status.dart diff --git a/app_dart/test/src/model/_github_gold_status.dart b/packages/cocoon_integration_test/lib/src/model/_github_gold_status.dart similarity index 100% rename from app_dart/test/src/model/_github_gold_status.dart rename to packages/cocoon_integration_test/lib/src/model/_github_gold_status.dart diff --git a/app_dart/test/src/model/_github_webhook_message.dart b/packages/cocoon_integration_test/lib/src/model/_github_webhook_message.dart similarity index 100% rename from app_dart/test/src/model/_github_webhook_message.dart rename to packages/cocoon_integration_test/lib/src/model/_github_webhook_message.dart diff --git a/app_dart/test/src/model/_pr_check_run.dart b/packages/cocoon_integration_test/lib/src/model/_pr_check_run.dart similarity index 100% rename from app_dart/test/src/model/_pr_check_run.dart rename to packages/cocoon_integration_test/lib/src/model/_pr_check_run.dart diff --git a/app_dart/test/src/model/_suppressed_test_.dart b/packages/cocoon_integration_test/lib/src/model/_suppressed_test_.dart similarity index 100% rename from app_dart/test/src/model/_suppressed_test_.dart rename to packages/cocoon_integration_test/lib/src/model/_suppressed_test_.dart diff --git a/app_dart/test/src/model/_task.dart b/packages/cocoon_integration_test/lib/src/model/_task.dart similarity index 100% rename from app_dart/test/src/model/_task.dart rename to packages/cocoon_integration_test/lib/src/model/_task.dart diff --git a/app_dart/test/src/model/_tree_status_change.dart b/packages/cocoon_integration_test/lib/src/model/_tree_status_change.dart similarity index 100% rename from app_dart/test/src/model/_tree_status_change.dart rename to packages/cocoon_integration_test/lib/src/model/_tree_status_change.dart diff --git a/app_dart/test/src/model/check_run_matcher.dart b/packages/cocoon_integration_test/lib/src/model/check_run_matcher.dart similarity index 95% rename from app_dart/test/src/model/check_run_matcher.dart rename to packages/cocoon_integration_test/lib/src/model/check_run_matcher.dart index 9a88796ad2..2a65ec9be9 100644 --- a/app_dart/test/src/model/check_run_matcher.dart +++ b/packages/cocoon_integration_test/lib/src/model/check_run_matcher.dart @@ -5,7 +5,7 @@ import 'package:github/github.dart'; import 'package:test/test.dart'; -const isTarget = CheckRunMatcher._(TypeMatcher()); +const isCheckRun = CheckRunMatcher._(TypeMatcher()); final class CheckRunMatcher extends Matcher { const CheckRunMatcher._(this._delegate); diff --git a/app_dart/test/src/model/ci_yaml_matcher.dart b/packages/cocoon_integration_test/lib/src/model/ci_yaml_matcher.dart similarity index 100% rename from app_dart/test/src/model/ci_yaml_matcher.dart rename to packages/cocoon_integration_test/lib/src/model/ci_yaml_matcher.dart diff --git a/app_dart/test/src/model/firestore_matcher.dart b/packages/cocoon_integration_test/lib/src/model/firestore_matcher.dart similarity index 92% rename from app_dart/test/src/model/firestore_matcher.dart rename to packages/cocoon_integration_test/lib/src/model/firestore_matcher.dart index e9034609ad..bdca4a4a3d 100644 --- a/app_dart/test/src/model/firestore_matcher.dart +++ b/packages/cocoon_integration_test/lib/src/model/firestore_matcher.dart @@ -117,23 +117,30 @@ abstract final class ModelMatcher> extends Matcher { @override @nonVirtual - Description describeMismatch(Object? item, Description description, _, _) { + Description describeMismatch( + Object? item, + Description mismatchDescription, + _, + _, + ) { // Not a document and not the wrapped type. if (item is! g.Document) { - return description.add('not a Document'); + return mismatchDescription.add('not a Document'); } // Not a saved document (does not have a name). if (item.name == null) { - return description.add('not a saved Document (missing "name")'); + return mismatchDescription.add('not a saved Document (missing "name")'); } // Not a document of the expected type. if (!_isPathTo(item.name!, metadata)) { final collection = p.posix.basename(p.posix.dirname(item.name!)); - return description.add('not a $T, belongs to collection "$collection"'); + return mismatchDescription.add( + 'not a $T, belongs to collection "$collection"', + ); } - return _delegate.describeMismatch(item, description, {}, false); + return _delegate.describeMismatch(item, mismatchDescription, {}, false); } } diff --git a/app_dart/test/src/model/ref_matcher.dart b/packages/cocoon_integration_test/lib/src/model/ref_matcher.dart similarity index 100% rename from app_dart/test/src/model/ref_matcher.dart rename to packages/cocoon_integration_test/lib/src/model/ref_matcher.dart diff --git a/packages/cocoon_integration_test/lib/src/server.dart b/packages/cocoon_integration_test/lib/src/server.dart new file mode 100644 index 0000000000..db03e8fa8d --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/server.dart @@ -0,0 +1,92 @@ +// Copyright 2026 The Flutter Authors. 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:cocoon_service/cocoon_service.dart'; +import 'package:cocoon_service/server.dart'; +import 'package:cocoon_service/src/service/commit_service.dart'; + +import '../testing.dart'; + +class IntegrationServer { + IntegrationServer({ + FakeConfig? config, + FakeFirestoreService? firestore, + FakeBigQueryService? bigQuery, + FakeDashboardAuthentication? authProvider, + FakeDashboardAuthentication? swarmingAuthProvider, + FakeGerritService? gerritService, + FakeBuildBucketClient? buildBucketClient, + FakeLuciBuildService? luciBuildService, + FakeScheduler? scheduler, + FakeCiYamlFetcher? ciYamlFetcher, + FakeBuildStatusService? buildStatusService, + FakeContentAwareHashService? contentAwareHashService, + CacheService? cache, + }) { + this.config = config ?? FakeConfig(webhookKeyValue: 'fake-secret'); + this.firestore = firestore ?? FakeFirestoreService(); + this.bigQuery = bigQuery ?? FakeBigQueryService(); + this.authProvider = authProvider ?? FakeDashboardAuthentication(); + this.swarmingAuthProvider = + swarmingAuthProvider ?? FakeDashboardAuthentication(); + this.gerritService = gerritService ?? FakeGerritService(); + this.buildBucketClient = buildBucketClient ?? FakeBuildBucketClient(); + this.luciBuildService = + luciBuildService ?? + FakeLuciBuildService(config: this.config, firestore: this.firestore); + this.scheduler = + scheduler ?? + FakeScheduler( + config: this.config, + firestore: this.firestore, + bigQuery: this.bigQuery, + ); + this.ciYamlFetcher = ciYamlFetcher ?? FakeCiYamlFetcher(); + this.buildStatusService = buildStatusService ?? FakeBuildStatusService(); + this.contentAwareHashService = + contentAwareHashService ?? + FakeContentAwareHashService(config: this.config); + this.cache = cache ?? FakeCacheService(); + + server = createServer( + config: this.config, + firestore: this.firestore, + bigQuery: this.bigQuery, + cache: this.cache, + authProvider: this.authProvider, + swarmingAuthProvider: this.swarmingAuthProvider, + branchService: BranchService( + config: this.config, + gerritService: this.gerritService, + ), + buildBucketClient: this.buildBucketClient, + luciBuildService: this.luciBuildService, + githubChecksService: GithubChecksService(this.config), + commitService: CommitService( + config: this.config, + firestore: this.firestore, + ), + gerritService: this.gerritService, + scheduler: this.scheduler, + ciYamlFetcher: this.ciYamlFetcher, + buildStatusService: this.buildStatusService, + contentAwareHashService: this.contentAwareHashService, + ); + } + + late final Server server; + late final FakeConfig config; + late final FakeFirestoreService firestore; + late final FakeBigQueryService bigQuery; + late final FakeDashboardAuthentication authProvider; + late final FakeDashboardAuthentication swarmingAuthProvider; + late final FakeGerritService gerritService; + late final FakeBuildBucketClient buildBucketClient; + late final FakeLuciBuildService luciBuildService; + late final FakeScheduler scheduler; + late final FakeCiYamlFetcher ciYamlFetcher; + late final FakeBuildStatusService buildStatusService; + late final FakeContentAwareHashService contentAwareHashService; + late final CacheService cache; +} diff --git a/packages/cocoon_integration_test/lib/src/utilities/build_bucket_messages.dart b/packages/cocoon_integration_test/lib/src/utilities/build_bucket_messages.dart new file mode 100644 index 0000000000..aa24202304 --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/utilities/build_bucket_messages.dart @@ -0,0 +1,720 @@ +// Copyright 2024 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:buildbucket/buildbucket_pb.dart' as bbv2; +import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; +import 'package:cocoon_service/src/service/luci_build_service/user_data.dart'; +import 'package:fixnum/fixnum.dart'; + +PushMessage createPushMessage( + Int64 id, { + required BuildBucketUserData userData, + String? project = 'flutter', + String? bucket = 'try', + String? builder = 'Windows Engine Drone', + int number = 259942, + bbv2.Status? status = bbv2.Status.SCHEDULED, + bool? addBuildSet = true, + List extraTags = const [], +}) { + final pubSubCallBack = createPubSubCallBack( + id, + project: project, + bucket: bucket, + builder: builder, + number: number, + status: status, + userData: userData, + extraTags: extraTags, + ); + + final pubSubCallBackMap = + pubSubCallBack.toProto3Json() as Map; + + final pubSubCallBackString = jsonEncode(pubSubCallBackMap); + + return PushMessage(data: pubSubCallBackString); +} + +bbv2.PubSubCallBack createPubSubCallBack( + Int64 id, { + required BuildBucketUserData userData, + String? project = 'flutter', + String? bucket = 'try', + String? builder = 'Windows Engine Drone', + int number = 259942, + bbv2.Status? status = bbv2.Status.SCHEDULED, + List extraTags = const [], +}) { + // this contains BuildsV2PubSub and UserData (List). + final buildsPubSub = createBuild( + id, + project: project, + bucket: bucket, + builder: builder, + number: number, + status: status, + extraTags: extraTags, + ); + return bbv2.PubSubCallBack( + buildPubsub: buildsPubSub, + userData: userData.toBytes(), + ); +} + +bbv2.BuildsV2PubSub createBuild( + Int64 id, { + String? project = 'flutter', + String? bucket = 'try', + String? builder = 'Windows Engine Drone', + int number = 259942, + bbv2.Status? status = bbv2.Status.SCHEDULED, + List extraTags = const [], +}) { + final build = bbv2.BuildsV2PubSub().createEmptyInstance(); + build.mergeFromProto3Json( + jsonDecode( + createBuildString( + id, + project: project, + bucket: bucket, + builder: builder, + number: number, + status: status, + ), + ) + as Map, + ); + if (extraTags.isNotEmpty) { + build.build.tags.addAll(extraTags); + } + return build; +} + +String createBuildString( + Int64 id, { + String? project = 'flutter', + String? bucket = 'try', + String? builder = 'Windows Engine Drone', + int number = 259942, + bbv2.Status? status = bbv2.Status.SCHEDULED, +}) { + return ''' + { + "build": { + "id": "$id", + "builder": { + "project": "${project ?? 'flutter'}", + "bucket": "${bucket ?? 'try'}", + "builder": "${builder ?? 'Linux web_long_running_tests_1_5'}" + }, + "number": $number, + "createdBy": "user:flutter-dashboard@appspot.gserviceaccount.com", + "createTime": "2024-06-03T15:48:25.490485466Z", + "startTime": "2024-06-03T15:48:35.560843535Z", + "endTime": "2024-06-03T16:05:18.072809938Z", + "updateTime": "2024-06-03T16:05:18.072809938Z", + "status": "${status?.name ?? 'SUCCESS'}", + "input": { + "experiments": [ + "luci.buildbucket.agent.cipd_installation", + "luci.buildbucket.agent.start_build", + "luci.buildbucket.backend_alt", + "luci.buildbucket.backend_go", + "luci.buildbucket.bbagent_getbuild", + "luci.buildbucket.bq_exporter_go", + "luci.buildbucket.parent_tracking", + "luci.buildbucket.use_bbagent", + "luci.recipes.use_python3" + ] + }, + "output": { + "logs": [ + { + "name": "stdout", + "viewUrl": "https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8746138145094216865/+/u/stdout", + "url": "logdog://logs.chromium.org/flutter/buildbucket/cr-buildbucket/8746138145094216865/+/u/stdout" + }, + { + "name": "stderr", + "viewUrl": "https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8746138145094216865/+/u/stderr", + "url": "logdog://logs.chromium.org/flutter/buildbucket/cr-buildbucket/8746138145094216865/+/u/stderr" + } + ], + "status": "SUCCESS" + }, + "infra": { + "buildbucket": { + "requestedProperties": { + "bringup": false, + "cores": 8, + "dependencies": [ + { + "dependency": "curl", + "version": "version:7.64.0" + }, + { + "dependency": "android_sdk", + "version": "version:34v3" + }, + { + "dependency": "chrome_and_driver", + "version": "version:119.0.6045.9" + }, + { + "dependency": "goldctl", + "version": "git_revision:720a542f6fe4f92922c3b8f0fdcc4d2ac6bb83cd" + } + ], + "device_type": "none", + "exe_cipd_version": "refs/heads/main", + "git_branch": "master", + "git_ref": "refs/pull/149147/head", + "git_url": "https://github.com/flutter/flutter", + "os": "Ubuntu", + "presubmit_max_attempts": 2, + "recipe": "flutter/flutter_drone", + "shard": "web_long_running_tests", + "subshard": "1_5", + "tags": [ + "framework", + "hostonly", + "shard", + "linux" + ] + }, + "requestedDimensions": [ + { + "key": "os", + "value": "Ubuntu" + }, + { + "key": "device_type", + "value": "none" + }, + { + "key": "cores", + "value": "8" + } + ], + "hostname": "cr-buildbucket.appspot.com", + "experimentReasons": { + "luci.best_effort_platform": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.agent.cipd_installation": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.agent.start_build": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.backend_alt": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.backend_go": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.bbagent_getbuild": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.bq_exporter_go": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.canary_software": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.parent_tracking": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.buildbucket.use_bbagent": "EXPERIMENT_REASON_BUILDER_CONFIG", + "luci.buildbucket.use_bbagent_race": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.non_production": "EXPERIMENT_REASON_GLOBAL_DEFAULT", + "luci.recipes.use_python3": "EXPERIMENT_REASON_BUILDER_CONFIG" + }, + "agent": { + "input": { + "data": { + "bbagent_utility_packages": { + "cipd": { + "server": "chrome-infra-packages.appspot.com", + "specs": [ + { + "package": "infra/tools/luci/cas/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + } + ] + }, + "onPath": [ + "bbagent_utility_packages", + "bbagent_utility_packages/bin" + ] + }, + "cipd_bin_packages": { + "cipd": { + "server": "chrome-infra-packages.appspot.com", + "specs": [ + { + "package": "infra/3pp/tools/git/\${platform}", + "version": "version:2@2.42.0.chromium.11" + }, + { + "package": "infra/tools/git/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/luci/git-credential-luci/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/luci/docker-credential-luci/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/luci/vpython3/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/luci/lucicfg/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/luci-auth/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/bb/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/cloudtail/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/prpc/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577" + }, + { + "package": "infra/tools/rdb/\${platform}", + "version": "git_revision:069157ce739832ec1a0a3fe11b2e37e632de50e9" + }, + { + "package": "infra/tools/luci/led/\${platform}", + "version": "git_revision:037d7079cf3faced3842e597c9dfcc7475b2ddca" + } + ] + }, + "onPath": [ + "cipd_bin_packages", + "cipd_bin_packages/bin" + ] + }, + "cipd_bin_packages/cpython3": { + "cipd": { + "server": "chrome-infra-packages.appspot.com", + "specs": [ + { + "package": "infra/3pp/tools/cpython3/\${platform}", + "version": "version:2@3.8.10.chromium.34" + } + ] + }, + "onPath": [ + "cipd_bin_packages/cpython3", + "cipd_bin_packages/cpython3/bin" + ] + }, + "kitchen-checkout": { + "cipd": { + "server": "chrome-infra-packages.appspot.com", + "specs": [ + { + "package": "flutter/recipe_bundles/flutter.googlesource.com/recipes", + "version": "refs/heads/main" + } + ] + } + } + }, + "cipdSource": { + "cipd": { + "cipd": { + "server": "chrome-infra-packages.appspot.com", + "specs": [ + { + "package": "infra/tools/cipd/\${platform}", + "version": "git_revision:215bc891d3d06dd49b11109abc9319a38aa66f0a" + } + ] + }, + "onPath": [ + "cipd", + "cipd/bin" + ] + } + } + }, + "output": { + "resolvedData": { + "": { + "cipd": { + "specs": [ + { + "package": "infra/tools/luci/bbagent/linux-amd64", + "version": "6tIw2DHVEcYg5xt0ETPIUzriHt6IfBcQp8ji-SvXcH8C" + } + ] + } + }, + "bbagent_utility_packages": { + "cipd": { + "specs": [ + { + "package": "infra/tools/luci/cas/linux-amd64", + "version": "pGapntrQBvOpG_fzREhX19L2a7rLGwyZEB4VqXDfBzgC" + } + ] + } + }, + "cipd_bin_packages": { + "cipd": { + "specs": [ + { + "package": "infra/3pp/tools/git/linux-amd64", + "version": "L93GSopVoB8RNkV6raxVg1eXHQmZdcYTrXgZoSTLWFEC" + }, + { + "package": "infra/tools/git/linux-amd64", + "version": "Xqu_HXC1MH-P79yv4Su2jDHjdlBlV_so9HF3ax8_YSsC" + }, + { + "package": "infra/tools/luci/git-credential-luci/linux-amd64", + "version": "f6M4HQ7vio2mfNQBCsVxBBugrsqd3p46Wvgb77mPakwC" + }, + { + "package": "infra/tools/luci/docker-credential-luci/linux-amd64", + "version": "kAqKupATGDUHCyutoNNS4eO4BQoAW9flmdKLzAs5gX4C" + }, + { + "package": "infra/tools/luci/vpython3/linux-amd64", + "version": "oe3aQL5rg2k6c6SGSFhCImGfhnl2zDPAFhdaCpruw_AC" + }, + { + "package": "infra/tools/luci/lucicfg/linux-amd64", + "version": "fLMtVWN-baUP3k_0YQt9dvY1_nBaHbju4g605ds38NEC" + }, + { + "package": "infra/tools/luci-auth/linux-amd64", + "version": "n4LZf93sXiBgdmdasB5L90v-usbwR4bRfrTU1TRNWzUC" + }, + { + "package": "infra/tools/bb/linux-amd64", + "version": "z6fapR2_VkZiA0KVeKLa1IhNpE49LLMR0Wj8-GbKMNQC" + }, + { + "package": "infra/tools/cloudtail/linux-amd64", + "version": "nhss9Uy2MR1OjQpgxCPE-p7kSOObNvgRnm9sBCIciQMC" + }, + { + "package": "infra/tools/prpc/linux-amd64", + "version": "vo1eow0ro1pQ5h-LjJ17Ra2EwTnt3C3U7rsSDwTrDAcC" + }, + { + "package": "infra/tools/rdb/linux-amd64", + "version": "zujGNFHlaTKRZBiMD_ypyXTeX8ypJfRDTkI3Rhx2AtEC" + }, + { + "package": "infra/tools/luci/led/linux-amd64", + "version": "9MscsPmNzDEXsue8XFb0B8fENKbCp9tkjo4EGsSV0IEC" + } + ] + } + }, + "cipd_bin_packages/cpython3": { + "cipd": { + "specs": [ + { + "package": "infra/3pp/tools/cpython3/linux-amd64", + "version": "3p-c2NpZEJWyv4KiHJopTR1ScaHxDKBRMfXlzpre-IwC" + } + ] + } + }, + "kitchen-checkout": { + "cipd": { + "specs": [ + { + "package": "flutter/recipe_bundles/flutter.googlesource.com/recipes", + "version": "PUKnbYmIYQbnhME2pu4sISywm3vPYbxQjRL3CnRv0HMC" + } + ] + } + } + }, + "status": "SUCCESS", + "agentPlatform": "linux-amd64", + "totalDuration": "4s" + }, + "source": { + "cipd": { + "package": "infra/tools/luci/bbagent/\${platform}", + "version": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577", + "server": "chrome-infra-packages.appspot.com" + } + }, + "purposes": { + "bbagent_utility_packages": "PURPOSE_BBAGENT_UTILITY", + "kitchen-checkout": "PURPOSE_EXE_PAYLOAD" + }, + "cipdClientCache": { + "name": "cipd_client_f970720a374db65e431d9836bdd8bc091f12dd8c12a454b5a67f5b163006301e", + "path": "cipd_client" + }, + "cipdPackagesCache": { + "name": "cipd_cache_9237a0836331b01a61cb7a5ed59c6f7b1fa85bf7f14cc136be4a6237cbd59011", + "path": "cipd_cache" + } + }, + "knownPublicGerritHosts": [ + "android.googlesource.com", + "aomedia.googlesource.com", + "boringssl.googlesource.com", + "chromium.googlesource.com", + "dart.googlesource.com", + "dawn.googlesource.com", + "fuchsia.googlesource.com", + "gn.googlesource.com", + "go.googlesource.com", + "llvm.googlesource.com", + "pdfium.googlesource.com", + "quiche.googlesource.com", + "skia.googlesource.com", + "swiftshader.googlesource.com", + "webrtc.googlesource.com" + ], + "buildNumber": true + }, + "logdog": { + "hostname": "logs.chromium.org", + "project": "flutter", + "prefix": "buildbucket/cr-buildbucket/8746138145094216865" + }, + "resultdb": { + "hostname": "results.api.cr.dev" + }, + "bbagent": { + "payloadPath": "kitchen-checkout", + "cacheDir": "cache" + }, + "backend": { + "config": { + "agent_binary_cipd_filename": "bbagent\${EXECUTABLE_SUFFIX}", + "agent_binary_cipd_pkg": "infra/tools/luci/bbagent/\${platform}", + "agent_binary_cipd_server": "chrome-infra-packages.appspot.com", + "agent_binary_cipd_vers": "git_revision:2aba496613f92a5b06d577f82b5d028225d3d577", + "priority": 30, + "service_account": "flutter-try-builder@chops-service-accounts.iam.gserviceaccount.com" + }, + "task": { + "id": { + "target": "swarming://chromium-swarm", + "id": "69f79b2ca0f23910" + }, + "link": "https://chromium-swarm.appspot.com/task?id=69f79b2ca0f23910&o=true&w=true", + "status": "SUCCESS", + "details": { + "bot_dimensions": { + "bot_config": [ + "bot_config.py" + ], + "caches": [ + "cipd_cache_9237a0836331b01a61cb7a5ed59c6f7b1fa85bf7f14cc136be4a6237cbd59011", + "cipd_client_f970720a374db65e431d9836bdd8bc091f12dd8c12a454b5a67f5b163006301e", + "engine_main_builder", + "engine_main_git", + "flutter_main_android_sdk_version_34v3_legacy", + "flutter_main_chrome_and_driver_version_119_0_6045_9_legacy", + "flutter_main_open_jdk_version_17_legacy", + "gradle", + "packages_main_android_sdk_version_33v6_legacy", + "packages_main_chrome_and_driver_version_114_0_legacy", + "packages_main_open_jdk_version_11_legacy" + ], + "cipd_platform": [ + "linux-amd64" + ], + "cores": [ + "8" + ], + "cpu": [ + "x86", + "x86-64", + "x86-64-Broadwell_GCE", + "x86-64-avx2" + ], + "device_os": [ + "none" + ], + "device_type": [ + "none" + ], + "display_attached": [ + "0" + ], + "gce": [ + "1" + ], + "gcp": [ + "flutter-machines-prod" + ], + "gpu": [ + "none" + ], + "id": [ + "flutter-try-flutterprj-ubuntu-us-central1-b-2-s2lu" + ], + "image": [ + "dart-focal-24052600-54a1aca43d9" + ], + "inside_docker": [ + "0" + ], + "kernel": [ + "5.15.0-1060-gcp" + ], + "kvm": [ + "1" + ], + "locale": [ + "en_US.UTF-8" + ], + "machine_type": [ + "n1-standard-8" + ], + "os": [ + "Linux", + "Ubuntu", + "Ubuntu-20", + "Ubuntu-20.04", + "Ubuntu-20.04.6" + ], + "pool": [ + "luci.flutter.try" + ], + "puppet_env": [ + "production" + ], + "python": [ + "3", + "3.8", + "3.8.10+chromium.23" + ], + "server_version": [ + "7672-d26f562" + ], + "ssd": [ + "1" + ], + "zone": [ + "us", + "us-central", + "us-central1", + "us-central1-b" + ] + } + }, + "updateId": "1717430716453135104" + }, + "caches": [ + { + "name": "pub_cache", + "path": ".pub-cache" + }, + { + "name": "flutter_main_android_sdk_version_34v3_legacy", + "path": "android" + }, + { + "name": "flutter_main_android_sdk_version_34v3", + "path": "android_sdk" + }, + { + "name": "flutter_main_builder", + "path": "builder" + }, + { + "name": "flutter_main_chrome_and_driver_version_119_0_6045_9_legacy", + "path": "chrome" + }, + { + "name": "flutter_main_chrome_and_driver_version_119_0_6045_9", + "path": "chrome_and_driver" + }, + { + "name": "flutter_main_curl_version_7_64_0", + "path": "curl" + }, + { + "name": "flutter_main_git", + "path": "git" + }, + { + "name": "flutter_main_goldctl_git_revision_720a542f6fe4f92922c3b8f0fdcc4d2ac6bb83cd", + "path": "goldctl" + }, + { + "name": "gradle", + "path": "gradle" + }, + { + "name": "vpython", + "path": "vpython", + "envVar": "VPYTHON_VIRTUALENV_ROOT" + } + ], + "taskDimensions": [ + { + "key": "cores", + "value": "8" + }, + { + "key": "device_type", + "value": "none" + }, + { + "key": "os", + "value": "Ubuntu" + }, + { + "key": "pool", + "value": "luci.flutter.try" + } + ], + "hostname": "chromium-swarm.appspot.com" + } + }, + "tags": [ + { + "key": "buildset", + "value": "pr/git/149147" + }, + { + "key": "buildset", + "value": "sha/git/5bbe0ce383e7ed77c68911a20358bbdc2f4c69dd" + }, + { + "key": "cipd_version", + "value": "refs/heads/main" + }, + { + "key": "github_checkrun", + "value": "25743375958" + }, + { + "key": "github_link", + "value": "https://github.com/flutter/flutter/pull/149147" + }, + { + "key": "user_agent", + "value": "flutter-cocoon" + } + ], + "exe": { + "cipdPackage": "flutter/recipe_bundles/flutter.googlesource.com/recipes", + "cipdVersion": "refs/heads/main", + "cmd": [ + "luciexe" + ] + }, + "schedulingTimeout": "21600s", + "executionTimeout": "3600s", + "gracePeriod": "30s" + }, + "buildLargeFields": "eJzMnH2QFOWdx9ND2Jl9diDQEcx17nINIWfS1rzu7OzslpejklTqqu4uSVXq6v4yXf3yzEyzPd2TfllYQ5IFdFlmw4vAIqTALGdF1sRXkFJLqFP/UOpOyz0tFd85RQ/PQ6nzTvBKNNXvM9O9yy7l0z3+IwPT/fv+vt2f7/N0z9N90yUA/g+AVaBLgZxQh/i1xIqyqGsaVDL2/2lekSUIloOEwkJ6ncyq+GJiUT6bBStADw+HBQ7S2kgd4l3ElyXjm0djIMnDOpR4KHECVPHDsfztMdBH9YKvg/gwVFRBlvBlxFL7j4P96WIhnQXXAOBuNmLsjdMVEQxSJfBn3mZLiaSzWW9h2Nhj80ZLiB5G4hVZ4GmVHwJ/S/0QrGr5wleJ5VxVkWuQZiSe5hVhGCpglbf7lcQ1zu5zuYF0Nl3MFvrSA4CmbgTf877WT/RVBI1W4LBgdZDPMn2FfLlYhoXyQH4gn+d62VI5W+Y5rsDnGa7IsqVejgfXtqjpJuIVWeQ5TQQrQMLaY102/tr2HiwBcVYRpIpex2Pkl8D7GEiucY6PwkL8FYx6CQMDICFIqsZIHMRTxPV1RV4HOU11jmBKYWGqrsh8xvmWmuFhmdFFDRzAQKIuMlpZVmr4bzBiG8bJksYIElRSQo2pwL/mZW4IKoOZTIVT0oKc4URZ51M1RhmCWl1kOJipyHJFhBkesgIj5XJr1SqT7ysOFgdgvr80wA2Ue/l8iSsy2XKul833ZYt5Ll/IQtjf359nYa7cB4t8IceyhWIpyxZ7IQOLbG+2AP4eXLvGOi1pKFUECWYEVRYZDfJ4jsqAFOhSoTIMFfybxKqqptXVwYzzDesf0ky9rtZlLc3JNbASAMNhVmEkrooniK4aoxoW46C7IteYljP7m2BlXYGqztYEja4xG2hG02Ctrql49/IvWf+tNYhQdVatMgpvbJej+8AqsNj6/DVi5XrI0qIsVWhFlyRBqtAaVDXVOKK6CmmOUfEYiYE+8GWNqah4Kn896CG6ywpTg+tlZQgAIlGVVU2WxBEQJ6zdGn8QBUnfADIgbjSjKyK+hljtNF8RtKrOGt1m2iAGq0BizZCgcVUo4Suor4LloAfWdMMqusJBU8pqa58KLBspoMCymqnropjJFQZyhf5MFTK8sZlxxtKaMrJOZs3NloA4J8osCxXzFMXBYk5WoOcUuRZ8AwDLbImpQYN8ThSgpKUdcUtBTFaNQ/KPrC5pOvgH34FX1zNKTZAqeJ7KgrR74Jt6N7EW9FrK/GrLkf8WWAY3QJoT6jztELyc+IrZodGVmqkxggRWgK/odVFmeLrOcENMBapmQ/8ElrjIGScK/kPqB+B7roQSUXTwyqWhxNdlQdLUdFnnqqrApASprDApYzvzK2mTnrRBzGbsu+AGMAiSFdlLEpwivt3HsjDLwd5SL+yHfH8/VywN5HJMPtvbV2JZnsuXC1xxgOcb2ENdoEeFml6nWV0QeTyZePnfLh7tWjaz/9M7YoTzaersm3fGyCT13xgAii7RdtLXHedEuaKmHfvSslIx/8Y9g8xdszo3BLUMp6SaP5b6C8VcbylX6MsOFPK5YqnYl7k+o2eaNGW8ioQoyhVergSW/MKrUZcwsLQGa7IyQtcVuSyIENfCabm1KlFH33ZrReptDMRFuVIxgKmF07NdjhDQN2uXGhy0g5W0DvgguTpw5rKaXC9oVfInI1pVlsjedC6XLjWwVxeD+I9/SgpSWXaxGf34n48Y2LxpYfPgC5sXkUnqFQx0reEhq1dwAZ2XP/4pbWjJiLRZioBofGwrQ32CgeVwA+R0TZAlkocaI4gqrqLv0y1K20UJGW3HvoLUaQx0qRov6xpeRd+wVYng0XZpVWlgJfC171chNyTrGtlGBe6c4DMvfrB5EZFMXDA/jT832YiRyQZ2MA5Wz7btxoqgkSaL7l5OvXfvlkVET+KM+Wn/s4/9jExSu2MuMzdj6Lx1ZNIO8O44LWi0KdPlaRRDY/z8JVAPxIJY2xGtP34OG9E55Wd0Z8xldEu0Rtn8/joycxy0r8hnGWpcFXeIPPfERz8jkokPLeTfuPMerEP4NGVGy2eLhE7j0xLXIXzOIqYj+LS0Rchns4AGdiwOvjUnn5z9j7hD5fiHz92DuQPxhZ27jxqM7vcY3RqVtY5UF9MtUZx87SqohwJJvTVyl/ywbo/ULz+v+zxexyK3y0Z2c6QeOdh+Ggd/NSu2CmR40r1H45D68LnHjjZxe/73Jw1uf+txOx6FxYZW936SC+7NYZscKIN6JJDc3dH75Ed3R7SO+dndb7ELFSWaAaFVn6Uk/AEhSMXg2htYJfNdk2nIkwbB1833Lup15qYN7NCVptWcCBmP/ZnHnz/psb/rkbOvdsq82tQZ7by6RUKnzastcR0yr55FTEfMqy1tEc6rmwU0sMfj4LpZAVV1tibzughJdUTiXEp3HbrtNY/S+8e3f2RQetCjdFsU5rpiaUOsi+otYZ+AwTqoRwN53dMBTvmh3RmxZ35yf+uRG8n0r02gjW/o079AGQ3s2Tj4zjwg1us8o0EX4+knHvvIw/j0oc2NGJmkpjyMJ6J12pLrgrw1OrNblVD/EojyZEe45Yf51sh98+N8u4dzoyNss4Eei9wrB+lbusASY36swOFUnVFUD9tTD26diHlz5IP79hrYvuv9niqjM9RenmUpcskcQmNaYDHqlkD4RsLq2c+XHkb3foTOYu51qxRW8/bV6bowOrZqNbCxOPhLe6ckJ0tloUKmUsYcVkmVIaPpClS9W0evPrE3RvQkdj5t3jqanLyRTFIT3oC2CWHWOGRbGul2jS4sv0Rj3jzLU38MxAflSH8lZX6iUI30C1ZCbfPGqdEILbJHp43R2OIMSZMJsAxKqq5A2lzxKoqQxx3YpnacuJFI2h/OvDi1CbPWxjnoKejca9fkoiah8Wu2ekbSBLC1McTO/SxtCMkDPzv/5S0E+nmIFtis1ELq2ypHfYKBnnWqLKVlXavrGj4cYsdNdQklpLabajawRxPgmvZvkN/Ofwd38uDSxRObMDcdLhz5fMJIh//10iFEu2g6T7sJEZJdzTWpvYEpgXJ4CZTjjwpEw8v8qlP/48WFHrIVdmT8PMT+7djYFGuNjZtC7rw5OoZDbL8lPt6Ng2RFYXgRkhzDVaEbG2fOH/6NERu3mp9OHdtx3oiNs15soLzwMQXRpiA3LlBd+ATUorYExsSGkDr2p4MWQu/+VHjLu8pFuOS+RYR9kYtoyX1AKeodDMRFQdV4Ae21fMtpZtUL55S2ajWwG8Cff998TpBkJJ60nhMkm57cc1Cf/vdnznvg75o+MWauob4DgNRc22/0XZ24u3jyctMOZ15/9xMjSaa9OwM7kd6FbHs0kvYkz37xMoHsVuRVqKGeCkyjAx3jmj+vJjvCP3+i3endUkD7Y/1CZNozIHQ/1i9cDHW8bW6E9qfShQhsnjWh+6n0KhU1sKcAyC0oJu1rNSscx8cm/t+LyqnbjhrZS93vRWXHHIeWK7mOOA4t13nPBkbmoY5yzx+bBzrGR3903utFJ9q1jQuVascnurWNVyeIOtkWobd1lGvNMbqnY6xridIsWPYDeb0kygxP2u+UcINy9IM3xmJuUE7fPb5nkTFJPd4NVrVvM/vEdOb03q3eTmb2fLZ7EZk016nZaYtynZojk7Zlzj4ZRbRObd4CqPsCw3R7pOb4w3MborP4KrRQ272w3BypTXY4/ioqa+wsPNSWhSgXe19ZVHP2oVrsvSAVDexkF1jBO8HV8qYhJ54u/eE/9iwiehJvWfn3+7u7yST1sXc7bj06Rx1hdLMwN55UNAbOWZTaFxhJKJcYBOvxxxCiJQbzLG/+rmMnD8LfdYLV2GGD6HeduWo2sIkusNRZqcLLnCYruMPK9H++1E0k7Q/jl85PGddU5zxyEL41xvl131LkIoPorTHB1aitgawg/LWjTYefEUS/dlyprrlOz4YD4Tq9Nhk2FYjW6QUWa2DnEuBvFF0iNahqaZ5RNLIsK2Tw+7tI80Vc5u0K5+VfZI7uwx1kZp45dDhG9CTuet68KbF934/IJPW0N0s+jDB1FV2i3R7osqzQwT3QpmzzUsPpgc7RfS5xhxAN81+QPur9QEb/2MHO+qk+0qEe+3PgX73p+VQHW2wnx8EO9dXJmhfjoNt8hNFQhzs5MX34yR8RSfvDhZdPjGJkknrDG3WHEPruiHHxryBysL0QdTnw5VMI11R4EvxAIlpTMUdJ6jVvhF0XRtM2ImXUndrXse9joEer1dlsvcyIpRrKWYRXu6kgqllEYLEGlgJLVE1WIFmDmiJwxsWoxfP41hdGMZfuc0++adDdwHJg+d8JoihIFfInisxBVYXeNqO7P2ja5uFtx46Z21zsAn/h22jjkCCKpNkddHcwM/G7Td4ORl85bi5kG/MmIr9GdzRshbSrMGMopC2Fbsz8As3RmVdx6kjgFALl06Bz6/LnEaqnQReog7rZG/5/FZU7dnDdFIUjzsD9Xhf4+izoGVMCF7zTl9+ZaALv+DOTBnibPfB+GbqLhj4Xu5FQTWwuTd0RCB3K25tzqfIjh+r25oJUUKMecAgX5M+lycYN0YL8K1duYJ93gW/MAptd2eXtVOPypMfb/qnXf2fwts3jDeV65Vl6cfboMIdovfL8qlN3BWKH8mnWKwjzk4fqadaFCjEnSDZ84U+Q3EdtLf7CnSC1Fp9zvFvHDDMuf2c+2zbl8XfmwNt3RT7eGfoiGu+aS3fOeGeqiny8C1YR7XhnaopkvGuq3MDe6gLELLAxPOuyduH1XX/wWJs6Om1cFZoG2qyFbyDDsy5q4RrYVJk6HEgayjccziHKDxqqNxwuRAT1mXe36ReR+GJjtj50LxzKLi4GPfY7/+2FpDZWYzsfNLC6z7pku/2BXTEyaT7QYWOF8IEO+8XtLStEET3QEVCK2hQIDsLlEc0i/KAgWh4xZ1HqjAeGGE7jNglV9N1alf4UAAD//9ANEzk=" + } + '''; +} diff --git a/app_dart/test/src/utilities/entity_generators.dart b/packages/cocoon_integration_test/lib/src/utilities/entity_generators.dart similarity index 99% rename from app_dart/test/src/utilities/entity_generators.dart rename to packages/cocoon_integration_test/lib/src/utilities/entity_generators.dart index db320f0ac8..fd765fb87c 100644 --- a/app_dart/test/src/utilities/entity_generators.dart +++ b/packages/cocoon_integration_test/lib/src/utilities/entity_generators.dart @@ -18,7 +18,7 @@ import 'package:cocoon_service/src/service/firestore.dart'; import 'package:fixnum/fixnum.dart'; import 'package:github/github.dart' as github; -import '../service/fake_scheduler.dart'; +import '../fakes/fake_scheduler.dart'; Task generateFirestoreTask( int i, { diff --git a/packages/cocoon_integration_test/lib/src/utilities/matchers.dart b/packages/cocoon_integration_test/lib/src/utilities/matchers.dart new file mode 100644 index 0000000000..ce8605a15b --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/utilities/matchers.dart @@ -0,0 +1,15 @@ +// Copyright 2021 The Flutter Authors. 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:test/test.dart'; + +Matcher throwsExceptionWith(String messageSubString) { + return throwsA( + isA().having( + (T e) => e.toString(), + 'description', + contains(messageSubString), + ), + ); +} diff --git a/app_dart/test/src/utilities/mocks.dart b/packages/cocoon_integration_test/lib/src/utilities/mocks.dart similarity index 97% rename from app_dart/test/src/utilities/mocks.dart rename to packages/cocoon_integration_test/lib/src/utilities/mocks.dart index 0a36bc2db6..a5ccfc38a2 100644 --- a/app_dart/test/src/utilities/mocks.dart +++ b/packages/cocoon_integration_test/lib/src/utilities/mocks.dart @@ -26,7 +26,7 @@ import 'package:mockito/annotations.dart'; import 'package:neat_cache/neat_cache.dart'; import 'package:process/process.dart'; -import '../../service/cache_service_test.dart'; +import '../fakes/fake_entry.dart'; export 'mocks.mocks.dart'; @@ -68,8 +68,6 @@ export 'mocks.mocks.dart'; // ), ], ) -void main() {} - // ignore: unreachable_from_main class ThrowingGitHub implements GitHub { @override diff --git a/app_dart/test/src/utilities/mocks.mocks.dart b/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart similarity index 99% rename from app_dart/test/src/utilities/mocks.mocks.dart rename to packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart index d915ef8736..1890f6e94b 100644 --- a/app_dart/test/src/utilities/mocks.mocks.dart +++ b/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.4.6 from annotations -// in cocoon_service/test/src/utilities/mocks.dart. +// in cocoon_integration_test/src/utilities/mocks.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes @@ -10,6 +10,7 @@ import 'dart:typed_data' as _i27; import 'package:buildbucket/buildbucket_pb.dart' as _i6; import 'package:cocoon_common/rpc_model.dart' as _i19; +import 'package:cocoon_integration_test/src/fakes/fake_entry.dart' as _i26; import 'package:cocoon_service/cocoon_service.dart' as _i17; import 'package:cocoon_service/src/foundation/github_checks_util.dart' as _i10; import 'package:cocoon_service/src/model/ci_yaml/ci_yaml.dart' as _i41; @@ -54,8 +55,6 @@ import 'package:mockito/src/dummies.dart' as _i20; import 'package:neat_cache/neat_cache.dart' as _i16; import 'package:process/src/interface/process_manager.dart' as _i38; -import '../../service/cache_service_test.dart' as _i26; - // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters diff --git a/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart b/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart new file mode 100644 index 0000000000..7896dd6d85 --- /dev/null +++ b/packages/cocoon_integration_test/lib/src/utilities/webhook_generators.dart @@ -0,0 +1,1331 @@ +// Copyright 2019 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:cocoon_service/protos.dart' as pb; +import 'package:cocoon_service/src/model/github/checks.dart'; +import 'package:cocoon_service/src/model/luci/pubsub_message.dart'; +import 'package:cocoon_service/src/service/config.dart'; +import 'package:github/github.dart'; +import 'package:github/hooks.dart'; +import 'package:test/test.dart'; + +PushMessage generateGithubWebhookMessage({ + String event = 'pull_request', + String action = 'merged', + int number = 123, + String? baseRef, + String baseSha = '4cd12fc8b7d4cc2d8609182e1c4dea5cddc86890', + String headSha = 'be6ff099a4ee56e152a5fa2f37edd10f79d1269a', + String login = 'dash', + String headRef = 'abc', + bool isDraft = false, + bool merged = false, + bool mergeable = true, + String mergeCommitSha = 'fd6b46416c18de36ce87d0241994b2da180cab4c', + RepositorySlug? slug, + bool includeChanges = false, + bool withAutosubmit = false, + bool withRevertOf = false, + DateTime? closedAt, + Iterable additionalLabels = const [], +}) { + final data = + (pb.GithubWebhookMessage.create() + ..event = event + ..payload = _generatePullRequestEvent( + action, + number, + baseRef, + baseSha: baseSha, + headSha: headSha, + login: login, + headRef: headRef, + isDraft: isDraft, + merged: merged, + isMergeable: mergeable, + slug: slug, + mergeCommitSha: mergeCommitSha, + includeChanges: includeChanges, + withAutosubmit: withAutosubmit, + withRevertOf: withRevertOf, + closedAt: closedAt, + additionalLabels: additionalLabels, + )) + .writeToJson(); + return PushMessage(data: data, messageId: 'abc123'); +} + +String _generatePullRequestEvent( + String action, + int number, + String? baseRef, { + RepositorySlug? slug, + String login = 'flutter', + String baseSha = '4cd12fc8b7d4cc2d8609182e1c4dea5cddc86890', + String headRef = 'wait_for_reassemble', + required String headSha, + bool includeCqLabel = false, + bool isDraft = false, + bool merged = false, + bool isMergeable = true, + String mergeCommitSha = 'fd6b46416c18de36ce87d0241994b2da180cab4c', + bool includeChanges = false, + DateTime? closedAt, + required bool withAutosubmit, + required bool withRevertOf, + Iterable additionalLabels = const [], +}) { + slug ??= Config.flutterSlug; + baseRef ??= Config.defaultBranch(slug); + + var labelId = 1000; + Map generateLabel(String name) { + labelId++; + return { + 'id': labelId, + 'node_id': base64Encode('$labelId'.codeUnits), + 'url': 'https://api.github.com/repos/${slug!.fullName}/labels/$name', + 'name': name, + 'color': '207de5', + 'default': false, + }; + } + + final labels = [ + if (includeCqLabel) generateLabel('cla: yes'), + if (withAutosubmit) generateLabel('autosubmit'), + if (withRevertOf) generateLabel('revert of'), + + // This matches the behavior of this function before refactoring to have a + // more structured way to add test labels. It would be nice to refactor + // these out. + generateLabel('framework'), + generateLabel('tool'), + ...additionalLabels.map(generateLabel), + ]; + + return '''{ + "action": "$action", + "number": $number, + "pull_request": { + "url": "https://api.github.com/repos/${slug.fullName}/pulls/$number", + "id": 294034, + "node_id": "MDExOlB1bGxSZXF1ZXN0Mjk0MDMzODQx", + "html_url": "https://github.com/${slug.fullName}/pull/$number", + "diff_url": "https://github.com/${slug.fullName}/pull/$number.diff", + "patch_url": "https://github.com/${slug.fullName}/pull/$number.patch", + "issue_url": "https://api.github.com/repos/${slug.fullName}/issues/$number", + "number": $number, + "state": "open", + "locked": false, + "title": "Defer reassemble until reload is finished", + "user": { + "login": "$login", + "id": 862741, + "node_id": "MDQ6VXNlcjg2MjA3NDE=", + "avatar_url": "https://avatars3.githubusercontent.com/u/8620741?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + }, + "draft" : "$isDraft", + "body": "The body", + "created_at": "2019-07-03T07:14:35Z", + "updated_at": "2019-07-03T16:34:53Z", + "closed_at": ${closedAt == null ? 'null' : '"${closedAt.toUtc().toIso8601String()}"'}, + "merged_at": "2019-07-03T16:34:53Z", + "merge_commit_sha": "$mergeCommitSha", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "requested_teams": [], + "labels": ${const JsonEncoder.withIndent(' ').convert(labels)}, + "milestone": null, + "commits_url": "https://api.github.com/repos/${slug.fullName}/pulls/$number/commits", + "review_comments_url": "https://api.github.com/repos/${slug.fullName}/pulls/$number/comments", + "review_comment_url": "https://api.github.com/repos/${slug.fullName}/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/${slug.fullName}/issues/$number/comments", + "statuses_url": "https://api.github.com/repos/${slug.fullName}/statuses/be6ff099a4ee56e152a5fa2f37edd10f79d1269a", + "head": { + "label": "$login:$headRef", + "ref": "$headRef", + "sha": "$headSha", + "user": { + "login": "$login", + "id": 8620741, + "node_id": "MDQ6VXNlcjg2MjA3NDE=", + "avatar_url": "https://avatars3.githubusercontent.com/u/8620741?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 131232406, + "node_id": "MDEwOlJlcG9zaXRvcnkxMzEyMzI0MDY=", + "name": "${slug.name}", + "full_name": "${slug.fullName}", + "private": false, + "owner": { + "login": "flutter", + "id": 8620741, + "node_id": "MDQ6VXNlcjg2MjA3NDE=", + "avatar_url": "https://avatars3.githubusercontent.com/u/8620741?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/${slug.fullName}", + "description": "Flutter makes it easy and fast to build beautiful mobile apps.", + "fork": true, + "url": "https://api.github.com/repos/${slug.fullName}", + "forks_url": "https://api.github.com/repos/${slug.fullName}/forks", + "keys_url": "https://api.github.com/repos/${slug.fullName}/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/${slug.fullName}/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/${slug.fullName}/teams", + "hooks_url": "https://api.github.com/repos/${slug.fullName}/hooks", + "issue_events_url": "https://api.github.com/repos/${slug.fullName}/issues/events{/number}", + "events_url": "https://api.github.com/repos/${slug.fullName}/events", + "assignees_url": "https://api.github.com/repos/${slug.fullName}/assignees{/user}", + "branches_url": "https://api.github.com/repos/${slug.fullName}/branches{/branch}", + "tags_url": "https://api.github.com/repos/${slug.fullName}/tags", + "blobs_url": "https://api.github.com/repos/${slug.fullName}/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/${slug.fullName}/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/${slug.fullName}/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/${slug.fullName}/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/${slug.fullName}/statuses/{sha}", + "languages_url": "https://api.github.com/repos/${slug.fullName}/languages", + "stargazers_url": "https://api.github.com/repos/${slug.fullName}/stargazers", + "contributors_url": "https://api.github.com/repos/${slug.fullName}/contributors", + "subscribers_url": "https://api.github.com/repos/${slug.fullName}/subscribers", + "subscription_url": "https://api.github.com/repos/${slug.fullName}/subscription", + "commits_url": "https://api.github.com/repos/${slug.fullName}/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/${slug.fullName}/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/${slug.fullName}/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/${slug.fullName}/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/${slug.fullName}/contents/{+path}", + "compare_url": "https://api.github.com/repos/${slug.fullName}/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/${slug.fullName}/merges", + "archive_url": "https://api.github.com/repos/${slug.fullName}/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/${slug.fullName}/downloads", + "issues_url": "https://api.github.com/repos/${slug.fullName}/issues{/number}", + "pulls_url": "https://api.github.com/repos/${slug.fullName}/pulls{/number}", + "milestones_url": "https://api.github.com/repos/${slug.fullName}/milestones{/number}", + "notifications_url": "https://api.github.com/repos/${slug.fullName}/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/${slug.fullName}/labels{/name}", + "releases_url": "https://api.github.com/repos/${slug.fullName}/releases{/id}", + "deployments_url": "https://api.github.com/repos/${slug.fullName}/deployments", + "created_at": "2018-04-27T02:03:08Z", + "updated_at": "2019-06-27T06:56:59Z", + "pushed_at": "2019-07-03T19:40:11Z", + "git_url": "git://github.com/${slug.fullName}.git", + "ssh_url": "git@github.com:${slug.fullName}.git", + "clone_url": "https://github.com/${slug.fullName}.git", + "svn_url": "https://github.com/${slug.fullName}", + "homepage": "https://flutter.io", + "size": 94508, + "stargazers_count": 1, + "watchers_count": 1, + "language": "Dart", + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": { + "key": "other", + "name": "Other", + "spdx_id": "NOASSERTION", + "url": null, + "node_id": "MDc6TGljZW5zZTA=" + }, + "forks": 0, + "open_issues": 0, + "watchers": 1, + "default_branch": "$kDefaultBranchName" + } + }, + "base": { + "label": "flutter:$baseRef", + "ref": "$baseRef", + "sha": "$baseSha", + "user": { + "login": "flutter", + "id": 14101776, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE0MTAxNzc2", + "avatar_url": "https://avatars3.githubblahblahblah", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 31792824, + "node_id": "MDEwOlJlcG9zaXRvcnkzMTc5MjgyNA==", + "name": "${slug.name}", + "full_name": "${slug.fullName}", + "private": false, + "owner": { + "login": "flutter", + "id": 14101776, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE0MTAxNzc2", + "avatar_url": "https://avatars3.githubblahblahblah", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/${slug.fullName}", + "description": "Flutter makes it easy and fast to build beautiful mobile apps.", + "fork": false, + "url": "https://api.github.com/repos/${slug.fullName}", + "forks_url": "https://api.github.com/repos/${slug.fullName}/forks", + "keys_url": "https://api.github.com/repos/${slug.fullName}/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/${slug.fullName}/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/${slug.fullName}/teams", + "hooks_url": "https://api.github.com/repos/${slug.fullName}/hooks", + "issue_events_url": "https://api.github.com/repos/${slug.fullName}/issues/events{/number}", + "events_url": "https://api.github.com/repos/${slug.fullName}/events", + "assignees_url": "https://api.github.com/repos/${slug.fullName}/assignees{/user}", + "branches_url": "https://api.github.com/repos/${slug.fullName}/branches{/branch}", + "tags_url": "https://api.github.com/repos/${slug.fullName}/tags", + "blobs_url": "https://api.github.com/repos/${slug.fullName}/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/${slug.fullName}/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/${slug.fullName}/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/${slug.fullName}/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/${slug.fullName}/statuses/{sha}", + "languages_url": "https://api.github.com/repos/${slug.fullName}/languages", + "stargazers_url": "https://api.github.com/repos/${slug.fullName}/stargazers", + "contributors_url": "https://api.github.com/repos/${slug.fullName}/contributors", + "subscribers_url": "https://api.github.com/repos/${slug.fullName}/subscribers", + "subscription_url": "https://api.github.com/repos/${slug.fullName}/subscription", + "commits_url": "https://api.github.com/repos/${slug.fullName}/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/${slug.fullName}/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/${slug.fullName}/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/${slug.fullName}/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/${slug.fullName}/contents/{+path}", + "compare_url": "https://api.github.com/repos/${slug.fullName}/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/${slug.fullName}/merges", + "archive_url": "https://api.github.com/repos/${slug.fullName}/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/${slug.fullName}/downloads", + "issues_url": "https://api.github.com/repos/${slug.fullName}/issues{/number}", + "pulls_url": "https://api.github.com/repos/${slug.fullName}/pulls{/number}", + "milestones_url": "https://api.github.com/repos/${slug.fullName}/milestones{/number}", + "notifications_url": "https://api.github.com/repos/${slug.fullName}/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/${slug.fullName}/labels{/name}", + "releases_url": "https://api.github.com/repos/${slug.fullName}/releases{/id}", + "deployments_url": "https://api.github.com/repos/${slug.fullName}/deployments", + "created_at": "2015-03-06T22:54:58Z", + "updated_at": "2019-07-04T02:08:44Z", + "pushed_at": "2019-07-04T02:03:04Z", + "git_url": "git://github.com/${slug.fullName}.git", + "ssh_url": "git@github.com:${slug.fullName}.git", + "clone_url": "https://github.com/${slug.fullName}.git", + "svn_url": "https://github.com/${slug.fullName}", + "homepage": "https://flutter.dev", + "size": 65507, + "stargazers_count": 68944, + "watchers_count": 68944, + "language": "Dart", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 7987, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 6536, + "license": { + "key": "other", + "name": "Other", + "spdx_id": "NOASSERTION", + "url": null, + "node_id": "MDc6TGljZW5zZTA=" + }, + "forks": 7987, + "open_issues": 6536, + "watchers": 68944, + "default_branch": "$kDefaultBranchName" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/${slug.fullName}/pulls/$number" + }, + "html": { + "href": "https://github.com/${slug.fullName}/pull/$number" + }, + "issue": { + "href": "https://api.github.com/repos/${slug.fullName}/issues/$number" + }, + "comments": { + "href": "https://api.github.com/repos/${slug.fullName}/issues/$number/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/${slug.fullName}/pulls/$number/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/${slug.fullName}/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/${slug.fullName}/pulls/$number/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/${slug.fullName}/statuses/deadbeef" + } + }, + "author_association": "MEMBER", + "draft" : $isDraft, + "merged": $merged, + "mergeable": $isMergeable, + "rebaseable": true, + "mergeable_state": "draft", + "merged_by": null, + "comments": 1, + "review_comments": 0, + "maintainer_can_modify": true, + "commits": 5, + "additions": 55, + "deletions": 36, + "changed_files": 5 + }, + ${includeChanges ? ''' + "changes": { + "base": { + "ref": { + "from": "master" + }, + "sha": { + "from": "b3af5d64d3e6e2110b07d71909fc432537339659" + } + } + },''' : ''} + "repository": { + "id": 1868532, + "node_id": "MDEwOlJlcG9zaXRvcnkxODY4NTMwMDI=", + "name": "${slug.name}", + "full_name": "${slug.fullName}", + "private": false, + "owner": { + "login": "flutter", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/${slug.fullName}", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/${slug.fullName}", + "forks_url": "https://api.github.com/repos/${slug.fullName}/forks", + "keys_url": "https://api.github.com/repos/${slug.fullName}/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/${slug.fullName}/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/${slug.fullName}/teams", + "hooks_url": "https://api.github.com/repos/${slug.fullName}/hooks", + "issue_events_url": "https://api.github.com/repos/${slug.fullName}/issues/events{/number}", + "events_url": "https://api.github.com/repos/${slug.fullName}/events", + "assignees_url": "https://api.github.com/repos/${slug.fullName}/assignees{/user}", + "branches_url": "https://api.github.com/repos/${slug.fullName}/branches{/branch}", + "tags_url": "https://api.github.com/repos/${slug.fullName}/tags", + "blobs_url": "https://api.github.com/repos/${slug.fullName}/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/${slug.fullName}/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/${slug.fullName}/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/${slug.fullName}/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/${slug.fullName}/statuses/{sha}", + "languages_url": "https://api.github.com/repos/${slug.fullName}/languages", + "stargazers_url": "https://api.github.com/repos/${slug.fullName}/stargazers", + "contributors_url": "https://api.github.com/repos/${slug.fullName}/contributors", + "subscribers_url": "https://api.github.com/repos/${slug.fullName}/subscribers", + "subscription_url": "https://api.github.com/repos/${slug.fullName}/subscription", + "commits_url": "https://api.github.com/repos/${slug.fullName}/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/${slug.fullName}/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/${slug.fullName}/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/${slug.fullName}/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/${slug.fullName}/contents/{+path}", + "compare_url": "https://api.github.com/repos/${slug.fullName}/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/${slug.fullName}/merges", + "archive_url": "https://api.github.com/repos/${slug.fullName}/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/${slug.fullName}/downloads", + "issues_url": "https://api.github.com/repos/${slug.fullName}/issues{/number}", + "pulls_url": "https://api.github.com/repos/${slug.fullName}/pulls{/number}", + "milestones_url": "https://api.github.com/repos/${slug.fullName}/milestones{/number}", + "notifications_url": "https://api.github.com/repos/${slug.fullName}/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/${slug.fullName}/labels{/name}", + "releases_url": "https://api.github.com/repos/${slug.fullName}/releases{/id}", + "deployments_url": "https://api.github.com/repos/${slug.fullName}/deployments", + "created_at": "2019-05-15T15:19:25Z", + "updated_at": "2019-05-15T15:19:27Z", + "pushed_at": "2019-05-15T15:20:32Z", + "git_url": "git://github.com/${slug.fullName}.git", + "ssh_url": "git@github.com:${slug.fullName}.git", + "clone_url": "https://github.com/${slug.fullName}.git", + "svn_url": "https://github.com/${slug.fullName}", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "$kDefaultBranchName" + }, + "sender": { + "login": "$login", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + } +}'''; +} + +PushMessage generateCheckRunEvent({ + String action = 'created', + int numberOfPullRequests = 1, +}) { + var data = + '''{ + "action": "$action", + "check_run": { + "id": 128620228, + "node_id": "MDg6Q2hlY2tSdW4xMjg2MjAyMjg=", + "head_sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "external_id": "", + "url": "https://api.github.com/repos/flutter/flutter/check-runs/128620228", + "html_url": "https://github.com/flutter/flutter/runs/128620228", + "details_url": "https://octocoders.io", + "status": "queued", + "conclusion": null, + "started_at": "2019-05-15T15:21:12Z", + "completed_at": null, + "output": { + "title": null, + "summary": null, + "text": null, + "annotations_count": 0, + "annotations_url": "https://api.github.com/repos/flutter/flutter/check-runs/128620228/annotations" + }, + "name": "Octocoders-linter", + "check_suite": { + "id": 118578147, + "node_id": "MDEwOkNoZWNrU3VpdGUxMTg1NzgxNDc=", + "head_branch": "changes", + "head_sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "status": "queued", + "conclusion": null, + "url": "https://api.github.com/repos/flutter/flutter/check-suites/118578147", + "before": "6113728f27ae82c7b1a177c8d03f9e96e0adf246", + "after": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "pull_requests": [ + { + "url": "https://api.github.com/repos/flutter/flutter/pulls/2", + "id": 279147437, + "number": 2, + "head": { + "ref": "changes", + "sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "repo": { + "id": 186853002, + "url": "https://api.github.com/repos/flutter/flutter", + "name": "flutter" + } + }, + "base": { + "ref": "master", + "sha": "f95f852bd8fca8fcc58a9a2d6c842781e32a215e", + "repo": { + "id": 186853002, + "url": "https://api.github.com/repos/flutter/flutter", + "name": "flutter" + } + } + } + ], + "app": { + "id": 29310, + "node_id": "MDM6QXBwMjkzMTA=", + "owner": { + "login": "Octocoders", + "id": 38302899, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjM4MzAyODk5", + "avatar_url": "https://avatars1.githubusercontent.com/u/38302899?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Octocoders", + "html_url": "https://github.com/Octocoders", + "followers_url": "https://api.github.com/users/Octocoders/followers", + "following_url": "https://api.github.com/users/Octocoders/following{/other_user}", + "gists_url": "https://api.github.com/users/Octocoders/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Octocoders/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Octocoders/subscriptions", + "organizations_url": "https://api.github.com/users/Octocoders/orgs", + "repos_url": "https://api.github.com/users/Octocoders/repos", + "events_url": "https://api.github.com/users/Octocoders/events{/privacy}", + "received_events_url": "https://api.github.com/users/Octocoders/received_events", + "type": "Organization", + "site_admin": false + }, + "name": "octocoders-linter", + "description": "", + "external_url": "https://octocoders.io", + "html_url": "https://github.com/apps/octocoders-linter", + "created_at": "2019-04-19T19:36:24Z", + "updated_at": "2019-04-19T19:36:56Z", + "permissions": { + "administration": "write", + "checks": "write", + "contents": "write", + "deployments": "write", + "issues": "write", + "members": "write", + "metadata": "read", + "organization_administration": "write", + "organization_hooks": "write", + "organization_plan": "read", + "organization_projects": "write", + "organization_user_blocking": "write", + "pages": "write", + "pull_requests": "write", + "repository_hooks": "write", + "repository_projects": "write", + "statuses": "write", + "team_discussions": "write", + "vulnerability_alerts": "read" + }, + "events": [] + }, + "created_at": "2019-05-15T15:20:31Z", + "updated_at": "2019-05-15T15:20:31Z" + }, + "app": { + "id": 29310, + "node_id": "MDM6QXBwMjkzMTA=", + "owner": { + "login": "Octocoders", + "id": 38302899, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjM4MzAyODk5", + "avatar_url": "https://avatars1.githubusercontent.com/u/38302899?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Octocoders", + "html_url": "https://github.com/Octocoders", + "followers_url": "https://api.github.com/users/Octocoders/followers", + "following_url": "https://api.github.com/users/Octocoders/following{/other_user}", + "gists_url": "https://api.github.com/users/Octocoders/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Octocoders/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Octocoders/subscriptions", + "organizations_url": "https://api.github.com/users/Octocoders/orgs", + "repos_url": "https://api.github.com/users/Octocoders/repos", + "events_url": "https://api.github.com/users/Octocoders/events{/privacy}", + "received_events_url": "https://api.github.com/users/Octocoders/received_events", + "type": "Organization", + "site_admin": false + }, + "name": "octocoders-linter", + "description": "", + "external_url": "https://octocoders.io", + "html_url": "https://github.com/apps/octocoders-linter", + "created_at": "2019-04-19T19:36:24Z", + "updated_at": "2019-04-19T19:36:56Z", + "permissions": { + "administration": "write", + "checks": "write", + "contents": "write", + "deployments": "write", + "issues": "write", + "members": "write", + "metadata": "read", + "organization_administration": "write", + "organization_hooks": "write", + "organization_plan": "read", + "organization_projects": "write", + "organization_user_blocking": "write", + "pages": "write", + "pull_requests": "write", + "repository_hooks": "write", + "repository_projects": "write", + "statuses": "write", + "team_discussions": "write", + "vulnerability_alerts": "read" + }, + "events": [] + }, + "pull_requests": ['''; + + for (var i = 0; i < numberOfPullRequests; i++) { + data += + '''{ + "url": "https://api.github.com/repos/flutter/flutter/pulls/2", + "id": 279147437, + "number": ${i + 2}, + "head": { + "ref": "changes", + "sha": "ec26c3e57ca3a959ca5aad62de7213c562f8c821", + "repo": { + "id": 186853002, + "url": "https://api.github.com/repos/flutter/flutter", + "name": "flutter" + } + }, + "base": { + "ref": "master", + "sha": "f95f852bd8fca8fcc58a9a2d6c842781e32a215e", + "repo": { + "id": 186853002, + "url": "https://api.github.com/repos/flutter/flutter", + "name": "flutter" + } + } + }'''; + if (i < numberOfPullRequests - 1) { + data += ','; + } + } + data += '''], + "deployment": { + "url": "https://api.github.com/repos/flutter/flutter/deployments/326191728", + "id": 326191728, + "node_id": "MDEwOkRlcGxveW1lbnQzMjYxOTE3Mjg=", + "task": "deploy", + "original_environment": "lab", + "environment": "lab", + "description": null, + "created_at": "2021-02-18T08:22:48Z", + "updated_at": "2021-02-18T09:47:16Z", + "statuses_url": "https://api.github.com/repos/flutter/flutter/deployments/326191728/statuses", + "repository_url": "https://api.github.com/repos/flutter/flutter" + } + }, + "repository": { + "id": 186853002, + "node_id": "MDEwOlJlcG9zaXRvcnkxODY4NTMwMDI=", + "name": "flutter", + "full_name": "flutter/flutter", + "private": false, + "owner": { + "login": "flutter", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/flutter/flutter", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/flutter/flutter", + "forks_url": "https://api.github.com/repos/flutter/flutter/forks", + "keys_url": "https://api.github.com/repos/flutter/flutter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/flutter/flutter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/flutter/flutter/teams", + "hooks_url": "https://api.github.com/repos/flutter/flutter/hooks", + "issue_events_url": "https://api.github.com/repos/flutter/flutter/issues/events{/number}", + "events_url": "https://api.github.com/repos/flutter/flutter/events", + "assignees_url": "https://api.github.com/repos/flutter/flutter/assignees{/user}", + "branches_url": "https://api.github.com/repos/flutter/flutter/branches{/branch}", + "tags_url": "https://api.github.com/repos/flutter/flutter/tags", + "blobs_url": "https://api.github.com/repos/flutter/flutter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/flutter/flutter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/flutter/flutter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/flutter/flutter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/flutter/flutter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/flutter/flutter/languages", + "stargazers_url": "https://api.github.com/repos/flutter/flutter/stargazers", + "contributors_url": "https://api.github.com/repos/flutter/flutter/contributors", + "subscribers_url": "https://api.github.com/repos/flutter/flutter/subscribers", + "subscription_url": "https://api.github.com/repos/flutter/flutter/subscription", + "commits_url": "https://api.github.com/repos/flutter/flutter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/flutter/flutter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/flutter/flutter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/flutter/flutter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/flutter/flutter/contents/{+path}", + "compare_url": "https://api.github.com/repos/flutter/flutter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/flutter/flutter/merges", + "archive_url": "https://api.github.com/repos/flutter/flutter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/flutter/flutter/downloads", + "issues_url": "https://api.github.com/repos/flutter/flutter/issues{/number}", + "pulls_url": "https://api.github.com/repos/flutter/flutter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/flutter/flutter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/flutter/flutter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/flutter/flutter/labels{/name}", + "releases_url": "https://api.github.com/repos/flutter/flutter/releases{/id}", + "deployments_url": "https://api.github.com/repos/flutter/flutter/deployments", + "created_at": "2019-05-15T15:19:25Z", + "updated_at": "2019-05-15T15:21:03Z", + "pushed_at": "2019-05-15T15:20:57Z", + "git_url": "git://github.com/flutter/flutter.git", + "ssh_url": "git@github.com:flutter/flutter.git", + "clone_url": "https://github.com/flutter/flutter.git", + "svn_url": "https://github.com/flutter/flutter", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Ruby", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 1, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "forks": 1, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "flutter", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/flutter", + "html_url": "https://github.com/flutter", + "followers_url": "https://api.github.com/users/flutter/followers", + "following_url": "https://api.github.com/users/flutter/following{/other_user}", + "gists_url": "https://api.github.com/users/flutter/gists{/gist_id}", + "starred_url": "https://api.github.com/users/flutter/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/flutter/subscriptions", + "organizations_url": "https://api.github.com/users/flutter/orgs", + "repos_url": "https://api.github.com/users/flutter/repos", + "events_url": "https://api.github.com/users/flutter/events{/privacy}", + "received_events_url": "https://api.github.com/users/flutter/received_events", + "type": "User", + "site_admin": false + } +}'''; + final message = pb.GithubWebhookMessage(event: 'check_run', payload: data); + return PushMessage(data: message.writeToJson(), messageId: 'abc123'); +} + +PushMessage generateCreateBranchMessage( + String branchName, + String repository, { + bool forked = false, +}) { + final createEvent = generateCreateBranchEvent( + branchName, + repository, + forked: forked, + ); + final message = pb.GithubWebhookMessage( + event: 'create', + payload: jsonEncode(createEvent), + ); + return PushMessage(data: message.writeToJson(), messageId: 'abc123'); +} + +CreateEvent generateCreateBranchEvent( + String branchName, + String repository, { + bool forked = false, +}) => CreateEvent.fromJson( + jsonDecode(''' +{ + "ref": "$branchName", + "ref_type": "branch", + "master_branch": "master", + "description": null, + "pusher_type": "user", + "repository": { + "id": 186853002, + "node_id": "MDEwOlJlcG9zaXRvcnkxODY4NTMwMDI=", + "name": "${repository.split('/')[1]}", + "full_name": "$repository", + "private": false, + "owner": { + "login": "${repository.split('/')[0]}", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/$repository", + "description": null, + "fork": $forked, + "url": "https://api.github.com/repos/$repository", + "forks_url": "https://api.github.com/repos/$repository/forks", + "keys_url": "https://api.github.com/repos/$repository/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/$repository/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/$repository/teams", + "hooks_url": "https://api.github.com/repos/$repository/hooks", + "issue_events_url": "https://api.github.com/repos/$repository/issues/events{/number}", + "events_url": "https://api.github.com/repos/$repository/events", + "assignees_url": "https://api.github.com/repos/$repository/assignees{/user}", + "branches_url": "https://api.github.com/repos/$repository/branches{/branch}", + "tags_url": "https://api.github.com/repos/$repository/tags", + "blobs_url": "https://api.github.com/repos/$repository/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/$repository/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/$repository/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/$repository/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/$repository/statuses/{sha}", + "languages_url": "https://api.github.com/repos/$repository/languages", + "stargazers_url": "https://api.github.com/repos/$repository/stargazers", + "contributors_url": "https://api.github.com/repos/$repository/contributors", + "subscribers_url": "https://api.github.com/repos/$repository/subscribers", + "subscription_url": "https://api.github.com/repos/$repository/subscription", + "commits_url": "https://api.github.com/repos/$repository/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/$repository/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/$repository/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/$repository/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/$repository/contents/{+path}", + "compare_url": "https://api.github.com/repos/$repository/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/$repository/merges", + "archive_url": "https://api.github.com/repos/$repository/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/$repository/downloads", + "issues_url": "https://api.github.com/repos/$repository/issues{/number}", + "pulls_url": "https://api.github.com/repos/$repository/pulls{/number}", + "milestones_url": "https://api.github.com/repos/$repository/milestones{/number}", + "notifications_url": "https://api.github.com/repos/$repository/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/$repository/labels{/name}", + "releases_url": "https://api.github.com/repos/$repository/releases{/id}", + "deployments_url": "https://api.github.com/repos/$repository/deployments", + "created_at": "2019-05-15T15:19:25Z", + "updated_at": "2019-05-15T15:20:41Z", + "pushed_at": "2019-05-15T15:20:56Z", + "git_url": "git://github.com/$repository.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/$repository.git", + "svn_url": "https://github.com/$repository", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Ruby", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 1, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "forks": 1, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +}''') + as Map, +); + +PushMessage generatePushMessage( + String branch, + String organization, + String repository, +) { + final event = generatePushEvent(branch, organization, repository); + final message = pb.GithubWebhookMessage( + event: 'push', + payload: jsonEncode(event), + ); + return PushMessage(data: message.writeToJson(), messageId: 'abc123'); +} + +Map generatePushEvent( + String branch, + String organization, + String repository, { + String sha = 'def456def456def456', + String message = 'Commit-message', + String avatarUrl = 'https://fakegithubcontent.com/google_profile', + String username = 'googledotcom', +}) => + jsonDecode(''' +{ + "ref": "refs/heads/$branch", + "before": "abc123abc123abc123", + "after": "$sha", + "sender": { + "login": "$username", + "avatar_url": "$avatarUrl" + }, + "commits": [ + { + "id": "ba2f6608108d174c4a6e6e093a4ddcf313656748", + "message": "Adding null safety", + "timestamp": "2023-09-05T15:01:04-05:00", + "url": "https://github.com/org/repo/commit/abc123abc123abc123" + } + ], + "head_commit": { + "id": "$sha", + "message": "$message", + "timestamp": "2023-09-05T15:01:04-05:00", + "url": "https://github.com/org/repo/commit/abc123abc123abc123" + }, + "repository": { + "name": "$repository", + "full_name": "$organization/$repository" + } +} +''') + as Map; + +PushMessage generateMergeGroupMessage({ + required String repository, + required String action, + required String message, + DateTime? publishTime, + String? reason, + String? headSha, + String? headRef, +}) { + if (action == 'destroyed' && + !MergeGroupEvent.destroyReasons.contains(reason)) { + fail( + 'Invalid reason "$reason" for merge group "destroyed" event. The reason ' + 'must be one of: ${MergeGroupEvent.destroyReasons}', + ); + } + final webhookMessage = pb.GithubWebhookMessage( + event: 'merge_group', + payload: generateMergeGroupEventString( + action: action, + message: message, + repository: repository, + reason: reason, + headSha: headSha, + headRef: headRef, + ), + ); + publishTime ??= DateTime.now(); + return PushMessage( + data: webhookMessage.writeToJson(), + messageId: 'abc123', + publishTime: publishTime.toUtc().toIso8601String(), + ); +} + +String generateMergeGroupEventString({ + required String action, + required String message, + required String repository, + String? headSha, + String? headRef, + String? reason, +}) { + headSha ??= 'c9affbbb12aa40cb3afbe94b9ea6b119a256bebf'; + headRef ??= 'refs/heads/gh-readonly-queue/main/pr-15-$headSha'; + return ''' +{ +"action": "$action", +${reason != null ? '"reason": "$reason",' : ''} +"merge_group": { + "head_sha": "$headSha", + "head_ref": "$headRef", + "base_sha": "172355550dde5881b0269972ea4cbe5a6d0561bc", + "base_ref": "refs/heads/main", + "head_commit": { + "id": "c9affbbb12aa40cb3afbe94b9ea6b119a256bebf", + "tree_id": "556b9a8db18c974738d9d5e15988ae9a67e96b91", + "message": "$message", + "timestamp": "2024-10-15T20:24:16Z", + "author": { + "name": "John Doe", + "email": "johndoe@example.org" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + } +}, +"repository": { + "id": 186853002, + "node_id": "MDEwOlJlcG9zaXRvcnkxODY4NTMwMDI=", + "name": "${repository.split('/')[1]}", + "full_name": "$repository", + "private": false, + "owner": { + "login": "${repository.split('/')[0]}", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/$repository", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/$repository", + "forks_url": "https://api.github.com/repos/$repository/forks", + "keys_url": "https://api.github.com/repos/$repository/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/$repository/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/$repository/teams", + "hooks_url": "https://api.github.com/repos/$repository/hooks", + "issue_events_url": "https://api.github.com/repos/$repository/issues/events{/number}", + "events_url": "https://api.github.com/repos/$repository/events", + "assignees_url": "https://api.github.com/repos/$repository/assignees{/user}", + "branches_url": "https://api.github.com/repos/$repository/branches{/branch}", + "tags_url": "https://api.github.com/repos/$repository/tags", + "blobs_url": "https://api.github.com/repos/$repository/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/$repository/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/$repository/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/$repository/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/$repository/statuses/{sha}", + "languages_url": "https://api.github.com/repos/$repository/languages", + "stargazers_url": "https://api.github.com/repos/$repository/stargazers", + "contributors_url": "https://api.github.com/repos/$repository/contributors", + "subscribers_url": "https://api.github.com/repos/$repository/subscribers", + "subscription_url": "https://api.github.com/repos/$repository/subscription", + "commits_url": "https://api.github.com/repos/$repository/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/$repository/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/$repository/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/$repository/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/$repository/contents/{+path}", + "compare_url": "https://api.github.com/repos/$repository/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/$repository/merges", + "archive_url": "https://api.github.com/repos/$repository/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/$repository/downloads", + "issues_url": "https://api.github.com/repos/$repository/issues{/number}", + "pulls_url": "https://api.github.com/repos/$repository/pulls{/number}", + "milestones_url": "https://api.github.com/repos/$repository/milestones{/number}", + "notifications_url": "https://api.github.com/repos/$repository/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/$repository/labels{/name}", + "releases_url": "https://api.github.com/repos/$repository/releases{/id}", + "deployments_url": "https://api.github.com/repos/$repository/deployments", + "created_at": "2019-05-15T15:19:25Z", + "updated_at": "2019-05-15T15:20:41Z", + "pushed_at": "2019-05-15T15:20:56Z", + "git_url": "git://github.com/$repository.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/$repository.git", + "svn_url": "https://github.com/$repository", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Ruby", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 1, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "forks": 1, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" +}, +"organization": { + "login": "flutter", + "id": 14101776, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE0MTAxNzc2", + "url": "https://api.github.com/orgs/flutter", + "repos_url": "https://api.github.com/orgs/flutter/repos", + "events_url": "https://api.github.com/orgs/flutter/events", + "hooks_url": "https://api.github.com/orgs/flutter/hooks", + "issues_url": "https://api.github.com/orgs/flutter/issues", + "members_url": "https://api.github.com/orgs/flutter/members{/member}", + "public_members_url": "https://api.github.com/orgs/flutter/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/14101776?v=4", + "description": "Flutter is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, desktop, and embedded devices from a single codebase." +}, +"enterprise": { + "id": 1732, + "slug": "alphabet", + "name": "Alphabet", + "node_id": "MDEwOkVudGVycHJpc2UxNzMy", + "avatar_url": "https://avatars.githubusercontent.com/b/1732?v=4", + "description": "", + "website_url": "https://abc.xyz/", + "html_url": "https://github.com/enterprises/alphabet", + "created_at": "2019-12-19T00:30:52Z", + "updated_at": "2024-07-18T11:54:37Z" +}, +"sender": { + "login": "johndoe", + "id": 1924313, + "node_id": "MDQ6VXNlcjE5MjQzMTM=", + "avatar_url": "https://avatars.githubusercontent.com/u/1924313?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/johndoe", + "html_url": "https://github.com/johndoe", + "followers_url": "https://api.github.com/users/johndoe/followers", + "following_url": "https://api.github.com/users/johndoe/following{/other_user}", + "gists_url": "https://api.github.com/users/johndoe/gists{/gist_id}", + "starred_url": "https://api.github.com/users/johndoe/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/johndoe/subscriptions", + "organizations_url": "https://api.github.com/users/johndoe/orgs", + "repos_url": "https://api.github.com/users/johndoe/repos", + "events_url": "https://api.github.com/users/johndoe/events{/privacy}", + "received_events_url": "https://api.github.com/users/johndoe/received_events", + "type": "User", + "site_admin": false +}, +"installation": { + "id": 10381585, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTAzODE1ODU=" +} +} +'''; +} diff --git a/packages/cocoon_integration_test/lib/testing.dart b/packages/cocoon_integration_test/lib/testing.dart new file mode 100644 index 0000000000..767ae23221 --- /dev/null +++ b/packages/cocoon_integration_test/lib/testing.dart @@ -0,0 +1,39 @@ +// Copyright 2026 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/fakes/fake_auth_client.dart'; +export 'src/fakes/fake_big_query_service.dart'; +export 'src/fakes/fake_build_bucket_client.dart'; +export 'src/fakes/fake_build_status_service.dart'; +export 'src/fakes/fake_cache_service.dart'; +export 'src/fakes/fake_ci_yaml_fetcher.dart'; +export 'src/fakes/fake_config.dart'; +export 'src/fakes/fake_content_aware_hash_service.dart'; +export 'src/fakes/fake_dashboard_authentication.dart'; +export 'src/fakes/fake_entry.dart'; +export 'src/fakes/fake_firebase_jwt_validator.dart'; +export 'src/fakes/fake_firestore_service.dart'; + +export 'src/fakes/fake_gerrit_service.dart'; +export 'src/fakes/fake_get_files_changed.dart'; +export 'src/fakes/fake_github_service.dart'; +export 'src/fakes/fake_graphql_client.dart'; +export 'src/fakes/fake_http.dart'; +export 'src/fakes/fake_luci_build_service.dart'; +export 'src/fakes/fake_pubsub.dart'; +export 'src/fakes/fake_request_handler.dart'; +export 'src/fakes/fake_scheduler.dart'; +export 'src/fakes/fake_tabledata_resource.dart'; + +export 'src/integration_http_client.dart'; +export 'src/model/check_run_matcher.dart'; +export 'src/model/ci_yaml_matcher.dart'; +export 'src/model/firestore_matcher.dart'; +export 'src/model/ref_matcher.dart'; + +export 'src/utilities/build_bucket_messages.dart'; +export 'src/utilities/entity_generators.dart'; +export 'src/utilities/matchers.dart'; +export 'src/utilities/mocks.dart'; +export 'src/utilities/webhook_generators.dart'; diff --git a/packages/cocoon_integration_test/pubspec.yaml b/packages/cocoon_integration_test/pubspec.yaml new file mode 100644 index 0000000000..534e7d13b9 --- /dev/null +++ b/packages/cocoon_integration_test/pubspec.yaml @@ -0,0 +1,46 @@ +name: cocoon_integration_test +description: Integration testing environment for Cocoon. +version: 1.0.0 +publish_to: none + +resolution: workspace + +environment: + sdk: ^3.10.8 + +dependencies: + appengine: ^0.13.11 + buildbucket: + path: ../buildbucket-dart + cocoon_common: + path: ../cocoon_common + cocoon_server: + path: ../cocoon_server + cocoon_server_test: + path: ../cocoon_server_test + cocoon_service: + path: ../../app_dart + collection: ^1.19.1 + fixnum: 1.1.1 + github: 9.25.0 + googleapis: 14.0.0 + googleapis_auth: ^2.0.0 + gql: ^1.0.1 + graphql: ^5.2.3 + http: ^1.2.1 + jose_plus: ^0.4.7 + json_annotation: ^4.9.0 + logging: ^1.3.0 + meta: ^1.16.0 + mockito: ^5.6.3 + neat_cache: ^2.0.5 + path: ^1.9.1 + process: ^5.0.5 + retry: ^3.1.2 + test: ^1.26.3 + yaml: ^3.1.3 + +dev_dependencies: + build_runner: ^2.4.15 + json_serializable: ^6.9.4 + lints: ^6.0.0 \ No newline at end of file diff --git a/app_dart/test/src/service/fake_firestore_service_test.dart b/packages/cocoon_integration_test/test/fake_firestore_service_test.dart similarity index 99% rename from app_dart/test/src/service/fake_firestore_service_test.dart rename to packages/cocoon_integration_test/test/fake_firestore_service_test.dart index afe4e95d07..5fbca6b4a6 100644 --- a/app_dart/test/src/service/fake_firestore_service_test.dart +++ b/packages/cocoon_integration_test/test/fake_firestore_service_test.dart @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cocoon_integration_test/testing.dart'; import 'package:cocoon_server_test/test_logging.dart'; import 'package:cocoon_service/src/service/firestore.dart'; import 'package:googleapis/firestore/v1.dart' as g; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import 'fake_firestore_service.dart'; - void main() { useTestLoggerPerTest(); diff --git a/packages/cocoon_integration_test/test/server_test.dart b/packages/cocoon_integration_test/test/server_test.dart new file mode 100644 index 0000000000..2663ce3f0e --- /dev/null +++ b/packages/cocoon_integration_test/test/server_test.dart @@ -0,0 +1,14 @@ +// Copyright 2026 The Flutter Authors. 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:cocoon_integration_test/cocoon_integration_test.dart'; +import 'package:test/test.dart'; + +void main() { + test('IntegrationServer starts', () async { + final server = IntegrationServer(); + expect(server.server, isNotNull); + expect(server.config, isNotNull); + }); +} diff --git a/pubspec.yaml b/pubspec.yaml index d5f1bb74ac..aa93cd6c0a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,6 +19,7 @@ workspace: - packages/cocoon_common_test - packages/cocoon_server - packages/cocoon_server_test + - packages/cocoon_integration_test - dev/cocoon_code_health - dev/githubanalysis