# 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.


# Serial stack test suite (T8) -- native host build.
#
# testSerial: compiles packet.c, security.c and secLink.c from the shared
# serial library unmodified against the in-process loopback shim
# (loopShim.h), using the same -include / stubs/ trick as tools/proxy.
# testSerialProxy: compiles the same sources against the proxy's socket
# shim (sockShim.h) plus proxy.c itself (main renamed via -Dmain) and
# drives the proxy end-to-end over real sockets from testProxy.c.
#
# `make` builds and runs both; `make proxy` runs only the proxy suite;
# `make asan` is the default build; `make plain` builds without sanitizers.

CC       = gcc
SAN     ?= 1
SERIAL   = ../../libs/kpunch/serial
PROXYDIR = ../../tools/proxy
STUBS    = $(PROXYDIR)/stubs
BINDIR   = ../../../bin/test

# Sanitized (SAN=1, the default, matching the other host suites) and plain
# builds keep separate object directories and binaries so a mode switch
# never links stale objects.
ifeq ($(SAN),1)
SANFLAGS = -fsanitize=address,undefined -fno-omit-frame-pointer
OBJDIR   = ../../../obj/test/serial/san
TARGET   = $(BINDIR)/testSerial
else
SANFLAGS =
OBJDIR   = ../../../obj/test/serial/plain
TARGET   = $(BINDIR)/testSerialPlain
endif

CFLAGS  ?= -O1 -g -Wall -Wextra -Werror $(SANFLAGS)
LDFLAGS ?= $(SANFLAGS)

# testSerial interposes secCipherCreate/secDhCreate to drive allocation
# failure paths.  Kept out of LDFLAGS so a coverage LDFLAGS override on
# the command line cannot lose the wraps.
WRAP_LDFLAGS = -Wl,--wrap=secCipherCreate -Wl,--wrap=secDhCreate

# testSerialProxy interposes accept/listen/secLinkOpen the same way, gated
# by environment variables inside testProxy.c.
PROXY_WRAP_LDFLAGS = -Wl,--wrap=accept -Wl,--wrap=listen -Wl,--wrap=secLinkOpen

PROXY_TARGET = $(TARGET)Proxy

OBJS  = $(OBJDIR)/loopShim.o $(OBJDIR)/packet.o $(OBJDIR)/security.o \
        $(OBJDIR)/secLink.o $(OBJDIR)/testSerial.o
POBJS = $(OBJDIR)/sockShim.o $(OBJDIR)/sockPacket.o $(OBJDIR)/security.o \
        $(OBJDIR)/sockSecLink.o $(OBJDIR)/proxyMain.o $(OBJDIR)/testProxy.o

.PHONY: all build asan plain proxy clean

all: build
	$(TARGET)
	$(PROXY_TARGET)

build: $(TARGET) $(PROXY_TARGET)

# Kept for compatibility: `make asan` is now the default build.
asan: all

plain:
	$(MAKE) SAN=0 all

proxy: $(PROXY_TARGET)
	$(PROXY_TARGET)

$(TARGET): $(OBJS) | $(BINDIR)
	$(CC) $(LDFLAGS) $(WRAP_LDFLAGS) -o $@ $(OBJS)

$(PROXY_TARGET): $(POBJS) | $(BINDIR)
	$(CC) $(LDFLAGS) $(PROXY_WRAP_LDFLAGS) -o $@ $(POBJS)

$(OBJDIR)/loopShim.o: loopShim.c loopShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -c -o $@ $<

$(OBJDIR)/testSerial.o: testSerial.c loopShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(SERIAL) -c -o $@ $<

$(OBJDIR)/testProxy.o: testProxy.c $(PROXYDIR)/sockShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(SERIAL) -I$(PROXYDIR) -c -o $@ $<

# Library sources against the loopback shim: block the real rs232.h,
# inject loopShim.h, stub the DOS-only headers (pc.h, go32.h, sys/farptr.h).
$(OBJDIR)/packet.o: $(SERIAL)/packet/packet.c loopShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I. -I$(STUBS) -include loopShim.h -c -o $@ $<

$(OBJDIR)/security.o: $(SERIAL)/security/security.c | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(STUBS) -c -o $@ $<

$(OBJDIR)/secLink.o: $(SERIAL)/seclink/secLink.c loopShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I. -include loopShim.h -c -o $@ $<

# The same library sources against the proxy's socket shim, plus proxy.c
# itself with main() renamed so the test harness can fork and call it.
$(OBJDIR)/sockShim.o: $(PROXYDIR)/sockShim.c $(PROXYDIR)/sockShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -c -o $@ $<

$(OBJDIR)/proxyMain.o: $(PROXYDIR)/proxy.c $(PROXYDIR)/sockShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -Dmain=proxyMain -c -o $@ $<

$(OBJDIR)/sockPacket.o: $(SERIAL)/packet/packet.c $(PROXYDIR)/sockShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(PROXYDIR) -I$(STUBS) -include $(PROXYDIR)/sockShim.h -c -o $@ $<

$(OBJDIR)/sockSecLink.o: $(SERIAL)/seclink/secLink.c $(PROXYDIR)/sockShim.h | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(PROXYDIR) -include $(PROXYDIR)/sockShim.h -c -o $@ $<

$(OBJDIR):
	mkdir -p $(OBJDIR)

$(BINDIR):
	mkdir -p $(BINDIR)

clean:
	rm -rf $(OBJDIR) $(TARGET) $(PROXY_TARGET)
