Skip to content

start work on a testing plan for devtools #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ analyzer:
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
exclude:
- build/**

linter:
rules:
Expand Down
10 changes: 6 additions & 4 deletions lib/device/device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,13 @@ class ExtensionTracker {
if (result is Isolate) {
final Isolate isolate = result;

for (String rpc in isolate.extensionRPCs) {
if (!extensionToIsolatesMap.containsKey(rpc)) {
extensionToIsolatesMap[rpc] = new Set<IsolateRef>();
if (isolate.extensionRPCs != null) {
for (String rpc in isolate.extensionRPCs) {
if (!extensionToIsolatesMap.containsKey(rpc)) {
extensionToIsolatesMap[rpc] = new Set<IsolateRef>();
}
extensionToIsolatesMap[rpc].add(isolateRef);
}
extensionToIsolatesMap[rpc].add(isolateRef);
}
}

Expand Down
7 changes: 7 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'framework/framework.dart';
import 'globals.dart';
import 'logging/logging.dart';
import 'memory/memory.dart';
import 'model/model.dart';
import 'performance/performance.dart';
import 'service.dart';
import 'timeline/timeline.dart';
Expand Down Expand Up @@ -39,6 +40,8 @@ class PerfToolFramework extends Framework {
addScreen(new LoggingScreen());

initGlobalUI();

initTestingModel();
}

void initGlobalUI() {
Expand Down Expand Up @@ -80,6 +83,10 @@ class PerfToolFramework extends Framework {
.listen(_rebuildIsolateSelect);
}

void initTestingModel() {
App.register(this);
}

IsolateRef get currentIsolate => serviceInfo.isolateManager.selectedIsolate;

void _handleIsolateSelect() {
Expand Down
136 changes: 136 additions & 0 deletions lib/model/model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// An application model used to programmatically query and drive the UI.
///
/// This is largely intended to aid in testing.

library model;

import 'dart:async';
import 'dart:convert';
import 'dart:js' as js;

import 'package:devtools/main.dart';

import '../framework/framework.dart';
import '../logging/logging.dart';

// TODO(devoncarew): Only enable logging after enabled by the client.

class App {
App(this.framework) {
_register<void>('echo', echo);
_register<void>('switchPage', switchPage);
_register<String>('currentPageId', currentPageId);

// LoggingScreen
_register<void>('logs.clearLogs', logsClearLogs);
_register<int>('logs.logCount', logsLogCount);
}

static void register(PerfToolFramework framework) {
final App app = new App(framework);
app._bind();
}

final PerfToolFramework framework;

void _bind() {
final js.JsObject binding = new js.JsObject.jsify(<dynamic, dynamic>{});
binding['send'] = (String method, int id, dynamic arg) {
try {
final dynamic result = _dispatch(method, id, arg);
Future<dynamic>.value(result).then((dynamic result) {
_sendResponseResult(id, result);
}).catchError((dynamic error, StackTrace stackTrace) {
_sendReponseError(id, error, stackTrace);
});
} catch (error, stackTrace) {
_sendReponseError(id, error, stackTrace);
}
};

js.context['devtools'] = binding;

_sendNotification('app.inited');
}

Future<void> echo(dynamic message) async {
_sendNotification('app.echo', message);
}

Future<void> switchPage(dynamic pageId) async {
final Screen screen = framework.getScreen(pageId);
if (screen == null) {
throw 'page $pageId not found';
}
framework.load(screen);

// TODO(devoncarew): Listen for and log framework page change events?
}

Future<String> currentPageId([dynamic _]) async {
return framework.current?.id;
}

Future<void> logsClearLogs([dynamic _]) async {
final LoggingScreen screen = framework.getScreen('logs');
screen.loggingTable.setRows(<LogData>[]);
}

Future<int> logsLogCount([dynamic _]) async {
final LoggingScreen screen = framework.getScreen('logs');
return screen.loggingTable.rows.length;
}

void _sendNotification(String event, [dynamic params]) {
final Map<String, dynamic> map = <String, dynamic>{
'event': event,
};
if (params != null) {
map['params'] = params;
}
print('[${jsonEncode(map)}]');
}

void _sendResponseResult(int id, [dynamic result]) {
final Map<String, dynamic> map = <String, dynamic>{
'id': id,
};
if (result != null) {
map['result'] = result;
}
print('[${jsonEncode(map)}]');
}

void _sendReponseError(int id, dynamic error, StackTrace stackTrace) {
final Map<String, dynamic> map = <String, dynamic>{
'id': id,
'error': <String, String>{
'message': error.toString(),
'stackTrace': stackTrace.toString(),
},
};
print('[${jsonEncode(map)}]');
}

dynamic _dispatch(String method, int id, dynamic arg) {
final Handler<dynamic> handler = _handlers[method];
if (handler != null) {
return handler(arg);
} else {
print('handler not found for $method()');
throw 'no handler found for $method()';
}
}

final Map<String, Handler<dynamic>> _handlers = <String, Handler<dynamic>>{};

void _register<T>(String idMethod, Handler<T> fn) {
_handlers[idMethod] = fn;
}
}

typedef Future<T> Handler<T>(dynamic arg);
18 changes: 18 additions & 0 deletions lib/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:intl/intl.dart';
import 'package:path/path.dart' as path;
import 'package:vm_service_lib/vm_service_lib.dart';

const String loremIpsum = '''
Expand Down Expand Up @@ -90,3 +92,19 @@ class Property<T> {

Stream<T> get onValueChange => _changeController.stream;
}

/// The directory used to store per-user settings for Dart tooling.
Directory getDartPrefsDirectory() {
return new Directory(path.join(getUserHomeDir(), '.dart'));
}

/// Return the user's home directory.
String getUserHomeDir() {
final String envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
final String value = Platform.environment[envKey];
return value == null ? '.' : value;
}

/// A typedef to represent a function taking no arguments and with no return
/// value.
typedef void VoidFunction();
3 changes: 3 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ dependencies:
intl: ^0.15.0
logging: ^0.11.0
meta: ^1.1.0
path: ^1.6.0
vm_service_lib: ^0.3.9

dev_dependencies:
build_runner: any
build_web_compilers: any
test: ^1.0.0
webdev: 0.2.4
webkit_inspection_protocol: ^0.3.6
36 changes: 36 additions & 0 deletions test/fixtures/logging_app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2018 The Chromium 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:async';
import 'dart:developer';
import 'dart:io';

// Allow a test driver to communicate with this app through the controller.
final Controller controller = new Controller();

void main() {
print('starting app');
log('starting app');

// Don't exit until it's indicated we should by the controller.
new Timer(const Duration(days: 1), () {});
}

class Controller {
int count = 0;

void emitLog() {
count++;

print('emitLog called');
log('emit log $count', name: 'logging');
}

void shutdown() {
print('stopping app');
log('stopping app');

exit(0);
}
}
Loading