blob: 5d399093603987892132a31f458212719f14e6eb [file] [log] [blame]
// 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:io';
import 'package:cocoon_service/src/model/appengine/branch.dart';
import 'package:cocoon_service/src/request_handlers/update_branches.dart';
import 'package:cocoon_service/src/request_handling/body.dart';
import 'package:cocoon_service/src/service/datastore.dart';
import 'package:gcloud/db.dart';
import 'package:github/github.dart' show GitCommit, GitCommitUser, RepositoryCommit;
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import '../src/datastore/fake_config.dart';
import '../src/datastore/fake_datastore.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/utilities/mocks.dart';
void main() {
group('update branches', () {
late FakeConfig config;
late RequestHandlerTester tester;
late UpdateBranches handler;
late FakeHttpRequest request;
late FakeDatastoreDB db;
FakeClientContext clientContext;
FakeKeyHelper keyHelper;
late MockRepositoriesService mockRepositoriesService;
final MockProcessManager processManager = MockProcessManager();
String stdoutResult = '72fe8a9ec3af4d76097f09a9c01bf31c62a942aa refs/heads/main';
const String testBranchSha = '72fe8a9ec3af4d76097f09a9c01bf31c62a942aa';
Future<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 T?;
}
setUp(() {
db = FakeDatastoreDB();
clientContext = FakeClientContext();
request = FakeHttpRequest();
keyHelper = FakeKeyHelper(applicationContext: clientContext.applicationContext);
tester = RequestHandlerTester(request: request);
final MockGitHub mockGitHubClient = MockGitHub();
mockRepositoriesService = MockRepositoriesService();
when(mockGitHubClient.repositories).thenReturn(mockRepositoriesService);
when(processManager.runSync(any)).thenAnswer((Invocation invocation) => ProcessResult(1, 0, stdoutResult, ''));
config = FakeConfig(dbValue: db, keyHelperValue: keyHelper, githubClient: mockGitHubClient);
handler = UpdateBranches(
config: config,
datastoreProvider: (DatastoreDB db) => DatastoreService(config.db, 5),
processManager: processManager,
);
const String id = 'flutter/flutter/main';
int lastActivity = DateTime.tryParse("2019-05-15T15:20:56Z")!.millisecondsSinceEpoch;
final Key<String> branchKey = db.emptyKey.append<String>(Branch, id: id);
final Branch currentBranch = Branch(
key: branchKey,
lastActivity: lastActivity,
);
db.values[currentBranch.key] = currentBranch;
});
test('should not retrieve branches older than 2 months', () async {
expect(db.values.values.whereType<Branch>().length, 1);
when(mockRepositoriesService.getCommit(any, any)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(RepositoryCommit(
sha: testBranchSha,
commit: GitCommit(
committer: GitCommitUser(
'dash',
'dash@google.com',
DateTime.now().subtract(const Duration(days: 90)),
))));
});
final List<dynamic> result = (await decodeHandlerBody())!;
expect(result, isEmpty);
});
test('should retrieve branches with commit acitivities in the past week', () async {
expect(db.values.values.whereType<Branch>().length, 1);
// a recent commit is added for each of the 6 repos
when(mockRepositoriesService.getCommit(any, any)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(RepositoryCommit(
sha: testBranchSha,
commit: GitCommit(
committer: GitCommitUser(
'dash',
'dash@google.com',
DateTime.now(),
))));
});
final List<dynamic> result = (await decodeHandlerBody())!;
List<String> repos = [];
for (dynamic k in result) {
repos.add('${k['branch']['repository']}/${k['branch']['branch']}');
}
expect(repos, contains('flutter/flutter/main')); //flutter/flutter/main is updated
expect(result.length, 1);
expect(db.values.values.whereType<Branch>().length, 1);
});
test('should not retrieve branch if updated commit acitivities happened long ago', () async {
expect(db.values.values.whereType<Branch>().length, 1);
when(mockRepositoriesService.getCommit(any, any)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(RepositoryCommit(
sha: testBranchSha,
commit: GitCommit(
committer: GitCommitUser(
'dash',
'dash@google.com',
DateTime.tryParse('2020-05-15T15:20:56Z'),
))));
});
final List<dynamic> result = (await decodeHandlerBody())!;
expect(result, isEmpty);
});
test('should throw exception when git ls-remote fails', () async {
expect(db.values.values.whereType<Branch>().length, 1);
when(processManager.runSync(any)).thenAnswer((Invocation invocation) => ProcessResult(1, -1, stdoutResult, ''));
when(mockRepositoriesService.getCommit(any, any)).thenAnswer((Invocation invocation) {
return Future<RepositoryCommit>.value(RepositoryCommit(
sha: testBranchSha,
commit: GitCommit(
committer: GitCommitUser(
'dash',
'dash@google.com',
DateTime.tryParse('2020-05-15T15:20:56Z'),
))));
});
expect(() => decodeHandlerBody<List<dynamic>>(), throwsA(const TypeMatcher<FormatException>()));
});
});
}