blob: 1031a1db5f3b292eda031797fedeac4f7f49dbb4 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Tests that check automatic approval of failures on a revert on the CI
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import '../result.dart';
import 'fakes.dart';
import 'test_data.dart';
void main() async {
test('fetch commit that is a revert', () async {
final builderTest = BuilderTest(revertCommitHash, revertUnchangedChange);
builderTest.firestore.commits[revertedCommitHash] = revertedCommit;
when(builderTest.client.get(any))
.thenAnswer((_) => Future(() => ResponseFake(revertGitilesLog)));
await builderTest.storeBuildCommitsInfo();
expect(builderTest.builder.endIndex, revertCommit['index']);
expect(builderTest.builder.startIndex, landedCommit['index'] + 1);
expect(await builderTest.builder.firestore.getCommit(revertCommitHash),
revertCommit);
});
test('fetch commit that is a reland (as a reland)', () async {
final builderTest = BuilderTest(relandCommitHash, relandUnchangedChange);
builderTest.firestore.commits[revertedCommitHash] = revertedCommit;
when(builderTest.client.get(any)).thenAnswer(
(_) => Future(() => ResponseFake(revertAndRelandGitilesLog)));
await builderTest.storeBuildCommitsInfo();
expect(builderTest.builder.endIndex, relandCommit['index']);
expect(builderTest.builder.startIndex, revertCommit['index'] + 1);
expect(await builderTest.builder.firestore.getCommit(revertCommitHash),
revertCommit);
expect(
await builderTest.builder.firestore.getCommit(commit56Hash), commit56);
expect(await builderTest.builder.firestore.getCommit(relandCommitHash),
relandCommit);
});
test('fetch commit that is a reland (as a revert)', () async {
final builderTest =
RevertBuilderTest(relandCommitHash, relandUnchangedChange);
when(builderTest.client.get(any))
.thenAnswer((_) => Future(() => ResponseFake(relandGitilesLog)));
await builderTest.storeBuildCommitsInfo();
expect(builderTest.builder.endIndex, relandCommit['index']);
expect(builderTest.builder.startIndex, revertCommit['index'] + 1);
expect(await builderTest.builder.firestore.getCommit(relandCommitHash),
relandCommit);
});
test('Automatically approve expected failure on revert', () async {
final builderTest = RevertBuilderTest(revertCommitHash, revertChange);
await builderTest.update();
await builderTest.storeChange(revertChange);
expect(
builderTest.firestore.results.values
.where((result) => result[fBlamelistEndIndex] == 55)
.single,
revertResult);
});
test('Revert in blamelist, doesn\'t match new failure', () async {
final builderTest =
RevertBuilderTest(commit56Hash, commit56UnmatchingChange);
await builderTest.update();
await builderTest.storeChange(commit56UnmatchingChange);
await builderTest.storeChange(commit56DifferentNameChange);
await builderTest.storeChange(commit56Change);
expect(
(await builderTest.firestore
.findActiveResults(commit56UnmatchingChange))
.single['approved'],
false);
expect(
(await builderTest.firestore
.findActiveResults(commit56DifferentNameChange))
.single['approved'],
false);
expect(
(await builderTest.firestore.findActiveResults(commit56Change))
.single['approved'],
true);
});
}
class RevertBuilderTest extends BuilderTest {
RevertBuilderTest(String commitHash, Map<String, dynamic> firstChange)
: super(commitHash, firstChange) {
expect(revertedCommit[fIndex] + 1, fakeFirestoreCommitsFirstIndex);
expect(revertCommit[fIndex] - 1, fakeFirestoreCommitsLastIndex);
firestore.commits
..[revertedCommitHash] = revertedCommit
..[revertCommitHash] = revertCommit
..[commit56Hash] = commit56;
firestore.results['revertedResult id'] = revertedResult;
}
}
// Commits
const String revertedCommitHash = '50abcd55abcd';
const int revertedReview = 3926;
const int revertedIndex = 50;
Map<String, dynamic> revertedCommit = Map.unmodifiable({
'author': 'gerrit_reverted_user@example.com',
'created': DateTime.parse('2019-11-22 02:01:00Z'),
'index': revertedIndex,
'title': 'A commit reverted by commit 55, with index 50',
'review': revertedReview,
'hash': revertedCommitHash,
});
const String revertCommitHash = '55ffffdddd';
const int revertReview = 3426;
const int revertIndex = 55;
Map<String, dynamic> revertCommit = Map.unmodifiable({
'author': 'gerrit_revert_user@example.com',
'created': DateTime.parse('2019-11-29 16:15:00Z'),
'index': revertIndex,
'title': 'Revert "${revertedCommit[fTitle]}"',
'hash': revertCommitHash,
'review': revertReview,
'revert_of': revertedCommitHash,
});
const String commit56Hash = '56ffeeddccbbaa00';
Map<String, dynamic> commit56 = Map.unmodifiable({
'author': 'gerrit_revert_user@example.com',
'created': DateTime.parse('2019-11-29 17:15:00Z'),
'index': revertIndex + 1,
'title': 'A commit with index 56',
'hash': commit56Hash,
});
const String relandCommitHash = '57eeddccff7733';
const int relandReview = 98999;
Map<String, dynamic> relandCommit = Map.unmodifiable({
'author': 'gerrit_reland_user@example.com',
'created': DateTime.parse('2020-01-13 06:16:00Z'),
'index': revertIndex + 2,
'title': 'Reland "${revertedCommit[fTitle]}"',
'hash': relandCommitHash,
'review': relandReview,
'reland_of': revertedCommitHash,
});
// Changes
// This change is an unchanged passing result, used as the first result in
// a chunk with no changed results.
const Map<String, dynamic> revertUnchangedChange = {
"name": "dart2js_extra/local_function_signatures_strong_test/none",
"configuration": "dart2js-new-rti-linux-x64-d8",
"suite": "dart2js_extra",
"test_name": "local_function_signatures_strong_test/none",
"time_ms": 2384,
"result": "Pass",
"expected": "Pass",
"matches": false,
"bot_name": "luci-dart-try-xenial-70-8fkh",
"commit_hash": revertCommitHash,
"previous_commit_hash": landedCommitHash,
"commit_time": 1563576771,
"build_number": "401",
"previous_build_number": "400",
"changed": false,
};
Map<String, dynamic> relandUnchangedChange = Map.from(revertUnchangedChange)
..["commit_hash"] = relandCommitHash
..["previous_commit_hash"] = revertCommitHash;
const Map<String, dynamic> revertChange = {
"name": "test_suite/fixed_broken_test",
"configuration": "a_different_configuration",
"suite": "test_suite",
"test_name": "fixed_broken_test",
"time_ms": 2384,
"result": "RuntimeError",
"expected": "Pass",
"matches": false,
"bot_name": "a_ci_bot",
"commit_hash": revertCommitHash,
"commit_time": 1563576771,
"build_number": "314",
"builder_name": "dart2js-rti-linux-x64-d8",
"flaky": false,
"previous_flaky": false,
"previous_result": "Pass",
"previous_commit_hash": existingCommitHash,
"previous_commit_time": 1563576211,
"previous_build_number": "313",
"changed": true,
};
const Map<String, dynamic> revertedChange = {
"name": "test_suite/fixed_broken_test",
"configuration": "a_configuration",
"suite": "test_suite",
"test_name": "fixed_broken_test",
"time_ms": 2384,
"result": "Pass",
"expected": "Pass",
"matches": true,
"bot_name": "a_ci_bot",
"commit_hash": revertedCommitHash,
"commit_time": 1563576771,
"build_number": "308",
"builder_name": "dart2js-rti-linux-x64-d8",
"flaky": false,
"previous_flaky": false,
"previous_result": "RuntimeError",
"previous_commit_hash": "a nonexistent hash",
"previous_commit_time": 1563576211,
"previous_build_number": "306",
"changed": true
};
Map<String, dynamic> commit56Change = Map.from(revertChange)
..['commit_hash'] = commit56Hash;
Map<String, dynamic> commit56UnmatchingChange = Map.from(commit56Change)
..['configuration'] = 'a_configuration'
..['commit_hash'] = commit56Hash
..['result'] = 'CompileTimeError';
Map<String, dynamic> commit56DifferentNameChange = Map.from(commit56Change)
..['commit_hash'] = commit56Hash
..['name'] = 'test_suite/broken_test'
..['test_name'] = 'broken_test';
// Results
const Map<String, dynamic> revertResult = {
"configurations": ["a_different_configuration"],
"active": true,
"active_configurations": ["a_different_configuration"],
"name": "test_suite/fixed_broken_test",
"result": "RuntimeError",
"expected": "Pass",
"previous_result": "Pass",
"blamelist_start_index": commit53Index,
"blamelist_end_index": revertIndex,
"pinned_index": revertIndex,
"approved": true,
};
const Map<String, dynamic> revertedResult = {
"configurations": ["a_configuration"],
"name": "test_suite/fixed_broken_test",
"result": "Pass",
"expected": "Pass",
"previous_result": "RuntimeError",
"blamelist_start_index": revertedIndex,
"blamelist_end_index": revertedIndex,
};
// Git logs
String escape(s) => s.replaceAll('"', '\\"');
String revertGitilesLog = gitilesLog([revertCommitJson]);
String relandGitilesLog = gitilesLog([relandCommitJson(relandAsRevert)]);
String revertAndRelandGitilesLog = gitilesLog(
[relandCommitJson(relandAsReland), commit56Json, revertCommitJson]);
String gitilesLog(List<String> commitLogs) => '''
)]}'
{
"log": [
${commitLogs.join(",\n")}
]
}
''';
String revertCommitJson = '''
{
"commit": "$revertCommitHash",
"parents": ["$landedCommitHash"],
"author": {
"email": "${revertCommit[fAuthor]}"
},
"committer": {
"time": "Fri Nov 29 16:15:00 2019 +0000"
},
"message": "${escape(revertCommit[fTitle])}\\n\\nThis reverts commit $revertedCommitHash.\\nChange-Id: I89b88c3d9f7c743fc340ee73a45c3f57059bcf30\\nReviewed-on: https://dart-review.googlesource.com/c/sdk/+/$revertReview\\n\\n"
}
''';
String commit56Json = '''
{
"commit": "$commit56Hash",
"parents": ["$revertCommitHash"],
"author": {
"email": "${commit56[fAuthor]}"
},
"committer": {
"time": "Fri Nov 29 17:15:00 2019 +0000"
},
"message": "${escape(commit56[fTitle])}\\n\\nNo line like: This reverts commit $revertedCommitHash.\\nChange-Id: I89b88c3d9f7c743fc340ee73a45c3f57059bcf30\\nNo review line either\\n\\n"
}
''';
String relandCommitJson(String relandLine) => '''
{
"commit": "$relandCommitHash",
"parents": ["$commit56Hash"],
"author": {
"email": "${relandCommit[fAuthor]}"
},
"committer": {
"time": "Mon Jan 13 06:16:00 2020 +0000"
},
"message": "${escape(relandCommit[fTitle])}\\n\\n$relandLine\\nChange-Id: I89b88c3d9f7c743fc340ee73a45c3f57059bcf30\\nReviewed-on: https://dart-review.googlesource.com/c/sdk/+/$relandReview\\n\\n"
}
''';
String relandAsRevert = "This reverts commit $revertCommitHash.";
String relandAsReland = "This is a reland of $revertedCommitHash";