# The MIT License (MIT)
#
# Copyright (C) 2026 Scott Duensing
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

# Package library suite: pkgTest against the package library's sources
# (src/libs/kpunch/pkg), built for the host with miniz, Monocypher and the
# crypto library's SHA-256 as pkg.lib has them, and the package server's
# client (pkgnet, over http and json; pkgTestNet.c runs a server of its
# own on the host's sockets); softwareTest and
# pkgbuildTest run the Software and Package Builder programs (compiled
# from their projects) through the shell fixture with those sources and
# the file operations library (appDrive.c: what the two share).

include ../dvxtest/dvxtest.mk

.DEFAULT_GOAL := all

PKG_DIR   = $(DVXTEST_ROOT)/src/libs/kpunch/pkg
MINIZ_DIR = $(PKG_DIR)/thirdparty/miniz
MONO_DIR  = $(SEC_DIR)/thirdparty/monocypher/src
SEC_DIR   = $(DVXTEST_ROOT)/src/libs/kpunch/crypto
NET_DIR   = $(DVXTEST_ROOT)/src/libs/kpunch/pkgnet
HTTP_DIR  = $(DVXTEST_ROOT)/src/libs/kpunch/http
JSON_DIR  = $(DVXTEST_ROOT)/src/libs/kpunch/json
BINDIR    = $(DVXTEST_BINDIR)/pkg
TEST_BIN  = $(BINDIR)/pkgTest
APP_TESTS = $(BINDIR)/softwareTest $(BINDIR)/pkgbuildTest
SHELLDIR     = $(DVXTEST_ROOT)/src/libs/kpunch/dvxshell
SHELLTESTDIR = $(DVXTEST_ROOT)/src/test/shell
FILEOPS_DIR  = $(DVXTEST_ROOT)/src/libs/kpunch/fileops
APPS_SO_DIR  = $(DVXTEST_OBJDIR)/apps
FILEOPS_OBJS = $(patsubst $(FILEOPS_DIR)/%.c,$(BINDIR)/fileops/%.o,$(wildcard $(FILEOPS_DIR)/*.c))
SHELL_OBJS   = $(patsubst $(SHELLDIR)/%.c,$(BINDIR)/shell/%.o,$(wildcard $(SHELLDIR)/*.c))
SHFIX_OBJ    = $(BINDIR)/shellFixture.o
SW_CFLAGS    = $(CFLAGS) -fno-omit-frame-pointer -I$(SHELLDIR) -I$(SHELLTESTDIR) -DDVXTEST_APPS_DIR='"$(APPS_SO_DIR)"' -DDVXTEST_FIXTURES_DIR='"$(BINDIR)"' -DSHELLTEST_BASSTUB_SO='"$(DVXTEST_BASSTUB_SO)"' -DSHELLTEST_BASCOMP='"$(DVXTEST_BASCOMP)"'
PKG_SRCS  = $(addprefix $(PKG_DIR)/,pkgBas.c pkgCli.c pkgDb.c pkgDpk.c pkgFormat.c pkgIni.c pkgManifest.c pkgOp.c pkgPlan.c pkgSign.c pkgSignMake.c pkgTrust.c pkgZip.c pkgZipJob.c pkgZipWrite.c) $(MINIZ_DIR)/miniz.c $(MONO_DIR)/monocypher.c $(MONO_DIR)/optional/monocypher-ed25519.c $(SEC_DIR)/secHash.c $(SEC_DIR)/secSign.c $(SEC_DIR)/security.c $(NET_DIR)/pkgNet.c $(NET_DIR)/pkgNetBas.c $(HTTP_DIR)/http.c $(HTTP_DIR)/httpBas.c $(JSON_DIR)/json.c $(JSON_DIR)/jsonBas.c $(DVXTEST_DIR)/hostLookup.c
PKG_OBJS  = $(patsubst %.c,$(BINDIR)/obj/%.o,$(notdir $(PKG_SRCS)))
CFLAGS    = $(DVXTEST_CFLAGS) -I$(PKG_DIR) -I$(NET_DIR) -I$(HTTP_DIR) -I$(JSON_DIR) -I$(MINIZ_DIR) -I$(MONO_DIR) -I$(DVXTEST_ROOT)/src/libs/kpunch -I$(DVXTEST_BASICDIR) -DBASIC_INCLUDE_DIR='"$(DVXTEST_ROOT)/src/include/basic"' $(PKG_MINIZ_FLAGS)

vpath %.c $(PKG_DIR) $(MINIZ_DIR) $(MONO_DIR) $(MONO_DIR)/optional $(SEC_DIR) $(NET_DIR) $(HTTP_DIR) $(JSON_DIR) $(DVXTEST_DIR)

.PHONY: all run clean host-tools

all: run

$(BINDIR)/obj/%.o: %.c $(DVX_MAKEFILES)
	@mkdir -p $(dir $@)
	$(HOSTCC) $(CFLAGS) -c -o $@ $<

$(TEST_BIN): pkgTest.c pkgTestBas.c pkgTestEngine.c pkgTestNet.c pkgServe.c pkgServe.h $(DVXTEST_DIR)/lookupHook.c $(PKG_OBJS) $(DVX_MAKEFILES) $(DVXTEST_ARCHIVES) $(DVXTEST_TASKS_A) $(DVXTEST_BASRT_A) | dvxtest-libs
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(CFLAGS) -o $@ pkgTest.c pkgTestBas.c pkgTestEngine.c pkgTestNet.c pkgServe.c $(DVXTEST_DIR)/lookupHook.c $(PKG_OBJS) $(DVXTEST_BASRT_A) $(DVXTEST_LDFLAGS) -Wl,--wrap=getaddrinfo -Wl,--whole-archive $(DVXTEST_LIBDVX_A) $(DVXTEST_TASKS_A) $(DVXTEST_LIB) -Wl,--no-whole-archive -ldl -lm

$(BINDIR)/fileops/%.o: $(FILEOPS_DIR)/%.c $(DVX_MAKEFILES)
	@mkdir -p $(dir $@)
	$(HOSTCC) $(SW_CFLAGS) -c -o $@ $<

$(BINDIR)/shell/%.o: $(SHELLDIR)/%.c $(DVX_MAKEFILES)
	@mkdir -p $(dir $@)
	$(HOSTCC) $(SW_CFLAGS) -c -o $@ $<

$(SHFIX_OBJ): $(SHELLTESTDIR)/shellFixture.c $(DVX_MAKEFILES)
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(SW_CFLAGS) -c -o $@ $<

$(BINDIR)/appDrive.o: appDrive.c appDrive.h $(DVX_MAKEFILES)
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(SW_CFLAGS) -c -o $@ $<

$(BINDIR)/pkgServe.o: pkgServe.c pkgServe.h $(DVX_MAKEFILES)
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(SW_CFLAGS) -c -o $@ $<

$(APP_TESTS): $(BINDIR)/%: %.c $(BINDIR)/appDrive.o $(BINDIR)/pkgServe.o $(PKG_OBJS) $(FILEOPS_OBJS) $(SHELL_OBJS) $(SHFIX_OBJ) $(DVX_MAKEFILES) $(DVXTEST_ARCHIVES) $(DVXTEST_TASKS_A) $(DVXTEST_BASRT_A) $(DVXTEST_BASSTUB_SO) | dvxtest-libs dvxtest-apps dvxtest-bascomp
	@mkdir -p $(BINDIR)
	$(HOSTCC) $(SW_CFLAGS) -o $@ $< $(BINDIR)/appDrive.o $(BINDIR)/pkgServe.o $(PKG_OBJS) $(FILEOPS_OBJS) $(SHELL_OBJS) $(SHFIX_OBJ) $(DVXTEST_LDFLAGS) -Wl,--whole-archive $(DVXTEST_BASRT_A) $(DVXTEST_LIBDVX_A) $(DVXTEST_TASKS_A) $(DVXTEST_LIB) -Wl,--no-whole-archive -ldl -lm

host-tools:
	$(MAKE) -C $(DVXTEST_ROOT)/src/tools host COV=0

dvxtest-apps: | host-tools

-include $(TEST_BIN).d $(PKG_OBJS:.o=.d) $(FILEOPS_OBJS:.o=.d) $(SHELL_OBJS:.o=.d) $(SHFIX_OBJ:.o=.d) $(BINDIR)/appDrive.d $(BINDIR)/pkgServe.d $(APP_TESTS:=.d)

run: $(TEST_BIN) $(APP_TESTS)
	cd $(BINDIR) && ASAN_OPTIONS=detect_leaks=1 ./pkgTest
	# Every app plugin exports the same appDescriptor symbol by design,
	# which ASan's ODR checker flags under RTLD_GLOBAL.
	cd $(BINDIR) && ASAN_OPTIONS=detect_leaks=1:detect_odr_violation=0 ./softwareTest
	cd $(BINDIR) && ASAN_OPTIONS=detect_leaks=1:detect_odr_violation=0 ./pkgbuildTest

clean:
	rm -rf $(BINDIR)
