# Copyright (C) 2012 The Meme Factory, Inc. http://www.meme.com/ # # This file is part of Gombe-MI. # # Gombe-MI is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gombe-MI. If not, see . # # Load data, possibly testing. # # Syntax: # run_sql [ prereq | test | testcommit | save | show ] psql_args file # # Env vars: THIS_TEST Name of test. # RUN_TEST_SOCK Socket to pipe test sql into. # # Karl O. Pinc # # Actions: # prereq: Loads the data into the db and compares with results/$file # to see if it succeeds. # test: Load data into db, compare with results/$file and report result. # testcommit: Run a commit for the test and report (final) result. # save: Save the result as a successful run in results/$file. # show: Print output of load on screen. # # Side Effects: # Loads data into the db. # Touches loaded/$file to let make know the load prerequsites are # satisfied. # Actions prereq and test print to the screen. "test" leaves status on the # screen when done. # # Bugs: # Has a race condition. The initial inotifywait might, possibly, # not establish it's wait until after the psql process has # finished and closed the file. This is unlikely since we establish # the wait before sending any sql, but possible. It all depends # on the OS scheduler. # export action="$1" export PSQL_ARGS="$2" export path="$3" export file=$(basename $path) export tfile=/tmp/$0_$$ export sigfile=/tmp/$0_sig_$$ exec_sql () { socat -u STDIN UNIX-SENDTO:$RUN_TEST_SOCK } reset_line () { tput hpa 0 tput dl1 } #filter_sql () { # if [ -e filters/$file ] ; then # if [ ! -x filters/$file ] ; then cleanup () { rm -rf $tfile $sigfile ;# also ends inotifywait process, if any } trap cleanup 0 1 2 # Make the file which notes sql completion exist so we can wait on it. touch $sigfile inotifywait -qq -e close $sigfile & ## Get out of the run queue to avoid the race condition. # (Be sure to note in the README that this requires GNU sleep.) #env sleep 0.001 inotifypid=$! if [ "$action" = "prereq" ] \ || [ "$action" = "test" ] \ || [ "$action" = "testcommit" ] ; then printf '%-25s ........... ' "$THIS_TEST" fi case $action in test) if [ ! -e results/$file ] ; then printf 'fail (no saved results)\n' exit 1 fi ;; prereq|testcommit) if [ ! -e results/$file ] ; then printf 'fail (prereq %s, no saved results)\n' $file exit 1 fi ;; esac # Run the commands and capture the result. printf '\\o %s\n' $tfile | exec_sql # show what's executing #printf '\n%s\n' $path cat $path | exec_sql if [ -n "$INCLUDE_COMMIT" ] \ && [ "$file" = "$THIS_TEST" ] \ && [ "$THIS_TEST" != 'commit' ] ; then # The test is finished, but requires the transaction be commited. # (Capture the output of the transaction commit in the test output.) cat sql/commit | exec_sql touch loaded/commit fi printf '\\o\n' | exec_sql # Write a file with content when we're done. # With this we can be sure that we're really finished. # (We can't just wait on closure of our data file because it # might be somebody else that closed it.) printf '\\o %s\n' "$sigfile" | exec_sql printf "select 'done' as data;\n" | exec_sql printf '\\o\n' | exec_sql # Wait on the inotifywait for sql completion. wait $inotifypid # Loop, in case it was somebody else that closed the file. # (It would be nice to look for specific content, but # if there's an aborted transaction then we'll get # an error instead of our content.) while [ -e $sigfile ] && [ ! -s $sigfile ] ; do # Wait some more for file to close, but poll # to break out of race condition. The # file might have closed while we tested for done-ness. inotifywait -t 1 -qq -e close $sigfile done cmp -s results/$file $tfile result=$? if [ $result -ne 0 ] ; then case $action in test) printf 'fail\n' ;; prereq|testcommit) # This with -v for debugging when things go wonky and prerequsites # don't load as prerequsites but load file when tested independenly. # (Having to do this is a sign that you're running in a transaction # and need to commit and start a new one.) #cat $tfile printf 'fail (prereq %s)\n' $file ;; esac else case $action in test|testcommit) touch loaded/$file printf 'pass' if [ -e loaded/commit ] || [ ! -e loaded/begin ] ; then # All done with transaction related stuff, test is done. printf '\n' else reset_line fi ;; prereq) touch loaded/$file printf 'pass (%s)' $file reset_line esac fi if [ "$action" = 'show' ] ; then cat $tfile exit 0 fi if [ "$action" = 'save' -a "$file" = "$THIS_TEST" ] ; then mv $tfile results/$file exit $? fi exit $result