Tests
Tests are written in a test {}
block to unit test the expression by matching it against a list
of strings.
Syntax
Section titled “Syntax”let Test = 'test' '{' TestCase* '}';
let TestCase = | TestCaseMatch | TestCaseMatchAll | TestCaseReject;
let TestCaseMatch = 'match' TestCaseSingleMatch ';';let TestCaseMatchAll = 'match' TestCaseMatches? 'in' String ';';let TestCaseReject = 'reject' 'in'? String ';';
let TestCaseMatches = TestCaseSingleMatch (',' TestCaseSingleMatch)*;
let TestCaseSingleMatch = String TestCaptures?;
let TestCaptures = 'as' '{' TestCapturesInner? '}';
let TestCapturesInner = TestCapture (',' TestCapture)* ','?;
let TestCapture = TestCaptureName ':' String;
let TestCaptureName = | Number | Ident;
Test may only appear in the top-level scope, so the following is forbidden:
( test {} # ERROR 'foo')
Example
Section titled “Example”test {
reject 'john.doe@mailbox';
reject in 'There is no valid email@address in this string';}
:(![s '@']+) '@' :domain(![s '@']+ '.' ![s '@'])
Support
Section titled “Support”Tests are supported in all flavors, but can only be executed with PCRE2 at the moment. This is done
by passing --test=pcre2
to the CLI.
Behavior
Section titled “Behavior”A test case can either assert that something matches (with match
) or does not match (with
reject
). Pomsky supports two matching modes, exact match and substring match. The substring
matching mode is used when the test case includes the in
keyword.
Syntax | Behavior |
---|---|
match 'foo'; | expects exact match |
reject 'foo'; | expects no exact match |
match 'f', 'o' in 'foo'; | expects substring match ‘f’ |
reject in 'foo'; | expects no substring matches |
When using substring matches, all matches must be specified and in the correct order. The matches do not overlap. You can specify capturing groups for each substring match individually.
When specifying capturing groups, you do not need to specify all of them; only the specified groups are compared. They can appear in any order. Unnamed capturing groups are assigned an ascending number, starting with 1. The capturing group 0 is the entire match.
Tests are only executed when the --test
option is used in the CLI.
Compilation
Section titled “Compilation”Tests do not produce any output. However, when the --test
flag is used, the expression is
compiled twice: Once for the target flavor, and again for PCRE2. The compiled PCRE2 pattern is
used for testing and discarded afterwards.
Issues
Section titled “Issues”The potential mismatch between the target flavor and the flavor used for testing can result in false positives (where PCRE2 accepts a pattern that is illegal in the target flavor) and false negatives (where PCRE2 fails to match a pattern that would match in the target flavor).
One common example is when the expression contains a lookbehind assertion of variable length. PCRE2 only supports constant-length lookbehind due to technical limitations.
Security concerns
Section titled “Security concerns”Since PCRE2 is a backtracking regex engine, an attacker should not be allowed to compile and test untrusted Pomsky expressions on a server, as this can lead to exponential backtracking and exhaust the server’s resources.
History
Section titled “History”Initial implementation in Pomsky 0.11
- Supports only PCRE2