You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#!/usr/bin/env bash-shlib # -*- mode: shell-script -*-
include shunit
depends sed grep git mkdir readlink
export -f matches export grep
tmp=/tmp tprog="../bin/compose" tprog=$(readlink -f $tprog)
export PATH=".:$PATH" short_tprog=$(basename "$tprog")
## ## Convenience function ##
init_test() { test_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) cd "$test_tmpdir" export CACHEDIR="$test_tmpdir/.cache" export VARDIR="$test_tmpdir/.var" mkdir -p "$CACHEDIR" }
tear_test() { rm -rf "$test_tmpdir" }
## ## Tests ##
## # Checking arguments test_calling_sourcing() {
assert_list <<EOF
### Calling and sourcing
## -- call of '$short_tprog' with no arg fails (errlvl != 0)
! "$tprog"
## -- source '$short_tprog' should not fail
. "$tprog"
EOF
}
test_mixin_functions() {
init_test
assert_list <<EOF
### Testing get_docker_compose_mixin_from_metadata
## -- Empty metadata.yml
export CHARM_STORE=$test_tmpdir mkdir $test_tmpdir/testcharm cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml
EOF2
. "$tprog"
_setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" expected='\ labels: - compose.charm=testcharm' [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- volumes
export CHARM_STORE=$test_tmpdir export CONFIGSTORE=/tmp/CONFIG export DATASTORE=/tmp/DATA mkdir -p $test_tmpdir/testcharm cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml data-resources: - /a config-resources: - /b host-resources: - /tmp:/tmp EOF2
. "$tprog"
_setup_state_dir out=\$(get_docker_compose_mixin_from_metadata testcharm) || exit 1 expected="\ labels: - compose.charm=testcharm volumes: - /tmp/DATA/testcharm/a:/a:rw - /tmp/CONFIG/testcharm/b:/b:rw - /tmp:/tmp:rw"
[ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- docker-compose
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml docker-compose: volumes: - /any:/vol entrypoint: any EOF2
. "$tprog"
_setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ entrypoint: any labels: - compose.charm=testcharm volumes: - /any:/vol" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- image
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml docker-image: toto EOF2
. "$tprog"
_setup_state_dir
out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ image: toto labels: - compose.charm=testcharm"
[ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- build
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm/build cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml # XXX new content to invalidate cache EOF2
. "$tprog"
_setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ build: $test_tmpdir/testcharm/build labels: - compose.charm=testcharm"
[ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- subordinate with image
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml subordinate: true docker-image: toto EOF2
. "$tprog"
_setup_state_dir ! get_docker_compose_mixin_from_metadata testcharm
## -- subordinate with build subdir
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm/build cat <<EOF2 > $test_tmpdir/testcharm/metadata.yml subordinate: true EOF2
. "$tprog"
_setup_state_dir ! get_docker_compose_mixin_from_metadata testcharm
EOF tear_test }
function test_merge_yaml {
init_test
assert_list <<EOF
### Testing merge_yaml
## -- basic example
. "$tprog"
_setup_state_dir test "\$(merge_yaml <(echo " a: b: 1 c: - d - e ") <(echo " a: y: 3 b: 2 c: - new x: 1 "))" == "a: b: 2 c: - d - e - new y: 3 x: 1"
## -- Nothing
. "$tprog"
_setup_state_dir test -z "\$(merge_yaml <(echo) <(echo))"
## -- No variable expansions
. "$tprog"
_setup_state_dir
out=\$(merge_yaml <(echo '- \$\$') <(echo "- a")) test "\$out" == '- \$\$ - a' || { echo -e "** merge_yaml:\n\$out"; exit 1 }
EOF
}
function test_merge_yaml_str {
init_test
assert_list <<EOF
### Testing merge_yaml_str
## -- basic example
. "$tprog"
_setup_state_dir test "\$(merge_yaml_str " a: b: 1 c: - d - e " " a: y: 3 b: 2 c: - new x: 1 ")" == "a: b: 2 c: - d - e - new y: 3 x: 1"
## -- Nothing
. "$tprog"
_setup_state_dir test -z "\$(merge_yaml_str "" "")"
## -- No variable expansions
. "$tprog"
_setup_state_dir
out=\$(merge_yaml_str '- \$\$' "- a") test "\$out" == '- \$\$ - a' || { echo -e "** merge_yaml_str:\n\$out"; exit 1 }
EOF }
function test_merge_yaml_str {
init_test
assert_list <<EOF
### Testing merge_yaml_str
## -- basic example
. "$tprog"
_setup_state_dir test "\$(merge_yaml_str " a: b: 1 c: - d - e " " a: y: 3 b: 2 c: - new x: 1 ")" == "a: b: 2 c: - d - e - new y: 3 x: 1"
## -- Nothing
. "$tprog"
_setup_state_dir test -z "\$(merge_yaml_str "" "")"
## -- No variable expansions
. "$tprog"
_setup_state_dir
out=\$(merge_yaml_str '- \$\$' "- a") test "\$out" == '- \$\$ - a' || { echo -e "** merge_yaml_str:\n\$out"; exit 1 }
EOF }
function test_yaml_key_val_str {
init_test
assert_list <<EOF
### Testing yaml_key_val_str
## -- basic example
. "$tprog"
_setup_state_dir out="\$(yaml_key_val_str "a" "data: | hello multi line b: x: 1 y: 2 ")"
test "\$out" == "a: data: 'hello
multi
line
' b: x: 1 y: 2" || { echo -e "** yaml_key_val_str:\n\$out" exit 1 }
EOF }
test_get_compose_service_def() {
init_test
assert_list <<EOF
### Testing get_compose_service_def
## -- Simple (no docker-compose)
export CHARM_STORE=$test_tmpdir mkdir $test_tmpdir/www touch $test_tmpdir/www/metadata.yml
. "$tprog"
_setup_state_dir out="\$(get_compose_service_def www)" test "\$out" == "charm: www" || { echo OUTPUT: echo "\$out" false }
## -- Simple (no docker-compose, no charm dir)
export CHARM_STORE=$test_tmpdir
. "$tprog"
_setup_state_dir ! get_compose_service_def www_not_existent
## -- Simple (compose is self sufficient)
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/www
cat <<EOF2 > $test_tmpdir/compose.yml toto: charm: www blabla: xxx EOF2
. "$tprog"
_setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml out="\$(get_compose_service_def toto)" test "\$out" == "charm: www blabla: xxx" || { echo -e "** get_compose_service_def toto:\n\$out" exit 1 }
## -- Addition of default charm
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/www
cat <<EOF2 > $test_tmpdir/compose.yml www: blabla: xxx EOF2
. "$tprog"
_setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml test "\$(get_compose_service_def www)" == "blabla: xxx charm: www"
EOF }
## ## ## function test_get_master_service_for_service() {
init_test
assert_list <<EOF
### Testing get_master_service_for_service
## -- Simple (no subordinate)
export CHARM_STORE=$test_tmpdir mkdir $test_tmpdir/www cat <<EOF2 > $test_tmpdir/www/metadata.yml EOF2
. "$tprog"
_setup_state_dir test "\$(get_master_service_for_service www)" == "www"
## -- subordinate
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} touch $test_tmpdir/mysql/metadata.yml cat <<EOF2 > $test_tmpdir/www/metadata.yml subordinate: true requires: a-label-for-relation: interface: a-name-relation scope: container
EOF2
cat <<EOF2 > $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2
. "$tprog"
_setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml test "\$(get_master_service_for_service www)" == "mysql" EOF
}
## ## ## function test_get_docker_compose_service_mixin() {
init_test
assert_list <<EOF
### Testing get_docker_compose_service_mixin
## -- Simple (no compose, no subordinate)
export CHARM_STORE=$test_tmpdir mkdir $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2
. "$tprog"
_setup_state_dir
out=\$(_get_docker_compose_service_mixin www | shyaml get-value www.volumes) [[ "\$out" == "\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" ]] || { echo -e "** _get_docker_compose_service_mixin www:\n\$out"; exit 1 }
## -- Simple (compose, but no subordinate)
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2
touch $test_tmpdir/mysql/metadata.yml
cat <<EOF2 > $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2
. "$tprog"
_setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml
out="\$(_get_docker_compose_service_mixin www)" || exit 1 [ "\$out" == "www: labels: - compose.service=www - compose.master-service=www - compose.project=\$(basename "$test_tmpdir") - compose.charm=www links: - mysql volumes: - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" ] || { echo -e "OUT:\n\$out" exit 1 }
## -- compose, subordinate
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b requires: a-name-relation: interface: a-name-relation scope: container EOF2
cat <<EOF2 > $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2
. "$tprog"
_setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml out="\$(_get_docker_compose_service_mixin www)" || exit 1 expected="mysql: labels: - compose.service=www - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=www volumes: - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } EOF }
function test_get_docker_compose {
init_test
assert_list <<EOF
### Testing get_docker_compose
## -- no docker-compose
export CHARM_STORE=$test_tmpdir mkdir $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2
. "$tprog"
_setup_state_dir out=\$(get_docker_compose www) echo "OUT:" echo "\$out"
out=\$(echo "\$out" | shyaml get-value services.www.volumes) echo "OUT volumes:" echo "\$out" test "\$out" == "\\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw"
## -- simple with docker-compose
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2
cat <<EOF2 > $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d EOF2
cat <<EOF2 > $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata EOF2
. "$tprog"
COMPOSE_YML_FILE=$test_tmpdir/compose.yml
_setup_state_dir
out=\$(get_docker_compose www | shyaml get-value services.www.volumes) test "\$out" == "\\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" || { echo -e "** get_docker_compose www:\n\$out" exit 1 }
out=\$(get_docker_compose_links web_site | shyaml get-value web_site.links) test "\$out" == "- mysql" || { echo -e "** get_docker_compose_links web_site:\n\$out" exit 1 }
out=\$(get_docker_compose web_site | shyaml get-value services) expected="\ mysql: labels: - compose.service=mysql - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=mysql volumes: - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw web_site: labels: - compose.service=web_site - compose.master-service=web_site - compose.project=$(basename "$test_tmpdir") - compose.charm=www links: - mysql volumes: - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw" test "\$out" == "\$expected" || { echo -e "** get_docker_compose web_site:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
## -- subordinate
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b requires: my-db-connection: interface: db-connection scope: container EOF2
cat <<EOF2 > $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d EOF2
cat <<EOF2 > $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata
EOF2
. "$tprog"
COMPOSE_YML_FILE=$test_tmpdir/compose.yml
_setup_state_dir
# should fail because of missing relations ! get_docker_compose www || exit 1
# volumes gets mixed out="\$(get_docker_compose web_site | shyaml get-value services.mysql.volumes)"
test "\$out" == "\ - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw" || { echo -e "OUT:\n\$out" exit 1 }
## -- subordinate with complex features
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b requires: my-db-connection: interface: db-connection scope: container docker-compose: volumes: - /special-volume-from-www:/special-volume-from-www EOF2
cat <<EOF2 > $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d docker-compose: entrypoint: custom-entrypoint volumes: - /special-volume-from-mysql:/special-volume-from-mysql EOF2
cat <<EOF2 > $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata
EOF2
. "$tprog"
COMPOSE_YML_FILE=$test_tmpdir/compose.yml
_setup_state_dir
# should fail because of missing relations #! get_docker_compose www || exit 1
# volumes gets mixed out="\$(get_docker_compose web_site | shyaml get-value services.mysql)" expected="\ entrypoint: custom-entrypoint labels: - compose.service=web_site - compose.charm=www - compose.service=mysql - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=mysql volumes: - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw - /special-volume-from-www:/special-volume-from-www - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw - /special-volume-from-mysql:/special-volume-from-mysql"
test "\$out" == "\$expected" || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 }
EOF tear_test
}
## XXXvlab: only broken due to Wrap being used for relations
# function test_run_service_relations {
# init_test
# assert_list <<EOF
# ### Testing run_service_relations
# ## -- no docker-compose
# export CHARM_STORE=$test_tmpdir # mkdir $test_tmpdir/{www,mysql} # cat <<EOF2 > $test_tmpdir/www/metadata.yml # data-resources: # - /tmp/a # config-resources: # - /tmp/b # EOF2
# . "$tprog"
# _setup_state_dir # echo "Docker Compose:" # get_docker_compose www # echo "Run Service relations:" # _run_service_relation() { # echo "\$FUNCNAME: received $*" # } # out=\$(run_service_relations www) # test -z "\$out"
# ## -- simple with docker-compose
# export CHARM_STORE=$test_tmpdir # mkdir -p $test_tmpdir/{www,mysql} # cat <<EOF2 > $test_tmpdir/www/metadata.yml # data-resources: # - /tmp/a # config-resources: # - /tmp/b # EOF2
# cat <<EOF2 > $test_tmpdir/mysql/metadata.yml # data-resources: # - /tmp/c # config-resources: # - /tmp/d # EOF2
# cat <<EOF2 > $test_tmpdir/compose.yml # web_site: # charm: www # relations: # db-connection: # mysql: # user: toto # dbname: tata
# EOF2
# . "$tprog"
# COMPOSE_YML_FILE=$test_tmpdir/compose.yml
# _setup_state_dir
# _setup_state_dir # echo "Docker Compose:" # get_docker_compose web_site # echo "Run Service relations:"
# _run_service_relation() { # echo "\$FUNCNAME \$2 <-- \$1 --> \$3" # } # export -f _run_service_relation
# out=\$(run_service_relations www) # test -z "\$out" || exit 1
# out=\$(run_service_relations web_site) # echo "OUT: \$out" # test "\$out" == "_run_service_relation web_site <-- db-connection --> mysql"
# ## -- subordinate
# export CHARM_STORE=$test_tmpdir # mkdir -p $test_tmpdir/{www,mysql} # cat <<EOF2 > $test_tmpdir/www/metadata.yml # subordinate: true # data-resources: # - /tmp/a # config-resources: # - /tmp/b # requires: # my-db-connection: # interface: db-connection # scope: container # EOF2
# cat <<EOF2 > $test_tmpdir/mysql/metadata.yml # data-resources: # - /tmp/c # config-resources: # - /tmp/d # EOF2
# cat <<EOF2 > $test_tmpdir/compose.yml # web_site: # charm: www # relations: # db-connection: # mysql: # user: toto # dbname: tata
# EOF2
# . "$tprog"
# COMPOSE_YML_FILE=$test_tmpdir/compose.yml
# _setup_state_dir # echo "Docker Compose:" # get_docker_compose web_site # echo "Run Service relations:"
# _run_service_relation() { # echo "\$FUNCNAME \$2 <-- \$1 --> \$3" # } # export -f _run_service_relation
# out=\$(run_service_relations www) # test -z "\$out" || exit 1
# out=\$(run_service_relations web_site) # echo "\$out" # test "\$out" == "_run_service_relation web_site <-- db-connection --> mysql"
# EOF # tear_test
# }
function test_get_docker_compose_2() { init_test
assert_list <<EOF
## -- Simple
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql,pg} touch $test_tmpdir/www/metadata.yml touch $test_tmpdir/mysql/metadata.yml
cat <<EOF2 > $test_tmpdir/compose.yml app: charm: app relations: web-proxy: www: user: toto db: mysql EOF2
. "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir
out=\$(get_docker_compose_links "app") test "\$out" == "app: links: - www - mysql" || { echo -e "** get_docker_compose_links:\n\$out"; exit 1 }
## -- reverse-tech-dep
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml provides: web-proxy: tech-dep: reversed EOF2 touch $test_tmpdir/mysql/metadata.yml
cat <<EOF2 > $test_tmpdir/compose.yml web_site: charm: mysql relations: web-proxy: www: user: toto EOF2
. "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir
out=\$(get_charm_relation_def "www" "web-proxy") || exit 1 test "\$out" == "tech-dep: reversed" || { echo -e "** get_charm_relation_def:\n\$out"; exit 1 }
out=\$(get_charm_tech_dep_orientation_for_relation "www" "web-proxy") test "\$out" == "reversed" || { echo -e "** get_charm_tech_dep_orientation_for_relation:\n\$out"; exit 1 }
out=\$(get_docker_compose_links "web_site") expected="www: links: - web_site" test "\$out" == "\$expected" || { echo -e "** get_docker_compose_links:\n\$out\nExpected:\n\$expected"; exit 1 }
out=\$(get_docker_compose web_site | shyaml get-value services.www.links) test "\$out" == "- web_site" || { echo -e "** get_docker_compose:\n\$out"; exit 1 }
EOF
tear_test }
function test_compose_config {
init_test
export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat <<EOF2 > $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b requires: my-db-connection: interface: db-connection scope: container docker-compose: volumes: - /special-volume-from-www:/special-volume-from-www EOF2
cat <<EOF2 > $test_tmpdir/mysql/metadata.yml docker-image: docker.0k.io/mysql data-resources: - /tmp/c config-resources: - /tmp/d docker-compose: entrypoint: custom-entrypoint volumes: - /special-volume-from-mysql:/special-volume-from-mysql EOF2
cat <<EOF2 > $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata
EOF2
assert_list <<EOF
### Testing get_compose_config - syntax validation from docker-compose
## -- no service provided
cd "$test_tmpdir"
export DISABLE_SYSTEM_CONFIG_FILE=true "$tprog" config
## -- simple service provided
cd "$test_tmpdir"
export DISABLE_SYSTEM_CONFIG_FILE=true "$tprog" config mysql
## -- complex service provided
cd "$test_tmpdir"
export DISABLE_SYSTEM_CONFIG_FILE=true "$tprog" config web_site
EOF
tear_test }
continue_on_error="0" testbench $*
|