blob: 6e9df501d7cb995906022a187de2e52e2c8b8ebe [file] [log] [blame]
// 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 'dart:convert';
import 'package:cocoon_service/cocoon_service.dart';
import 'package:cocoon_service/src/model/appengine/commit.dart';
import 'package:cocoon_service/src/model/appengine/stage.dart';
import 'package:cocoon_service/src/model/appengine/task.dart';
import 'package:cocoon_service/src/service/build_status_provider.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:gcloud/db.dart';
import 'package:test/test.dart';
import '../src/datastore/fake_config.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/request_handling/fake_http.dart';
import '../src/request_handling/request_handler_tester.dart';
import '../src/service/fake_build_status_provider.dart';
import '../src/utilities/entity_generators.dart';
void main() {
group('GetGreenCommits', () {
late FakeConfig config;
FakeClientContext clientContext;
FakeKeyHelper keyHelper;
FakeBuildStatusService buildStatusService;
late RequestHandlerTester tester;
late GetGreenCommits handler;
final Commit commit1 = generateCommit(1, timestamp: 3, sha: 'ea28a9c34dc701de891eaf74503ca4717019f829');
final Commit commit2 = generateCommit(2, timestamp: 1, sha: 'd5b0b3c8d1c5fd89302089077ccabbcfaae045e4');
final Commit commitBranched = generateCommit(
2,
timestamp: 1,
sha: 'ffffffffffffffffffffffffffffffffaae045e4',
branch: 'flutter-2.13-candidate.0',
);
final Task task1Succeed = generateTask(1, status: Task.statusSucceeded);
final Task task2Failed = generateTask(2, status: Task.statusFailed); // should fail if included
final Task task3FailedFlaky =
generateTask(3, status: Task.statusFailed, isFlaky: true); // should succeed if included because `bringup: true`
final Task task4SucceedFlaky = generateTask(4, status: Task.statusSucceeded, isFlaky: true);
final Stage stageOneSucceed =
Stage('cocoon', commit1, [task1Succeed], Task.statusInProgress); // should scceed, since task 1 succeed
final Stage stageFailed = Stage(
'luci',
commit1,
[task1Succeed, task2Failed],
Task.statusInProgress,
); // should fail, since task 1 succeed and task2 fail
final Stage stageMultipleSucceed = Stage(
'cocoon',
commit2,
[task1Succeed, task4SucceedFlaky],
Task.statusInProgress,
); // should succeed, since both task 1 and task 4 succeed
final Stage stageFailedFlaky = Stage(
'luci',
commit2,
[task1Succeed, task3FailedFlaky],
Task.statusInProgress,
); // should succeed, even though it includes task 3
Future<List<T?>?> decodeHandlerBody<T>() async {
final Body body = await tester.get(handler);
return (await utf8.decoder.bind(body.serialize() as Stream<List<int>>).transform(json.decoder).single
as List<dynamic>)
.cast<T>();
}
setUp(() {
clientContext = FakeClientContext();
keyHelper = FakeKeyHelper(applicationContext: clientContext.applicationContext);
tester = RequestHandlerTester();
config = FakeConfig(keyHelperValue: keyHelper);
buildStatusService = FakeBuildStatusService(commitStatuses: <CommitStatus>[]);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
});
test('no green commits', () async {
final List<String?> result = (await decodeHandlerBody())!;
expect(result, isEmpty);
});
test('should return commits with all tasks succeed', () async {
buildStatusService = FakeBuildStatusService(
commitStatuses: <CommitStatus>[
CommitStatus(commit1, <Stage>[stageOneSucceed]),
CommitStatus(commit2, <Stage>[stageOneSucceed, stageMultipleSucceed]),
],
);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
final List<String?> result = (await decodeHandlerBody())!;
expect(result.length, 2);
expect(result, <String>[
commit2.sha!,
commit1.sha!,
]);
});
test('should fail commits that have failed task without [bringup: true] label', () async {
buildStatusService = FakeBuildStatusService(
commitStatuses: <CommitStatus>[
CommitStatus(commit1, <Stage>[stageFailed]),
CommitStatus(commit2, <Stage>[stageOneSucceed, stageMultipleSucceed]),
],
);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
final List<String?> result = (await decodeHandlerBody())!;
expect(result.length, 1);
expect(result, <String>[commit2.sha!]);
});
test('should return commits with failed tasks but with `bringup: true` label', () async {
buildStatusService = FakeBuildStatusService(
commitStatuses: <CommitStatus>[
CommitStatus(commit1, <Stage>[stageFailed]),
CommitStatus(commit2, <Stage>[stageFailedFlaky]),
],
);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
final List<String?> result = (await decodeHandlerBody())!;
expect(result.length, 1);
expect(result, <String>[commit2.sha!]);
});
test('should return commits with both flaky and succeeded tasks', () async {
buildStatusService = FakeBuildStatusService(
commitStatuses: <CommitStatus>[
CommitStatus(commit1, <Stage>[stageOneSucceed, stageMultipleSucceed]),
CommitStatus(commit2, <Stage>[stageOneSucceed, stageFailedFlaky]),
],
);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
final List<String?> result = (await decodeHandlerBody())!;
expect(result.length, 2);
expect(result, <String>[
commit2.sha!,
commit1.sha!,
]);
});
test('should return branched commits', () async {
buildStatusService = FakeBuildStatusService(
commitStatuses: <CommitStatus>[
CommitStatus(commitBranched, <Stage>[stageOneSucceed]),
],
);
tester.request = FakeHttpRequest(
queryParametersValue: <String, String>{
GetGreenCommits.kBranchParam: commitBranched.branch!,
},
);
handler = GetGreenCommits(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
buildStatusProvider: (_) => buildStatusService,
);
final List<String?> result = (await decodeHandlerBody())!;
expect(result, <String>[
commitBranched.sha!,
]);
});
});
}