4343 * There is no need to write a `select` clause or query predicate. All of the differences between
4444 * expected results and actual results will be reported in the `failures()` query predicate.
4545 *
46- * To annotate the test source code with an expected result, place a comment on the
46+ * To annotate the test source code with an expected result, place a comment starting with a `$` on the
4747 * same line as the expected result, with text of the following format as the body of the comment:
4848 *
49- * `$ tag=expected-value`
49+ * `tag=expected-value`
5050 *
5151 * Where `tag` is the value of the `tag` parameter from `hasActualResult()`, and `expected-value` is
5252 * the value of the `value` parameter from `hasActualResult()`. The `=expected-value` portion may be
5353 * omitted, in which case `expected-value` is treated as the empty string. Multiple expectations may
54- * be placed in the same comment, as long as each is prefixed by a `$` . Any actual result that
54+ * be placed in the same comment. Any actual result that
5555 * appears on a line that does not contain a matching expected result comment will be reported with
5656 * a message of the form "Unexpected result: tag=value". Any expected result comment for which there
5757 * is no matching actual result will be reported with a message of the form
6060 * Example:
6161 * ```cpp
6262 * int i = x + 5; // $const=5
63- * int j = y + (7 - 3) // $const=7 $ const=3 $ const=4 // The result of the subtraction is a constant.
63+ * int j = y + (7 - 3) // $const=7 const=3 const=4 // The result of the subtraction is a constant.
6464 * ```
6565 *
66- * For tests that contain known false positives and false negatives , it is possible to further
67- * annotate that a particular expected result is known to be a false positive , or that a particular
68- * missing result is known to be a false negative :
66+ * For tests that contain known missing and spurious results , it is possible to further
67+ * annotate that a particular expected result is known to be spurious , or that a particular
68+ * missing result is known to be missing :
6969 *
70- * `$f+: tag=expected-value` // False positive
71- * `$f-: tag=expected-value` // False negative
70+ * `$ SPURIOUS: tag=expected-value` // Spurious result
71+ * `$ MISSING: tag=expected-value` // Missing result
7272 *
73- * A false positive expectation is treated as any other expected result, except that if there is no
74- * matching actual result, the message will be of the form "Fixed false positive : tag=value". A
75- * false negative expectation is treated as if there were no expected result, except that if a
73+ * A spurious expectation is treated as any other expected result, except that if there is no
74+ * matching actual result, the message will be of the form "Fixed spurious result : tag=value". A
75+ * missing expectation is treated as if there were no expected result, except that if a
7676 * matching expected result is found, the message will be of the form
77- * "Fixed false negative: tag=value".
77+ * "Fixed missing result: tag=value".
78+ *
79+ * A single line can contain all the expected, spurious and missing results of that line. For instance:
80+ * `$ tag1=value1 SPURIOUS: tag2=value2 MISSING: tag3=value3`.
7881 *
7982 * If the same result value is expected for two or more tags on the same line, there is a shorthand
8083 * notation available:
8184 *
82- * `$ tag1,tag2=expected-value`
85+ * `tag1,tag2=expected-value`
8386 *
8487 * is equivalent to:
8588 *
86- * `$ tag1=expected-value $ tag2=expected-value`
89+ * `tag1=expected-value tag2=expected-value`
8790 */
8891
8992private import InlineExpectationsTestPrivate
@@ -126,7 +129,7 @@ abstract class InlineExpectationsTest extends string {
126129 (
127130 exists ( FalseNegativeExpectation falseNegative |
128131 falseNegative .matchesActualResult ( actualResult ) and
129- message = "Fixed false negative :" + falseNegative .getExpectationText ( )
132+ message = "Fixed missing result :" + falseNegative .getExpectationText ( )
130133 )
131134 or
132135 not exists ( ValidExpectation expectation | expectation .matchesActualResult ( actualResult ) ) and
@@ -143,7 +146,7 @@ abstract class InlineExpectationsTest extends string {
143146 message = "Missing result:" + expectation .getExpectationText ( )
144147 or
145148 expectation instanceof FalsePositiveExpectation and
146- message = "Fixed false positive :" + expectation .getExpectationText ( )
149+ message = "Fixed spurious result :" + expectation .getExpectationText ( )
147150 )
148151 )
149152 or
@@ -160,20 +163,84 @@ abstract class InlineExpectationsTest extends string {
160163 * is treated as part of the expected results, except that the comment may contain a `//` sequence
161164 * to treat the remainder of the line as a regular (non-interpreted) comment.
162165 */
163- private string expectationCommentPattern ( ) { result = "\\s*( \\$(?:[^/]|/[^/])*)(?://.*)?" }
166+ private string expectationCommentPattern ( ) { result = "\\s*\\$( (?:[^/]|/[^/])*)(?://.*)?" }
164167
165168/**
166- * RegEx pattern to match a single expected result, not including the leading `$`. It starts with an
167- * optional `f+:` or `f-:`, followed by one or more comma-separated tags containing only letters,
168- * `-`, and `_`, optionally followed by `=` and the expected value .
169+ * The possible columns in an expectation comment. The `TDefaultColumn` branch represents the first
170+ * column in a comment. This column is not precedeeded by a name. `TNamedColumn(name)` represents a
171+ * column containing expected results preceeded by the string `name:` .
169172 */
170- private string expectationPattern ( ) {
171- result = "(?:(f(?:\\+|-)):)?((?:[A-Za-z-_]+)(?:\\s*,\\s*[A-Za-z-_]+)*)(?:=(.*))?"
173+ private newtype TColumn =
174+ TDefaultColumn ( ) or
175+ TNamedColumn ( string name ) { name = [ "MISSING" , "SPURIOUS" ] }
176+
177+ bindingset [ start, content]
178+ private int getEndOfColumnPosition ( int start , string content ) {
179+ result =
180+ min ( string name , int cand |
181+ exists ( TNamedColumn ( name ) ) and
182+ cand = content .indexOf ( name + ":" ) and
183+ cand > start
184+ |
185+ cand
186+ )
187+ or
188+ not exists ( string name |
189+ exists ( TNamedColumn ( name ) ) and
190+ content .indexOf ( name + ":" ) > start
191+ ) and
192+ result = content .length ( )
193+ }
194+
195+ private string getAnExpectation ( LineComment comment , TColumn column ) {
196+ exists ( string content |
197+ content = comment .getContents ( ) .regexpCapture ( expectationCommentPattern ( ) , 1 ) and
198+ (
199+ column = TDefaultColumn ( ) and
200+ exists ( int end |
201+ end = getEndOfColumnPosition ( 0 , content ) and
202+ result = content .prefix ( end ) .splitAt ( " " ) .trim ( )
203+ )
204+ or
205+ exists ( string name , int start , int end |
206+ column = TNamedColumn ( name ) and
207+ start = content .indexOf ( name + ":" ) + name .length ( ) + 1 and
208+ end = getEndOfColumnPosition ( start , content ) and
209+ result = content .substring ( start , end ) .splitAt ( " " ) .trim ( )
210+ )
211+ ) and
212+ result != ""
213+ )
214+ }
215+
216+ bindingset [ expectation]
217+ private string getATag ( string expectation ) {
218+ (
219+ result = expectation .prefix ( expectation .indexOf ( "=" ) ) .splitAt ( "," ) .trim ( )
220+ or
221+ not exists ( expectation .indexOf ( "=" ) ) and
222+ result = expectation .splitAt ( "," ) .trim ( )
223+ )
172224}
173225
174- private string getAnExpectation ( LineComment comment ) {
175- result = comment .getContents ( ) .regexpCapture ( expectationCommentPattern ( ) , 1 ) .splitAt ( "$" ) .trim ( ) and
176- result != ""
226+ bindingset [ expectation]
227+ private string getValueForTag ( string expectation ) {
228+ result = expectation .suffix ( expectation .indexOf ( "=" ) + 1 )
229+ }
230+
231+ private string getColumnString ( TColumn column ) {
232+ column = TDefaultColumn ( ) and result = ""
233+ or
234+ column = TNamedColumn ( result )
235+ }
236+
237+ /**
238+ * RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
239+ * more comma-separated tags containing only letters, `-`, and `_`, optionally followed by `=` and the
240+ * expected value.
241+ */
242+ private string expectationPattern ( ) {
243+ result = "((?:[A-Za-z-_]+)(?:\\s*,\\s*[A-Za-z-_]+)*)(?:=(.*))?"
177244}
178245
179246private newtype TFailureLocatable =
@@ -183,24 +250,19 @@ private newtype TFailureLocatable =
183250 test .hasActualResult ( location , element , tag , value )
184251 } or
185252 TValidExpectation ( LineComment comment , string tag , string value , string knownFailure ) {
186- exists ( string expectation |
187- expectation = getAnExpectation ( comment ) and
188- expectation .regexpMatch ( expectationPattern ( ) ) and
189- tag = expectation .regexpCapture ( expectationPattern ( ) , 2 ) .splitAt ( "," ) .trim ( ) and
253+ exists ( string expectation , TColumn column |
254+ expectation = getAnExpectation ( comment , column ) and
255+ tag = getATag ( expectation ) and
190256 (
191- if exists ( expectation . regexpCapture ( expectationPattern ( ) , 3 ) )
192- then value = expectation . regexpCapture ( expectationPattern ( ) , 3 )
257+ if exists ( getValueForTag ( expectation ) )
258+ then value = getValueForTag ( expectation )
193259 else value = ""
194260 ) and
195- (
196- if exists ( expectation .regexpCapture ( expectationPattern ( ) , 1 ) )
197- then knownFailure = expectation .regexpCapture ( expectationPattern ( ) , 1 )
198- else knownFailure = ""
199- )
261+ knownFailure = getColumnString ( column )
200262 )
201263 } or
202264 TInvalidExpectation ( LineComment comment , string expectation ) {
203- expectation = getAnExpectation ( comment ) and
265+ expectation = getAnExpectation ( comment , _ ) and
204266 not expectation .regexpMatch ( expectationPattern ( ) )
205267 }
206268
@@ -265,16 +327,17 @@ private class ValidExpectation extends Expectation, TValidExpectation {
265327 }
266328}
267329
330+ /* Note: These next three classes correspond to all the possible values of type `TColumn`. */
268331class GoodExpectation extends ValidExpectation {
269332 GoodExpectation ( ) { getKnownFailure ( ) = "" }
270333}
271334
272335class FalsePositiveExpectation extends ValidExpectation {
273- FalsePositiveExpectation ( ) { getKnownFailure ( ) = "f+ " }
336+ FalsePositiveExpectation ( ) { getKnownFailure ( ) = "SPURIOUS " }
274337}
275338
276339class FalseNegativeExpectation extends ValidExpectation {
277- FalseNegativeExpectation ( ) { getKnownFailure ( ) = "f- " }
340+ FalseNegativeExpectation ( ) { getKnownFailure ( ) = "MISSING " }
278341}
279342
280343class InvalidExpectation extends Expectation , TInvalidExpectation {
0 commit comments