lots of exercises in java... from https://github.com/exercism/java

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #!/usr/bin/env bash
  2. TRACK=java
  3. TRACK_REPO="$TRACK"
  4. TRACK_SRC_EXT="java"
  5. CPU_CORES=`getconf NPROCESSORS_ONLN 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1`
  6. EXERCISES_TO_SOLVE=$@
  7. on_exit() {
  8. echo ">>> on_exit()"
  9. if [[ "$xapi_pid" != "" ]] ; then
  10. kill $xapi_pid
  11. echo "stopped x-api (pid=${xapi_pid})"
  12. fi
  13. cd $EXECPATH
  14. echo "<<< on_exit()"
  15. }
  16. assert_installed() {
  17. local binary=$1
  18. echo ">>> assert_installed(binary=\"${binary}\")"
  19. if [[ "`which $binary`" == "" ]]; then
  20. echo "${binary} not found; it is required to perform this test."
  21. echo -e "Have you completed the setup instructions at https://github.com/exercism/${TRACK_REPO} ?\n"
  22. echo "PATH=${PATH}"
  23. echo "aborting."
  24. exit 1
  25. fi
  26. echo "<<< assert_installed()"
  27. }
  28. assert_ruby_installed() {
  29. local ruby_app_home="$1"
  30. echo ">>> assert_ruby_installed(ruby_app_home=\"${ruby_app_home}\")"
  31. pushd "${ruby_app_home}"
  32. local current_ruby_ver=`ruby --version | egrep --only-matching "[0-9]+\.[0-9]+\.[0-9]+"`
  33. local expected_ruby_ver=`cat Gemfile | awk -F\' '/ruby /{print $2}'`
  34. popd
  35. if [[ "${expected_ruby_ver}" != "" && "${current_ruby_ver}" != "${expected_ruby_ver}" ]]; then
  36. echo "${ruby_app_home} requires Ruby ${expected_ruby_ver}; current Ruby version is ${current_ruby_ver}."
  37. echo -e "Ruby used: `which ruby`.\n"
  38. echo -e "Have you completed the setup instructions at https://github.com/exercism/${TRACK_REPO} ?\n"
  39. echo "PATH=${PATH}"
  40. echo "aborting."
  41. exit 1
  42. fi
  43. echo "<<< assert_ruby_installed()"
  44. }
  45. clean() {
  46. local build_dir="$1"
  47. echo ">>> clean(build_dir=\"${build_dir}\")"
  48. # empty, absolute path, or parent reference are considered dangerous to rm -rf against.
  49. if [[ "${build_dir}" == "" || ${build_dir} =~ ^/ || ${build_dir} =~ \.\. ]] ; then
  50. echo "Value for build_dir looks dangerous. Aborting."
  51. exit 1
  52. fi
  53. local build_path=$( pwd )/${build_dir}
  54. if [[ -d "${build_path}" ]] ; then
  55. echo "Cleaning journey script build output directory (${build_path})."
  56. rm -rf "${build_path}"
  57. fi
  58. cd exercises
  59. "$EXECPATH"/gradlew clean
  60. cd ..
  61. echo "<<< clean()"
  62. }
  63. get_operating_system() {
  64. case $(uname) in
  65. (Darwin*)
  66. echo "mac";;
  67. (Linux*)
  68. echo "linux";;
  69. (Windows*)
  70. echo "windows";;
  71. (MINGW*)
  72. echo "windows";;
  73. (*)
  74. echo "linux";;
  75. esac
  76. }
  77. get_cpu_architecture() {
  78. case $(uname -m) in
  79. (*64*)
  80. echo 64bit;;
  81. (*686*)
  82. echo 32bit;;
  83. (*386*)
  84. echo 32bit;;
  85. (*)
  86. echo 64bit;;
  87. esac
  88. }
  89. get_optimal_amount_of_jobs() {
  90. if [ "$CPU_CORES" -gt "1" ]; then
  91. echo $((CPU_CORES-1))
  92. else
  93. echo 1
  94. fi
  95. }
  96. download_exercism_cli() {
  97. local os="$1"
  98. local arch="$2"
  99. local exercism_home="$3"
  100. echo ">>> download_exercism_cli(os=\"${os}\", arch=\"${arch}\", exercism_home=\"${exercism_home}\")"
  101. local CLI_RELEASES=https://github.com/exercism/cli/releases
  102. local latest=${CLI_RELEASES}/latest
  103. # "curl..." :: HTTP 302 headers, including "Location" -- URL to redirect to.
  104. # "awk..." :: pluck last path segment from "Location" (i.e. the version number)
  105. local version="$(curl --head --silent ${latest} | awk -v FS=/ '/Location:/{print $NF}' | tr -d '\r')"
  106. local download_url_suffix
  107. local unzip_command
  108. local unzip_from_file_option
  109. if [[ ${os} == "windows" ]] ; then
  110. download_url_suffix="zip"
  111. unzip_command="unzip -d"
  112. unzip_from_file_option=""
  113. else
  114. download_url_suffix="tgz"
  115. unzip_command="tar xz -C"
  116. unzip_from_file_option="-f"
  117. fi
  118. local download_url=${CLI_RELEASES}/download/${version}/exercism-${os}-${arch}.${download_url_suffix}
  119. mkdir -p ${exercism_home}
  120. local temp=`mktemp`
  121. curl -s --location ${download_url} > ${temp}
  122. ${unzip_command} ${exercism_home} ${unzip_from_file_option} ${temp}
  123. echo "<<< download_exercism_cli()"
  124. }
  125. git_clone() {
  126. local repo_name="$1"
  127. local dest_path="$2"
  128. echo ">>> git_clone(repo_name=\"${repo_name}\", dest_path=\"${dest_path}\")"
  129. git clone https://github.com/exercism/${repo_name} ${dest_path}
  130. echo "<<< git_clone()"
  131. }
  132. make_local_trackler() {
  133. local trackler="$1"
  134. local xapi_home="$2"
  135. echo ">>> make_local_trackler(trackler=\"${trackler}\", xapi_home=\"${xapi_home}\")"
  136. local track_root=$( pwd )
  137. pushd ${trackler}
  138. # Get the version of Trackler x-api is currently using
  139. local version=$( grep -m 1 'trackler' ${xapi_home}/Gemfile.lock | sed 's/.*(//' | sed 's/)//' )
  140. git checkout v${version}
  141. git submodule init -- problem-specifications
  142. git submodule update
  143. # Bake in local copy of this track; this is what we are testing.
  144. rmdir tracks/${TRACK}
  145. mkdir -p tracks/${TRACK}/exercises
  146. cp ${track_root}/config.json tracks/${TRACK}
  147. cp -r ${track_root}/exercises tracks/${TRACK}
  148. gem install bundler
  149. bundle install --jobs $(get_optimal_amount_of_jobs)
  150. gem build trackler.gemspec
  151. # Make *this* the gem that x-api uses when we build x-api.
  152. gem install --local trackler-*.gem
  153. popd > /dev/null
  154. echo "<<< make_local_trackler()"
  155. }
  156. start_x_api() {
  157. local xapi_home="$1"
  158. echo ">>> start_x_api(xapi_home=\"${xapi_home}\")"
  159. pushd $xapi_home
  160. gem install bundler
  161. bundle install --jobs $(get_optimal_amount_of_jobs)
  162. RACK_ENV=development rackup &
  163. xapi_pid=$!
  164. sleep 5
  165. echo "x-api is running (pid=${xapi_pid})."
  166. popd > /dev/null
  167. echo "<<< start_x_api()"
  168. }
  169. configure_exercism_cli() {
  170. local exercism_home="$1"
  171. local exercism_configfile="$2"
  172. local xapi_port=$3
  173. echo ">>> configure_exercism_cli(exercism_home=\"${exercism_home}\", exercism_configfile=\"${exercism_configfile}\", xapi_port=${xapi_port})"
  174. local exercism="./exercism --config ${exercism_configfile}"
  175. mkdir -p "${exercism_home}"
  176. pushd "${exercism_home}"
  177. $exercism configure --dir="${exercism_home}"
  178. $exercism configure --api http://localhost:${xapi_port}
  179. $exercism debug
  180. popd
  181. echo "<<< configure_exercism_cli()"
  182. }
  183. solve_all_exercises() {
  184. local exercism_exercises_dir="$1"
  185. local exercism_configfile="$2"
  186. echo ">>> solve_all_exercises(exercism_exercises_dir=\"${exercism_exercises_dir}\", exercism_configfile=\"${exercism_configfile}\")"
  187. local track_root=$( pwd )
  188. local exercism_cli="./exercism --config ${exercism_configfile}"
  189. local exercises=`cat config.json | jq '.exercises[].slug + " "' --join-output`
  190. local total_exercises=`cat config.json | jq '.exercises | length'`
  191. local current_exercise_number=1
  192. local tempfile="${TMPDIR:-/tmp}/journey-test.sh-unignore_all_tests.txt"
  193. pushd ${exercism_exercises_dir}
  194. for exercise in $exercises; do
  195. echo -e "\n\n"
  196. echo "=================================================="
  197. echo "${current_exercise_number} of ${total_exercises} -- ${exercise}"
  198. echo "=================================================="
  199. ${exercism_cli} fetch ${TRACK} $exercise
  200. cp -R -H ${track_root}/exercises/${exercise}/.meta/src/reference/${TRACK}/* ${exercism_exercises_dir}/${TRACK}/${exercise}/src/main/${TRACK}/
  201. pushd ${exercism_exercises_dir}/${TRACK}/${exercise}
  202. # Check that tests compile before we strip @Ignore annotations
  203. "$EXECPATH"/gradlew compileTestJava
  204. # Ensure we run all the tests (as delivered, all but the first is @Ignore'd)
  205. for testfile in `find . -name "*Test.${TRACK_SRC_EXT}"`; do
  206. # Strip @Ignore annotations to ensure we run the tests (as delivered, all but the first is @Ignore'd).
  207. # Note that unit-test.sh also strips @Ignore annotations via the Gradle task copyTestsFilteringIgnores.
  208. # The stripping implementations here and in copyTestsFilteringIgnores should be kept consistent.
  209. sed 's/@Ignore\(\(.*\)\)\{0,1\}//' ${testfile} > "${tempfile}" && mv "${tempfile}" "${testfile}"
  210. done
  211. "$EXECPATH"/gradlew test
  212. popd
  213. current_exercise_number=$((current_exercise_number + 1))
  214. done
  215. popd
  216. }
  217. solve_single_exercise() {
  218. local exercism_exercises_dir="$1"
  219. local exercism_configfile="$2"
  220. local exercise_to_solve="$3"
  221. echo ">>> solve_all_exercises(exercism_exercises_dir=\"${exercism_exercises_dir}\", exercism_configfile=\"${exercism_configfile}\", exercise_to_solve=\"$exercise_to_solve\")"
  222. local track_root=$( pwd )
  223. local exercism_cli="./exercism --config ${exercism_configfile}"
  224. local tempfile="${TMPDIR:-/tmp}/journey-test.sh-unignore_all_tests.txt"
  225. pushd ${exercism_exercises_dir}
  226. echo -e "\n\n"
  227. echo "=================================================="
  228. echo "Solving ${exercise_to_solve}"
  229. echo "=================================================="
  230. ${exercism_cli} fetch ${TRACK} $exercise_to_solve
  231. cp -R -H ${track_root}/exercises/${exercise_to_solve}/.meta/src/reference/${TRACK}/* ${exercism_exercises_dir}/${TRACK}/${exercise_to_solve}/src/main/${TRACK}/
  232. pushd ${exercism_exercises_dir}/${TRACK}/${exercise_to_solve}
  233. # Check that tests compile before we strip @Ignore annotations
  234. "$EXECPATH"/gradlew compileTestJava
  235. # Ensure we run all the tests (as delivered, all but the first is @Ignore'd)
  236. for testfile in `find . -name "*Test.${TRACK_SRC_EXT}"`; do
  237. # Strip @Ignore annotations to ensure we run the tests (as delivered, all but the first is @Ignore'd).
  238. # Note that unit-test.sh also strips @Ignore annotations via the Gradle task copyTestsFilteringIgnores.
  239. # The stripping implementations here and in copyTestsFilteringIgnores should be kept consistent.
  240. sed 's/@Ignore\(\(.*\)\)\{0,1\}//' ${testfile} > "${tempfile}" && mv "${tempfile}" "${testfile}"
  241. done
  242. "$EXECPATH"/gradlew test
  243. popd
  244. popd
  245. }
  246. main() {
  247. # all functions assume current working directory is repository root.
  248. cd "${SCRIPTPATH}/.."
  249. local track_root=$( pwd )
  250. local build_dir="build"
  251. local build_path="${track_root}/${build_dir}"
  252. local xapi_home="${build_path}/x-api"
  253. local trackler_home="${build_path}/trackler"
  254. local exercism_home="${build_path}/exercism"
  255. local exercism_configfile=".journey-test.exercism.json"
  256. local xapi_port=9292
  257. # fail fast if required binaries are not installed.
  258. assert_installed "jq"
  259. clean "${build_dir}"
  260. # Download everything we need in parallel
  261. git_clone "x-api" "${xapi_home}" &
  262. git_clone "trackler" "${trackler_home}" &
  263. download_exercism_cli $(get_operating_system) $(get_cpu_architecture) "${exercism_home}" &
  264. wait
  265. # Check and install the ruby stuff we need in parallel
  266. assert_ruby_installed "${trackler_home}" &
  267. assert_ruby_installed "${xapi_home}" &
  268. wait
  269. # Make a local version of trackler
  270. make_local_trackler "${trackler_home}" "${xapi_home}"
  271. # Start-up a local instance of x-api so we can fetch the exercises through it.
  272. start_x_api "${xapi_home}"
  273. # Create a CLI install and config just for this build; this script does not use your CLI install.
  274. configure_exercism_cli "${exercism_home}" "${exercism_configfile}" "${xapi_port}"
  275. if [[ $EXERCISES_TO_SOLVE == "" ]]; then
  276. solve_all_exercises "${exercism_home}" "${exercism_configfile}"
  277. else
  278. for exercise in $EXERCISES_TO_SOLVE
  279. do solve_single_exercise "${exercism_home}" "${exercism_configfile}" "${exercise}"
  280. done
  281. fi
  282. }
  283. ##########################################################################
  284. # Execution begins here...
  285. # If any command fails, fail the script.
  286. set -ex
  287. SCRIPTPATH=$( pushd `dirname $0` > /dev/null && pwd && popd > /dev/null )
  288. EXECPATH=$( pwd )
  289. # Make output easier to read in CI
  290. TERM=dumb
  291. xapi_pid=""
  292. trap on_exit EXIT
  293. main