Skip to content

Commit ae44a94

Browse files
authored
Merge pull request #9421 from RasmusWL/inline-brackets
Inline Expectation Tests: Allow `tag[foo bar]`
2 parents be2dfff + b65a10d commit ae44a94

File tree

9 files changed

+134
-48
lines changed

9 files changed

+134
-48
lines changed

cpp/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

csharp/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

go/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

java/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

python/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

python/ql/test/experimental/meta/MaDTest.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ class MadSinkTest extends InlineExpectationsTest {
1111
MadSinkTest() { this = "MadSinkTest" }
1212

1313
override string getARelevantTag() {
14-
exists(string kind | exists(ModelOutput::getASinkNode(kind)) | result = "mad-sink__" + kind)
14+
exists(string kind | exists(ModelOutput::getASinkNode(kind)) |
15+
result = "mad-sink[" + kind + "]"
16+
)
1517
}
1618

1719
override predicate hasActualResult(Location location, string element, string tag, string value) {
@@ -21,7 +23,7 @@ class MadSinkTest extends InlineExpectationsTest {
2123
location = sink.getLocation() and
2224
element = sink.toString() and
2325
value = prettyNodeForInlineTest(sink) and
24-
tag = "mad-sink__" + kind
26+
tag = "mad-sink[" + kind + "]"
2527
)
2628
}
2729
}

python/ql/test/library-tests/frameworks/asyncpg/test.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ async def test_connection():
77
try:
88
# The file-like object is passed in as a keyword-only argument.
99
# See https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.connection.Connection.copy_from_query
10-
await conn.copy_from_query("sql", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
11-
await conn.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
10+
await conn.copy_from_query("sql", output="filepath") # $ mad-sink[sql-injection]="sql" mad-sink[path-injection]="filepath"
11+
await conn.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink[sql-injection]="sql" mad-sink[path-injection]="filepath"
1212

13-
await conn.copy_from_table("table", output="filepath") # $ mad-sink__path-injection="filepath"
14-
await conn.copy_to_table("table", source="filepath") # $ mad-sink__path-injection="filepath"
13+
await conn.copy_from_table("table", output="filepath") # $ mad-sink[path-injection]="filepath"
14+
await conn.copy_to_table("table", source="filepath") # $ mad-sink[path-injection]="filepath"
1515

16-
await conn.execute("sql") # $ mad-sink__sql-injection="sql"
17-
await conn.executemany("sql") # $ mad-sink__sql-injection="sql"
18-
await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
19-
await conn.fetchrow("sql") # $ mad-sink__sql-injection="sql"
20-
await conn.fetchval("sql") # $ mad-sink__sql-injection="sql"
16+
await conn.execute("sql") # $ mad-sink[sql-injection]="sql"
17+
await conn.executemany("sql") # $ mad-sink[sql-injection]="sql"
18+
await conn.fetch("sql") # $ mad-sink[sql-injection]="sql"
19+
await conn.fetchrow("sql") # $ mad-sink[sql-injection]="sql"
20+
await conn.fetchval("sql") # $ mad-sink[sql-injection]="sql"
2121

2222
finally:
2323
await conn.close()
@@ -27,7 +27,7 @@ async def test_prepared_statement():
2727
conn = await asyncpg.connect()
2828

2929
try:
30-
pstmt = await conn.prepare("psql") # $ mad-sink__sql-injection="psql"
30+
pstmt = await conn.prepare("psql") # $ mad-sink[sql-injection]="psql"
3131
pstmt.executemany()
3232
pstmt.fetch()
3333
pstmt.fetchrow()
@@ -46,7 +46,7 @@ async def test_cursor():
4646
cursor = await conn.cursor("sql") # $ getSql="sql" constructedSql="sql"
4747
await cursor.fetch()
4848

49-
pstmt = await conn.prepare("psql") # $ mad-sink__sql-injection="psql"
49+
pstmt = await conn.prepare("psql") # $ mad-sink[sql-injection]="psql"
5050
pcursor = await pstmt.cursor() # $ getSql="psql"
5151
await pcursor.fetch()
5252

@@ -69,37 +69,37 @@ async def test_connection_pool():
6969
pool = await asyncpg.create_pool()
7070

7171
try:
72-
await pool.copy_from_query("sql", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
73-
await pool.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink__sql-injection="sql" mad-sink__path-injection="filepath"
74-
await pool.copy_from_table("table", output="filepath") # $ mad-sink__path-injection="filepath"
75-
await pool.copy_to_table("table", source="filepath") # $ mad-sink__path-injection="filepath"
72+
await pool.copy_from_query("sql", output="filepath") # $ mad-sink[sql-injection]="sql" mad-sink[path-injection]="filepath"
73+
await pool.copy_from_query("sql", "arg1", "arg2", output="filepath") # $ mad-sink[sql-injection]="sql" mad-sink[path-injection]="filepath"
74+
await pool.copy_from_table("table", output="filepath") # $ mad-sink[path-injection]="filepath"
75+
await pool.copy_to_table("table", source="filepath") # $ mad-sink[path-injection]="filepath"
7676

77-
await pool.execute("sql") # $ mad-sink__sql-injection="sql"
78-
await pool.executemany("sql") # $ mad-sink__sql-injection="sql"
79-
await pool.fetch("sql") # $ mad-sink__sql-injection="sql"
80-
await pool.fetchrow("sql") # $ mad-sink__sql-injection="sql"
81-
await pool.fetchval("sql") # $ mad-sink__sql-injection="sql"
77+
await pool.execute("sql") # $ mad-sink[sql-injection]="sql"
78+
await pool.executemany("sql") # $ mad-sink[sql-injection]="sql"
79+
await pool.fetch("sql") # $ mad-sink[sql-injection]="sql"
80+
await pool.fetchrow("sql") # $ mad-sink[sql-injection]="sql"
81+
await pool.fetchval("sql") # $ mad-sink[sql-injection]="sql"
8282

8383
async with pool.acquire() as conn:
84-
await conn.execute("sql") # $ mad-sink__sql-injection="sql"
84+
await conn.execute("sql") # $ mad-sink[sql-injection]="sql"
8585

8686
conn = await pool.acquire()
8787
try:
88-
await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
88+
await conn.fetch("sql") # $ mad-sink[sql-injection]="sql"
8989
finally:
9090
await pool.release(conn)
9191

9292
finally:
9393
await pool.close()
9494

9595
async with asyncpg.create_pool() as pool:
96-
await pool.execute("sql") # $ mad-sink__sql-injection="sql"
96+
await pool.execute("sql") # $ mad-sink[sql-injection]="sql"
9797

9898
async with pool.acquire() as conn:
99-
await conn.execute("sql") # $ mad-sink__sql-injection="sql"
99+
await conn.execute("sql") # $ mad-sink[sql-injection]="sql"
100100

101101
conn = await pool.acquire()
102102
try:
103-
await conn.fetch("sql") # $ mad-sink__sql-injection="sql"
103+
await conn.fetch("sql") # $ mad-sink[sql-injection]="sql"
104104
finally:
105105
await pool.release(conn)

ql/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

ruby/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
239239

240240
/**
241241
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
242-
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
243-
* must not be a digit), optionally followed by `=` and the expected value.
242+
* more comma-separated tags optionally followed by `=` and the expected value.
243+
*
244+
* Tags must be only letters, digits, `-` and `_` (note that the first character
245+
* must not be a digit), but can contain anything enclosed in a single set of
246+
* square brackets.
247+
*
248+
* Examples:
249+
* - `tag`
250+
* - `tag=value`
251+
* - `tag,tag2=value`
252+
* - `tag[foo bar]=value`
253+
*
254+
* Not allowed:
255+
* - `tag[[[foo bar]`
244256
*/
245257
private string expectationPattern() {
246258
exists(string tag, string tags, string value |
247-
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
259+
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
248260
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
249261
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
250262
// For example, `b"foo"`.

0 commit comments

Comments
 (0)