Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.syntax; |
| 15 | |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 16 | import static com.google.common.truth.Truth.assertThat; |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 17 | |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 18 | import com.google.devtools.build.lib.events.Event; |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 19 | import com.google.devtools.build.lib.syntax.util.EvaluationTestCase; |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 20 | import org.junit.Test; |
| 21 | import org.junit.runner.RunWith; |
| 22 | import org.junit.runners.JUnit4; |
| 23 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 24 | /** |
| 25 | * Tests for the validation process of Skylark files. |
| 26 | */ |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 27 | @RunWith(JUnit4.class) |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 28 | public class ValidationTest extends EvaluationTestCase { |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 29 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 30 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 31 | public void testAssignmentNotValidLValue() { |
Michajlo Matijkiw | 8c539ea | 2017-02-22 23:02:46 +0000 | [diff] [blame] | 32 | checkError("cannot assign to '\"a\"'", "'a' = 1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 33 | } |
| 34 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 35 | @Test |
laurentlb | e368449 | 2017-08-21 12:02:46 +0200 | [diff] [blame] | 36 | public void testAugmentedAssignmentWithMultipleLValues() { |
| 37 | checkError("cannot perform augmented assignment on a list or tuple expression", "a, b += 2, 3"); |
| 38 | } |
| 39 | |
| 40 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 41 | public void testReturnOutsideFunction() throws Exception { |
laurentlb | a9b9aea | 2017-09-04 17:39:09 +0200 | [diff] [blame] | 42 | checkError("return statements must be inside a function", "return 2\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 43 | } |
| 44 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 45 | @Test |
laurentlb | a0fd766 | 2017-05-10 12:26:15 -0400 | [diff] [blame] | 46 | public void testLoadAfterStatement() throws Exception { |
| 47 | env = newEnvironmentWithSkylarkOptions("--incompatible_bzl_disallow_load_after_statement=true"); |
| 48 | checkError( |
| 49 | "load() statements must be called before any other statement", |
| 50 | "a = 5", |
| 51 | "load(':b.bzl', 'c')"); |
| 52 | } |
| 53 | |
| 54 | @Test |
| 55 | public void testAllowLoadAfterStatement() throws Exception { |
| 56 | env = |
| 57 | newEnvironmentWithSkylarkOptions("--incompatible_bzl_disallow_load_after_statement=false"); |
| 58 | parse("a = 5", "load(':b.bzl', 'c')"); |
| 59 | } |
| 60 | |
| 61 | @Test |
laurentlb | 77ffee3 | 2017-06-07 12:16:45 -0400 | [diff] [blame] | 62 | public void testForbiddenToplevelIfStatement() throws Exception { |
laurentlb | 77ffee3 | 2017-06-07 12:16:45 -0400 | [diff] [blame] | 63 | checkError("if statements are not allowed at the top level", "if True: a = 2"); |
| 64 | } |
| 65 | |
| 66 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 67 | public void testTwoFunctionsWithTheSameName() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 68 | checkError( |
| 69 | "Variable foo is read only", "def foo():", " return 1", "def foo(x, y):", " return 1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 72 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 73 | public void testFunctionLocalVariable() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 74 | checkError( |
| 75 | "name 'a' is not defined", |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 76 | "def func2(b):", |
| 77 | " c = b", |
| 78 | " c = a", |
| 79 | "def func1():", |
| 80 | " a = 1", |
| 81 | " func2(2)"); |
| 82 | } |
| 83 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 84 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 85 | public void testFunctionLocalVariableDoesNotEffectGlobalValidationEnv() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 86 | checkError("name 'a' is not defined", "def func1():", " a = 1", "def func2(b):", " b = a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 89 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 90 | public void testFunctionParameterDoesNotEffectGlobalValidationEnv() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 91 | checkError("name 'a' is not defined", "def func1(a):", " return a", "def func2():", " b = a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 92 | } |
| 93 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 94 | @Test |
fzaiser | 6ccff29 | 2017-08-28 17:50:51 +0200 | [diff] [blame] | 95 | public void testDefinitionByItself() throws Exception { |
laurentlb | 09ec261 | 2018-08-27 12:35:56 -0700 | [diff] [blame] | 96 | // Variables are assumed to be statically visible in the block (even if they might not be |
| 97 | // initialized). |
| 98 | parse("a = a"); |
| 99 | parse("a += a"); |
| 100 | parse("[[] for a in a]"); |
| 101 | parse("def f():", " for a in a: pass"); |
| 102 | } |
| 103 | |
| 104 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 105 | public void testLocalValidationEnvironmentsAreSeparated() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 106 | parse("def func1():", " a = 1", "def func2():", " a = 'abc'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 109 | @Test |
laurentlb | 09ec261 | 2018-08-27 12:35:56 -0700 | [diff] [blame] | 110 | public void testBuiltinsCanBeShadowed() throws Exception { |
laurentlb | 09ec261 | 2018-08-27 12:35:56 -0700 | [diff] [blame] | 111 | parse("repr = 1"); |
| 112 | } |
| 113 | |
| 114 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 115 | public void testSkylarkGlobalVariablesAreReadonly() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 116 | checkError("Variable a is read only", "a = 1", "a = 2"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 117 | } |
| 118 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 119 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 120 | public void testFunctionDefRecursion() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 121 | parse("def func():", " func()\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 122 | } |
| 123 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 124 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 125 | public void testMutualRecursion() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 126 | parse("def foo(i):", " bar(i)", "def bar(i):", " foo(i)", "foo(4)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 127 | } |
| 128 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 129 | @Test |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 130 | public void testFunctionDefinedBelow() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 131 | parse("def bar(): a = foo() + 'a'", "def foo(): return 1\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 134 | @Test |
laurentlb | 09ec261 | 2018-08-27 12:35:56 -0700 | [diff] [blame] | 135 | public void testGlobalDefinedBelow() throws Exception { |
| 136 | env = newEnvironmentWithSkylarkOptions("--incompatible_static_name_resolution=true"); |
| 137 | parse("def bar(): return x", "x = 5\n"); |
| 138 | } |
| 139 | |
| 140 | @Test |
| 141 | public void testLocalVariableDefinedBelow() throws Exception { |
| 142 | env = newEnvironmentWithSkylarkOptions("--incompatible_static_name_resolution=true"); |
| 143 | parse( |
| 144 | "def bar():", |
| 145 | " for i in range(5):", |
| 146 | " if i > 2: return x", |
| 147 | " x = i" // x is visible in the entire function block |
| 148 | ); |
| 149 | } |
| 150 | |
| 151 | @Test |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 152 | public void testFunctionDoesNotExist() { |
Laurent Le Brun | e102a2d | 2017-01-02 12:06:18 +0000 | [diff] [blame] | 153 | checkError("name 'foo' is not defined", "def bar(): a = foo() + 'a'"); |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 157 | public void testTupleLiteralWorksForDifferentTypes() throws Exception { |
| 158 | parse("('a', 1)"); |
| 159 | } |
| 160 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 161 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 162 | public void testDictLiteralDifferentValueTypeWorks() throws Exception { |
| 163 | parse("{'a': 1, 'b': 'c'}"); |
| 164 | } |
| 165 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 166 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 167 | public void testNoneAssignment() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 168 | parse("def func():", " a = None", " a = 2", " a = None\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 169 | } |
| 170 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 171 | @Test |
Laurent Le Brun | 65ec957 | 2015-03-16 10:45:07 +0000 | [diff] [blame] | 172 | public void testNoneIsAnyType() throws Exception { |
| 173 | parse("None + None"); |
| 174 | parse("2 == None"); |
| 175 | parse("None > 'a'"); |
| 176 | parse("[] in None"); |
| 177 | parse("5 * None"); |
| 178 | } |
| 179 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 180 | // Skylark built-in functions specific tests |
| 181 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 182 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 183 | public void testFuncReturningDictAssignmentAsLValue() throws Exception { |
Vladimir Moskva | 1077038 | 2016-08-23 15:04:54 +0000 | [diff] [blame] | 184 | parse( |
Florian Weikert | a6dae6b | 2015-08-04 20:17:23 +0000 | [diff] [blame] | 185 | "def my_dict():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 186 | " return {'a': 1}", |
| 187 | "def func():", |
Vladimir Moskva | 1077038 | 2016-08-23 15:04:54 +0000 | [diff] [blame] | 188 | " my_dict()['b'] = 2"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 189 | } |
| 190 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 191 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 192 | public void testEmptyLiteralGenericIsSetInLaterConcatWorks() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 193 | parse("def func():", " s = {}", " s['a'] = 'b'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 194 | } |
| 195 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 196 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 197 | public void testModulesReadOnlyInFuncDefBody() { |
Vladimir Moskva | d200daf | 2016-12-23 16:35:37 +0000 | [diff] [blame] | 198 | parse("def func():", " cmd_helper = depset()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 199 | } |
| 200 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 201 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 202 | public void testBuiltinGlobalFunctionsReadOnlyInFuncDefBody() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 203 | parse("def func():", " rule = 'abc'"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 204 | } |
| 205 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 206 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 207 | public void testBuiltinGlobalFunctionsReadOnlyAsFuncDefArg() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 208 | parse("def func(rule):", " return rule"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 209 | } |
| 210 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 211 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 212 | public void testFunctionReturnsFunction() { |
| 213 | parse( |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 214 | "def rule(*, implementation): return None", |
| 215 | "def impl(ctx): return None", |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 216 | "", |
| 217 | "skylark_rule = rule(implementation = impl)", |
| 218 | "", |
| 219 | "def macro(name):", |
| 220 | " skylark_rule(name = name)"); |
| 221 | } |
| 222 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 223 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 224 | public void testTypeForBooleanLiterals() { |
| 225 | parse("len([1, 2]) == 0 and True"); |
| 226 | parse("len([1, 2]) == 0 and False"); |
| 227 | } |
| 228 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 229 | @Test |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 230 | public void testDollarErrorDoesNotLeak() throws Exception { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 231 | setFailFast(false); |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 232 | parseFile( |
| 233 | "def GenerateMapNames():", " a = 2", " b = [3, 4]", " if a not b:", " print(a)"); |
laurentlb | 566ef5a | 2018-05-22 10:35:06 -0700 | [diff] [blame] | 234 | assertContainsError("syntax error at 'b': expected 'in'"); |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 235 | // Parser uses "$error" symbol for error recovery. |
| 236 | // It should not be used in error messages. |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 237 | for (Event event : getEventCollector()) { |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 238 | assertThat(event.getMessage()).doesNotContain("$error$"); |
| 239 | } |
| 240 | } |
| 241 | |
laurentlb | 1e5352d | 2018-11-06 12:25:55 -0800 | [diff] [blame] | 242 | @Test |
| 243 | public void testPositionalAfterStarArg() throws Exception { |
| 244 | env = newEnvironmentWithSkylarkOptions("--incompatible_strict_argument_ordering=true"); |
| 245 | checkError( |
| 246 | "positional argument is misplaced (positional arguments come first)", |
| 247 | "def fct(*args, **kwargs): pass", |
| 248 | "fct(1, *[2], 3)"); |
| 249 | } |
| 250 | |
| 251 | @Test |
| 252 | public void testTwoStarArgs() throws Exception { |
| 253 | env = newEnvironmentWithSkylarkOptions("--incompatible_strict_argument_ordering=true"); |
| 254 | checkError( |
| 255 | "*arg argument is misplaced", |
| 256 | "def fct(*args, **kwargs):", |
| 257 | " pass", |
| 258 | "fct(1, 2, 3, *[], *[])"); |
| 259 | } |
| 260 | |
| 261 | @Test |
| 262 | public void testKeywordArgAfterStarArg() throws Exception { |
| 263 | env = newEnvironmentWithSkylarkOptions("--incompatible_strict_argument_ordering=true"); |
| 264 | checkError( |
| 265 | "keyword argument is misplaced (keyword arguments must be before any *arg or **kwarg)", |
| 266 | "def fct(*args, **kwargs): pass", |
| 267 | "fct(1, *[2], a=3)"); |
| 268 | } |
| 269 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 270 | private void parse(String... lines) { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 271 | parseFile(lines); |
Ulf Adams | b089c8d | 2015-10-26 12:20:33 +0000 | [diff] [blame] | 272 | assertNoWarningsOrErrors(); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | private void checkError(String errorMsg, String... lines) { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 276 | setFailFast(false); |
| 277 | parseFile(lines); |
Ulf Adams | c708f96 | 2015-10-22 12:02:28 +0000 | [diff] [blame] | 278 | assertContainsError(errorMsg); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 279 | } |
| 280 | } |