informix-db/Makefile
Ryan Malloy 783b2bec97 Verify Informix 14.10 and 12.10; make the version matrix reproducible
Closes out the field report that prompted 2026.05.08.2. Full integration
suite, same commit, all green:

  Informix 15.0.1.0.3DE     241 / 241
  Informix 14.10.FC7W1DE    241 / 241
  Informix 12.10.FC12W1DE   241 / 241

Including smart-LOB. The 28-type round-trip produces byte-identical wire
output on all three — same type codes, same encoded lengths, same values.
There is no 12-vs-14-vs-15 wire difference for anything we support.

Testing three versions by hand was tedious and undocumented, which is
part of why it never happened. Now:

  make ifx-legacy-up      12.10 on 9089, 14.10 on 9090, alongside 15 on 9088
  make ifx-legacy-setup   blobspace1 + sbspace1 in both
  make test-matrix        the suite against all three

tests/setup-spaces.sh absorbs the per-image differences that made this
annoying: 12.10/14.10 use a flat INFORMIXDIR while 15 nests a versioned
subdirectory; ONCONFIG is named differently across images; `bash -lc`
wipes INFORMIXDIR and makes every utility fail with a misleading
"Unable to read $INFORMIXDIR (/usr/informix)"; and 12.10 DE ships no
ontape at all (the level-0 archive turns out to be unnecessary anyway).
Without blobspace1/sbspace1, ~21 tests fail with errors that look like
driver bugs and aren't.

The documented workflow was validated from scratch — containers removed,
recreated via compose, spaces created via the script, matrix run — rather
than written up afterward from whichever commands happened to work. The
README claim this replaces was wrong precisely because nobody did that.
2026-08-27 00:36:35 -06:00

138 lines
5.6 KiB
Makefile

# informix-db — common dev commands
#
# uv-managed; run `make help` for the full target list.
# Image digest pinned in tests/docker-compose.yml; mirrored here for
# tab-complete-able commands like `make ifx-logs` that don't go through
# docker-compose.
IFX_CONTAINER ?= informix-db-test
.PHONY: help install lint format test test-integration test-all test-pdu \
ifx-up ifx-down ifx-logs ifx-shell ifx-status \
capture clean
help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) \
| awk -F':.*## ' '{printf " %-20s %s\n", $$1, $$2}'
# ----------------------------------------------------------------------------
# Python / dev workflow
# ----------------------------------------------------------------------------
install: ## Sync dev dependencies (uv sync --extra dev)
uv sync --extra dev
lint: ## Run ruff
uv run ruff check src/ tests/
format: ## Auto-format with ruff
uv run ruff format src/ tests/
uv run ruff check src/ tests/ --fix
test: ## Run unit tests (no Docker required)
uv run pytest
test-integration: ## Run integration tests (needs Informix container; see `make ifx-up`). Excludes benchmarks; use `make bench` for those.
uv run pytest -m "integration and not benchmark"
test-all: ## Run unit + integration tests (no benchmarks; use `make bench` for those)
uv run pytest -m "not benchmark"
test-pdu: ## Run only the JDBC-vs-Python PDU regression test
uv run pytest tests/test_pdu_match.py -v
bench: ## Run all benchmarks (needs container for end-to-end; codec works standalone)
uv run pytest tests/benchmarks/ -m benchmark --benchmark-only \
--benchmark-columns=median,iqr,mean,stddev,ops,rounds \
--benchmark-sort=mean
bench-codec: ## Run codec micro-benchmarks only (no container required)
uv run pytest tests/benchmarks/test_codec_perf.py -m benchmark --benchmark-only \
--benchmark-columns=median,iqr,mean,stddev,ops,rounds \
--benchmark-sort=mean
bench-save: ## Save current bench run under .results/ (manual: copy to baseline.json)
uv run pytest tests/benchmarks/ -m benchmark --benchmark-only \
--benchmark-storage=tests/benchmarks/.results \
--benchmark-save=run
# ----------------------------------------------------------------------------
# Informix dev container
# ----------------------------------------------------------------------------
ifx-up: ## Start the Informix dev container (pinned by digest)
docker compose -f tests/docker-compose.yml up -d
@echo " Container: $(IFX_CONTAINER)"
@echo " Listener: 127.0.0.1:9088 (SQLI native)"
@echo " Login: informix / in4mix on database sysmaster"
ifx-down: ## Stop and remove the Informix container
docker compose -f tests/docker-compose.yml down
ifx-logs: ## Tail the container logs
docker logs -f $(IFX_CONTAINER)
ifx-shell: ## Drop into a shell inside the container
docker exec -it $(IFX_CONTAINER) bash
ifx-status: ## Check container health and listener readiness
@docker ps --filter name=$(IFX_CONTAINER) --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
@nc -zv 127.0.0.1 9088 2>&1 | head -1
ifx-spaces: ## Create blobspace1 + sbspace1 in the Informix 15 container (needed for LOB tests)
tests/setup-spaces.sh $(IFX_CONTAINER)
# ----------------------------------------------------------------------------
# Server-compatibility matrix: Informix 12.10 / 14.10 alongside 15
# ----------------------------------------------------------------------------
# The legacy containers run on 9089 / 9090 so they coexist with the primary
# 15 container on 9088. The integration suite targets whichever server
# IFX_PORT names, so the matrix is just the same suite three times.
ifx-legacy-up: ## Start Informix 12.10 (9089) and 14.10 (9090) alongside 15
docker compose -f tests/docker-compose.legacy.yml up -d
@echo " 12.10 -> 127.0.0.1:9089"
@echo " 14.10 -> 127.0.0.1:9090"
@echo " Engine init takes ~1-3 min on first start; then: make ifx-legacy-setup"
ifx-legacy-setup: ## Create blobspace1 + sbspace1 in both legacy containers
tests/setup-spaces.sh informix-db-test-1210
tests/setup-spaces.sh informix-db-test-1410
ifx-legacy-down: ## Stop and remove the legacy containers
docker compose -f tests/docker-compose.legacy.yml down
test-matrix: ## Run the integration suite against 15 (9088), 14.10 (9090), and 12.10 (9089)
@echo "=== Informix 15 (9088) ==="
@IFX_PORT=9088 uv run pytest -m "integration and not benchmark" -q --no-header
@echo "=== Informix 14.10 (9090) ==="
@IFX_PORT=9090 uv run pytest -m "integration and not benchmark" -q --no-header
@echo "=== Informix 12.10 (9089) ==="
@IFX_PORT=9089 uv run pytest -m "integration and not benchmark" -q --no-header
# ----------------------------------------------------------------------------
# Phase 0 spike: re-capture wire traffic against the dev container
# ----------------------------------------------------------------------------
capture: ## Re-capture all three reference scenarios (JDBC) under socat
@for s in connect-only select-1 dml-cycle; do \
echo "=== $$s ==="; \
socat -d -d -x TCP-LISTEN:9090,reuseaddr TCP:127.0.0.1:9088 \
2>"docs/CAPTURES/$$s.socat.log" & \
SOCAT_PID=$$!; \
sleep 0.4; \
IFX_PORT=9090 java -cp "build/ifxjdbc.jar:build/" tests.reference.RefClient $$s; \
sleep 0.3; \
kill $$SOCAT_PID 2>/dev/null; \
wait 2>/dev/null; \
echo " → docs/CAPTURES/$$s.socat.log"; \
done
# ----------------------------------------------------------------------------
# Cleanup
# ----------------------------------------------------------------------------
clean: ## Remove build artifacts and caches (keeps captures and decompiled JDBC source)
rm -rf dist/ .pytest_cache/ .ruff_cache/ .mypy_cache/
find src tests -name __pycache__ -type d -exec rm -rf {} +