Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(iota-transactional-test-runner): document run-graphql syntax #4699

Open
wants to merge 11 commits into
base: sc-platform/transactional-tests-syntax
Choose a base branch
from
89 changes: 89 additions & 0 deletions crates/iota-transactional-test-runner/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,95 @@ in the respective sections.

### `run-graphql`

Allows to execute GraphQL queries with optional options and returns the output.

#### Syntax:

```
//# run-graphql [OPTIONS]
<GraphQL-query>
```

#### Options:

```
--show-usage: Displays usage information for the command.
--show-headers: Includes HTTP headers in the output.
--show-service-version: Displays the version of the service handling the GraphQL query.
samuel-rufi marked this conversation as resolved.
Show resolved Hide resolved
--cursors <cursor-list>: Specifies a list of cursors to be used within the query.
```

#### Query Interpolation

The command supports **query interpolation**, allowing you to dynamically replace parts of the GraphQL query at runtime.
It supports the following placeholders:

1. **Object Placeholders**
- **Syntax**: `@{obj_x_y}` or `@{obj_x_y_opt}`
samuel-rufi marked this conversation as resolved.
Show resolved Hide resolved
- Here, `(x, y)` corresponds to the transaction index and the creation index of the object within that transaction. The placeholder will be replaced with the object ID as a string (like `0xABCD...`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the transaction index? I know it captures the order of creation within the test, but I don't recall if it is sequence number of the command that included the transaction (e.g. init) or the absolute sequence number of the transaction. Could elaborate/disambiguate?

Copy link
Member Author

@samuel-rufi samuel-rufi Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, it's the task index, therefore it does not necessarily align with the absolute sequence number of the transaction. When the IotaTestAdapter gets initialized, we set the next_fake to (0,0).
For each objectID we create in the same task, we use the very same task index:

    fn enumerate_fake(&mut self, id: ObjectID) -> FakeID {
        if let Some(fake) = self.object_enumeration.get_by_left(&id) {
            return *fake;
        }
        let (task, i) = self.next_fake;
        let fake_id = FakeID::Enumerated(task, i);
        self.object_enumeration.insert(id, fake_id);

        self.next_fake = (task, i + 1);
        fake_id
    }

the next_fake is only ever increased when we switch to the next task:

    fn next_task(&mut self) {
        self.next_fake = (self.next_fake.0 + 1, 0)
    }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored with fe77000


2. **Named Address Placeholders**
- **Syntax**: `@{NamedAddr}` or `@{NamedAddr_opt}`
- Substitutes known accounts and addresses that have been created during the initialization step, e.g. `init --protocol-version 1 --addresses P0=0x0 --accounts A B --simulator`

3. **Cursors**
- **Syntax**: `//# run-graphql --cursors string1 string2 ...`
- Depending on the query, the raw strings passed to `--cursors` might be required in JSON, BCS or any other format that the query expects.
- Each string passed is automatically Base64-encoded (as all cursor values are expected to be Base64-encoded) and can be accessed in the query as `@{cursor_0}`, `@{cursor_1}`, etc., in the order provided.
- To generate cursor values from objects at runtime, the strings passed must correspond to the format `@{obj_x_y}` or `@{obj_x_y, checkpoint}` and are translated to Base64-encoded object cursors.

All of the above rules (object placeholders, named address placeholders, cursor strings) can be used in a single query.
Any placeholder or cursor that cannot be mapped to a known variable, object, or address will cause an error.

#### Examples

The following example query will replace the placeholder `@{cursor_0}` with the Base64-encoded [transaction block cursor](../../crates/iota-graphql-rpc/src/types/transaction_block.rs) `{"c":3,"t":1,"tc":1}` where `c` is the checkpoint sequence number, `t` is the transaction sequence number, and `tc` is the transaction checkpoint number.
Cursor values depend on the query and the underlying schema. The cursor value above example is specific to the GraphQL `transactionBlocks` query.
`@{A}` and `@{P0}` will be replaced with the addresses `A` and `P0` respectively that were created during the initialization step.

```
//# run-graphql --cursors {"c":3,"t":1,"tc":1}
{
transactionBlocks(first: 1, after: "@{cursor_0}", filter: {signAddress: "@{A}"}) {
samuel-rufi marked this conversation as resolved.
Show resolved Hide resolved
nodes {
sender {
fakeCoinBalance: balance(type: "@{P0}::fake::FAKE") {
totalBalance
}
allBalances: balances {
nodes {
coinType {
repr
}
coinObjectCount
totalBalance
}
}
}
}
}
}
```

An example of a query that generates an object cursor at runtime:

```
//# run-graphql --cursors @{obj_6_0}
{
address(address: "@{A}") {
objects(first: 2 after: "@{cursor_0}") {
edges {
node {
contents {
json
}
}
}
}
}
}
```

### `force-object-snapshot-catchup`

### `bench`
Expand Down
Loading