Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: pkg/analysis_server/test/completion_test_support.dart

Issue 785013002: Ported completion tests (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/analysis_server/test/completion_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library test.completion.support;
6
7 import 'dart:collection';
8
9 import 'package:analysis_server/src/protocol.dart';
10 import 'package:analyzer/src/generated/java_core.dart';
11 import 'package:unittest/unittest.dart';
12
13 import 'domain_completion_test.dart';
14
15 /**
16 * A base class for classes containing completion tests.
17 */
18 class CompletionTestCase extends CompletionTest {
19 static const String CURSOR_MARKER = '!';
20
21 List get suggestedCompletions =>
22 suggestions.map(
23 (CompletionSuggestion suggestion) => suggestion.completion).toList();
24
25 void assertHasCompletion(String completion) {
26 int expectedOffset = completion.indexOf(CURSOR_MARKER);
27 if (expectedOffset >= 0) {
28 if (completion.indexOf(CURSOR_MARKER, expectedOffset + 1) >= 0) {
29 fail(
30 "Invalid completion, contains multiple cursor positions: '$completio n'");
31 }
32 completion = completion.replaceFirst(CURSOR_MARKER, '');
33 } else {
34 expectedOffset = completion.length;
35 }
36 CompletionSuggestion matchingSuggestion;
37 suggestions.forEach((CompletionSuggestion suggestion) {
38 if (suggestion.completion == completion) {
39 if (matchingSuggestion == null) {
40 matchingSuggestion = suggestion;
41 } else {
42 fail(
43 "Expected exactly one '$completion' but found multiple:\n $sugges tedCompletions");
44 }
45 }
46 });
47 if (matchingSuggestion == null) {
48 fail("Expected '$completion' but found none:\n $suggestedCompletions");
49 }
50 expect(matchingSuggestion.selectionOffset, equals(expectedOffset));
51 expect(matchingSuggestion.selectionLength, equals(0));
52 }
53
54 void assertHasNoCompletion(String completion) {
55 if (suggestions.any(
56 (CompletionSuggestion suggestion) => suggestion.completion == completion )) {
57 fail(
58 "Did not expect completion '$completion' but found:\n $suggestedCompl etions");
59 }
60 }
61
62 runTest(LocationSpec spec, [Map<String, String> extraFiles]) {
63 super.setUp();
64 String content = spec.source;
65 addFile(testFile, content);
66 this.testCode = content;
67 completionOffset = spec.testLocation;
68 if (extraFiles != null) {
69 extraFiles.forEach((String fileName, String content) {
70 addFile(fileName, content);
71 });
72 }
73 return getSuggestions().then((_) {
74 try {
75 //expect(replacementOffset, equals(completionOffset));
76 //expect(replacementLength, equals(0));
77 for (String result in spec.positiveResults) {
78 assertHasCompletion(result);
79 }
80 for (String result in spec.negativeResults) {
81 assertHasNoCompletion(result);
82 }
83 } finally {
84 super.tearDown();
85 }
86 });
87 }
88
89 /**
90 * Generate a set of completion tests based on the given [originalSource].
91 *
92 * The source string has completion points embedded in it, which are
93 * identified by '!X' where X is a single character. Each X is matched to
94 * positive or negative results in the array of [validationStrings].
95 * Validation strings contain the name of a prediction with a two character
96 * prefix. The first character of the prefix corresponds to an X in the
97 * [originalSource]. The second character is either a '+' or a '-' indicating
98 * whether the string is a positive or negative result.
99 *
100 * The [originalSource] is the source for a completion test that contains
101 * completion points. The [validationStrings] are the positive and negative
102 * predictions.
103 */
104 static void buildTests(String baseName, String originalSource,
105 List<String> results, [Map<String, String> extraFiles]) {
106 List<LocationSpec> completionTests =
107 LocationSpec.from(originalSource, results);
108 completionTests.sort((LocationSpec first, LocationSpec second) {
109 return first.id.compareTo(second.id);
110 });
111 if (completionTests.isEmpty) {
112 test(baseName, () {
113 fail(
114 "Expected exclamation point ('!') within the source denoting the"
115 "position at which code completion should occur");
116 });
117 }
118 for (LocationSpec spec in completionTests) {
119 test("$baseName-${spec.id}", () {
120 CompletionTestCase test = new CompletionTestCase();
121 return test.runTest(spec, extraFiles);
122 });
123 }
124 }
125 }
126
127 /**
128 * A specification of the completion results expected at a given location.
129 */
130 class LocationSpec {
131 String id;
132 int testLocation = -1;
133 List<String> positiveResults = <String>[];
134 List<String> negativeResults = <String>[];
135 String source;
136
137 LocationSpec(this.id);
138
139 /**
140 * Parse a set of tests from the given `originalSource`. Return a list of the
141 * specifications that were parsed.
142 *
143 * The source string has test locations embedded in it, which are identified
144 * by '!X' where X is a single character. Each X is matched to positive or
145 * negative results in the array of [validationStrings]. Validation strings
146 * contain the name of a prediction with a two character prefix. The first
147 * character of the prefix corresponds to an X in the [originalSource]. The
148 * second character is either a '+' or a '-' indicating whether the string is
149 * a positive or negative result. If logical not is needed in the source it
150 * can be represented by '!!'.
151 *
152 * The [originalSource] is the source for a test that contains test locations.
153 * The [validationStrings] are the positive and negative predictions.
154 */
155 static List<LocationSpec> from(String originalSource,
156 List<String> validationStrings) {
157 Map<String, LocationSpec> tests = new HashMap<String, LocationSpec>();
158 String modifiedSource = originalSource;
159 int modifiedPosition = 0;
160 while (true) {
161 int index = modifiedSource.indexOf('!', modifiedPosition);
162 if (index < 0) {
163 break;
164 }
165 int n = 1; // only delete one char for double-bangs
166 String id = modifiedSource.substring(index + 1, index + 2);
167 if (id != '!') {
168 n = 2;
169 LocationSpec test = new LocationSpec(id);
170 tests[id] = test;
171 test.testLocation = index;
172 } else {
173 modifiedPosition = index + 1;
174 }
175 modifiedSource =
176 modifiedSource.substring(0, index) + modifiedSource.substring(index + n);
177 }
178 if (modifiedSource == originalSource) {
179 throw new IllegalStateException("No tests in source: " + originalSource);
180 }
181 for (String result in validationStrings) {
182 if (result.length < 3) {
183 throw new IllegalStateException("Invalid location result: " + result);
184 }
185 String id = result.substring(0, 1);
186 String sign = result.substring(1, 2);
187 String value = result.substring(2);
188 LocationSpec test = tests[id];
189 if (test == null) {
190 throw new IllegalStateException(
191 "Invalid location result id: $id for: $result");
192 }
193 test.source = modifiedSource;
194 if (sign == '+') {
195 test.positiveResults.add(value);
196 } else if (sign == '-') {
197 test.negativeResults.add(value);
198 } else {
199 String err = "Invalid location result sign: $sign for: $result";
200 throw new IllegalStateException(err);
201 }
202 }
203 List<String> badPoints = <String>[];
204 List<String> badResults = <String>[];
205 for (LocationSpec test in tests.values) {
206 if (test.testLocation == -1) {
207 badPoints.add(test.id);
208 }
209 if (test.positiveResults.isEmpty && test.negativeResults.isEmpty) {
210 badResults.add(test.id);
211 }
212 }
213 if (!(badPoints.isEmpty && badResults.isEmpty)) {
214 StringBuffer err = new StringBuffer();
215 if (!badPoints.isEmpty) {
216 err.write("No test location for tests:");
217 for (String ch in badPoints) {
218 err
219 ..write(' ')
220 ..write(ch);
221 }
222 err.write(' ');
223 }
224 if (!badResults.isEmpty) {
225 err.write("No results for tests:");
226 for (String ch in badResults) {
227 err
228 ..write(' ')
229 ..write(ch);
230 }
231 }
232 throw new IllegalStateException(err.toString());
233 }
234 return tests.values.toList();
235 }
236 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/test/completion_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698