Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
231 lines (212 loc) · 12.4 KB
/
Copy pathMakefile
File metadata and controls
231 lines (212 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# vgi-java — top-level test driver
#
# Mirrors vgi-go's Makefile shape: build, test, test-single, test-http.
# Tests are run by the C++ extension's unittest binary at
# $(VGI_BUILD_DIR)/test/unittest, from inside the vgi extension checkout.
#
# VGI_DIR is that checkout (the C++ extension repo: test/sql, scripts/run_tests.py,
# and its build/). It defaults to a sibling checkout of this repo; override it with
# make test VGI_DIR=/path/to/vgi
# VGI_BUILD_DIR (default $(VGI_DIR)/build/release) is still honored on its own:
# set only it, as older invocations did, and VGI_DIR is derived from it
# (<vgi>/build/<type> -> <vgi>).
ifneq ($(origin VGI_BUILD_DIR),undefined)
VGI_DIR ?= $(abspath $(VGI_BUILD_DIR)/../..)
endif
VGI_DIR ?= ../vgi
VGI_BUILD_DIR ?= $(VGI_DIR)/build/release
DUCKDB ?= $(VGI_BUILD_DIR)/duckdb
VGI_EXT ?= $(VGI_BUILD_DIR)/extension/vgi/vgi.duckdb_extension
UNITTEST ?= $(VGI_BUILD_DIR)/test/unittest
# Every lane hands the runner the extension's no_error_skip.json. Without a
# --test-config, DuckDB's sqllogictest runner turns any error containing "HTTP"
# or "Unable to connect" into a SKIP (exit 0) -- and over the http transport
# every worker error contains "HTTP", so real failures were reported as skips.
# Passed explicitly (run_tests.py also defaults to it) so a VGI_DIR too old to
# have the file fails loudly instead of quietly masking again.
TEST_CONFIG ?= $(abspath $(VGI_DIR))/test/configs/no_error_skip.json
EXAMPLE_WORKER := $(CURDIR)/vgi-example-worker/build/install/vgi-example-worker/bin/vgi-example-worker
# launch:<argv> location → C++ extension uses the AF_UNIX launcher protocol
# (see $(VGI_DIR)/docs/launcher-protocol.md) instead of subprocess-fork
# per ATTACH. Amortises JVM cold-start across the whole test run.
LAUNCHER_PREFIX ?= launch:
EXAMPLE_LOCATION := $(LAUNCHER_PREFIX)$(EXAMPLE_WORKER)
# Auxiliary fixture workers.
#
# 44 of the shared suite's 326 files gate on `require-env`, and 11 of those
# gates name a fixture worker serving a *different* catalog than `example`.
# ci/wrappers/ already routes the one worker binary into each of them (via
# VGI_WORKER_CATALOG_NAME), and ci/run-integration.sh exports them — but this
# lane did not, so a developer ran 282 cases locally while CI ran 293. Eleven
# files' worth of behaviour was CI-only, which is the wrong way round: the
# expensive lane should be the one that finds LESS.
#
# The wrappers exec $VGI_WORKER_BIN, so they need it in the environment.
WRAPPERS := $(CURDIR)/ci/wrappers
VERSIONED_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-versioned
VERSIONED_TABLES_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-versioned-tables
ATTACH_OPTIONS_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-attach-options
BAD_ENUM_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-bad-enum
BAD_PROTOCOL_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-bad-protocol
WRITABLE_TX_LOCATION := $(LAUNCHER_PREFIX)$(WRAPPERS)/vgi-worker-txfix
# Every fixture-worker variable the shared suite reads, in one place so `test`
# and `test-single` cannot drift apart.
#
# VGI_ATTACH_OPTIONS_REQUIRED_WORKER is the same wrapper as
# VGI_ATTACH_OPTIONS_WORKER: that worker serves the `attach_options_required`
# catalog too, and upstream split those assertions into their own file behind
# their own env var.
# VGI_WRITABLE_TX_WORKER is the txfix writable-table / transaction-hook fixture
# (vgi docs/writable_tx_fixtures.md), the same binary routed by its wrapper.
# VGI_TEST_BRANCH_DIR is the scratch dir the multi_branch_* fixtures and the
# .test files that seed them (parquet / csv) must BOTH name. The vgi Makefile
# exports it, so this lane inherited it under `make test_java` and not when run
# standalone — 7 files skipped depending on how you invoked the same target.
VGI_TEST_BRANCH_DIR ?= $(shell python3 -c 'import tempfile;print(tempfile.gettempdir())')
# VGI_RPC_FIXTURE_SCOPE puts the branch dir into the launcher's worker identity.
# The launcher shares one worker per (argv, cwd, VGI_RPC_* env) tuple, and
# VGI_TEST_BRANCH_DIR is not VGI_RPC_*: two lanes on one host using this same
# worker binary with different branch dirs shared a JVM that had read the OTHER
# lane's dir at startup, so scan_planning_filtered.test read a plan record the
# worker had written elsewhere. The worker ignores the variable itself.
FIXTURE_ENV := \
VGI_WORKER_BIN=$(EXAMPLE_WORKER) \
VGI_TEST_BRANCH_DIR=$(VGI_TEST_BRANCH_DIR) \
VGI_RPC_FIXTURE_SCOPE=$(VGI_TEST_BRANCH_DIR) \
VGI_TEST_WORKER=$(EXAMPLE_LOCATION) \
VGI_VERSIONED_WORKER=$(VERSIONED_LOCATION) \
VGI_VERSIONED_TABLES_WORKER=$(VERSIONED_TABLES_LOCATION) \
VGI_ATTACH_OPTIONS_WORKER=$(ATTACH_OPTIONS_LOCATION) \
VGI_ATTACH_OPTIONS_REQUIRED_WORKER=$(ATTACH_OPTIONS_LOCATION) \
VGI_BAD_ENUM_WORKER=$(BAD_ENUM_LOCATION) \
VGI_BAD_PROTOCOL_WORKER=$(BAD_PROTOCOL_LOCATION) \
VGI_WRITABLE_TX_FIXTURES=1 \
VGI_WRITABLE_TX_WORKER=$(WRITABLE_TX_LOCATION) \
VGI_REQUIRE_LAUNCHER_TRANSPORT=1
.PHONY: build smoke test test-http test-single clean print-engine-skips
## Build all worker dist images.
build:
./gradlew :vgi-example-worker:installDist
## Smoke: ATTACH + add_values(1,2). Pre-built worker assumed.
smoke: build
@if [ ! -x "$(DUCKDB)" ]; then \
echo "DuckDB binary missing at $(DUCKDB) — build the C++ extension first:"; \
echo " (cd $(VGI_DIR) && make release)"; \
exit 1; \
fi
@echo "Running smoke test against worker: $(EXAMPLE_LOCATION)"
@$(DUCKDB) -unsigned -c "LOAD '$(VGI_EXT)'; \
ATTACH 'example' AS example (TYPE vgi, LOCATION '$(EXAMPLE_LOCATION)'); \
SELECT example.add_values(1, 2) AS result; \
DETACH example;"
## Run the in-scope integration tests.
##
## Exclusions (audited 2026-08-21 — each is anchored so it drops exactly the
## files named, nothing else):
##
## simple_writable/ — writable VGI is genuinely unimplemented in this repo;
## there is no writable worker to point these at. (Upstream has no
## `writable/` directory today, so no glob is needed for one.)
##
## attach/ddl_wire_contract.test — KNOWN FAILURE against this worker, not a
## scope gap. vgi-rpc-java's RpcServer.validateParameterContract rejects the
## C++ extension's catalog_schema_create request over two disagreements:
## (a) it treats a dictionary-encoded utf8 (`on_conflict: Utf8[dictionary: 0]`)
## as a different type from plain `Utf8`, and (b) it wants `tags` non-nullable
## where the client sends it nullable. Reproduced 2026-08-21. Fix the
## validator, then delete this line — do NOT re-broaden the glob.
##
## Deliberately NOT excluded any more:
## * bearer_auth/ — the worker has wired bearer auth since 40af24a
## (2026-06-13, Main.java buildHttpConfig); the test self-skips on
## `require-env VGI_TEST_BEARER_TOKEN`, which this lane does not set.
## Wiring a real bearer lane needs an HTTP worker booted on an ephemeral
## port (see vgi-rust ci/run-integration.sh) — follow-up work.
## * the rest of attach/ — 12 of the 13 files gate on fixture-worker env vars
## (VGI_VERSIONED*_WORKER / VGI_ATTACH_OPTIONS*_WORKER) that ci/run-integration.sh
## exports but this lane does not, so they skip visibly instead of silently
## vanishing from the staged set.
## * accumulate/attach_scope.test and catalog/multi_branch_two_writable.test —
## both pass here; they were only ever collateral damage of the unanchored
## `*attach*` / `*writable*` globs.
# Coverage gates — see the note in vgi/Makefile (VGI_EXPECTED_SKIPS), and
# ci/run-integration.sh, which has had MIN_EXECUTED / EXPECTED_SKIP_REASONS all
# along. This target did not: it invoked `unittest` bare, and a lane that stops
# running tests reports GREEN under that (fewer results, all passing). So the
# repo could pass `make test` while the CI script would have caught the same
# lane silently shrinking. Same two gates, same reasoning, now on both paths.
#
# Java runs 299 today (294, plus the five catalog/catalog_contents*.test files,
# which now run against this worker's own contents_* fixture catalogs).
JAVA_MIN_EXECUTED ?= 295
# Parallel. This lane was once pinned serial because -j 6 failed 8
# table_buffering files; the cause was the crash-recovery tests SIGKILLing the
# shared launcher JVM, not a java-worker race. Those tests now live in vgi's
# test_deferred/crash_recovery/ and no longer run here.
JAVA_JOBS ?= 6
# Engine-gated native tests (VGI_DIR/CLAUDE.md, "Gate only the cases that need
# the feature"). The native Makefile decides which engine features the built
# DuckDB has (VGI_ENGINE_TEST_VARS: on Haybarn each is 1, on upstream unset) and
# the skip reasons that gating produces (VGI_ENGINE_EXPECTED_SKIPS). Take both
# from VGI_DIR instead of restating them, so a new engine gate needs no change
# here. The skip list is read with `--eval` (GNU make >= 4); an older make falls
# back to `require-env-not VAR` for each variable engine_test_env reports set.
VGI_ENGINE_TEST_ENV := $(shell $(MAKE) -s --no-print-directory -C $(VGI_DIR) engine_test_env 2>/dev/null)
VGI_ENGINE_EXPECTED_SKIPS := $(strip $(shell $(MAKE) -s --no-print-directory -C $(VGI_DIR) \
--eval 'vgi_java_print_engine_skips: ; $$(info $$(VGI_ENGINE_EXPECTED_SKIPS))@:' vgi_java_print_engine_skips 2>/dev/null))
ifeq ($(VGI_ENGINE_EXPECTED_SKIPS),)
VGI_ENGINE_EXPECTED_SKIPS := $(foreach kv,$(VGI_ENGINE_TEST_ENV),--allow-skip 'require-env-not $(firstword $(subst =, ,$(kv)))')
endif
COVERAGE_GATE := --min-executed $(JAVA_MIN_EXECUTED) \
--allow-skip 'require spatial' \
--allow-skip 'require-env VGI_DOCKER_IMAGE' \
--allow-skip 'require-env VGI_DOCKER_TCP_IMAGE' \
--allow-skip 'require-env VGI_GITHUB_NETWORK_TESTS' \
--allow-skip 'require-env VGI_TEST_ICEBERG' \
--allow-skip 'require-env VGI_TEST_COMPANION_TARGET' \
--allow-skip 'require-env VGI_TEST_BEARER_TOKEN' \
--allow-skip 'require-env VGI_TEST_BRANCH_DIR' \
--allow-skip 'require-env VGI_HTTP_TRANSPORT' \
--allow-skip 'require-env VGI_HTTP_DISABLE_ZSTD' \
--allow-skip 'require-env VGI_HTTP_NO_COMPRESSION' \
--allow-skip 'require-env VGI_VERSIONED_HTTP_WORKER' \
--allow-skip 'require-env VGI_VERSIONED_TABLES_HTTP_WORKER' \
--allow-skip 'require-env VGI_WORKER_SUPPORTS_DYNAMIC_CODE' \
--allow-skip 'require-env VGI_SIMPLE_WRITABLE_WORKER' \
--allow-skip 'require-env VGI_SCHEMA_RECONCILE_DB' \
--allow-skip 'require-env VGI_RULES_WORKER' \
--allow-skip 'require-env VGI_REQUIRE_LAUNCHER_TRANSPORT' \
--allow-skip 'require-env VGI_ATTACH_OPTIONS_REQUIRED_WORKER' \
--allow-skip 'require-env VGI_BAD_ENUM_WORKER' \
--allow-skip 'require-env VGI_BAD_PROTOCOL_WORKER' \
--allow-skip 'require-env VGI_DATABASE_BUN_WORKER' \
--allow-skip 'require-env VGI_DATABASE_PYTHON_WORKER' \
--allow-skip 'require-env VGI_DATABASE_RUST_WORKER' \
--allow-skip 'require-env VGI_MALFORMED_BATCH_WORKER' \
--allow-skip 'require-env VGI_ROWID_CONSTRAINT_WORKER' \
$(VGI_ENGINE_EXPECTED_SKIPS)
test: build
@cd $(VGI_DIR) && set -a && eval "$$($(MAKE) -s --no-print-directory engine_test_env 2>/dev/null)" && set +a && \
$(FIXTURE_ENV) python3 scripts/run_tests.py -j $(JAVA_JOBS) --test-config $(TEST_CONFIG) $(COVERAGE_GATE) \
"test/sql/integration/*" "~test/sql/integration/simple_writable/*"
## The whole suite over the HTTP transport, exactly as CI's `integration (http)`
## lane runs it: ci/run-integration.sh boots the example worker (and the
## versioned / versioned_tables / attach_options catalogs) as HTTP servers, with
## the skip allowlist and executed-case floor, and --test-config
## $(TEST_CONFIG) so no worker error is reported as a skip. Driven by this
## checkout's unittest instead of CI's prebuilt haybarn-unittest, which links
## its extensions (RUNNER_LINKS_EXTENSIONS=1: no INSTALL preprocessing).
test-http: build
@VGI_SRC=$(abspath $(VGI_DIR)) HAYBARN_UNITTEST=$(abspath $(UNITTEST)) \
VGI_WORKER_BIN=$(EXAMPLE_WORKER) VGI_TEST_CONFIG=$(TEST_CONFIG) TRANSPORT=http \
RUNNER_LINKS_EXTENSIONS=1 \
ci/run-integration.sh
## Run a single sqllogictest by file name.
test-single: build
@if [ -z "$(TEST)" ]; then echo "usage: make test-single TEST=test/sql/integration/scalar/add_values.test"; exit 1; fi
@cd $(VGI_DIR) && set -a && eval "$$($(MAKE) -s --no-print-directory engine_test_env 2>/dev/null)" && set +a && $(FIXTURE_ENV) $(abspath $(UNITTEST)) --test-config $(TEST_CONFIG) --test-dir $(abspath $(VGI_DIR)) "$(TEST)"
clean:
./gradlew clean
## Show the engine-gated skip reasons and variables taken from VGI_DIR.
print-engine-skips:
@$(info engine env: $(VGI_ENGINE_TEST_ENV))$(info engine skips: $(VGI_ENGINE_EXPECTED_SKIPS)):