#!/bin/bash

# Once we have libcognitect-test-runner-clojure (which is not in
# unstable yet) and /usr/share/java/cognitect.test-runner.jar in the
# classpath, we can replace much of this with the -m ... invocations
# in deps.edn, using -i/e :network, etc.

set -ueo pipefail

usage() { echo "run-build-tests: [--src <PATH|JAR> ] [network | isolated]"; }
misuse() { usage 1>&2; exit 2; }

src=src/main/clojure
while test $# -ne 0; do
    case "$1" in
        --src)
            test "$#" -gt 1 || misuse
            src="$2"
            shift 2
            ;;
        *) break ;;
    esac
done

selector='' # remove or filter :network?
isolated='' # src/test-isolated instead of src/test?
case $# in
    0) selector=remove ;;
    1) case "$1" in
           network) selector=filter ;;
           isolated) isolated=true ;;
           *) misuse ;;
       esac
       ;;
    *) misuse ;;
esac

# common classpath
cp=($(< debian/libpomegranate-clojure.classpath))
test "${cp[0]}" = usr/share/java/pomegranate.jar
unset cp[0] # drop it (we're testing src/)
cp=(src/test/clojure
    "$src"
    /usr/share/java/tools.namespace.jar
    "${cp[@]}")

if test "$isolated"; then
    test_cp="src/test-isolated/clojure:$(IFS=:; echo "${cp[*]}")"
    set -x
    java -cp "$test_cp" clojure.main - <<-EOF
	(ns debian.test.pomegranate
	  (:require
	   [clojure.test :refer [run-tests successful?]]
	   [clojure.java.io :refer [as-file]]
	   [clojure.tools.namespace :refer [find-namespaces-in-dir]]))
	(let [nss (find-namespaces-in-dir (as-file "src/test-isolated/clojure"))]
	  (apply require nss)
	  (System/exit (if (successful? (apply run-tests nss)) 0 2)))
	EOF
    exit 0
fi

test_cp="$(IFS=:; echo "${cp[*]}")"
set -x
java -cp "$test_cp" clojure.main - <<EOF
(ns debian.test.pomegranate
  (:require
   [clojure.java.io :refer [as-file]]
   [clojure.test :refer [run-tests successful? test-vars]]
   [clojure.tools.namespace :refer [find-namespaces-in-dir]]))

(def ^:dynamic *test-ns-vars* nil)

;; Taken from clojure.test -- we have to redefine the whole thing
;; because redefing test-all-vars doesn't work (presumably due to
;; direct linking).
(defn test-ns
  [ns]
  ;; Assumes there are no test-ns-hooks
  (binding [clojure.test/*report-counters* (ref clojure.test/*initial-report-counters*)]
    (let [ns-obj (the-ns ns)]
      (clojure.test/do-report {:type :begin-test-ns, :ns ns-obj})
      (*test-ns-vars* ns-obj)
      (clojure.test/do-report {:type :end-test-ns, :ns ns-obj}))
    @clojure.test/*report-counters*))

(let [nss (find-namespaces-in-dir (as-file "src/test/clojure"))
      _ (apply require nss)
      test-no-net (fn test-no-net [ns]
                    (test-vars (->> ns ns-interns vals ($selector #(-> % meta :network)))))]
  ;; Cheat, until we can switch to cognitect.test-runner
  (with-redefs [clojure.test/test-ns test-ns]
    (binding [*test-ns-vars* test-no-net]
      (System/exit (if (successful? (apply run-tests nss)) 0 2)))))
EOF
