SHELL=/bin/bash

# Test directories are all subdirectories
TEST_DIRS := $(sort $(patsubst %/, %, $(wildcard */)))

# Check root directory set
$(if $(ROOT),,$(error "Please run make from root directory!"))
# Reset the OCaml path for Jane Street testbed
OCAML_PATH := $(strip $(shell opam config exec --switch rotor-testbed -- opam config var lib || echo -n ""))
OCAML_PATH := $(if $(OCAML_PATH),$(OCAML_PATH),$(shell (opam config exec --switch rotor-testbed -- ocamlfind printconf path || echo -n "") | (read dir; echo -n "$$dir")))
$(if $(OCAML_PATH),,$(error "Cannot find OCaml path!"))
# Check that the Jane Street path is available in the expected environment var
$(if $(JANE_STREET_PATH),,$(error "JANE_STREET_PATH not set!"))

# Get the depth of the JS path
JSPATH_DEPTH := $(words $(subst /, ,$(subst  ,,$(JANE_STREET_PATH))))

CMD := $(ROOT)/$(MAIN_EXE)

# Config files
OCAML_INCLUDE_FILE := include-ocaml
JS_INCLUDE_FILE := include-js
SOURCES_FILE := libs
DEPS_FILE := filedeps

.PHONY: $(TEST_DIRS) deploy_testbed remove_artifacts run_tests load_config_and_run_tests all clean

all: $(TEST_DIRS)

$(TEST_DIRS): $(OCAML_INCLUDE_FILE) $(JS_INCLUDE_FILE) $(SOURCES_FILE) $(DEPS_FILE)
	@TEST_DIR="$@" $(MAKE) --no-print-directory load_config_and_run_tests

deploy_testbed:
	@rm -fR $(JANE_STREET_PATH)
	@mkdir $(JANE_STREET_PATH)
	@tar -xvzf js-testbed.tar.gz -C $(JANE_STREET_PATH)
	@(cd $(JANE_STREET_PATH) && jbuilder build)

load_config_and_run_tests:
	@INCLUDE_PARAMS=""; \
	while read INCLUDE || [ -n "$$INCLUDE" ] ; do \
		INCLUDE_PARAMS="$$INCLUDE_PARAMS -I $(OCAML_PATH)/$$INCLUDE"; \
	done < $(OCAML_INCLUDE_FILE); \
	while read INCLUDE || [ -n "$$INCLUDE" ] ; do \
		INCLUDE_PARAMS="$$INCLUDE_PARAMS -I $$INCLUDE"; \
	done < $(JS_INCLUDE_FILE); \
	export INCLUDE_PARAMS; \
	INPUT_DIRS=""; \
	while read INPUTDIR LIB || [ -n "$$INPUTDIR" ]; do \
		INPUT_DIRS="$$INPUT_DIRS -d $$INPUTDIR"; \
		if [ -n "$$LIB" ]; then \
			INPUT_DIRS="$$INPUT_DIRS -lib $$LIB"; \
		fi \
	done < "$(SOURCES_FILE)"; \
	export INPUT_DIRS; \
	$(MAKE) --no-print-directory run_tests

remove_artifacts:
	@rm -f $(TEST_DIR)/*.patch
	@rm -f $(TEST_DIR)/*.log
	@rm -f $(TEST_DIR)/*.err

run_tests: remove_artifacts
	@if [ -z "$(TEST_DIR)" ]; then echo >&2 "No test directory!" && exit 1; fi
	@echo "Running tests in: $(TEST_DIR)"
	@TEST_CNT=0; \
	while read PARAMS || [ -n "$$PARAMS" ]; do \
		TEST_CNT=$$(($$TEST_CNT+1)); \
		echo -ne "\tTest $$TEST_CNT: "; \
		CMD_OUTPUT=$$(cd "$$JANE_STREET_PATH" && \
			"$(CMD)" $(INCLUDE_PARAMS) $(INPUT_DIRS) \
				-get-deps-from-file "$(ROOT)/test/jane-street/$(DEPS_FILE)" \
				-log-file="$(ROOT)/test/jane-street/$(TEST_DIR)/$$TEST_CNT.log" \
				-r $(TEST_DIR) $$PARAMS 2>&1); \
		EXIT_CODE="$$?"; \
		if [ ! $$EXIT_CODE -eq 0 ]; then \
			if [ -n "$$CMD_OUTPUT" ]; then echo "$$CMD_OUTPUT" > "$(TEST_DIR)/$$TEST_CNT.err"; fi; \
			echo "failed (tool returned exit code $$EXIT_CODE)"; \
		else \
			echo "$$CMD_OUTPUT" > "$(TEST_DIR)/$$TEST_CNT.patch"; \
			diff "$(TEST_DIR)/$$TEST_CNT.patch" "$(TEST_DIR)/$$TEST_CNT.expect" >/dev/null 2>&1; \
			if [ $$? -eq 0 ]; then \
				echo "passed"; \
			else \
				echo "failed (patch output different from expected)"; \
			fi; \
		fi; \
	done < "$(TEST_DIR)/tests"

CLEAN_TARGETS := $(patsubst %,%.clean,$(TEST_DIRS))

clean: $(CLEAN_TARGETS)

%.clean:
	@TEST_DIR="$*" $(MAKE) --no-print-directory remove_artifacts