| // 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!); |
| } |
| } |