run.sh 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #!/bin/bash
  2. set -e
  3. dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
  4. self="$(basename "$0")"
  5. usage() {
  6. cat <<EOUSAGE
  7. usage: $self [-t test ...] image:tag [...]
  8. ie: $self debian:wheezy
  9. $self -t utc python:3
  10. $self -t utc python:3 -t python-hy
  11. This script processes the specified Docker images to test their running
  12. environments.
  13. EOUSAGE
  14. }
  15. # arg handling
  16. opts="$(getopt -o 'ht:c:?' --long 'dry-run,help,test:,config:' -- "$@" || { usage >&2 && false; })"
  17. eval set -- "$opts"
  18. declare -A argTests=()
  19. declare -a configs=()
  20. dryRun=
  21. while true; do
  22. flag=$1
  23. shift
  24. case "$flag" in
  25. --dry-run) dryRun=1 ;;
  26. --help|-h|'-?') usage && exit 0 ;;
  27. --test|-t) argTests["$1"]=1 && shift ;;
  28. --config|-c) configs+=("$(readlink -f "$1")") && shift ;;
  29. --) break ;;
  30. *)
  31. {
  32. echo "error: unknown flag: $flag"
  33. usage
  34. } >&2
  35. exit 1
  36. ;;
  37. esac
  38. done
  39. if [ $# -eq 0 ]; then
  40. usage >&2
  41. exit 1
  42. fi
  43. # declare configuration variables
  44. declare -a globalTests=()
  45. declare -A testAlias=()
  46. declare -A imageTests=()
  47. declare -A globalExcludeTests=()
  48. declare -A explicitTests=()
  49. # if there are no user-specified configs, use the default config
  50. if [ ${#configs} -eq 0 ]; then
  51. configs+=("$dir/config.sh")
  52. fi
  53. # load the configs
  54. declare -A testPaths=()
  55. for conf in "${configs[@]}"; do
  56. . "$conf"
  57. # Determine the full path to any newly-declared tests
  58. confDir="$(dirname "$conf")"
  59. for testName in ${globalTests[@]} ${imageTests[@]}; do
  60. [ "${testPaths[$testName]}" ] && continue
  61. if [ -d "$confDir/tests/$testName" ]; then
  62. # Test directory found relative to the conf file
  63. testPaths[$testName]="$confDir/tests/$testName"
  64. elif [ -d "$dir/tests/$testName" ]; then
  65. # Test directory found in the main tests/ directory
  66. testPaths[$testName]="$dir/tests/$testName"
  67. fi
  68. done
  69. done
  70. didFail=
  71. for dockerImage in "$@"; do
  72. echo "testing $dockerImage"
  73. if ! docker inspect "$dockerImage" &> /dev/null; then
  74. echo $'\timage does not exist!'
  75. didFail=1
  76. continue
  77. fi
  78. repo="${dockerImage%:*}"
  79. tagVar="${dockerImage#*:}"
  80. #version="${tagVar%-*}"
  81. variant="${tagVar##*-}"
  82. testRepo=$repo
  83. [ -z "${testAlias[$repo]}" ] || testRepo="${testAlias[$repo]}"
  84. explicitVariant=
  85. if [ \
  86. "${explicitTests[:$variant]}" \
  87. -o "${explicitTests[$repo:$variant]}" \
  88. -o "${explicitTests[$testRepo:$variant]}" \
  89. ]; then
  90. explicitVariant=1
  91. fi
  92. testCandidates=()
  93. if [ -z "$explicitVariant" ]; then
  94. testCandidates+=( "${globalTests[@]}" )
  95. fi
  96. testCandidates+=(
  97. ${imageTests[:$variant]}
  98. )
  99. if [ -z "$explicitVariant" ]; then
  100. testCandidates+=(
  101. ${imageTests[$testRepo]}
  102. )
  103. fi
  104. testCandidates+=(
  105. ${imageTests[$testRepo:$variant]}
  106. )
  107. if [ "$testRepo" != "$repo" ]; then
  108. if [ -z "$explicitVariant" ]; then
  109. testCandidates+=(
  110. ${imageTests[$repo]}
  111. )
  112. fi
  113. testCandidates+=(
  114. ${imageTests[$repo:$variant]}
  115. )
  116. fi
  117. tests=()
  118. for t in "${testCandidates[@]}"; do
  119. if [ ${#argTests[@]} -gt 0 -a -z "${argTests[$t]}" ]; then
  120. # skipping due to -t
  121. continue
  122. fi
  123. if [ \
  124. ! -z "${globalExcludeTests[${testRepo}_$t]}" \
  125. -o ! -z "${globalExcludeTests[${testRepo}:${variant}_$t]}" \
  126. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  127. -o ! -z "${globalExcludeTests[${repo}_$t]}" \
  128. -o ! -z "${globalExcludeTests[${repo}:${variant}_$t]}" \
  129. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  130. ]; then
  131. # skipping due to exclude
  132. continue
  133. fi
  134. tests+=( "$t" )
  135. done
  136. currentTest=0
  137. totalTest="${#tests[@]}"
  138. for t in "${tests[@]}"; do
  139. (( currentTest+=1 ))
  140. echo -ne "\t'$t' [$currentTest/$totalTest]..."
  141. # run test against dockerImage here
  142. # find the script for the test
  143. scriptDir="${testPaths[$t]}"
  144. if [ -d "$scriptDir" ]; then
  145. script="$scriptDir/run.sh"
  146. if [ -x "$script" -a ! -d "$script" ]; then
  147. # TODO dryRun logic
  148. if output="$("$script" $dockerImage)"; then
  149. if [ -f "$scriptDir/expected-std-out.txt" ] && ! d="$(echo "$output" | diff -u "$scriptDir/expected-std-out.txt" - 2>/dev/null)"; then
  150. echo 'failed; unexpected output:'
  151. echo "$d"
  152. didFail=1
  153. else
  154. echo 'passed'
  155. fi
  156. else
  157. echo 'failed'
  158. didFail=1
  159. fi
  160. else
  161. echo "skipping"
  162. echo >&2 "error: $script missing, not executable or is a directory"
  163. didFail=1
  164. continue
  165. fi
  166. else
  167. echo "skipping"
  168. echo >&2 "error: unable to locate test '$t'"
  169. didFail=1
  170. continue
  171. fi
  172. done
  173. done
  174. if [ "$didFail" ]; then
  175. exit 1
  176. fi