# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
# Copyright (c) 2017-2024 Brett Sheffield <bacs@librecast.net>

TESTRUNNER := @TESTRUNNER@
CFLAGS := @CFLAGS@ -fno-builtin-malloc -fno-builtin-calloc -I../src
CPPFLAGS := @CPPFLAGS@
FALSE := @FALSE@
TEST_SOURCES := $(wildcard ????-????.c)
TEST_PROGS ?= $(TEST_SOURCES:.c=.test)
TEST_MULTICAST_Linux := ip route get ff1e:: 2> /dev/null | wc -l
TEST_MULTICAST_FreeBSD := case $$(route -6 get ff1e:: 2> /dev/null) in *REJECT*) echo 0;; *DONE*) echo 1;; *) echo 0 ;; esac
TEST_MULTICAST_NetBSD := case $$(/sbin/route -n get -inet6 ff1e:: 2>/dev/null) in *REJECT*) echo 0;; *DONE*) echo 1;; *) echo 0 ;; esac
TEST_MULTICAST_OpenBSD := case $$(route -n get -inet6 ff1e:: 2> /dev/null) in *REJECT*) echo 0;; *DONE*) echo 1;; *) echo 0 ;; esac
TEST_MULTICAST_OUT = $(shell $(TEST_MULTICAST) || /bin/true)
TEST_MULTICAST = $(TEST_MULTICAST_$(shell uname -s))
LDFLAGS = @LDFLAGS@ -L../src -Wl,-rpath,../src
LDLIBS := @LIBS@
NETTOOLS := @IFCONFIG@ @IPROUTE@
NOTOBJS := ../src/lcagent.o
OBJS := test.o testdata.o testnet.o $(filter-out $(NOTOBJS), $(wildcard ../src/*.o))
LASTLOG := lastlog.log
LOGFILE := $(shell mktemp "testlog-XXXXXX")
ANSI_RESET = "\033[0m"
ANSI_BOLD := "\033[0m\033[2m"
ANSI_GREEN = "\033[32m"
ANSI_RED = "\033[31m"
ANSI_YELLOW = "\033[33m"
ANSI_WHITE = "\033[37m"
PASS = $(ANSI_RESET)$(ANSI_GREEN)\ OK$(ANSI_RESET)
WARN = $(ANSI_RESET)$(ANSI_YELLOW)WARN$(ANSI_RESET)
FAIL = $(ANSI_RESET)$(ANSI_RED)FAIL$(ANSI_RESET)
UNKN = $(ANSI_RESET)$(ANSI_WHITE)????$(ANSI_RESET)
VALGRIND_LEAK_KINDS = definite,indirect,possible
VALGRIND = valgrind --leak-check=full --show-leak-kinds=$(VALGRIND_LEAK_KINDS) --max-stackframe=20480160 --error-exitcode=2 --errors-for-leak-kinds=$(VALGRIND_LEAK_KINDS) --track-origins=yes

define runtest =
export HAVE_MULTICAST_ROUTES="$(TEST_MULTICAST_OUT)"
@printf $(ANSI_BOLD)
@echo -n " $(1:.test=) "
@echo "================================================================================" >>$(LOGFILE)
@echo "`date +"%Y-%m-%d %H:%M:%S"` test begins" >>$(LOGFILE)
@echo "--------------------------------------------------------------------------------" >>$(LOGFILE)
@echo -n "===> TEST $(1:.test=) " >>$(LOGFILE)
@$(MEMCHECK) ./$(1) 2>>$(LOGFILE)
ret=$$?
@echo "--------------------------------------------------------------------------------" >>$(LOGFILE)
@echo "`date +"%Y-%m-%d %H:%M:%S"` test ends" >>$(LOGFILE)
@if [ $$ret -eq 0 ]; then \
	printf $(PASS); echo; \
elif [ $$ret -eq 1 ]; then \
	printf $(WARN); echo; \
elif [ $$ret -eq 2 ]; then \
	printf $(FAIL); echo; \
	fails=$$(( fails + 1 )) ; \
else \
	printf $(UNKN); echo; \
	fails=$$(( fails + 1 )) ; \
fi
$(eval tests_run=$(shell echo $$(($(tests_run)+1))))

endef

.PHONY: test clean logclean tmpclean netcheck

test: $(TESTRUNNER)

.PHONY: newtest
newtest:
	$(EDITOR) `./newtest.sh`

netcheck: $(NETTOOLS)

ifconfig:
	ifconfig

iproute:
	@echo "== LINKS ===================================================================="
	ip -c=never -d link show
	@echo "== ADDR ====================================================================="
	ip -c=never addr show
	@echo "== ROUTE ===================================================================="
	ip -c=never route show
	ip -6 -c=never route show
	@echo "== NEIGHBOURS ==============================================================="
	ip -6 -c=never neighbour
	@echo "== MROUTE ==================================================================="
	ip -6 -c=never mroute
	@echo "== NETNS ===================================================================="
	ip -6 -c=never netns
	@echo "============================================================================="

%.test: %.c $(OBJS)
	$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(OBJS) $(LDLIBS)

%.o: %.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<

lctest: $(TEST_PROGS)
	lctest -b $^

memcheck:
	MEMCHECK="$(VALGRIND)" $(MAKE) test

memcheck/%:
	MEMCHECK="$(VALGRIND)" $(MAKE) test/$(@F)

# if $(@F) is a directory, run tests in that directory
test/%:
	@if [ -d "$(@F)" ]; then
		$(eval TEST_PROGS=$(notdir $(wildcard $(@F)/*.test)))
		TEST_PROGS="$(TEST_PROGS)" $(MAKE) maketest
	else
		$(eval TEST_PROGS=0000-$(@F).test)
		TEST_PROGS="$(TEST_PROGS)" $(MAKE) maketest
	fi

.ONESHELL: maketest

maketest: $(TEST_PROGS)
	@fails=0
	ln -sf $(LOGFILE) $(LASTLOG)
	$(foreach x,$^,$(call runtest,$(x)))
	@echo -e "\n$(TIMESTAMP) - tests done" >> $(LOGFILE)
	@echo -e "$(tests_run) tests run\nlogfile: $(LOGFILE)\n"
	@if [ $$fails -gt 0 ]; then \
		echo ", $$fails tests failed"; \
		$(FALSE);
	else
		echo
	fi

logclean:
	$(RM) testlog-?????? $(LASTLOG)

tmpclean:
	$(RM) -r ????-????-??????
	$(RM) -r ????-????.src.tmp.??????
	$(RM) -r ????-????.dst.tmp.??????

clean: logclean tmpclean
	$(RM) *.o *.test

realclean: clean
	$(RM) Makefile
