blob: e0720e00c159a2f637b19d7f340a9706fbf668e7 [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.
import 'dart:math';
import 'package:googleapis/firestore/v1.dart';
import 'package:mockito/mockito.dart';
import 'package:http/http.dart';
import 'package:builder/src/builder.dart';
import 'package:builder/src/commits_cache.dart';
import 'package:builder/src/firestore.dart';
import 'package:builder/src/result.dart';
import 'test_data.dart';
class BuilderTest {
final client = HttpClientMock();
final firestore = FirestoreServiceFake();
CommitsCache commitsCache;
Build builder;
String commitHash;
Map<String, dynamic> firstChange;
BuilderTest(this.commitHash, this.firstChange) {
commitsCache = CommitsCache(firestore, client);
builder = Build(commitHash, firstChange, commitsCache, firestore);
}
Future<void> update() async {
await storeBuildCommitsInfo();
}
Future<void> storeBuildCommitsInfo() async {
await builder.storeBuildCommitsInfo();
// Test expectations
}
Future<void> storeChange(Map<String, dynamic> change) async {
return builder.storeChange(change);
}
}
class FirestoreServiceFake extends Fake implements FirestoreService {
Map<String, Map<String, dynamic>> commits = Map.from(fakeFirestoreCommits);
Map<String, Map<String, dynamic>> results = Map.from(fakeFirestoreResults);
List<Map<String, dynamic>> fakeTryResults =
List.from(fakeFirestoreTryResults);
int addedResultIdCounter = 1;
@override
Future<bool> isStaging() async => false;
@override
Future<Commit> getCommit(String hash) async {
final commit = commits[hash];
if (commit == null) {
return null;
}
return Commit.fromJson(hash, commits[hash]);
}
@override
Future<Commit> getCommitByIndex(int index) {
for (final entry in commits.entries) {
if (entry.value[fIndex] == index) {
return Future.value(Commit.fromJson(entry.key, entry.value));
}
}
throw 'No commit found with index $index';
}
@override
Future<Commit> getLastCommit() => getCommitByIndex(
commits.values.map<int>((commit) => commit[fIndex]).reduce(max));
@override
Future<void> addCommit(String id, Map<String, dynamic> data) async {
commits[id] = data..[fHash] = id;
}
@override
Future<String> findResult(
Map<String, dynamic> change, int startIndex, int endIndex) {
String resultId;
int resultEndIndex;
for (final entry in results.entries) {
final result = entry.value;
if (result[fName] == change[fName] &&
result[fResult] == change[fResult] &&
result[fExpected] == change[fExpected] &&
result[fPreviousResult] == change[fPreviousResult] &&
result[fBlamelistEndIndex] >= startIndex &&
result[fBlamelistStartIndex] <= endIndex) {
if (resultEndIndex == null ||
resultEndIndex < result[fBlamelistEndIndex]) {
resultId = entry.key;
resultEndIndex = result[fBlamelistEndIndex];
}
}
}
return Future.value(resultId);
}
@override
Future<List<Document>> findActiveResults(
String name, String configuration) async {
return [
for (final id in results.keys)
if (results[id][fName] == name &&
results[id][fActiveConfigurations] != null &&
results[id][fActiveConfigurations].contains(configuration))
Document()
..fields = taggedMap(Map.from(results[id]))
..name = id
];
}
@override
Future<Document> storeResult(Map<String, dynamic> result) async {
final id = 'resultDocumentID$addedResultIdCounter';
addedResultIdCounter++;
results[id] = result;
return null;
}
@override
Future<bool> updateResult(
String resultId, String configuration, int startIndex, int endIndex,
{bool failure}) {
final result = Map<String, dynamic>.from(results[resultId]);
result[fBlamelistStartIndex] =
max<int>(startIndex, result[fBlamelistStartIndex]);
result[fBlamelistEndIndex] = min<int>(endIndex, result[fBlamelistEndIndex]);
if (!result[fConfigurations].contains(configuration)) {
result[fConfigurations] = List<String>.from(result[fConfigurations])
..add(configuration)
..sort();
}
if (failure) {
result[fActive] = true;
if (!result[fActiveConfigurations].contains(configuration)) {
result[fActiveConfigurations] =
List<String>.from(result[fActiveConfigurations])
..add(configuration)
..sort();
}
}
results[resultId] = result;
return Future.value(result[fApproved] ?? false);
}
@override
Future<void> removeActiveConfiguration(
Document activeResult, String configuration) async {
final result = Map<String, dynamic>.from(results[activeResult.name]);
result[fActiveConfigurations] = List.from(result[fActiveConfigurations])
..remove(configuration);
if (result[fActiveConfigurations].isEmpty) {
result.remove(fActiveConfigurations);
result.remove(fActive);
}
results[activeResult.name] = result;
}
@override
Future<List<Map<String, Value>>> findRevertedChanges(int index) async {
return results.values
.where((change) =>
change[fPinnedIndex] == index ||
(change[fBlamelistStartIndex] == index &&
change[fBlamelistEndIndex] == index))
.map(taggedMap)
.toList();
}
@override
Future<List<Map<String, Value>>> tryApprovals(int review) async {
return fakeTryResults
.where(
(result) => result[fReview] == review && result[fApproved] == true)
.map(taggedMap)
.toList();
}
@override
Future<List<Map<String, Value>>> tryResults(
int review, String configuration) async {
return fakeTryResults
.where((result) =>
result[fReview] == review &&
result[fConfigurations].contains(configuration))
.map(taggedMap)
.toList();
}
@override
Future<bool> reviewIsLanded(int review) =>
Future.value(commits.values.any((commit) => commit[fReview] == review));
}
class HttpClientMock extends Mock implements BaseClient {}
class ResponseFake extends Fake implements Response {
@override
String body;
ResponseFake(this.body);
}