Chromium Code Reviews| Index: pkg/analysis_server/bin/fuzz.dart |
| diff --git a/pkg/analysis_server/bin/fuzz.dart b/pkg/analysis_server/bin/fuzz.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8fc71d997bf51a221d91ea65c09d511fc48c29ec |
| --- /dev/null |
| +++ b/pkg/analysis_server/bin/fuzz.dart |
| @@ -0,0 +1,166 @@ |
| +// Copyright (c) 2014, 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:async'; |
| +import 'dart:io'; |
| + |
| +import 'package:args/args.dart'; |
| +import 'package:matcher/matcher.dart'; |
| +import 'package:path/path.dart' as path; |
| + |
| +import 'fuzz/server_manager.dart'; |
| + |
| +/** |
| + * Start analysis server as a separate process and use the stdio to communicate |
| + * with the server. |
| + */ |
| +void main(List<String> args) { |
| + new _FuzzTest().run(args); |
| +} |
| + |
| +/** |
| + * Instances of [_FuzzTest] launch and test an analysis server. |
| + * You must specify the location of the Dart SDK and the directory |
| + * containing sources to be analyzed. |
| + */ |
| +class _FuzzTest { |
| + |
| + //TODO (danrubel) extract common behavior for use in multiple test scenarios |
| + //TODO (danrubel) cleanup test to use async/await for better readability |
| + // VM flag --enable_async |
| + |
| + static const String DART_SDK_OPTION = 'dart-sdk'; |
| + static const String HELP_OPTION = 'help'; |
| + |
| + File serverSnapshot; |
| + Directory appDir; |
| + |
| + /// Parse the arguments and initialize the receiver |
| + /// Return `true` if proper arguments were provided |
| + bool parseArgs(List<String> args) { |
| + ArgParser parser = new ArgParser(); |
| + |
| + void error(String errMsg) { |
| + stderr.writeln(errMsg); |
| + print(''); |
| + _printUsage(parser); |
| + exitCode = 11; |
| + } |
| + |
| + parser.addOption(DART_SDK_OPTION, help: '[sdkPath] path to Dart SDK'); |
| + parser.addFlag( |
| + HELP_OPTION, |
| + help: 'print this help message without starting analysis', |
| + defaultsTo: false, |
| + negatable: false); |
| + |
| + ArgResults results; |
| + try { |
| + results = parser.parse(args); |
| + } on FormatException catch (e) { |
| + error(e.message); |
| + return false; |
| + } |
| + if (results[HELP_OPTION]) { |
| + _printUsage(parser); |
| + return false; |
| + } |
| + String sdkPath = results[DART_SDK_OPTION]; |
| + if (sdkPath is! String) { |
| + error('Missing path to Dart SDK'); |
| + return false; |
| + } |
| + Directory sdkDir = new Directory(sdkPath); |
| + if (!sdkDir.existsSync()) { |
| + error('Specified Dart SDK does not exist: $sdkPath'); |
| + return false; |
| + } |
| + if (results.rest.length == 0) { |
| + error('Expected directory to analyze'); |
| + return false; |
| + } |
| + appDir = new Directory(results.rest[0]); |
| + if (!appDir.existsSync()) { |
|
lukechurch
2014/09/21 05:36:10
What is an application directory? Do you mean that
danrubel
2014/09/22 18:27:25
This is the root directory containing the files to
|
| + error('Specified application directory does not exist: $appDir'); |
| + return false; |
| + } |
| + if (results.rest.length > 1) { |
| + error('Unexpected arguments after $appDir'); |
| + return false; |
| + } |
| + serverSnapshot = new File( |
| + path.join(sdkDir.path, 'bin', 'snapshots', 'analysis_server.dart.snapshot')); |
| + if (!serverSnapshot.existsSync()) { |
| + error('Analysis Server snapshot not found: $serverSnapshot'); |
| + return false; |
| + } |
| + return true; |
| + } |
| + |
| + /// Main entry point for launching, testing, and shutting down the server |
| + void run(List<String> args) { |
| + if (!parseArgs(args)) return; |
| + ServerManager.start(serverSnapshot.path).then((ServerManager manager) { |
| + runZoned(() { |
| + test(manager).then(manager.stop).then((_) { |
| + expect(manager.errorOccurred, isFalse); |
| + print('Test completed successfully'); |
|
lukechurch
2014/09/21 05:36:11
I don't really see these as tests as such, but mor
danrubel
2014/09/22 18:27:25
I'm happy to refactor in subsequent CLs as we/I be
|
| + }); |
| + }, onError: (error, stack) { |
| + stderr.writeln(error); |
|
lukechurch
2014/09/21 05:36:11
From experience of writing a couple of these thing
danrubel
2014/09/22 18:27:25
Fair enough. Will refactor in subsequent CLs.
|
| + print(stack); |
| + exitCode = 12; |
|
lukechurch
2014/09/21 05:36:11
Why 12?
danrubel
2014/09/22 18:27:25
Just picking a random exit code that's not 1 and u
|
| + manager.stop(); |
| + }); |
| + }); |
| + } |
| + |
| + /// Use manager to exercise the analysis server |
| + Future test(ServerManager manager) { |
| + |
| + // perform initial analysis |
| + return manager.analyze(appDir).then((AnalysisResults analysisResults) { |
| + print( |
| + 'Found ${analysisResults.errorCount} errors,' |
| + ' ${analysisResults.warningCount} warnings,' |
| + ' and ${analysisResults.hintCount} hints in ${analysisResults.elapsed}'); |
| + |
| + // edit a method body |
| + return manager.openFileNamed( |
| + 'domain_completion.dart').then((Editor editor) { |
| + return editor.moveAfter('Response processRequest(Request request) {'); |
| + }).then((Editor editor) { |
| + return editor.replace(0, '\nOb'); |
| + }).then((Editor editor) { |
| + |
| + // request code completion and assert results |
| + return editor.getSuggestions().then((List<CompletionResults> list) { |
| + expect(list, isNotNull); |
| + expect(list.length, equals(0)); |
|
lukechurch
2014/09/21 05:36:11
I don't follow this. Why would the list has of len
danrubel
2014/09/22 18:27:25
I'm getting an exception after text replacement bu
|
| + list.forEach((CompletionResults results) { |
| + print('${results.elapsed} received ${results.suggestionCount} suggestions'); |
| + }); |
| + return editor; |
| + }); |
| + |
| + }).then((Editor editor) { |
| + print('tests complete'); |
| + }); |
| + }); |
| + } |
| + |
| + void _printAnalysisSummary(AnalysisResults results) { |
| + print( |
| + 'Found ${results.errorCount} errors, ${results.warningCount} warnings,' |
| + ' and ${results.hintCount} hints in $results.elapsed'); |
| + } |
| + |
| + /// Print information about how to use the server. |
| + void _printUsage(ArgParser parser) { |
| + print('Usage: analyzer [flags] <application_directory>'); |
| + print(''); |
| + print('Supported flags are:'); |
| + print(parser.getUsage()); |
| + } |
| +} |