From 7515aec87f1b33c57d4da722a6d1cedd4c1b0c21 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sun, 16 Oct 2016 15:08:38 +0200 Subject: [PATCH] Add basic sharness tests (#504) * test: add sharness support files * test: add ipfs-test-lib.sh * test/sharness: unignore 'lib' directory below * test/sharness: add lib/test-lib-hashes.sh * test/sharness: add lib/iptb-lib.sh * test/sharness: add lib/test-lib.sh * test: ignore bin/ * sharness: improve the Makefile * sharness: add t0010-basic-commands.sh * test-lib: properly check the 'ipfs' tool we use * Add Makefile at the root This Makefile is just to launch Sharness tests for now. * .travis: add 'make test' script --- .travis.yml | 2 +- Makefile | 23 ++ test/.gitignore | 1 + test/ipfs-test-lib.sh | 107 +++++++ test/sharness/.gitignore | 4 + test/sharness/Makefile | 53 ++++ test/sharness/lib/install-sharness.sh | 60 ++++ test/sharness/lib/iptb-lib.sh | 39 +++ test/sharness/lib/test-lib-hashes.sh | 7 + test/sharness/lib/test-lib.sh | 384 ++++++++++++++++++++++++++ test/sharness/t0000-sharness.sh | 32 +++ test/sharness/t0010-basic-commands.sh | 29 ++ 12 files changed, 740 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 test/.gitignore create mode 100644 test/ipfs-test-lib.sh create mode 100644 test/sharness/.gitignore create mode 100644 test/sharness/Makefile create mode 100755 test/sharness/lib/install-sharness.sh create mode 100644 test/sharness/lib/iptb-lib.sh create mode 100644 test/sharness/lib/test-lib-hashes.sh create mode 100644 test/sharness/lib/test-lib.sh create mode 100755 test/sharness/t0000-sharness.sh create mode 100755 test/sharness/t0010-basic-commands.sh diff --git a/.travis.yml b/.travis.yml index 68f6dd805b..c15059ec44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - npm run lint - npm test - npm run coverage - + - make test before_script: - export DISPLAY=:99.0 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..fc242749d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +all: help + +test: test_expensive + +test_short: test_sharness_short + +test_expensive: test_sharness_expensive + +test_sharness_short: + $(MAKE) -j1 -C test/sharness/ + +test_sharness_expensive: + TEST_EXPENSIVE=1 $(MAKE) -j1 -C test/sharness/ + +help: + @echo 'TESTING TARGETS:' + @echo '' + @echo ' test - Run expensive tests' + @echo ' test_short - Run short tests and sharness tests' + @echo ' test_expensive - Run a few extras' + @echo ' test_sharness_short' + @echo ' test_sharness_expensive' + @echo '' diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000000..ae3c172604 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/test/ipfs-test-lib.sh b/test/ipfs-test-lib.sh new file mode 100644 index 0000000000..bba49febbe --- /dev/null +++ b/test/ipfs-test-lib.sh @@ -0,0 +1,107 @@ +# Generic test functions for ipfs cli tests + +# Quote arguments for sh eval +shellquote() { + _space='' + for _arg + do + # On Mac OS, sed adds a newline character. + # With a printf wrapper the extra newline is removed. + printf "$_space'%s'" "$(printf "%s" "$_arg" | sed -e "s/'/'\\\\''/g;")" + _space=' ' + done + printf '\n' +} + +# Echo the args, run the cmd, and then also fail, +# making sure a test case fails. +test_fsh() { + echo "> $@" + eval $(shellquote "$@") + echo "" + false +} + +# Same as sharness' test_cmp but using test_fsh (to see the output). +# We have to do it twice, so the first diff output doesn't show unless it's +# broken. +test_cmp() { + diff -q "$@" >/dev/null || test_fsh diff -u "$@" +} + +# Same as test_cmp above, but we sort files before comparing them. +test_sort_cmp() { + sort "$1" >"$1_sorted" && + sort "$2" >"$2_sorted" && + test_cmp "$1_sorted" "$2_sorted" +} + +# Same as test_cmp above, but we standardize directory +# separators before comparing the files. +test_path_cmp() { + sed -e "s/\\\\/\//g" "$1" >"$1_std" && + sed -e "s/\\\\/\//g" "$2" >"$2_std" && + test_cmp "$1_std" "$2_std" +} + +# Docker + +# This takes a Dockerfile, and a build context directory +docker_build() { + docker build --rm -f "$1" "$2" +} + +# This takes an image as argument and writes a docker ID on stdout +docker_run() { + docker run -d "$1" +} + +# This takes a docker ID and a command as arguments +docker_exec() { + if test "$CIRCLE" = 1 + then + sudo lxc-attach -n "$(docker inspect --format '{{.Id}}' $1)" -- /bin/bash -c "$2" + else + docker exec -t "$1" /bin/bash -c "$2" + fi +} + +# This takes a docker ID as argument +docker_stop() { + docker stop "$1" +} + +# Test whether all the expected lines are included in a file. The file +# can have extra lines. +# +# $1 - Path to file with expected lines. +# $2 - Path to file with actual output. +# +# Examples +# +# test_expect_success 'foo says hello' ' +# echo hello >expected && +# foo >actual && +# test_cmp expected actual +# ' +# +# Returns the exit code of the command set by TEST_CMP. +test_includes_lines() { + sort "$1" >"$1_sorted" && + sort "$2" >"$2_sorted" && + comm -2 -3 "$1_sorted" "$2_sorted" >"$2_missing" && + [ ! -s "$2_missing" ] || test_fsh comm -2 -3 "$1_sorted" "$2_sorted" +} + +# Depending on GNU seq availability is not nice. +# Git also has test_seq but it uses Perl. +test_seq() { + test "$1" -le "$2" || return + i="$1" + j="$2" + while test "$i" -le "$j" + do + echo "$i" + i=$(expr "$i" + 1) + done +} diff --git a/test/sharness/.gitignore b/test/sharness/.gitignore new file mode 100644 index 0000000000..093372a920 --- /dev/null +++ b/test/sharness/.gitignore @@ -0,0 +1,4 @@ +!/lib/ +lib/sharness/ +test-results/ +trash directory.*.sh/ diff --git a/test/sharness/Makefile b/test/sharness/Makefile new file mode 100644 index 0000000000..7b6258e2a8 --- /dev/null +++ b/test/sharness/Makefile @@ -0,0 +1,53 @@ +# Run sharness tests +# +# Copyright (c) 2016 Christian Couder +# MIT Licensed; see the LICENSE file in this repository. +# +# NOTE: run with TEST_VERBOSE=1 for verbose sharness tests. + +T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) +LIBDIR = lib +SHARNESSDIR = sharness +AGGREGATE = $(LIBDIR)/$(SHARNESSDIR)/aggregate-results.sh + + +BINS = ../bin/ipfs + +all: aggregate + +help: + @echo "- use 'make' or 'make all' to run all the tests" + @echo "- use 'make deps' to create an 'ipfs' executable in ../bin" + @echo "- to run tests manually, make sure to include ../bin in your PATH" + +clean: clean-test-results + @echo "*** $@ ***" + -rm -rf ../bin/ipfs + +clean-test-results: + @echo "*** $@ ***" + -rm -rf test-results + +$(T): clean-test-results deps + @echo "*** $@ ***" + ./$@ + +aggregate: clean-test-results $(T) + @echo "*** $@ ***" + ls test-results/t*-*.sh.*.counts | $(AGGREGATE) + +deps: sharness $(BINS) curl + +sharness: + @echo "*** checking $@ ***" + lib/install-sharness.sh + +../bin/ipfs: + mkdir -p ../bin + cd ../bin && ln -s ../../src/cli/bin.js ipfs + +curl: + @which curl >/dev/null || (echo "Please install curl!" && false) + +.PHONY: all help clean clean-test-results $(T) aggregate deps sharness + diff --git a/test/sharness/lib/install-sharness.sh b/test/sharness/lib/install-sharness.sh new file mode 100755 index 0000000000..ecc5834e1a --- /dev/null +++ b/test/sharness/lib/install-sharness.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# install-sharness.sh +# +# Copyright (c) 2014 Juan Batiz-Benet +# Copyright (c) 2015 Christian Couder +# MIT Licensed; see the LICENSE file in this repository. +# +# This script checks that Sharness is installed in: +# +# $(pwd)/$clonedir/$sharnessdir/ +# +# where $clonedir and $sharnessdir are configured below. +# +# If Sharness is not installed, this script will clone it +# from $urlprefix (defined below). +# +# If Sharness is not uptodate with $version (defined below), +# this script will fetch and will update the installed +# version to $version. +# + +# settings +version=ecba410b0b58400dd6517cfa6594fdac243d9056 +urlprefix=https://github.com/chriscool/sharness.git +clonedir=lib +sharnessdir=sharness + +if test -f "$clonedir/$sharnessdir/SHARNESS_VERSION_$version" +then + # There is the right version file. Great, we are done! + exit 0 +fi + +die() { + echo >&2 "$@" + exit 1 +} + +checkout_version() { + git checkout "$version" || die "Could not checkout '$version'" + rm -f SHARNESS_VERSION_* || die "Could not remove 'SHARNESS_VERSION_*'" + touch "SHARNESS_VERSION_$version" || die "Could not create 'SHARNESS_VERSION_$version'" + echo "Sharness version $version is checked out!" +} + +if test -d "$clonedir/$sharnessdir/.git" +then + # We need to update sharness! + cd "$clonedir/$sharnessdir" || die "Could not cd into '$clonedir/$sharnessdir' directory" + git fetch || die "Could not fetch to update sharness" +else + # We need to clone sharness! + mkdir -p "$clonedir" || die "Could not create '$clonedir' directory" + cd "$clonedir" || die "Could not cd into '$clonedir' directory" + + git clone "$urlprefix" || die "Could not clone '$urlprefix'" + cd "$sharnessdir" || die "Could not cd into '$sharnessdir' directory" +fi + +checkout_version diff --git a/test/sharness/lib/iptb-lib.sh b/test/sharness/lib/iptb-lib.sh new file mode 100644 index 0000000000..15402dff86 --- /dev/null +++ b/test/sharness/lib/iptb-lib.sh @@ -0,0 +1,39 @@ +# iptb test framework +# +# Copyright (c) 2014, 2016 Jeromy Johnson, Christian Couder +# MIT Licensed; see the LICENSE file in this repository. + +export IPTB_ROOT="$(pwd)/.iptb" + +ipfsi() { + dir="$1" + shift + IPFS_PATH="$IPTB_ROOT/$dir" ipfs "$@" +} + +check_has_connection() { + node="$1" + ipfsi "$node" swarm peers >"swarm_peers_$node" && + grep "ipfs" "swarm_peers_$node" >/dev/null +} + +startup_cluster() { + num_nodes="$1" + bound=$(expr "$num_nodes" - 1) + + test_expect_success "start up nodes" ' + iptb start + ' + + test_expect_success "connect nodes to eachother" ' + iptb connect [1-$bound] 0 + ' + + for i in $(test_seq 0 "$bound") + do + test_expect_success "node $i is connected" ' + check_has_connection "$i" || + test_fsh cat "swarm_peers_$i" + ' + done +} diff --git a/test/sharness/lib/test-lib-hashes.sh b/test/sharness/lib/test-lib-hashes.sh new file mode 100644 index 0000000000..5b62000d0d --- /dev/null +++ b/test/sharness/lib/test-lib-hashes.sh @@ -0,0 +1,7 @@ +# this file defines several useful hashes used across the test codebase. +# thus they can be defined + changed in one place + +HASH_WELCOME_DOCS="QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG" +HASH_GATEWAY_ASSETS="QmXB7PLRWH6bCiwrGh2MrBBjNkLv3mY3JdYXCikYZSwLED" +HASH_HELP_PAGE="QmY5heUM5qgRubMDD1og9fhCPA6QdkMp3QCwd4s7gJsyE7" +HASH_EMPTY_DIR="QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh new file mode 100644 index 0000000000..bcc0ecfaed --- /dev/null +++ b/test/sharness/lib/test-lib.sh @@ -0,0 +1,384 @@ +# Test framework for go-ipfs +# +# Copyright (c) 2014 Christian Couder +# MIT Licensed; see the LICENSE file in this repository. +# +# We are using sharness (https://github.com/chriscool/sharness) +# which was extracted from the Git test framework. + +# add current directory to path, for ipfs tool. +BIN=$(cd .. && echo `pwd`/bin) +PATH=${BIN}:${PATH} + +# assert the `ipfs` we're using is the right one. +if test $(which ipfs) != ${BIN}/ipfs; then + echo >&2 "Cannot find the tests' local ipfs tool." + echo >&2 "Please check test and ipfs tool installation." + JS_BIN=$(dirname $(dirname "${BIN}"))"/src/cli/bin.js" + echo >&2 "For js-ipfs, look for a symlink from '${BIN}/ipfs' to '${JS_BIN}'." + echo >&2 "Use 'make' or 'make deps' as it should install this symlink." + exit 1 +fi + +# set sharness verbosity. we set the env var directly as +# it's too late to pass in --verbose, and --verbose is harder +# to pass through in some cases. +test "$TEST_VERBOSE" = 1 && verbose=t + +# source the common hashes first. +. lib/test-lib-hashes.sh + + +SHARNESS_LIB="lib/sharness/sharness.sh" + +. "$SHARNESS_LIB" || { + echo >&2 "Cannot source: $SHARNESS_LIB" + echo >&2 "Please check Sharness installation." + exit 1 +} + +# Please put go-ipfs specific shell functions below + +# grab + output options +test "$TEST_NO_FUSE" != 1 && test_set_prereq FUSE +test "$TEST_EXPENSIVE" = 1 && test_set_prereq EXPENSIVE +test "$TEST_NO_DOCKER" != 1 && type docker >/dev/null 2>&1 && test_set_prereq DOCKER + +TEST_OS=$(uname -s | tr [a-z] [A-Z]) + +# Set a prereq as error messages are often different on Windows/Cygwin +expr "$TEST_OS" : "CYGWIN_NT" >/dev/null || test_set_prereq STD_ERR_MSG + +if test "$TEST_VERBOSE" = 1; then + echo '# TEST_VERBOSE='"$TEST_VERBOSE" + echo '# TEST_NO_FUSE='"$TEST_NO_FUSE" + echo '# TEST_EXPENSIVE='"$TEST_EXPENSIVE" + echo '# TEST_OS='"$TEST_OS" +fi + +# source our generic test lib +. ../../ipfs-test-lib.sh + +# source iptb lib +. ../lib/iptb-lib.sh + +test_cmp_repeat_10_sec() { + for i in $(test_seq 1 100) + do + test_cmp "$1" "$2" >/dev/null && return + go-sleep 100ms + done + test_cmp "$1" "$2" +} + +test_run_repeat_60_sec() { + for i in $(test_seq 1 600) + do + (test_eval_ "$1") && return + go-sleep 100ms + done + return 1 # failed +} + +test_wait_output_n_lines_60_sec() { + for i in $(test_seq 1 600) + do + test $(cat "$1" | wc -l | tr -d " ") -ge $2 && return + go-sleep 100ms + done + actual=$(cat "$1" | wc -l | tr -d " ") + test_fsh "expected $2 lines of output. got $actual" +} + +test_wait_open_tcp_port_10_sec() { + for i in $(test_seq 1 100) + do + # this is not a perfect check, but it's portable. + # cant count on ss. not installed everywhere. + # cant count on netstat using : or . as port delim. differ across platforms. + echo $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 + if [ $(netstat -aln | egrep "^tcp.*LISTEN" | egrep "[.:]$1" | wc -l) -gt 0 ]; then + return 0 + fi + go-sleep 100ms + done + return 1 +} + + +# test_config_set helps us make sure _we really did set_ a config value. +# it sets it and then tests it. This became elaborate because ipfs config +# was setting really weird things and am not sure why. +test_config_set() { + + # grab flags (like --bool in "ipfs config --bool") + test_cfg_flags="" # unset in case. + test "$#" = 3 && { test_cfg_flags=$1; shift; } + + test_cfg_key=$1 + test_cfg_val=$2 + + # when verbose, tell the user what config values are being set + test_cfg_cmd="ipfs config $test_cfg_flags \"$test_cfg_key\" \"$test_cfg_val\"" + test "$TEST_VERBOSE" = 1 && echo "$test_cfg_cmd" + + # ok try setting the config key/val pair. + ipfs config $test_cfg_flags "$test_cfg_key" "$test_cfg_val" + echo "$test_cfg_val" >cfg_set_expected + ipfs config "$test_cfg_key" >cfg_set_actual + test_cmp cfg_set_expected cfg_set_actual +} + +test_init_ipfs() { + + + # we set the Addresses.API config variable. + # the cli client knows to use it, so only need to set. + # todo: in the future, use env? + + test_expect_success "ipfs init succeeds" ' + export IPFS_PATH="$(pwd)/.ipfs" && + ipfs init -b=1024 > /dev/null + ' + + test_expect_success "prepare config -- mounting and bootstrap rm" ' + mkdir mountdir ipfs ipns && + test_config_set Mounts.IPFS "$(pwd)/ipfs" && + test_config_set Mounts.IPNS "$(pwd)/ipns" && + test_config_set Addresses.API "/ip4/127.0.0.1/tcp/0" && + test_config_set Addresses.Gateway "/ip4/127.0.0.1/tcp/0" && + test_config_set --json Addresses.Swarm "[ + \"/ip4/0.0.0.0/tcp/0\" +]" && + ipfs bootstrap rm --all || + test_fsh cat "\"$IPFS_PATH/config\"" + ' + +} + +test_config_ipfs_gateway_writable() { + test_expect_success "prepare config -- gateway writable" ' + test_config_set --bool Gateway.Writable true || + test_fsh cat "\"$IPFS_PATH/config\"" + ' +} + +test_wait_for_file() { + loops=$1 + delay=$2 + file=$3 + fwaitc=0 + while ! test -f "$file" + do + if test $fwaitc -ge $loops + then + echo "Error: timed out waiting for file: $file" + return 1 + fi + + go-sleep $delay + fwaitc=`expr $fwaitc + 1` + done +} + +test_set_address_vars() { + daemon_output="$1" + + test_expect_success "set up address variables" ' + API_MADDR=$(cat "$IPFS_PATH/api") && + API_ADDR=$(convert_tcp_maddr $API_MADDR) && + API_PORT=$(port_from_maddr $API_MADDR) && + + GWAY_MADDR=$(sed -n "s/^Gateway (.*) server listening on //p" "$daemon_output") && + GWAY_ADDR=$(convert_tcp_maddr $GWAY_MADDR) && + GWAY_PORT=$(port_from_maddr $GWAY_MADDR) + ' + + if ipfs swarm addrs local >/dev/null 2>&1; then + test_expect_success "set swarm address vars" ' + ipfs swarm addrs local > addrs_out && + SWARM_MADDR=$(grep "127.0.0.1" addrs_out) && + SWARM_PORT=$(port_from_maddr $SWARM_MADDR) + ' + fi +} + +test_launch_ipfs_daemon() { + + args="$@" + + test "$TEST_ULIMIT_PRESET" != 1 && ulimit -n 1024 + + test_expect_success "'ipfs daemon' succeeds" ' + ipfs daemon $args >actual_daemon 2>daemon_err & + ' + + # wait for api file to show up + test_expect_success "api file shows up" ' + test_wait_for_file 20 100ms "$IPFS_PATH/api" + ' + + test_set_address_vars actual_daemon + + # we say the daemon is ready when the API server is ready. + test_expect_success "'ipfs daemon' is ready" ' + IPFS_PID=$! && + pollEndpoint -ep=/version -host=$API_MADDR -v -tout=1s -tries=60 2>poll_apierr > poll_apiout || + test_fsh cat actual_daemon || test_fsh cat daemon_err || test_fsh cat poll_apierr || test_fsh cat poll_apiout + ' +} + +do_umount() { + if [ "$(uname -s)" = "Linux" ]; then + fusermount -u "$1" + else + umount "$1" + fi +} + +test_mount_ipfs() { + + # make sure stuff is unmounted first. + test_expect_success FUSE "'ipfs mount' succeeds" ' + do_umount "$(pwd)/ipfs" || true && + do_umount "$(pwd)/ipns" || true && + ipfs mount >actual + ' + + test_expect_success FUSE "'ipfs mount' output looks good" ' + echo "IPFS mounted at: $(pwd)/ipfs" >expected && + echo "IPNS mounted at: $(pwd)/ipns" >>expected && + test_cmp expected actual + ' + +} + +test_launch_ipfs_daemon_and_mount() { + + test_init_ipfs + test_launch_ipfs_daemon + test_mount_ipfs + +} + +test_kill_repeat_10_sec() { + # try to shut down once + wait for graceful exit + kill $1 + for i in $(test_seq 1 100) + do + go-sleep 100ms + ! kill -0 $1 2>/dev/null && return + done + + # if not, try once more, which will skip graceful exit + kill $1 + go-sleep 1s + ! kill -0 $1 2>/dev/null && return + + # ok, no hope. kill it to prevent it messing with other tests + kill -9 $1 2>/dev/null + return 1 +} + +test_kill_ipfs_daemon() { + + test_expect_success "'ipfs daemon' is still running" ' + kill -0 $IPFS_PID + ' + + test_expect_success "'ipfs daemon' can be killed" ' + test_kill_repeat_10_sec $IPFS_PID + ' +} + +test_curl_resp_http_code() { + curl -I "$1" >curl_output || { + echo "curl error with url: '$1'" + echo "curl output was:" + cat curl_output + return 1 + } + shift && + RESP=$(head -1 curl_output) && + while test "$#" -gt 0 + do + expr "$RESP" : "$1" >/dev/null && return + shift + done + echo "curl response didn't match!" + echo "curl response was: '$RESP'" + echo "curl output was:" + cat curl_output + return 1 +} + +test_must_be_empty() { + if test -s "$1" + then + echo "'$1' is not empty, it contains:" + cat "$1" + return 1 + fi +} + +test_should_contain() { + test "$#" = 2 || error "bug in the test script: not 2 parameters to test_should_contain" + if ! grep -q "$1" "$2" + then + echo "'$2' does not contain '$1', it contains:" + cat "$2" + return 1 + fi +} + +test_str_contains() { + find=$1 + shift + echo "$@" | egrep "\b$find\b" >/dev/null +} + +disk_usage() { + # normalize du across systems + case $(uname -s) in + Linux) + DU="du -sb" + ;; + FreeBSD) + DU="du -s -A -B 1" + ;; + Darwin | DragonFly | *) + DU="du -s" + ;; + esac + $DU "$1" | awk "{print \$1}" +} + +# output a file's permission in human readable format +generic_stat() { + # normalize stat across systems + case $(uname -s) in + Linux) + _STAT="stat -c %A" + ;; + FreeBSD | Darwin | DragonFly) + _STAT="stat -f %Sp" + ;; + esac + $_STAT "$1" +} + +test_check_peerid() { + peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && + test "$peeridlen" = "46" || { + echo "Bad peerid '$1' with len '$peeridlen'" + return 1 + } +} + +convert_tcp_maddr() { + echo $1 | awk -F'/' '{ printf "%s:%s", $3, $5 }' +} + +port_from_maddr() { + echo $1 | awk -F'/' '{ print $NF }' +} diff --git a/test/sharness/t0000-sharness.sh b/test/sharness/t0000-sharness.sh new file mode 100755 index 0000000000..c55d40ed86 --- /dev/null +++ b/test/sharness/t0000-sharness.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description="Show basic features of Sharness" + +. ./lib/sharness/sharness.sh + +test_expect_success "Success is reported like this" " + echo hello world | grep hello +" + +test_expect_success "Commands are chained this way" " + test x = 'x' && + test 2 -gt 1 && + echo success +" + +return_42() { + echo "Will return soon" + return 42 +} + +test_expect_success "You can test for a specific exit code" " + test_expect_code 42 return_42 +" + +test_expect_failure "We expect this to fail" " + test 1 = 2 +" + +test_done + +# vi: set ft=sh : diff --git a/test/sharness/t0010-basic-commands.sh b/test/sharness/t0010-basic-commands.sh new file mode 100755 index 0000000000..33d3ea8de2 --- /dev/null +++ b/test/sharness/t0010-basic-commands.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (c) 2014 Christian Couder +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test installation and some basic commands" + +. lib/test-lib.sh + +test_expect_success "current dir is writable" ' + echo "It works!" >test.txt +' + +test_expect_success "ipfs version succeeds" ' + ipfs version >version.txt +' + +test_expect_success "ipfs version shows js-ipfs" ' + grep "js-ipfs" version.txt >/dev/null || + test_fsh cat version.txt +' + +test_expect_success "ipfs version output looks good" ' + egrep "^js-ipfs version: [0-9]+\.[0-9]+\.[0-9]" version.txt >/dev/null || + test_fsh cat version.txt +' + +test_done