##
# LIBGTEST is the google test library
# GTEST_MAIN is the file that contains the google test
##
LIBGTEST = test/libgtest.a
GTEST_MAIN = $(GTEST)/src/gtest_main.cc
CFLAGS_GTEST += -I $(GTEST)/include -I $(GTEST)

##
# Target to build all models and test them. This needs to be before 
# the test-unit target.
##
MODEL_TESTS := $(shell find src/test/models -type f -name '*_test.cpp')
MODEL_TESTS := $(MODEL_TESTS:src/test/%_test.cpp=test/%)

MISSING_MODEL_TESTS := $(shell find src/models -type f -name '*.stan')
MISSING_MODEL_TESTS := $(MISSING_MODEL_TESTS:src/models/%.stan=models/%)
MISSING_MODEL_TESTS := $(filter-out $(MODEL_TESTS:test/%=%),$(MISSING_MODEL_TESTS))
.PHONY: test-models
test-models: $(addprefix runtest_no_fail/,$(MODEL_TESTS))
ifneq ($(MISSING_MODEL_TESTS),)
	@echo 
	@echo '-------------------- Missing $(words $(MISSING_MODEL_TESTS)) tests --------------------'
	@$(foreach missing,$(MISSING_MODEL_TESTS),\
	   echo '  src/$(missing).stan';)
endif

##
# Target to build bugs models
##
BUGS_TESTS := $(shell find src/test/models/bugs_examples -type f -name '*_test.cpp')
BUGS_TESTS := $(BUGS_TESTS:src/test/%_test.cpp=test/%)
.PHONY: test-bugs
test-bugs: $(addprefix runtest_no_fail/,$(BUGS_TESTS))

##
# Target to build unit tests. All unit tests are in src/test 
# and are named *_test.cpp
##
UNIT_TESTS := $(shell find src/test -type f -name '*_test.cpp')
UNIT_TESTS := $(UNIT_TESTS:src/test/%_test.cpp=test/%)
UNIT_TESTS := $(filter-out $(MODEL_TESTS),$(UNIT_TESTS))
.PHONY: test-unit
test-unit: $(addprefix runtest/,$(UNIT_TESTS))

##
# Target to build all tests
##
.PHONY: test-all
test-all: test-unit test-models

##
# Build the google test library.
## 
$(LIBGTEST): $(LIBGTEST)(test/gtest.o)

test/gtest.o: $(GTEST)/src/gtest-all.cc
	@mkdir -p test
	$(COMPILE.c) $(CFLAGS_GTEST) $< $(OUTPUT_OPTION)

##
# Generate autodependencies for test files.
# Adapted from the gnu make manual.
# http://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html#Automatic-Prerequisites
##

##
# Builds a single test with a stan model dependency
#
# Using a static pattern rule to make these tests depend on
# missing models.
##
.PRECIOUS: test/models/%.o models/%$(EXE)
$(addsuffix $(EXE),$(MODEL_TESTS)): test/models/%$(EXE): test/models/%.o models/%$(EXE) bin/libstan.a bin/libstanc.a
	@mkdir -p $(dir $@)
	@echo '------------------------------------------------------------'
	$(LINK.c) $(GTEST_MAIN) $< $(CFLAGS_GTEST) $(OUTPUT_OPTION) $(LIBGTEST) $(LDLIBS) $(LDLIBS_STANC)
ifeq ($(findstring test-,$(MAKECMDGOALS))$(findstring runtest_no_fail/,$(MAKECMDGOALS)),)
	-$@ --gtest_output="xml:$(basename $@).xml"
endif

##
# Builds a single test
##
test/gm/compile_models$(EXE) : test/gm/compile_models.o bin/libstan.a $(patsubst %.stan,%$(EXE),$(wildcard src/test/gm/model_specs/function_signatures*.stan))
	@mkdir -p $(dir $@)
	$(LINK.c) $(GTEST_MAIN) $< $(CFLAGS_GTEST) $(OUTPUT_OPTION) $(LIBGTEST) $(LDLIBS) $(LDLIBS_STANC)
ifeq ($(findstring test-,$(MAKECMDGOALS))$(findstring runtest/,$(MAKECMDGOALS)),)
	$@ --gtest_output="xml:$(basename $@).xml"
endif


.PRECIOUS: test/%.o
test/%$(EXE) : test/%.o bin/libstan.a bin/libstanc.a
	@mkdir -p $(dir $@)
	$(LINK.c) $(GTEST_MAIN) $< $(CFLAGS_GTEST) $(OUTPUT_OPTION) $(LIBGTEST) $(LDLIBS) $(LDLIBS_STANC)
ifeq ($(findstring test-,$(MAKECMDGOALS))$(findstring runtest/,$(MAKECMDGOALS)),)
	$@ --gtest_output="xml:$(basename $@).xml"
endif

test/%.o : src/test/%_test.cpp $(LIBGTEST)
	@mkdir -p $(dir $@)
	$(COMPILE.c) $(CFLAGS_GTEST) $< $(OUTPUT_OPTION)


##
# Rule for generating dependencies.
##
test/%.d : src/test/%_test.cpp
	@if test -d $(dir $@); \
	then \
	(set -e; \
	rm -f $@; \
	$(CC) $(CFLAGS) $(CFLAGS_GTEST) $(TARGET_ARCH) -MM $< > $@.$$$$; \
	sed -e 's,\($(notdir $*)\)\(_test\)\.o[ :]*,$(dir $@)\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$ ); \
	fi

ifneq (,$(filter test-unit,$(MAKECMDGOALS)))
  -include $(addsuffix .d, $(UNIT_TESTS)) 
endif
ifneq (,$(filter test-models,$(MAKECMDGOALS)))
  -include $(addsuffix .d, $(MODEL_TESTS)) 
endif
ifneq (,$(filter test-bugs,$(MAKECMDGOALS)))
  -include $(addsuffix .d, $(BUGS_TESTS)) 
endif
ifneq (,$(filter test-all,$(MAKECMDGOALS)))
  -include $(addsuffix .d, $(UNIT_TESTS)) 
  -include $(addsuffix .d, $(MODEL_TESTS)) 
endif

##
# run target which will allow for parallel execution of
# tests.
## 
.PHONY: runtest/%
.SECONDARY:
runtest/% : %$(EXE)
	@echo '------------------------------------------------------------'
	$< --gtest_output="xml:$*.xml";

.PHONY: runtest_no_fail/%
.SECONDARY:
runtest_no_fail/% : %$(EXE)
	@echo '------------------------------------------------------------'
	-$< --gtest_output="xml:$*.xml";

##
# target path_separator for use in some tests that need to 
# call executables.
##
.PHONY: path_separator
path_separator :
	@echo $(PATH_SEPARATOR)
