#!/bin/bash usage () { echo "Usage:$0 " } if [ $# -lt 1 ]; then echo "Error: No test URL given." >&2 echo "" >&2 usage >&2 exit 1 fi URL=$1 CURL="curl --silent --show-error" _TEST_SECTION() { echo "" echo $1 echo $1 | sed -e "s/./$2/g" } TEST_SECTION() { _TEST_SECTION "$1" = } TEST_SUBSECTION() { _TEST_SECTION "$1" - } TEST() { printf " $1" printf "%*s" $(( 52 - ${#1} )) | tr ' ' '.' (( tests_total++ )) || true } # Result of test depends on the exit status of last command TEST_END() { if [ $? -eq 0 ]; then echo -n "OK" else (( tests_failed++ )) || true echo -n "FAIL" fi # If we got an argument, append it after test result if [ -n "$1" ]; then echo " $1" else echo "" fi } # Print report of all previous test results TEST_REPORT() { echo "" echo "Test Report" echo "===========" if [ "$tests_failed" == "" ]; then echo "All $tests_total tests passed." echo "" return 0 else echo "$tests_failed of $tests_total tests failed." echo "" return 1 fi } # Does a string contain a regular expression pattern # # Example: # # contains "All's well that ends well" "s.well" contains() { grep -q "$2" <<< $1 } # POST to a URL endpoint with optional JSON data # # Usage: # # curl_post [data] [CURL_OPTIONS] curl_post() { $CURL ${3:-} -X POST ${2:+-H 'Content-Type: application/json' -d "$2"} $URL/$1 } # PUT to a URL endpoint with optional JSON data # # Usage: # # curl_post [data] [CURL_OPTIONS] curl_put() { $CURL ${3:-} -X PUT ${2:+-H 'Content-Type: application/json' -d "$2"} $URL/$1 } # GET from a URL endpoint # # Usage: # # curl_get [CURL_OPTIONS] curl_get() { $CURL ${2:-} $URL/$1 } # Create a new game of the specified engine type # # Usage: # # new_game new_game() { curl_post new/$1 | jq -r . } TEST_SECTION "LMNO (super-site for games)" TEST_SUBSECTION "Testing home page" home_page=$($CURL $URL) TEST "Contains 'Join Game'" contains "$home_page" "Join Game" TEST_END TEST "Contains 'Host a new game'" contains "$home_page" "Host a new game" TEST_END TEST_SUBSECTION "Creating some new games" TEST "Empires" empires_game_id=$(new_game empires) test "$empires_game_id" != "" TEST_END $empires_game_id TEST "Tic Tac Toe" tictactoe_game_id=$(new_game tictactoe) test "$tictactoe_game_id" != "" TEST_END $tictactoe_game_id TEST_SUBSECTION "Test redirects" TEST "Redirect of /GAMEID at top level" redirect=$(curl_get $empires_game_id) test "$redirect" = "Moved Permanently. Redirecting to /empires/$empires_game_id/" TEST_END TEST "Redirect of lowercase /gameid at top level" empires_game_id_lower=$(tr '[:upper:]' '[:lower:]' <<< $empires_game_id) redirect=$(curl_get $empires_game_id_lower) test "$redirect" = "Moved Permanently. Redirecting to /$empires_game_id/" TEST_END TEST "Redirect of lowercase /empires/gameid" redirect=$(curl_get empires/$empires_game_id_lower) test "$redirect" = "Moved Permanently. Redirecting to /empires/$empires_game_id/" TEST_END TEST_SECTION "Empires game" empires_game_path=empires/$empires_game_id TEST_SUBSECTION "Empires game /register" empires_register() { curl_post $empires_game_path/register "{\"name\": \"$1\", \"character\": \"$2\"}" } empires_players_string() { curl_get $empires_game_path/players | jq -r .[].name | tr '\n' ',' } empires_characters_string() { curl_get $empires_game_path/characters | jq -r .[] | tr '\n' ',' } TEST "Registering a player returns an ID" carl_id=$(empires_register Carl "Bugs Bunny" | jq -r .) test "$carl_id" = "1" TEST_END TEST "Registering several more players" empires_register Richard "Bob Hope" > /dev/null empires_register Kevin "Elvis Presley" > /dev/null empires_register Stacy Phineas > /dev/null empires_register David "Red Power Ranger" > /dev/null empires_register Nancy "Audrey Hepburn" > /dev/null bogus_id=$(empires_register Bogus "Mr. Bogus") TEST_END TEST 'Verify complete players list (with "Bogus")' players=$(empires_players_string) test "$players" = "Carl,Richard,Kevin,Stacy,David,Nancy,Bogus," TEST_END TEST 'Verify complete players list (with "Mr. Bogus")' characters=$(empires_characters_string) test "$characters" = "Bugs Bunny,Bob Hope,Elvis Presley,Phineas,Red Power Ranger,Audrey Hepburn,Mr. Bogus," TEST_END TEST_SUBSECTION "Empires game /deregister" empires_deregister() { curl_post $empires_game_path/deregister/$1 } TEST "Removing the bogus player" empires_deregister $bogus_id TEST_END TEST 'Verify modified players list (w/o "Bogus")"' players=$(empires_players_string) test "$players" = "Carl,Richard,Kevin,Stacy,David,Nancy," TEST_END TEST 'Verify modified characters list (w/o "Mr. Bogus")' characters=$(empires_characters_string) test "$characters" = "Bugs Bunny,Bob Hope,Elvis Presley,Phineas,Red Power Ranger,Audrey Hepburn," TEST_END TEST_SUBSECTION "Empires game /capture" empires_capture() { curl_post $empires_game_path/capture/$1/$2 } empires_empires_string() { # Get empires as a compact string (much more compact than JSON) curl_get $empires_game_path/empires | jq -c '.[] | [.id,.captures]' | tr '\n' ',' } TEST "Verify empires before any captures" empires=$(empires_empires_string) test "$empires" = "[1,[]],[2,[]],[3,[]],[4,[]],[5,[]],[6,[]]," TEST_END TEST "Perform some captures" empires_capture 1 2 empires_capture 3 5 empires_capture 4 6 empires_capture 3 4 TEST_END TEST "Verify empires after captures" empires=$(empires_empires_string) test "$empires" = "[1,[2]],[2,[]],[3,[5,4]],[4,[6]],[5,[]],[6,[]]," TEST_END TEST_SUBSECTION "Empires game /liberate" empires_liberate() { curl_post $empires_game_path/liberate/$1 } TEST "Liberate a player" empires_liberate 2 TEST_END TEST "Verify empires after liberate" empires=$(empires_empires_string) test "$empires" = "[1,[]],[2,[]],[3,[5,4]],[4,[6]],[5,[]],[6,[]]," TEST_END TEST_SUBSECTION "Empires game /reset" empires_reset() { curl_post $empires_game_path/reset } TEST "Reset the game" empires_reset TEST_END TEST "Verify players is now empty" players=$(empires_players_string) test "$players" = "" TEST_END TEST_SECTION "Tic Tac Toe game" tictactoe_game_path=tictactoe/$tictactoe_game_id tictactoe_profile() { curl_put /profile "{ \"nickname\": \"$1\" }" "-c .cookie-tictactoe" } tictactoe_move() { curl_post $tictactoe_game_path/move "{ \"move\": $1 }" "-b .cookie-tictactoe" } tictactoe_player_info() { curl_get $tictactoe_game_path/events "-m 0.1 -b .cookie-tictactoe" 2>&1 \ | grep player-info -A 1 \ | grep ^data } tictactoe_player_name() { curl_put $tictactoe_game_path/player "{ \"name\": \"$1\" }" "-b .cookie-tictactoe" } tictactoe_player_team() { curl_put $tictactoe_game_path/player "{ \"team\": \"$1\" }" "-b .cookie-tictactoe" } TEST_SUBSECTION "Tic Tac Toe player-info" TEST "Hit LMNO /profile to set name to 'curl'" tictactoe_profile curl TEST_END TEST "Verify player-info event reports 'curl' name" result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"curl","team":""}' TEST_END TEST_SUBSECTION "Tic Tac Toe /player" TEST "Change name to 'newname'" tictactoe_player_name newname result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"newname","team":""}' TEST_END TEST "Change team to 'X'" tictactoe_player_team X result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"newname","team":"X"}' TEST_END TEST "Change team to 'O'" tictactoe_player_team O result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"newname","team":"O"}' TEST_END TEST "Verify cannot change team to 'Z'" tictactoe_player_team Z result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"newname","team":"O"}' TEST_END TEST "Leave current team" tictactoe_player_team "" result=$(tictactoe_player_info) test "$result" = 'data: {"id":1,"name":"newname","team":""}' TEST_END TEST_SUBSECTION "Tic Tac Toe /move" TEST "First move doesn't require a team" result=$(tictactoe_move 0) test "$result" = '{"legal":true}' TEST_END TEST "Second move does require a team" result=$(tictactoe_move 4) test "$result" = '{"legal":false,"message":"It'"'"'s not your turn to move"}' TEST_END TEST "Illegal to move when it's not your turn" tictactoe_player_team X result=$(tictactoe_move 4) test "$result" = '{"legal":false,"message":"It'"'"'s not your turn to move"}' TEST_END TEST "Legal move to center square" tictactoe_player_team O result=$(tictactoe_move 4) test "$result" = '{"legal":true}' TEST_END TEST "Move to center square again is now illegal" tictactoe_player_team X result=$(tictactoe_move 4) test "$result" = '{"legal":false,"message":"Square is already occupied"}' TEST_END TEST_REPORT