// 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 'dart:convert';
import 'dart:core';

import 'package:buildbucket/buildbucket_pb.dart' as bbv2;
import 'package:cocoon_service/cocoon_service.dart';
import 'package:cocoon_service/src/model/appengine/commit.dart';
import 'package:cocoon_service/src/model/appengine/task.dart';
import 'package:cocoon_service/src/model/firestore/commit.dart' as firestore_commit;
import 'package:cocoon_service/src/model/firestore/task.dart' as firestore;
import 'package:cocoon_service/src/model/ci_yaml/target.dart';
import 'package:cocoon_service/src/model/github/checks.dart' as cocoon_checks;
import 'package:cocoon_service/src/model/luci/user_data.dart';
import 'package:cocoon_service/src/service/exceptions.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:cocoon_service/src/service/luci_build_service_v2.dart';
import 'package:fixnum/fixnum.dart';
import 'package:gcloud/datastore.dart';
import 'package:github/github.dart';
import 'package:googleapis/firestore/v1.dart' hide Status;
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import '../src/datastore/fake_config.dart';
import '../src/request_handling/fake_pubsub.dart';
import '../src/service/fake_gerrit_service.dart';
import '../src/service/fake_github_service.dart';
import '../src/utilities/build_bucket_v2_messages.dart';
import '../src/utilities/entity_generators.dart';
import '../src/utilities/mocks.dart';
import '../src/utilities/webhook_generators.dart';

void main() {
  late CacheService cache;
  late FakeConfig config;
  FakeGithubService githubService;
  late MockBuildBucketV2Client mockBuildBucketV2Client;
  late LuciBuildServiceV2 service;
  late RepositorySlug slug;
  late MockGithubChecksUtil mockGithubChecksUtil = MockGithubChecksUtil();
  late FakePubSub pubsub;

  final List<Target> targets = <Target>[
    generateTarget(1, properties: <String, String>{'os': 'abc'}),
  ];
  final PullRequest pullRequest = generatePullRequest(id: 1, repo: 'cocoon');

  group('getBuilds', () {
    final bbv2.Build macBuild = generateBbv2Build(Int64(998), name: 'Mac', status: bbv2.Status.STARTED);
    final bbv2.Build linuxBuild =
        generateBbv2Build(Int64(998), name: 'Linux', bucket: 'try', status: bbv2.Status.STARTED);

    setUp(() {
      cache = CacheService(inMemory: true);
      githubService = FakeGithubService();
      config = FakeConfig(githubService: githubService);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        gerritService: FakeGerritService(),
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'cocoon');
    });

    test('Null build', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[macBuild],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getTryBuilds(
        slug: Config.flutterSlug,
        sha: 'shasha',
        builderName: 'abcd',
      );
      expect(builds.first, macBuild);
    });

    test('Existing prod build', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getProdBuilds(
        slug: slug,
        commitSha: 'commit123',
        builderName: 'abcd',
      );
      expect(builds, isEmpty);
    });

    test('Existing try build', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[linuxBuild],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getTryBuilds(
        slug: Config.flutterSlug,
        sha: 'shasha',
        builderName: 'abcd',
      );
      expect(builds.first, linuxBuild);
    });

    test('Existing try build by pull request', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[linuxBuild],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getTryBuildsByPullRequest(
        pullRequest: PullRequest(
          id: 998,
          base: PullRequestHead(repo: Repository(fullName: 'flutter/cocoon')),
        ),
      );
      expect(builds.first, linuxBuild);
    });
  });

  group('getBuilders', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      githubService = FakeGithubService();
      config = FakeConfig(githubService: githubService);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        gerritService: FakeGerritService(),
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'flutter');
    });

    test('with one rpc call', () async {
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        return bbv2.ListBuildersResponse(
          builders: [
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test1')),
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test2')),
          ],
        );
      });
      final Set<String> builders = await service.getAvailableBuilderSet();
      expect(builders.length, 2);
      expect(builders.contains('test1'), isTrue);
    });

    test('with more than one rpc calls', () async {
      int retries = -1;
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        retries++;
        if (retries == 0) {
          return bbv2.ListBuildersResponse(
            builders: [
              bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test1')),
              bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test2')),
            ],
            nextPageToken: 'token',
          );
        } else if (retries == 1) {
          return bbv2.ListBuildersResponse(
            builders: [
              bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test3')),
              bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'test4')),
            ],
          );
        } else {
          return bbv2.ListBuildersResponse(builders: []);
        }
      });
      final Set<String> builders = await service.getAvailableBuilderSet();
      expect(builders.length, 4);
      expect(builders, <String>{'test1', 'test2', 'test3', 'test4'});
    });
  });

  group('buildsForRepositoryAndPr', () {
    final bbv2.Build macBuild = generateBbv2Build(Int64(999), name: 'Mac', status: bbv2.Status.STARTED);
    final bbv2.Build linuxBuild = generateBbv2Build(Int64(998), name: 'Linux', status: bbv2.Status.STARTED);

    setUp(() {
      cache = CacheService(inMemory: true);
      githubService = FakeGithubService();
      config = FakeConfig(githubService: githubService);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'cocoon');
    });

    test('Empty responses are handled correctly', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getTryBuilds(
        slug: RepositorySlug.full(pullRequest.base!.repo!.fullName),
        sha: pullRequest.head!.sha!,
        builderName: null,
      );
      expect(builds, isEmpty);
    });

    test('Response returning a couple of builds', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[macBuild],
              ),
            ),
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[linuxBuild],
              ),
            ),
          ],
        );
      });
      final Iterable<bbv2.Build> builds = await service.getTryBuilds(
        slug: RepositorySlug.full(pullRequest.base!.repo!.fullName),
        sha: pullRequest.head!.sha!,
        builderName: null,
      );
      expect(builds, equals(<bbv2.Build>{macBuild, linuxBuild}));
    });
  });

  group('scheduleBuilds', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      githubService = FakeGithubService();
      config = FakeConfig(githubService: githubService);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      mockGithubChecksUtil = MockGithubChecksUtil();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        githubChecksUtil: mockGithubChecksUtil,
        gerritService: FakeGerritService(branchesValue: <String>['master']),
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'cocoon');
    });

    test('schedule try builds successfully', () async {
      final PullRequest pullRequest = generatePullRequest();
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              scheduleBuild: generateBbv2Build(Int64(1)),
            ),
          ],
        );
      });
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));
      final List<Target> scheduledTargets = await service.scheduleTryBuilds(
        pullRequest: pullRequest,
        targets: targets,
      );

      final Iterable<String> scheduledTargetNames = scheduledTargets.map((Target target) => target.value.name);
      expect(scheduledTargetNames, <String>['Linux 1']);

      final bbv2.BatchRequest batchRequest = bbv2.BatchRequest().createEmptyInstance();
      batchRequest.mergeFromProto3Json(pubsub.messages.single);
      expect(batchRequest.requests.single.scheduleBuild, isNotNull);

      final bbv2.ScheduleBuildRequest scheduleBuild = batchRequest.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'try');
      expect(scheduleBuild.builder.builder, 'Linux 1');
      expect(scheduleBuild.notify.pubsubTopic, 'projects/flutter-dashboard/topics/build-bucket-presubmit');

      final Map<String, dynamic> userDataMap = UserData.decodeUserDataBytes(scheduleBuild.notify.userData);

      expect(userDataMap, <String, dynamic>{
        'repo_owner': 'flutter',
        'repo_name': 'flutter',
        'user_agent': 'flutter-cocoon',
        'check_run_id': 1,
        'commit_sha': 'abc',
        'commit_branch': 'master',
        'builder_name': 'Linux 1',
      });

      final Map<String, bbv2.Value> properties = scheduleBuild.properties.fields;
      final List<bbv2.RequestedDimension> dimensions = scheduleBuild.dimensions;
      expect(properties, <String, bbv2.Value>{
        'os': bbv2.Value(stringValue: 'abc'),
        'dependencies': bbv2.Value(listValue: bbv2.ListValue()),
        'bringup': bbv2.Value(boolValue: false),
        'git_branch': bbv2.Value(stringValue: 'master'),
        'git_url': bbv2.Value(stringValue: 'https://github.com/flutter/flutter'),
        'git_ref': bbv2.Value(stringValue: 'refs/pull/123/head'),
        'exe_cipd_version': bbv2.Value(stringValue: 'refs/heads/main'),
        'recipe': bbv2.Value(stringValue: 'devicelab/devicelab'),
      });
      expect(dimensions.length, 1);
      expect(dimensions[0].key, 'os');
      expect(dimensions[0].value, 'abc');
    });

    test('schedule try builds with github build labels successfully', () async {
      final PullRequest pullRequest = generatePullRequest();
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              scheduleBuild: generateBbv2Build(Int64(1)),
            ),
          ],
        );
      });
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));
      final List<Target> scheduledTargets = await service.scheduleTryBuilds(
        pullRequest: pullRequest,
        targets: targets,
      );
      final Iterable<String> scheduledTargetNames = scheduledTargets.map((Target target) => target.value.name);
      expect(scheduledTargetNames, <String>['Linux 1']);

      final bbv2.BatchRequest batchRequest = bbv2.BatchRequest().createEmptyInstance();
      batchRequest.mergeFromProto3Json(pubsub.messages.single);
      expect(batchRequest.requests.single.scheduleBuild, isNotNull);

      final bbv2.ScheduleBuildRequest scheduleBuild = batchRequest.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'try');
      expect(scheduleBuild.builder.builder, 'Linux 1');
      expect(scheduleBuild.notify.pubsubTopic, 'projects/flutter-dashboard/topics/build-bucket-presubmit');

      final Map<String, dynamic> userDataMap = UserData.decodeUserDataBytes(scheduleBuild.notify.userData);

      expect(userDataMap, <String, dynamic>{
        'repo_owner': 'flutter',
        'repo_name': 'flutter',
        'user_agent': 'flutter-cocoon',
        'check_run_id': 1,
        'commit_sha': 'abc',
        'commit_branch': 'master',
        'builder_name': 'Linux 1',
      });

      final Map<String, bbv2.Value> properties = scheduleBuild.properties.fields;
      final List<bbv2.RequestedDimension> dimensions = scheduleBuild.dimensions;
      expect(properties, <String, bbv2.Value>{
        'os': bbv2.Value(stringValue: 'abc'),
        'dependencies': bbv2.Value(listValue: bbv2.ListValue()),
        'bringup': bbv2.Value(boolValue: false),
        'git_branch': bbv2.Value(stringValue: 'master'),
        'git_url': bbv2.Value(stringValue: 'https://github.com/flutter/flutter'),
        'git_ref': bbv2.Value(stringValue: 'refs/pull/123/head'),
        'exe_cipd_version': bbv2.Value(stringValue: 'refs/heads/main'),
        'recipe': bbv2.Value(stringValue: 'devicelab/devicelab'),
      });
      expect(dimensions.length, 1);
      expect(dimensions[0].key, 'os');
      expect(dimensions[0].value, 'abc');
    });

    test('Schedule builds no-ops when targets list is empty', () async {
      await service.scheduleTryBuilds(
        pullRequest: pullRequest,
        targets: <Target>[],
      );
      verifyNever(mockGithubChecksUtil.createCheckRun(any, any, any, any));
    });
  });

  group('schedulePostsubmitBuilds', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: FakeConfig(),
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        githubChecksUtil: mockGithubChecksUtil,
        pubsub: pubsub,
      );
    });

    test('schedule packages postsubmit builds successfully', () async {
      final Commit commit = generateCommit(0);
      when(mockGithubChecksUtil.createCheckRun(any, Config.packagesSlug, any, 'Linux 1'))
          .thenAnswer((_) async => generateCheckRun(1));
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        return bbv2.ListBuildersResponse(
          builders: [
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'Linux 1')),
          ],
        );
      });
      final Tuple<Target, Task, int> toBeScheduled = Tuple<Target, Task, int>(
        generateTarget(
          1,
          properties: <String, String>{
            'recipe': 'devicelab/devicelab',
            'os': 'debian-10.12',
          },
          slug: Config.packagesSlug,
        ),
        generateTask(1),
        LuciBuildServiceV2.kDefaultPriority,
      );
      await service.schedulePostsubmitBuilds(
        commit: commit,
        toBeScheduled: <Tuple<Target, Task, int>>[
          toBeScheduled,
        ],
      );
      // Only one batch request should be published
      expect(pubsub.messages.length, 1);

      final bbv2.BatchRequest request = bbv2.BatchRequest().createEmptyInstance();
      request.mergeFromProto3Json(pubsub.messages.single);
      expect(request.requests.single.scheduleBuild, isNotNull);

      final bbv2.ScheduleBuildRequest scheduleBuild = request.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'prod');
      expect(scheduleBuild.builder.builder, 'Linux 1');
      expect(scheduleBuild.notify.pubsubTopic, 'projects/flutter-dashboard/topics/build-bucket-postsubmit');

      final Map<String, dynamic> userDataMap = UserData.decodeUserDataBytes(scheduleBuild.notify.userData);

      expect(userDataMap, <String, dynamic>{
        'commit_key': 'flutter/flutter/master/1',
        'task_key': '1',
        'check_run_id': 1,
        'commit_sha': '0',
        'commit_branch': 'master',
        'builder_name': 'Linux 1',
        'repo_owner': 'flutter',
        'repo_name': 'packages',
        'firestore_commit_document_name': '0',
        'firestore_task_document_name': '0_task1_1',
      });

      final Map<String, bbv2.Value> properties = scheduleBuild.properties.fields;
      expect(properties, <String, bbv2.Value>{
        'dependencies': bbv2.Value(listValue: bbv2.ListValue()),
        'bringup': bbv2.Value(boolValue: false),
        'git_branch': bbv2.Value(stringValue: 'master'),
        'exe_cipd_version': bbv2.Value(stringValue: 'refs/heads/master'),
        'os': bbv2.Value(stringValue: 'debian-10.12'),
        'recipe': bbv2.Value(stringValue: 'devicelab/devicelab'),
      });

      expect(scheduleBuild.exe, bbv2.Executable(cipdVersion: 'refs/heads/master'));
      expect(scheduleBuild.dimensions, isNotEmpty);
      expect(
        scheduleBuild.dimensions.singleWhere((bbv2.RequestedDimension dimension) => dimension.key == 'os').value,
        'debian-10.12',
      );
    });

    test('schedule postsubmit builds with correct userData for checkRuns', () async {
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));
      final Commit commit = generateCommit(0, repo: 'packages');
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        return bbv2.ListBuildersResponse(
          builders: [
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'Linux 1')),
          ],
        );
      });
      final Tuple<Target, Task, int> toBeScheduled = Tuple<Target, Task, int>(
        generateTarget(
          1,
          properties: <String, String>{
            'os': 'debian-10.12',
          },
          slug: RepositorySlug('flutter', 'packages'),
        ),
        generateTask(1),
        LuciBuildServiceV2.kDefaultPriority,
      );
      await service.schedulePostsubmitBuilds(
        commit: commit,
        toBeScheduled: <Tuple<Target, Task, int>>[
          toBeScheduled,
        ],
      );
      // Only one batch request should be published
      expect(pubsub.messages.length, 1);

      final bbv2.BatchRequest request = bbv2.BatchRequest().createEmptyInstance();
      request.mergeFromProto3Json(pubsub.messages.single);
      expect(request.requests.single.scheduleBuild, isNotNull);

      final bbv2.ScheduleBuildRequest scheduleBuild = request.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'prod');
      expect(scheduleBuild.builder.builder, 'Linux 1');
      expect(scheduleBuild.notify.pubsubTopic, 'projects/flutter-dashboard/topics/build-bucket-postsubmit');

      final Map<String, dynamic> userData = UserData.decodeUserDataBytes(scheduleBuild.notify.userData);

      expect(userData, <String, dynamic>{
        'commit_key': 'flutter/flutter/master/1',
        'task_key': '1',
        'check_run_id': 1,
        'commit_sha': '0',
        'commit_branch': 'master',
        'builder_name': 'Linux 1',
        'repo_owner': 'flutter',
        'repo_name': 'packages',
        'firestore_commit_document_name': '0',
        'firestore_task_document_name': '0_task1_1',
      });
    });

    test('return the orignal list when hitting buildbucket exception', () async {
      final Commit commit = generateCommit(0, repo: 'packages');
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        throw const BuildBucketException(1, 'error');
      });
      final Tuple<Target, Task, int> toBeScheduled = Tuple<Target, Task, int>(
        generateTarget(
          1,
          properties: <String, String>{
            'os': 'debian-10.12',
          },
          slug: RepositorySlug('flutter', 'packages'),
        ),
        generateTask(1),
        LuciBuildServiceV2.kDefaultPriority,
      );
      final List<Tuple<Target, Task, int>> results = await service.schedulePostsubmitBuilds(
        commit: commit,
        toBeScheduled: <Tuple<Target, Task, int>>[
          toBeScheduled,
        ],
      );
      expect(results, <Tuple<Target, Task, int>>[
        toBeScheduled,
      ]);
    });

    test('reschedule using checkrun event fails gracefully', () async {
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));

      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[],
              ),
            ),
          ],
        );
      });

      final pushMessage = generateCheckRunEvent(action: 'created', numberOfPullRequests: 1);
      final Map<String, dynamic> jsonMap = json.decode(pushMessage.data!);
      final Map<String, dynamic> jsonSubMap = json.decode(jsonMap['2']);
      final cocoon_checks.CheckRunEvent checkRunEvent = cocoon_checks.CheckRunEvent.fromJson(jsonSubMap);

      expect(
        () async => service.reschedulePostsubmitBuildUsingCheckRunEvent(
          checkRunEvent,
          commit: generateCommit(0),
          task: generateTask(0),
          target: generateTarget(0),
        ),
        throwsA(const TypeMatcher<NoBuildFoundException>()),
      );
    });

    test('do not create postsubmit checkrun for bringup: true target', () async {
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));
      final Commit commit = generateCommit(0, repo: Config.packagesSlug.name);
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        return bbv2.ListBuildersResponse(
          builders: [
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'Linux 1')),
          ],
        );
      });
      final Tuple<Target, Task, int> toBeScheduled = Tuple<Target, Task, int>(
        generateTarget(
          1,
          properties: <String, String>{
            'os': 'debian-10.12',
          },
          bringup: true,
          slug: Config.packagesSlug,
        ),
        generateTask(1, parent: commit),
        LuciBuildServiceV2.kDefaultPriority,
      );
      await service.schedulePostsubmitBuilds(
        commit: commit,
        toBeScheduled: <Tuple<Target, Task, int>>[
          toBeScheduled,
        ],
      );
      // Only one batch request should be published
      expect(pubsub.messages.length, 1);

      final bbv2.BatchRequest request = bbv2.BatchRequest().createEmptyInstance();
      request.mergeFromProto3Json(pubsub.messages.single);
      expect(request.requests.single.scheduleBuild, isNotNull);

      final bbv2.ScheduleBuildRequest scheduleBuild = request.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'staging');
      expect(scheduleBuild.builder.builder, 'Linux 1');
      expect(scheduleBuild.notify.pubsubTopic, 'projects/flutter-dashboard/topics/build-bucket-postsubmit');
      final Map<String, dynamic> userData = UserData.decodeUserDataBytes(scheduleBuild.notify.userData);
      // No check run related data.
      expect(userData, <String, dynamic>{
        'commit_key': 'flutter/packages/master/0',
        'task_key': '1',
        'firestore_commit_document_name': '0',
        'firestore_task_document_name': '0_task1_1',
      });
    });

    test('Skip non-existing builder', () async {
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));
      final Commit commit = generateCommit(0);
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 2'));
      when(mockBuildBucketV2Client.listBuilders(any)).thenAnswer((_) async {
        return bbv2.ListBuildersResponse(
          builders: [
            bbv2.BuilderItem(id: bbv2.BuilderID(bucket: 'prod', project: 'flutter', builder: 'Linux 2')),
          ],
        );
      });
      final Tuple<Target, Task, int> toBeScheduled1 = Tuple<Target, Task, int>(
        generateTarget(
          1,
          properties: <String, String>{
            'os': 'debian-10.12',
          },
        ),
        generateTask(1),
        LuciBuildService.kDefaultPriority,
      );
      final Tuple<Target, Task, int> toBeScheduled2 = Tuple<Target, Task, int>(
        generateTarget(
          2,
          properties: <String, String>{
            'os': 'debian-10.12',
          },
        ),
        generateTask(1),
        LuciBuildService.kDefaultPriority,
      );
      await service.schedulePostsubmitBuilds(
        commit: commit,
        toBeScheduled: <Tuple<Target, Task, int>>[
          toBeScheduled1,
          toBeScheduled2,
        ],
      );
      expect(pubsub.messages.length, 1);
      final bbv2.BatchRequest request = bbv2.BatchRequest().createEmptyInstance();
      request.mergeFromProto3Json(pubsub.messages.single);
      // Only existing builder: `Linux 2` is scheduled.
      expect(request.requests.length, 1);
      expect(request.requests.single.scheduleBuild, isNotNull);
      final bbv2.ScheduleBuildRequest scheduleBuild = request.requests.single.scheduleBuild;
      expect(scheduleBuild.builder.bucket, 'prod');
      expect(scheduleBuild.builder.builder, 'Linux 2');
    });
  });

  group('schedulePresubmitBuilds', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: FakeConfig(),
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        githubChecksUtil: mockGithubChecksUtil,
        pubsub: pubsub,
      );
    });

    test('reschedule using checkrun event', () async {
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any))
          .thenAnswer((_) async => generateCheckRun(1, name: 'Linux 1'));

      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[
                  generateBbv2Build(
                    Int64(1),
                    name: 'Linux',
                    status: bbv2.Status.ENDED_MASK,
                    tags: <bbv2.StringPair>[
                      bbv2.StringPair(key: 'buildset', value: 'pr/git/123'),
                      bbv2.StringPair(key: 'cipd_version', value: 'refs/heads/main'),
                      bbv2.StringPair(key: 'github_link', value: 'https://github.com/flutter/flutter/pull/1'),
                    ],
                    input: bbv2.Build_Input(properties: bbv2.Struct(fields: {'test': bbv2.Value(stringValue: 'abc')})),
                  ),
                ],
              ),
            ),
          ],
        );
      });
      when(mockBuildBucketV2Client.scheduleBuild(any)).thenAnswer((_) async => generateBbv2Build(Int64(1)));

      final pushMessage = generateCheckRunEvent(action: 'created', numberOfPullRequests: 1);
      final Map<String, dynamic> jsonMap = json.decode(pushMessage.data!);
      final Map<String, dynamic> jsonSubMap = json.decode(jsonMap['2']);
      final cocoon_checks.CheckRunEvent checkRunEvent = cocoon_checks.CheckRunEvent.fromJson(jsonSubMap);

      await service.reschedulePresubmitBuildUsingCheckRunEvent(
        checkRunEvent: checkRunEvent,
      );

      final List<dynamic> captured = verify(
        mockBuildBucketV2Client.scheduleBuild(
          captureAny,
        ),
      ).captured;
      expect(captured.length, 1);

      final bbv2.ScheduleBuildRequest scheduleBuildRequest = captured[0] as bbv2.ScheduleBuildRequest;

      final Map<String, dynamic> userData = UserData.decodeUserDataBytes(scheduleBuildRequest.notify.userData);

      expect(userData, <String, dynamic>{
        'check_run_id': 1,
        'commit_branch': 'master',
        'commit_sha': 'ec26c3e57ca3a959ca5aad62de7213c562f8c821',
        'repo_owner': 'flutter',
        'repo_name': 'flutter',
        'user_agent': 'flutter-cocoon',
      });

      final Map<String, dynamic> expectedProperties = {};
      expectedProperties['overrides'] = ['override: test'];
      final bbv2.Struct propertiesStruct = bbv2.Struct().createEmptyInstance();
      propertiesStruct.mergeFromProto3Json(expectedProperties);

      final Map<String, bbv2.Value> properties = scheduleBuildRequest.properties.fields;
      expect(properties['overrides'], propertiesStruct.fields['overrides']);
    });
  });

  group('cancelBuilds', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      config = FakeConfig();
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'cocoon');
    });

    test('Cancel builds when build list is empty', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[],
        );
      });
      await service.cancelBuilds(pullRequest: pullRequest, reason: 'new builds');
      // This is okay, it is getting called twice when it runs cancel builds
      // because the call is no longer being short-circuited. It calls batch in
      // tryBuildsForPullRequest and it calls in the top level cancelBuilds
      // function.
      verify(mockBuildBucketV2Client.batch(any)).called(1);
    });

    test('Cancel builds that are scheduled', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[
                  generateBbv2Build(Int64(998), name: 'Linux', status: bbv2.Status.STARTED),
                ],
              ),
            ),
          ],
        );
      });
      await service.cancelBuilds(pullRequest: pullRequest, reason: 'new builds');

      final List<dynamic> captured = verify(
        mockBuildBucketV2Client.batch(
          captureAny,
        ),
      ).captured;

      final List<bbv2.BatchRequest_Request> capturedBatchRequests = [];
      for (dynamic cap in captured) {
        capturedBatchRequests.add((cap as bbv2.BatchRequest).requests.first);
      }

      final bbv2.SearchBuildsRequest searchBuildRequest =
          capturedBatchRequests.firstWhere((req) => req.hasSearchBuilds()).searchBuilds;
      final bbv2.CancelBuildRequest cancelBuildRequest =
          capturedBatchRequests.firstWhere((req) => req.hasCancelBuild()).cancelBuild;
      expect(searchBuildRequest, isNotNull);
      expect(cancelBuildRequest, isNotNull);

      expect(cancelBuildRequest.id, Int64(998));
      expect(cancelBuildRequest.summaryMarkdown, 'new builds');
    });
  });

  group('failedBuilds', () {
    setUp(() {
      cache = CacheService(inMemory: true);
      githubService = FakeGithubService();
      config = FakeConfig(githubService: githubService);
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        pubsub: pubsub,
      );
      slug = RepositorySlug('flutter', 'flutter');
    });

    test('Failed builds from an empty list', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[],
        );
      });
      final List<bbv2.Build?> result = await service.failedBuilds(pullRequest: pullRequest, targets: <Target>[]);
      expect(result, isEmpty);
    });

    test('Failed builds from a list of builds with failures', () async {
      when(mockBuildBucketV2Client.batch(any)).thenAnswer((_) async {
        return bbv2.BatchResponse(
          responses: <bbv2.BatchResponse_Response>[
            bbv2.BatchResponse_Response(
              searchBuilds: bbv2.SearchBuildsResponse(
                builds: <bbv2.Build>[
                  generateBbv2Build(Int64(998), name: 'Linux 1', status: bbv2.Status.FAILURE),
                ],
              ),
            ),
          ],
        );
      });
      final List<bbv2.Build?> result =
          await service.failedBuilds(pullRequest: pullRequest, targets: <Target>[generateTarget(1)]);
      expect(result, hasLength(1));
    });
  });

  group('rescheduleBuild', () {
    late bbv2.BuildsV2PubSub rescheduleBuild;

    setUp(() {
      cache = CacheService(inMemory: true);
      config = FakeConfig();
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        pubsub: pubsub,
      );
      rescheduleBuild = createBuild(Int64(1), status: bbv2.Status.FAILURE, builder: 'Linux Host Engine');
    });

    test('Reschedule an existing build', () async {
      when(mockBuildBucketV2Client.scheduleBuild(any)).thenAnswer((_) async => generateBbv2Build(Int64(1)));
      final build = await service.rescheduleBuild(
        builderName: 'mybuild',
        build: rescheduleBuild.build,
        rescheduleAttempt: 2,
        userDataMap: {},
      );
      expect(build.id, Int64(1));
      expect(build.status, bbv2.Status.SUCCESS);
      final List<dynamic> captured = verify(mockBuildBucketV2Client.scheduleBuild(captureAny)).captured;
      expect(captured.length, 1);

      final bbv2.ScheduleBuildRequest scheduleBuildRequest = captured[0];
      expect(scheduleBuildRequest, isNotNull);
      final List<bbv2.StringPair> tags = scheduleBuildRequest.tags;
      final bbv2.StringPair attemptPair = tags.firstWhere((element) => element.key == 'current_attempt');
      expect(attemptPair.value, '2');
    });
  });

  group('checkRerunBuilder', () {
    late Commit commit;
    late Commit totCommit;
    late DatastoreService datastore;
    late MockGithubChecksUtil mockGithubChecksUtil;
    late MockFirestoreService mockFirestoreService;
    firestore.Task? firestoreTask;
    firestore_commit.Commit? firestoreCommit;
    setUp(() {
      cache = CacheService(inMemory: true);
      config = FakeConfig();
      firestoreTask = null;
      firestoreCommit = null;
      mockGithubChecksUtil = MockGithubChecksUtil();
      mockFirestoreService = MockFirestoreService();
      mockBuildBucketV2Client = MockBuildBucketV2Client();
      when(mockGithubChecksUtil.createCheckRun(any, any, any, any, output: anyNamed('output')))
          .thenAnswer((realInvocation) async => generateCheckRun(1));
      when(
        mockFirestoreService.batchWriteDocuments(
          captureAny,
          captureAny,
        ),
      ).thenAnswer((Invocation invocation) {
        return Future<BatchWriteResponse>.value(BatchWriteResponse());
      });
      when(
        mockFirestoreService.getDocument(
          captureAny,
        ),
      ).thenAnswer((Invocation invocation) {
        return Future<firestore_commit.Commit>.value(
          firestoreCommit,
        );
      });
      when(
        mockFirestoreService.queryRecentCommits(
          limit: captureAnyNamed('limit'),
          slug: captureAnyNamed('slug'),
          branch: captureAnyNamed('branch'),
        ),
      ).thenAnswer((Invocation invocation) {
        return Future<List<firestore_commit.Commit>>.value(
          <firestore_commit.Commit>[firestoreCommit!],
        );
      });
      pubsub = FakePubSub();
      service = LuciBuildServiceV2(
        config: config,
        cache: cache,
        buildBucketV2Client: mockBuildBucketV2Client,
        githubChecksUtil: mockGithubChecksUtil,
        pubsub: pubsub,
      );
      datastore = DatastoreService(config.db, 5);
    });

    test('Pass repo and properties correctly', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1, status: firestore.Task.statusFailed);
      firestoreCommit = generateFirestoreCommit(1);
      totCommit = generateCommit(1, repo: 'engine', branch: 'main');
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusFailed,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      expect(task.attempts, 1);
      expect(task.status, Task.statusFailed);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(pubsub.messages.length, 1);

      final bbv2.BatchRequest request = bbv2.BatchRequest().createEmptyInstance();
      request.mergeFromProto3Json(pubsub.messages.single);
      expect(request, isNotNull);
      final bbv2.ScheduleBuildRequest scheduleBuildRequest = request.requests.first.scheduleBuild;

      final Map<String, bbv2.Value> properties = scheduleBuildRequest.properties.fields;
      for (String key in Config.defaultProperties.keys) {
        expect(properties.containsKey(key), true);
      }
      expect(scheduleBuildRequest.priority, LuciBuildService.kRerunPriority);
      expect(scheduleBuildRequest.gitilesCommit.project, 'mirrors/engine');
      expect(scheduleBuildRequest.tags.firstWhere((tag) => tag.key == 'trigger_type').value, 'auto_retry');
      expect(rerunFlag, isTrue);
      expect(task.attempts, 2);
      expect(task.status, Task.statusInProgress);
    });

    test('Rerun a test failed builder', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1, status: firestore.Task.statusFailed);
      firestoreCommit = generateFirestoreCommit(1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusFailed,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isTrue);
    });

    test('Rerun an infra failed builder', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1, status: firestore.Task.statusInfraFailure);
      firestoreCommit = generateFirestoreCommit(1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusInfraFailure,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isTrue);
    });

    test('Skip rerun a failed test when task status update hit exception', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1, status: firestore.Task.statusInfraFailure);
      when(
        mockFirestoreService.batchWriteDocuments(
          captureAny,
          captureAny,
        ),
      ).thenAnswer((Invocation invocation) {
        throw InternalError();
      });
      firestoreCommit = generateFirestoreCommit(1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusFailed,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isFalse);
      expect(pubsub.messages.length, 0);
    });

    test('Do not rerun a successful builder', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusSucceeded,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isFalse);
    });

    test('Do not rerun a builder exceeding retry limit', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusInfraFailure,
        parent: totCommit,
        buildNumber: 1,
        attempts: 2,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isFalse);
    });

    test('Do not rerun a builder when not tip of tree', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1);
      totCommit = generateCommit(2, sha: 'def');
      commit = generateCommit(1, sha: 'abc');
      config.db.values[totCommit.key] = totCommit;
      config.db.values[commit.key] = commit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusInfraFailure,
        parent: commit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: commit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isFalse);
    });

    test('insert retried task document to firestore', () async {
      firestoreTask = generateFirestoreTask(1, attempts: 1, status: firestore.Task.statusInfraFailure);
      firestoreCommit = generateFirestoreCommit(1);
      totCommit = generateCommit(1);
      config.db.values[totCommit.key] = totCommit;
      config.maxLuciTaskRetriesValue = 1;
      final Task task = generateTask(
        1,
        status: Task.statusInfraFailure,
        parent: totCommit,
        buildNumber: 1,
      );
      final Target target = generateTarget(1);
      expect(firestoreTask!.attempts, 1);
      final bool rerunFlag = await service.checkRerunBuilder(
        commit: totCommit,
        task: task,
        target: target,
        datastore: datastore,
        firestoreService: mockFirestoreService,
        taskDocument: firestoreTask!,
      );
      expect(rerunFlag, isTrue);

      expect(firestoreTask!.attempts, 2);
      final List<dynamic> captured = verify(mockFirestoreService.batchWriteDocuments(captureAny, captureAny)).captured;
      expect(captured.length, 2);
      final BatchWriteRequest batchWriteRequest = captured[0] as BatchWriteRequest;
      expect(batchWriteRequest.writes!.length, 1);
      final Document insertedTaskDocument = batchWriteRequest.writes![0].update!;
      expect(insertedTaskDocument, firestoreTask);
      expect(firestoreTask!.status, firestore.Task.statusInProgress);
    });
  });
}
