Liquidity Extensions
The first step is to declare the Liquidity extensions we need. Let's create a tests/techel.liq to write our extensions into:
external get_balance :
[%stack: address] -> [%stack: tez]
= "GET_BALANCE"
external get_storage :
[%type: 'a] -> [%stack: address] -> [%stack: 'a option]
= "GET_STORAGE"
external apply_operations :
[%stack: operation list] -> unit
= "APPLY_OPERATIONS"
external start_set_source :
[%stack: address] -> unit
= "SET_SOURCE { #"
external end_set_source :
unit -> unit
= "}"
external must_fail :
[%stack: string option] -> [%stack: operation] -> [%stack: operation]
= "MUST_FAIL string"
It is not crucial to understand these rules precisely, only the power they give us. And that power is the following functions. What they do precisely will become clear when we use them later on.
get_balance address
: takes an address as parameter, and returns the balance of the contract at that addressget_storage [%type: 'g] address
: takes a type and an address as parameter, and returnsSome
of the storage of the contract at that address, if it has type'g
None
otherwise
apply_operations ops
: takes a list of operations and applies them right awaystart_set_source address
andend_set_source ()
: a very, very dirty hack to define a scope where all operations created appear to have been created by whatever is ataddress
must_fail msg_opt op
: tells techelson that the operationop
must fail; this succeeds iffop
fails andmsg_opt
isNone
, ormsg_opt
isSome msg
andop
failed precisely with stringmsg
.
Thanks to Liquidity's file import mechanism, we can use these functions in any Liquidity file
test.liq
with Techel.get_balance
, Techel.get_storage
etc. by simply calling Liquidity as
follows:
$ liquidity tests/techel.liq test.liq
NB: you only need to write
tests/techel.liq
once, and make sure you pass it to Liquidity when compiling your testcases, as intest.sh
below.
So let's fill in the test.sh
file so that it runs our tests. It takes the path to our (future)
Liquidity test file(s) as argument, and compiles it/them along with all the contracts in
contracts/
and the extensions we just defined. So, given some file tests/test.liq
, the script
- generates
tests/test.liq.techel
: contains the testcase and the contract(s) to test, and - runs techelson on
tests/test.liq.techel
.
#! /bin/bash
set -e
test_file="$1"
this_script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
techel_lib="$this_script_dir/tests/techel.liq"
# List of all the contracts.
contracts=""
for file in `find "$this_script_dir/contracts" -iname "*.liq"` ; do
contracts="$contracts $file"
done
# File liquidity will compile to.
target="$test_file.techel"
echo "Compiling $test_file..."
echo
liquidity --no-annot --no-simplify --no-peephole $techel_lib $contracts -o $target $test_file
echo
# Running techelson on the target.
echo "Running test $target"
echo
techelson $target
Warning: function
start_set_source
uses a dirty hack so that it works as a Liquidity extension (similar to a SQL injection). This is a temporary solution, eventually this hack will not be necessary.