Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 72 additions & 6 deletions docs/scripted_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ Available states (each state does the tasks in the state listed before it):
the test mailbox.
:::

### `user <N>`

* Default: \<none\>

Sets the username template for connection `<N>` (where `<N>` is a positive integer). This is useful when testing with different accounts on multiple connections. The value is typically set to `${user2}`, `${user3}`, etc. to use the username templates configured via command-line parameters.

### `ignore_extra_untagged`

* Default: `yes`
Expand Down Expand Up @@ -168,7 +174,7 @@ ok fetch 1 (uid flags)
* 1 fetch (uid $ flags $)
```

Using `$n`, where `n` is a number, maps to sequences at the beginning of a command. These are useful when receiving EXPUNGEs from another session. Example:
Using `$n`, where `n` is a number, maps to the UID at sequence position `n` in the current mailbox. These are useful when receiving EXPUNGEs from another session, where sequence numbers may shift. Example:

```
1 ok expunge
Expand All @@ -180,7 +186,7 @@ Using `$n`, where `n` is a number, maps to sequences at the beginning of a comma

### Case Sensitivity

Normally all strings are compared case-insensitively. If you need to support case-sensitive matching, use the `%{case:text} variable:
Normally all strings are compared case-insensitively. If you need to support case-sensitive matching, use the `${case:text}` variable:

```
ok list "" *
Expand Down Expand Up @@ -237,7 +243,7 @@ There are also some predefined variables:
If a list has no explicit directives, defaults are used (separately for each list within same command):

* "n FETCH ($!unordered=2)"
* "n FETCH (FLAGS ($!unordered $!noextra $!ignore=\recent))"
* "n FETCH (FLAGS ($!unordered $!noextra $!ignore=\recent $!ignore=$HasAttachment $!ignore=$HasNoAttachment))"
* "LIST ($!unordered)"
* "LSUB ($!unordered)"
* "STATUS mailbox ($!unordered=2)"
Expand All @@ -258,20 +264,80 @@ is fully expanded as:
So the FLAGS won't have `$!unordered` or `$!ignored=\recent`, but the parent FETCH list will have the default `$!unordered=2`.
:::

## Comments

Lines beginning with `#` are treated as comments and ignored by the parser.

```
# This is a comment and will be ignored
ok select $mailbox
```

## Preprocessing

You can use `!ifenv`, `!ifnenv`, `!else` and `!endif` to run tests only if specified environment variables exist. For example:
Preprocessing directives allow test files to be conditional, include delays, or produce custom output.

::: info
All directives begin with `!` and must appear on their own line.
:::

### Conditional Execution

| Directive | Description |
| --- | --- |
| `!ifenv <VAR>` | Start a block that runs only if the environment variable `<VAR>` is **set** (regardless of its value). |
| `!ifnenv <VAR>` | Start a block that runs only if the environment variable `<VAR>` is **not set**. |
| `!else` | Toggle the skip state. If the preceding `!ifenv`/`!ifnenv` block was being skipped, the `!else` block is executed and vice versa. Only one `!else` is allowed per `!ifenv`/`!ifnenv` block. |
| `!endif` | End the current `!ifenv`/`!ifnenv` block. The skip state is restored to what it was before the matching `!ifenv`/`!ifnenv`. |

The directives can be nested. Each `!ifenv`/`!ifnenv` must have a matching `!endif`.

```
!ifenv HAVE_FOO
# HAVE_FOO is defined
ok foo
* foo stuff
!else
# HAVE_FOO is NOT defined
ok fallback
* fallback response
!endif

!ifenv HAVE_BAR
!ifenv HAVE_BAZ
# HAVE_BAR and HAVE_BAZ are defined
ok both bar and baz
!endif
!endif
```

### Delay

| Directive | Description |
| --- | --- |
| `!sleep <interval>` | Pause for the specified interval before processing the next command. The interval is specified in milliseconds. |

```
ok some-command
# Delay for 500ms
!sleep 500
ok next-command
```

The "foo" command is run only if the `HAVE_FOO` environment variable exists.
### Output

Similarly `!ifnenv HAVE_FOO` block is run only if the `HAVE_FOO` environment variable doesn't exist.
| Directive | Description |
| --- | --- |
| `!output <text>` | Print `<text>` to the test output during execution. |

```
# This text will be printed in the test output
!output Starting optional test section
!ifenv HAVE_FOO
ok foo
* foo stuff
!endif
```

## Full Example

Expand Down
3 changes: 1 addition & 2 deletions src/test-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ test_parse_header_line(struct test_parser *parser, struct test *test,
return TRUE;
}
if (strcmp(key, "connections") == 0) {
test->connection_count = strcmp(value, "n") == 0 ? 2 :
strtoul(value, NULL, 10);
test->connection_count = strtoul(value, NULL, 10);
if (test->connection_count == 0 ||
test->connection_count > MAX_TEST_CONNECTIONS) {
*error_r = "Too many connections";
Expand Down
Loading