Namespace definitions

The rell.test namespace is only accessible within test modules

Example

@test module;

function test() {
rell.test.block().run();
}

Since

0.10.4

Types

Link copied to clipboard
type block

A test block builder; i.e. a builder for test blockchain blocks.

A test block consists of a list of test transactions that are executed when the block is built. A test transaction consists of a list of test operation calls, and a list of signing keypairs.

Test block timestamps

The timestamps of Rell test blocks are deterministic, and determined by the following rules:

  1. If the next block's timestamp was set explicitly via rell.test.set_next_block_time() or rell.test.set_next_block_time_delta(), that timestamp is used for the next block, and is then discarded (and will not be used by subsequent blocks).

  2. If the next block's timestamp was not set explicitly, and there is a previous block, the next block's timestamp is the timestamp of the previous block plus the block interval (rell.test.block_interval, which can be set with rell.test.set_block_interval()).

  3. If the next block's timestamp was not set explicitly, and there is no previous block, the timestamp of the next (and first) block will be 2020-01-01 00:00:00 UTC.

Link copied to clipboard
type failure

A test failure, with a message that gives the reason for the failure.

Link copied to clipboard
struct keypair

A keypair for testing only.

Not secure - unsuitable for production usage.

Link copied to clipboard
type op

A test operation call, consisting of a name (an operation's mount name), and a list of arguments (a list<gtv>).

Link copied to clipboard
type tx

A test transaction builder; i.e. a builder for test transactions that comprise blockchain blocks.

A test transaction consists of a list of test operation calls, and a list of signing keypairs. The test transaction builder type has functions that facilitate straightforward transaction construction by passing operations and keys in various formats.

Properties

Link copied to clipboard

The time interval that will be used to determine the time of the next block to be built.

The next block to be built will have a timestamp equal to rell.test.last_block_time + rell.test.block_interval unless it is explicitly set with rell.test.set_next_block_time() or rell.test.set_next_block_time_delta().

Defaults to 10000 (10 seconds).

Can be modified with rell.test.set_block_interval().

Link copied to clipboard

The test keypair used to sign all blocks built in the test context.

Not secure - unsuitable for production usage.

Link copied to clipboard

The default value for the time interval between each block in the blockchain, in milliseconds. Equal to 10000 (10 seconds).

Link copied to clipboard

The default value for the timestamp of the first block in the blockchain, in milliseconds. Equal to 2020-01-01 00:00:00 UTC, or 1577836800000.

This is a Unix epoch timestamp, i.e. the number of milliseconds that have elapsed since midnight on 1st January 1970.

Link copied to clipboard

The timestamp of the most recently built block in the blockchain, in milliseconds.

This is a Unix epoch timestamp, i.e. the number of milliseconds that have elapsed since midnight on 1st January 1970.

Link copied to clipboard

The timestamp of the most recently built block in the blockchain, in milliseconds.

If there are no blocks in the blockchain (i.e. if the first block in the blockchain has yet to be built), this is null.

If a value is present, it is a Unix epoch timestamp, i.e. the number of milliseconds that have elapsed since midnight on 1st January 1970.

Link copied to clipboard

The timestamp that the next block will have, once built, in milliseconds.

Equivalent to rell.test.last_block_time + rell.test.block_interval (assuming there is at least one block in the blockchain).

This is a Unix epoch timestamp, i.e. the number of milliseconds that will have elapsed since midnight on 1st January 1970.

Functions

Link copied to clipboard
function <T> assert_equals(actual: T, expected: T)

Assert two values are equal.

Link copied to clipboard
function assert_events(expected: (text, gtv)...)

Assert that the given events were emitted during the construction of the last block, in the specified order.

Events are emitted in application code using op_context.emit_event().

Example - single event:

Application code
operation main() {
op_context.emit_event("my_message_type", "my_data".to_gtv());
}
Test code
function test_main() {
main().run();

// Assertion passes
rell.test.assert_events(("my_message_type", "my_data".to_gtv()));
}

function test_main_bad_1() {
main().run();

// Assertion fails - wrong message type
rell.test.assert_events(("other_message_type", "my_data".to_gtv()));
}

function test_main_bad_2() {
main().run();

// Assertion fails - wrong message content
rell.test.assert_events(("my_message_type", "other_data".to_gtv()));
}

Example - multiple events:

Application code
operation main() {
op_context.emit_event("my_message_type", "my_data".to_gtv());
op_context.emit_event("other_message_type", "other_data".to_gtv());
}
Test code
function test_main() {
main().run();

// Assertion passes
rell.test.assert_events(
("my_message_type", "my_data".to_gtv()),
("other_message_type", "other_data".to_gtv())
);
}

function test_main_bad() {
main().run();

// Assertion fails - event order incorrect
rell.test.assert_events(
("other_message_type", "other_data".to_gtv()),
("my_message_type", "my_data".to_gtv())
);
}

To assert a subset of events, or to assert independently of event order, use rell.test.get_events() and make assertions over elements of the returned list.

Link copied to clipboard
function <T> assert_fails(fn: () -> T): rell.test.failure

Asserts a function fails; i.e. throws an exception.

Example

Application code
// This will throw a exception.
function bad(): integer {
return [0][1];
}
Test code
// This test will pass.
function test_bad() {
rell.test.assert_fails(bad(*));
}
function <T> assert_fails(expected_message: text, fn: () -> T): rell.test.failure

Asserts a function fails; i.e. throws an exception; with a given exception message.

Verifies that the given exception message is a substring of the exception thrown by the given function (if thrown).

Example

Application code
// This will throw a exception.
function bad(): integer {
return [0][1];
}
Test code
// This test will pass.
function test_bad() {
rell.test.assert_fails("out of bounds", bad(*));
}
Link copied to clipboard
function assert_false(actual: boolean)

Assert a value is false.

Prefer other assertion functions where possible, as they provide better error messages.

Link copied to clipboard
function <T: -comparable> assert_ge(actual: T, least_expected: T)

Assert that a value is greater than or equal to a given lower bound.

Link copied to clipboard
function <T: -comparable> assert_ge_le(actual: T, least_expected: T, greatest_expected: T)

Assert that a value falls within given bounds.

Specifically, assert that the value is greater than or equal to a lower bound, and less than or equal to an upper bound.

Link copied to clipboard
function <T: -comparable> assert_ge_lt(actual: T, least_expected: T, greatest_expected: T)

Assert that a value falls within given bounds.

Specifically, assert that the value is greater than or equal to a lower bound, and less than an upper bound.

Link copied to clipboard
function <T: -comparable> assert_gt(actual: T, least_expected: T)

Assert that a value is greater than a given lower bound.

Link copied to clipboard
function <T: -comparable> assert_gt_le(actual: T, least_expected: T, greatest_expected: T)

Assert that a value falls within given bounds.

Specifically, assert that the value is greater than a lower bound, and less than or equal to an upper bound.

Link copied to clipboard
function <T: -comparable> assert_gt_lt(actual: T, least_expected: T, greatest_expected: T)

Assert that a value falls within given bounds.

Specifically, assert that the value is greater than a lower bound, and less than an upper bound.

Link copied to clipboard
function <T: -comparable> assert_le(actual: T, greatest_expected: T)

Assert that a value is less than or equal to a given upper bound.

Link copied to clipboard
function <T: -comparable> assert_lt(actual: T, greatest_expected: T)

Assert that a value is less than a given upper bound.

Link copied to clipboard
function <T> assert_not_equals(actual: T, illegal: T)

Assert two values are unequal.

Link copied to clipboard
function <T: -any> assert_not_null(actual: T?)

Assert a value is not null.

Link copied to clipboard
function assert_null(actual: anything)

Assert a value is null.

Link copied to clipboard
function assert_true(actual: boolean)

Assert a value is true.

Prefer other assertion functions where possible, as they provide better error messages.

Link copied to clipboard
function get_events(): list<(text, gtv)>

Get all events that were emitted during the construction of the last block.

Events are emitted in application code using op_context.emit_event().

Example:

Application code
op_context.emit_event("my_message_type", "my_gtv_data".to_gtv());
op_context.emit_event("my_other_message_type", "my_gtv_data".to_gtv());
op_context.emit_event("my_another_message_type", "my_gtv_data".to_gtv());
Test code
// returns: [(my_message_type,"my_gtv_data"), (my_other_message_type,"my_gtv_data"), (my_another_message_type,"my_gtv_data")]
return rell.test.get_events();
Link copied to clipboard
function nop(): rell.test.op

Create a no-op test operation call.

The zero-argument rell.test.nop() is effectively an alias of rell.test.nop(x: integer) where a unique integer argument x is passed each time, serving the purpose of distinguishing transactions that are identical except for the presence of a nop call.

Example:

Illegal
rell.test.tx().op(my_op).run();
rell.test.tx().op(my_op).run(); // Not allowed; all transactions must be unique!
Legal
// Ok, the transactions are distinct since each nop automatically uses a different nonce.
rell.test.tx().op(my_op).op(rell.test.nop()).run();
rell.test.tx().op(my_op).op(rell.test.nop()).run();

Create a no-op test operation call.

Serves the purpose of distinguishing transactions that are identical except for the presence of a nop call.

rell.test.nop(x) is equivalent to rell.test.op('nop', x.to_gtv()), which is a test operation call to the predefined operation:

operation nop(v: gtv) {}

Example:

Illegal
rell.test.tx().op(my_op).op(rell.test.nop(x'00')).run();
rell.test.tx().op(my_op).op(rell.test.nop(x'00')).run(); // Not allowed; all transactions must be unique!
Legal
rell.test.tx().op(my_op).op(rell.test.nop(x'00')).run();
rell.test.tx().op(my_op).op(rell.test.nop(x'01')).run(); // Ok, since the transactions are distinct.
function nop(x: integer): rell.test.op

Create a no-op test operation call.

Serves the purpose of distinguishing transactions that are identical except for the presence of a nop call.

rell.test.nop(x) is equivalent to rell.test.op('nop', x.to_gtv()), which is a test operation call to the predefined operation:

operation nop(v: gtv) {}

Example:

Illegal
rell.test.tx().op(my_op).op(rell.test.nop(0)).run();
rell.test.tx().op(my_op).op(rell.test.nop(0)).run(); // Not allowed; all transactions must be unique!
Legal
rell.test.tx().op(my_op).op(rell.test.nop(0)).run();
rell.test.tx().op(my_op).op(rell.test.nop(1)).run(); // Ok, since the transactions are distinct.
function nop(x: text): rell.test.op

Create a no-op test operation call.

Serves the purpose of distinguishing transactions that are identical except for the presence of a nop call.

rell.test.nop(x) is equivalent to rell.test.op('nop', x.to_gtv()), which is a test operation call to the predefined operation:

operation nop(v: gtv) {}

Example:

Illegal
rell.test.tx().op(my_op).op(rell.test.nop("a")).run();
rell.test.tx().op(my_op).op(rell.test.nop("a")).run(); // Not allowed; all transactions must be unique!
Legal
rell.test.tx().op(my_op).op(rell.test.nop("a")).run();
rell.test.tx().op(my_op).op(rell.test.nop("z")).run(); // Ok, since the transactions are distinct.
Link copied to clipboard
function set_block_interval(interval: integer): integer

Set the time interval between future blocks in the blockchain, in milliseconds.

If the timestamp for the next block has been explicitly set by calling rell.test.set_next_block_time() or `rell.test.set_next_block_time_delta(), the new interval does not take effect until after the next block.

Link copied to clipboard

Set the timestamp that the next block will have, once built, in milliseconds.

time is a Unix epoch timestamp, i.e. the number of milliseconds that will have elapsed since midnight on 1st January 1970.

Link copied to clipboard

Set the timestamp that the next block will have, once built, relative to the previous block, in milliseconds.

Calling rell.time.set_next_block_time_delta(x) means the next block will have timestamp x milliseconds after the timestamp of the previous block.

rell.test.set_next_block_time_delta(delta) is equivalent to rell.test.set_next_block_time(rell.test.last_block_time + delta) if there is a previous block. Otherwise, this does nothing.