blob: 0d8e5b6c55847cc81cbdfe15b6996f2072626e78 [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: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();
late CommitsCache commitsCache;
late Build builder;
Map<String, dynamic> firstChange;
BuilderTest(this.firstChange) {
commitsCache = CommitsCache(firestore, client);
builder = Build(BuildInfo.fromResult(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 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
void noSuchMethod(Invocation invocation) =>
throw UnimplementedError(invocation.memberName.toString());
@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<SafeDocument>> 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))
SafeDocument(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 Document()
..fields = taggedMap(result)
..name = id;
}
@override
Future<bool> updateResult(
String resultId, String? configuration, int startIndex, int endIndex,
{required 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(
SafeDocument 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<SafeDocument>> tryApprovals(int review) async {
return fakeTryResults
.where(
(result) => result[fReview] == review && result[fApproved] == true)
.map(taggedMap)
.map((fields) => SafeDocument(Document()
..fields = fields
..name = ''))
.toList();
}
@override
Future<List<SafeDocument>> tryResults(
int review, String configuration) async {
return fakeTryResults
.where((result) =>
result[fReview] == review &&
result[fConfigurations].contains(configuration))
.map(taggedMap)
.map((fields) => SafeDocument(Document()
..fields = fields
..name = ''))
.toList();
}
@override
Future<bool> reviewIsLanded(int review) =>
Future.value(commits.values.any((commit) => commit[fReview] == review));
@override
Future<bool> hasPatchset(String review, String patchset) async => false;
@override
Future<bool> hasReview(String review) async => false;
@override
Future<void> storeReview(String review, Map<String, Value> data) async {}
@override
Future<void> storePatchset(String review, int patchset, String kind,
String? description, int patchsetGroup, int number) async {}
}
class HttpClientMock extends BaseClient {
String body = '';
void addDefaultResponse(String response) {
body = response;
}
@override
Future<StreamedResponse> send(BaseRequest request) async {
return StreamedResponse(Stream.fromIterable([]), 200);
}
@override
Future<Response> get(Uri uri, {Map<String, String>? headers}) async {
return Response(body, 200);
}
}