blob: 93a142c91ac3c45e918fdb00e31d69a32e8ea80a [file] [log] [blame]
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(https://fxbug.dev/84961): Fix null safety and remove this language version.
// @dart=2.9
import 'dart:convert';
import 'dart:io';
import 'package:mockito/mockito.dart';
import 'package:sl4f/sl4f.dart';
import 'package:test/test.dart';
class MockSsh extends Mock implements Ssh {}
void main(List<String> args) {
HttpServer fakeServer;
Sl4f sl4f;
MockSsh ssh;
setUp(() async {
ssh = MockSsh();
fakeServer = await HttpServer.bind('127.0.0.1', 18080);
sl4f = Sl4f('127.0.0.1', ssh, 18080);
});
tearDown(() async {
await fakeServer.close();
});
test('call RestartSession facade with no params', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.RestartSession');
expect(body['params'], null);
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).restartSession(), completion(equals('Success')));
});
test('call startBasemgr facade with params', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.StartBasemgr');
expect(body['params'], isNotNull);
expect(
body['params'],
containsPair(
'config',
allOf(containsPair('basemgr', contains('base_shell')),
containsPair('sessionmgr', contains('session_agents')))));
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).startBasemgr('''{
"basemgr": {
"base_shell": {
"url": "foo",
"args": ["--bar"]
}
},
"sessionmgr": {
"session_agents": ["baz"]
}
}'''), completion(equals('Success')));
});
test('call startBasemgr facade with no params', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.StartBasemgr');
expect(body['params'], isNotNull);
expect(body['params'], isEmpty);
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).startBasemgr(), completion(equals('Success')));
});
test('call LaunchMod facade with optional params', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.LaunchMod');
expect(body['params'],
{'mod_url': 'fake_url', 'mod_name': 'fake_name', 'story_name': null});
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).launchMod('fake_url', modName: 'fake_name'),
completion(equals('Success')));
});
test('call boot with no config', () async {
bool called = false;
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
if (body['method'] == 'modular_facade.IsBasemgrRunning') {
req.response.write(jsonEncode({
'id': body['id'],
'result': called,
'error': null,
}));
} else {
expect(body['method'], 'modular_facade.StartBasemgr');
expect(body['params'], isNotNull);
expect(body['params'], isEmpty);
called = true;
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
}
await req.response.close();
}
fakeServer.listen(handler);
await Modular(sl4f).boot();
expect(called, isTrue, reason: 'StartBasemgr facade not called');
});
test('call boot with custom config', () async {
bool called = false;
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
if (body['method'] == 'modular_facade.IsBasemgrRunning') {
req.response.write(jsonEncode({
'id': body['id'],
'result': called,
'error': null,
}));
} else {
expect(body['method'], 'modular_facade.StartBasemgr');
expect(body['params'], isNotNull);
expect(
body['params'],
containsPair(
'config',
allOf(containsPair('basemgr', contains('base_shell')),
containsPair('sessionmgr', contains('session_agents')))));
called = true;
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
}
await req.response.close();
}
fakeServer.listen(handler);
await Modular(sl4f).boot(config: '''{
"basemgr": {
"base_shell": {
"url": "foo",
"args": ["--bar"]
}
},
"sessionmgr": {
"session_agents": ["baz"]
}
}''');
expect(called, isTrue, reason: 'StartBasemgr facade not called');
});
test('isRunning: no', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.IsBasemgrRunning');
req.response.write(jsonEncode({
'id': body['id'],
'result': false,
'error': null,
}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).isRunning, completion(equals(false)));
});
test('isRunning: yes', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.IsBasemgrRunning');
req.response.write(jsonEncode({
'id': body['id'],
'result': true,
'error': null,
}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).isRunning, completion(equals(true)));
});
test('call KillBasemgr facade with no params', () {
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
expect(body['method'], 'modular_facade.KillBasemgr');
expect(body['params'], null);
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
await req.response.close();
}
fakeServer.listen(handler);
expect(Modular(sl4f).killBasemgr(), completion(equals('Success')));
});
test('shutdown kills modular when it owns it', () async {
bool killed = true;
void handler(HttpRequest req) async {
expect(req.contentLength, greaterThan(0));
final body = jsonDecode(await utf8.decoder.bind(req).join());
if (body['method'] == 'modular_facade.IsBasemgrRunning') {
req.response.write(jsonEncode({
'id': body['id'],
'result': !killed,
'error': null,
}));
} else if (body['method'] == 'modular_facade.StartBasemgr') {
expect(
body['params'],
isNotNull,
);
expect(body['params'], isEmpty);
killed = false;
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
} else {
expect(body['method'], 'modular_facade.KillBasemgr');
expect(body['params'], anyOf(isNull, isEmpty));
killed = true;
req.response.write(
jsonEncode({'id': body['id'], 'result': 'Success', 'error': null}));
}
await req.response.close();
}
fakeServer.listen(handler);
final modular = Modular(sl4f);
await modular.boot();
expect(modular.controlsBasemgr, isTrue,
reason: 'controlsBasemgr after boot');
await modular.shutdown();
expect(modular.controlsBasemgr, isFalse,
reason: 'still controlsBasemgr after shutdown');
expect(killed, isTrue, reason: 'did not call KillBasemgr');
});
test('modify config', () {
const fakeConfig = '''
{
"basemgr": {
"base_shell": {
"url": "fuchsia-pkg://fuchsia.com/base_shell#meta/base_shell.cmx",
"args": ["--base_shell_arg"]
},
"session_shells": [
{
"url": "fuchsia-pkg://fuchsia.com/session#meta/session.cmx"
}
],
"session_shell_arg": true
},
"sessionmgr": {
"session_agents": [
"fuchsia-pkg://fuchsia.com/component_foo#meta/foo_a.cmx",
"fuchsia-pkg://fuchsia.com/component_foo#meta/foo_b.cmx",
"fuchsia-pkg://fuchsia.com/component_bar#meta/bar.cmx"
],
"component_args": [
{
"uri": "fuchsia-pkg://fuchsia.com/component_foo#meta/foo_a.cmx",
"args": [
"--food=burger",
"--drink=coffee"
]
},
{
"uri": "fuchsia-pkg://fuchsia.com/component_bar#meta/bar.cmx",
"args": []
}
],
"agent_service_index": [
{
"service_name": "some.service.a",
"agent_url": "fuchsia-pkg://fuchsia.com/service_a#meta/service_a.cmx"
},
{
"service_name": "some.service.b",
"agent_url": "fuchsia-pkg://fuchsia.com/service_b#meta/service_b.cmx"
}
]
}
}
''';
// Can modify args.
final modified_1 =
Modular(sl4f).updateComponentArgs(fakeConfig, RegExp(r'foo_\w'), {
'food': 'salad',
'desert': 'cake',
});
final fooArgs =
jsonDecode(modified_1)['sessionmgr']['component_args'][0]['args'];
expect(fooArgs[0], '--drink=coffee', reason: 'did not keep arg --drink');
expect(fooArgs[1], '--food=salad', reason: 'did not update arg --food');
expect(fooArgs[2], '--desert=cake', reason: 'did not add new arg --desert');
expect(fooArgs.length, 3, reason: 'expect 3 args, got ${fooArgs.length}');
// Can insert args for components with empty args.
final modified_2 =
Modular(sl4f).updateComponentArgs(modified_1, RegExp('bar'), {
'animal': 'cat',
'happy': null,
});
final barArgs =
jsonDecode(modified_2)['sessionmgr']['component_args'][1]['args'];
expect(barArgs[0], '--animal=cat', reason: 'did not add arg --animal');
expect(barArgs[1], '--happy', reason: 'did not add arg --happy');
expect(barArgs.length, 2, reason: 'expect 2 args, got ${barArgs.length}');
// Check everything stays the same on a non-existent component
final modified_3 =
Modular(sl4f).updateComponentArgs(modified_2, RegExp('fake'), {
'animal': 'cat',
'happy': null,
});
final fakeArgs =
jsonDecode(modified_3)['sessionmgr']['component_args'][1]['args'];
expect(fakeArgs[0], '--animal=cat', reason: 'did not add arg --animal');
expect(fakeArgs[1], '--happy', reason: 'did not add arg --happy');
expect(fakeArgs.length, 2, reason: 'expect 2 args, got ${fakeArgs.length}');
});
}