| // Copyright (c) 2019, 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:io'; | |
| import 'package:expect/expect.dart'; | |
| import 'package:test_runner/src/static_error.dart'; | |
| import 'utils.dart'; | |
| void main() { | |
| testProperties(); | |
| testIsWarning(); | |
| testCompareTo(); | |
| testValidate(); | |
| } | |
| void testProperties() { | |
| var analyzer = StaticError( | |
| ErrorSource.analyzer, | |
| "E.CODE", | |
| path: 'test.dart', | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| sourceLines: {1, 3, 5}, | |
| ); | |
| Expect.equals(analyzer.source, ErrorSource.analyzer); | |
| Expect.equals(analyzer.message, "E.CODE"); | |
| Expect.equals(analyzer.path, 'test.dart'); | |
| Expect.equals(analyzer.line, 1); | |
| Expect.equals(analyzer.column, 2); | |
| Expect.equals(analyzer.length, 3); | |
| Expect.isTrue(analyzer.isSpecified); | |
| Expect.setEquals({1, 3, 5}, analyzer.sourceLines); | |
| var cfe = StaticError( | |
| ErrorSource.cfe, | |
| "Error.", | |
| path: '${Directory.current.path}/test.dart', | |
| line: 4, | |
| column: 5, | |
| ); | |
| Expect.equals(cfe.source, ErrorSource.cfe); | |
| Expect.equals(cfe.message, "Error."); | |
| Expect.equals(cfe.path, 'test.dart'); // Current path gets removed. | |
| Expect.equals(cfe.line, 4); | |
| Expect.equals(cfe.column, 5); | |
| Expect.equals(cfe.length, 0); | |
| Expect.isTrue(cfe.isSpecified); | |
| Expect.isTrue(cfe.sourceLines.isEmpty); | |
| var unspecified = StaticError( | |
| ErrorSource.web, | |
| "unspecified", | |
| path: 'test.dart', | |
| line: 1, | |
| column: 2, | |
| ); | |
| Expect.isFalse(unspecified.isSpecified); | |
| } | |
| void testIsWarning() { | |
| // Analyzer only. | |
| Expect.isTrue( | |
| makeError(analyzerError: "STATIC_WARNING.INVALID_OPTION").isWarning, | |
| ); | |
| Expect.isFalse( | |
| makeError(analyzerError: "SYNTACTIC_ERROR.MISSING_FUNCTION_BODY").isWarning, | |
| ); | |
| Expect.isFalse( | |
| makeError( | |
| analyzerError: "COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS", | |
| ).isWarning, | |
| ); | |
| // CFE only. | |
| Expect.isFalse(makeError(cfeError: "Any error message.").isWarning); | |
| // Web only. | |
| Expect.isFalse(makeError(webError: "Any error message.").isWarning); | |
| } | |
| void testCompareTo() { | |
| var errors = [ | |
| // Order by line. | |
| makeError(line: 1, column: 2, length: 2, cfeError: "E."), | |
| makeError(line: 2, column: 1, length: 1, cfeError: "E."), | |
| // Then column. | |
| makeError(line: 3, column: 1, length: 2, cfeError: "E."), | |
| makeError(line: 3, column: 2, length: 1, cfeError: "E."), | |
| // Then length. | |
| makeError(line: 4, column: 1, length: 1, cfeError: "Z."), | |
| makeError(line: 4, column: 1, length: 2, cfeError: "A."), | |
| // Then source. | |
| makeError(line: 5, column: 1, length: 1, analyzerError: "Z.CODE"), | |
| makeError(line: 5, column: 1, length: 1, cfeError: "A."), | |
| // Then message. | |
| makeError(line: 6, column: 1, length: 1, cfeError: "A."), | |
| makeError(line: 6, column: 1, length: 1, cfeError: "Z."), | |
| ]; | |
| // Every pair of errors in the array should be ordered correctly. | |
| for (var i = 0; i < errors.length; i++) { | |
| for (var j = 0; j < errors.length; j++) { | |
| var expected = (i - j).sign; | |
| Expect.equals( | |
| expected, | |
| errors[i].compareTo(errors[j]), | |
| "Expected $expected comparison for:\n${errors[i]}\n${errors[j]}", | |
| ); | |
| } | |
| } | |
| } | |
| void testValidate() { | |
| // No errors. | |
| expectValidate([], [], null); | |
| // Same errors. | |
| expectValidate( | |
| [ | |
| makeError(line: 1, column: 2, length: 3, analyzerError: "ERR.A"), | |
| makeError(line: 2, column: 2, length: 3, analyzerError: "ERR.B"), | |
| makeError(line: 3, column: 2, length: 3, analyzerError: "ERR.C"), | |
| ], | |
| [ | |
| // Order doesn't matter. | |
| makeError(line: 3, column: 2, length: 3, analyzerError: "ERR.C"), | |
| makeError(line: 1, column: 2, length: 3, analyzerError: "ERR.A"), | |
| makeError(line: 2, column: 2, length: 3, analyzerError: "ERR.B"), | |
| ], | |
| null, | |
| ); | |
| // Catches differences in any field. | |
| expectValidate( | |
| [ | |
| makeError(line: 1, column: 2, length: 3, analyzerError: "ERR.A"), | |
| makeError(line: 2, column: 2, length: 3, analyzerError: "ERR.B"), | |
| makeError(line: 3, column: 2, length: 3, analyzerError: "ERR.C"), | |
| ], | |
| [ | |
| makeError(line: 1, column: 9, length: 3, analyzerError: "ERR.A"), | |
| makeError(line: 2, column: 2, length: 9, analyzerError: "ERR.B"), | |
| makeError(line: 3, column: 2, length: 3, analyzerError: "ERR.Z"), | |
| ], | |
| """ | |
| - Wrong error location test.dart line 1, column 2, length 3: ERR.A | |
| Expected column 2 but was column 9. | |
| - Wrong error location test.dart line 2, column 2, length 3: ERR.B | |
| Expected length 3 but was length 9. | |
| - Wrong message at test.dart line 3, column 2, length 3: ERR.Z | |
| Expected: ERR.C""", | |
| ); | |
| expectValidate( | |
| [makeError(line: 4, column: 2, length: 3, cfeError: "Four.")], | |
| [makeError(line: 4, column: 2, length: 3, cfeError: "Zzz.")], | |
| """ | |
| - Wrong message at test.dart line 4, column 2, length 3: Zzz. | |
| Expected: Four.""", | |
| ); | |
| expectValidate( | |
| [makeError(line: 5, column: 2, length: 3, webError: "Web 5.")], | |
| [makeError(line: 5, column: 2, length: 3, webError: "Web Z.")], | |
| """ | |
| - Wrong message at test.dart line 5, column 2, length 3: Web Z. | |
| Expected: Web 5.""", | |
| ); | |
| // Unexpected errors. | |
| expectValidate( | |
| [ | |
| makeError(line: 2, column: 2, length: 3, cfeError: "One."), | |
| makeError(line: 4, column: 2, length: 3, cfeError: "Two."), | |
| makeError(line: 6, column: 2, length: 3, cfeError: "Tres."), | |
| ], | |
| [ | |
| makeError(line: 1, column: 2, length: 3, cfeError: "1."), | |
| makeError(line: 2, column: 2, length: 3, cfeError: "One."), | |
| makeError(line: 3, column: 2, length: 3, cfeError: "3."), | |
| makeError(line: 4, column: 2, length: 3, cfeError: "Two."), | |
| makeError(line: 5, column: 2, length: 3, cfeError: "5."), | |
| makeError(line: 6, column: 2, length: 3, cfeError: "Tres."), | |
| makeError(line: 7, column: 2, length: 3, cfeError: "7."), | |
| ], | |
| """ | |
| - Unexpected error at test.dart line 1, column 2, length 3: 1. | |
| - Unexpected error at test.dart line 3, column 2, length 3: 3. | |
| - Unexpected error at test.dart line 5, column 2, length 3: 5. | |
| - Unexpected error at test.dart line 7, column 2, length 3: 7.""", | |
| ); | |
| // Missing errors. | |
| expectValidate( | |
| [ | |
| makeError(line: 1, column: 2, length: 3, analyzerError: "ERR.A"), | |
| makeError(line: 2, column: 2, length: 3, analyzerError: "ERR.B"), | |
| makeError(line: 3, column: 2, length: 3, analyzerError: "ERR.C"), | |
| makeError(line: 4, column: 2, length: 3, analyzerError: "ERR.D"), | |
| makeError(line: 5, column: 2, length: 3, analyzerError: "ERR.E"), | |
| ], | |
| [ | |
| makeError(line: 2, column: 2, length: 3, analyzerError: "ERR.B"), | |
| makeError(line: 4, column: 2, length: 3, analyzerError: "ERR.D"), | |
| ], | |
| """ | |
| - Missing expected error at test.dart line 1, column 2, length 3: ERR.A | |
| - Missing expected error at test.dart line 3, column 2, length 3: ERR.C | |
| - Missing expected error at test.dart line 5, column 2, length 3: ERR.E""", | |
| ); | |
| // Unspecified errors. | |
| expectValidate( | |
| [ | |
| // Missing. | |
| makeError(line: 2, column: 2, length: 3, cfeError: "unspecified"), | |
| // Right. | |
| makeError(line: 6, column: 2, length: 3, cfeError: "unspecified"), | |
| ], | |
| [ | |
| makeError(line: 6, column: 2, length: 3, cfeError: "Actual 1."), | |
| // Unexpected. | |
| makeError(line: 9, column: 9, length: 3, cfeError: "Actual 2."), | |
| ], | |
| """ | |
| - Missing expected unspecified error at test.dart line 2, column 2, length 3. | |
| - Unexpected error at test.dart line 9, column 9, length 3: Actual 2.""", | |
| ); | |
| // Unspecified errors can match multiple errors on the same line. | |
| expectValidate( | |
| [makeError(line: 1, column: 2, length: 3, analyzerError: "unspecified")], | |
| [ | |
| makeError(line: 1, column: 1, length: 3, analyzerError: "ERROR.CODE1"), | |
| makeError(line: 1, column: 2, length: 3, analyzerError: "ERROR.CODE2"), | |
| makeError(line: 1, column: 3, length: 3, analyzerError: "ERROR.CODE3"), | |
| ], | |
| null, | |
| ); | |
| expectValidate( | |
| [makeError(line: 1, column: 2, length: 3, cfeError: "unspecified")], | |
| [ | |
| makeError(line: 1, column: 1, length: 3, cfeError: "Actual 1."), | |
| makeError(line: 1, column: 2, length: 3, cfeError: "Actual 2."), | |
| makeError(line: 1, column: 3, length: 3, cfeError: "Actual 3."), | |
| ], | |
| null, | |
| ); | |
| expectValidate( | |
| [makeError(line: 1, column: 2, length: 3, webError: "unspecified")], | |
| [ | |
| makeError(line: 1, column: 1, length: 3, webError: "Web 1."), | |
| makeError(line: 1, column: 2, length: 3, webError: "Web 2."), | |
| makeError(line: 1, column: 3, length: 3, webError: "Web 3."), | |
| ], | |
| null, | |
| ); | |
| // Same message. | |
| expectValidate( | |
| [ | |
| makeError(line: 1, column: 2, length: 1, cfeError: "message"), | |
| makeError(line: 2, column: 3, length: 2, cfeError: "message"), | |
| ], | |
| [ | |
| makeError(line: 1, column: 2, length: 1, cfeError: "message"), | |
| makeError(line: 2, column: 3, length: 2, cfeError: "message"), | |
| makeError(line: 3, column: 3, length: 3, cfeError: "message"), | |
| ], | |
| '- Unexpected error at test.dart line 3, column 3, length 3: message', | |
| ); | |
| // Same location. | |
| expectValidate( | |
| [ | |
| makeError(line: 1, column: 2, length: 1, cfeError: "message 1"), | |
| makeError(line: 1, column: 2, length: 1, cfeError: "message 2"), | |
| ], | |
| [ | |
| makeError(line: 1, column: 2, length: 1, cfeError: "wrong 1"), | |
| makeError(line: 1, column: 2, length: 1, cfeError: "wrong 2"), | |
| makeError(line: 1, column: 2, length: 1, cfeError: "wrong 3"), | |
| ], | |
| ''' | |
| - Wrong message at test.dart line 1, column 2, length 1: wrong 1 | |
| Expected: message 1 | |
| - Wrong message at test.dart line 1, column 2, length 1: wrong 2 | |
| Expected: message 2 | |
| - Unexpected error at test.dart line 1, column 2, length 1: wrong 3''', | |
| ); | |
| // Prefer match over wrong message. | |
| expectValidate( | |
| [ | |
| makeError(line: 10, column: 1, length: 1, cfeError: "match"), | |
| makeError(line: 10, column: 1, length: 1, cfeError: "a wrong message"), | |
| ], | |
| [ | |
| makeError(line: 1, column: 1, length: 1, cfeError: /* not a */ "match"), | |
| makeError(line: 10, column: 1, length: 1, cfeError: "match"), | |
| ], | |
| ''' | |
| - Missing expected error at test.dart line 10, column 1, length 1: a wrong message | |
| - Unexpected error at test.dart line 1, column 1, length 1: match''', | |
| ); | |
| // Combined. | |
| expectValidate( | |
| [ | |
| makeError(line: 10, column: 1, length: 1, cfeError: "match"), | |
| makeError(line: 20, column: 2, length: 2, cfeError: "missing"), | |
| makeError(line: 20, column: 2, length: 2, cfeError: "message"), | |
| makeError(line: 30, column: 3, length: 3, cfeError: "wrong location"), | |
| makeError(line: 40, column: 4, length: 4, cfeError: "match"), | |
| ], | |
| [ | |
| makeError(line: 1, column: 2, length: 1, cfeError: "unexpected"), | |
| makeError(line: 10, column: 3, length: 3, cfeError: "wrong location"), | |
| makeError(line: 20, column: 2, length: 2, cfeError: "wrong message"), | |
| makeError(line: 10, column: 1, length: 1, cfeError: "match"), | |
| makeError(line: 40, column: 4, length: 4, cfeError: "match"), | |
| ], | |
| ''' | |
| - Wrong error location test.dart line 30, column 3, length 3: wrong location | |
| Expected line 30 but was line 10. | |
| - Wrong message at test.dart line 20, column 2, length 2: wrong message | |
| Expected: message | |
| - Missing expected error at test.dart line 20, column 2, length 2: missing | |
| - Unexpected error at test.dart line 1, column 2, length 1: unexpected''', | |
| ); | |
| // If expectation has context, actual must match it. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| null, | |
| ); | |
| // Actual context is different. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| ], | |
| ), | |
| ], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context Z."), | |
| ], | |
| ), | |
| ], | |
| """ | |
| - Wrong context message at test.dart line 4, column 5, length 6: Context Z. | |
| Expected: Context A.""", | |
| ); | |
| // Missing some actual context. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| """ | |
| - Missing expected context message at test.dart line 4, column 5, length 6: Context A.""", | |
| ); | |
| // Missing all actual context. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| [makeError(line: 1, column: 2, length: 3, cfeError: "Error.")], | |
| """ | |
| - Missing expected context message at test.dart line 4, column 5, length 6: Context A. | |
| - Missing expected context message at test.dart line 7, column 8, length 9: Context B.""", | |
| ); | |
| // Unexpected extra actual context. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| ], | |
| ), | |
| ], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| """ | |
| - Unexpected context message at test.dart line 7, column 8, length 9: Context B.""", | |
| ); | |
| // Actual context owned by wrong error. | |
| // TODO(rnystrom): This error is pretty confusing. Ideally we would detect | |
| // this case specifically and give better guidance. | |
| expectValidate( | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error A.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 33, column: 5, length: 6, contextError: "Context."), | |
| ], | |
| ), | |
| makeError( | |
| line: 10, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error B.", | |
| context: [ | |
| makeError(line: 11, column: 5, length: 6, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error A.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| ], | |
| ), | |
| makeError( | |
| line: 10, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error B.", | |
| context: [ | |
| makeError(line: 11, column: 5, length: 6, contextError: "Context B."), | |
| makeError(line: 33, column: 5, length: 6, contextError: "Context."), | |
| ], | |
| ), | |
| ], | |
| """ | |
| - Missing expected context message at test.dart line 33, column 5, length 6: Context. | |
| - Unexpected context message at test.dart line 33, column 5, length 6: Context.""", | |
| ); | |
| // If expectation has no context at all, then ignore actual context. | |
| expectValidate( | |
| [makeError(line: 1, column: 2, length: 3, cfeError: "Error.")], | |
| [ | |
| makeError( | |
| line: 1, | |
| column: 2, | |
| length: 3, | |
| cfeError: "Error.", | |
| context: [ | |
| makeError(line: 4, column: 5, length: 6, contextError: "Context A."), | |
| makeError(line: 7, column: 8, length: 9, contextError: "Context B."), | |
| ], | |
| ), | |
| ], | |
| null, | |
| ); | |
| } | |
| void expectValidate( | |
| List<StaticError> expected, | |
| List<StaticError> actual, | |
| String? expectedValidation, | |
| ) { | |
| var actualValidation = StaticError.validateExpectations(expected, actual); | |
| if (expectedValidation == null) { | |
| Expect.isNull(actualValidation); | |
| } else { | |
| Expect.isNotNull(actualValidation); | |
| Expect.stringEquals(expectedValidation, actualValidation!); | |
| } | |
| } |