@@ -12,6 +12,51 @@ BENCH_KIND ?= all
1212
1313# Main packages to test/build
1414MAIN_PACKAGES := $(shell $(GO_CMD ) list ./...)
15+ COVERPKG := $(shell $(GO_CMD ) list ./... | grep -v '/cypher/parser$$' | tr '\n' ',' | sed 's/,$$//')
16+
17+ # Metric configuration
18+ METRICS_DIR ?= .coverage
19+ COVERAGE_PROFILE ?= $(METRICS_DIR ) /unit.out
20+ COVERAGE_FUNC_REPORT ?= $(METRICS_DIR ) /coverage.txt
21+ CYCLO_REPORT ?= $(METRICS_DIR ) /cyclomatic.txt
22+ CRAP_TEXT_REPORT ?= $(METRICS_DIR ) /crap.txt
23+ CRAP_JSON_REPORT ?= $(METRICS_DIR ) /crap.json
24+ QUALITY_TEXT_REPORT ?= $(METRICS_DIR ) /quality.txt
25+ QUALITY_JSON_REPORT ?= $(METRICS_DIR ) /quality.json
26+ METRICS_HTML_REPORT ?= $(METRICS_DIR ) /metrics.html
27+ METRICS_IGNORE ?= (^|/)(testdata|vendor)/|_test\.go$$|^cypher/parser/
28+ CYCLO_TOP ?= 20
29+ CYCLO_OVER ?= 25
30+ CRAP_TOP ?= 20
31+ CRAP_OVER ?= 30
32+ METRICS_ENFORCE ?= 0
33+ BENCHMARK_REPORT ?=
34+ BENCHMARK_BASELINE ?=
35+ BENCHMARK_REGRESSION ?= 0.20
36+ FUZZ_REPORT ?=
37+ MUTATION_REPORT ?=
38+ BACKEND_RESULT_ARGS ?=
39+ BACKEND_PG_REPORT ?= $(METRICS_DIR ) /integration-pg.json
40+ BACKEND_NEO4J_REPORT ?= $(METRICS_DIR ) /integration-neo4j.json
41+ QUALITY_BENCHMARK_REPORT ?= $(METRICS_DIR ) /benchmark.json
42+ QUALITY_BENCHMARK_MARKDOWN ?= $(METRICS_DIR ) /benchmark.md
43+
44+ QUALITY_INPUTS := $(BACKEND_RESULT_ARGS )
45+ ifneq ($(strip $(BENCHMARK_REPORT ) ) ,)
46+ QUALITY_INPUTS += -benchmark-report $(BENCHMARK_REPORT )
47+ endif
48+ ifneq ($(strip $(BENCHMARK_BASELINE ) ) ,)
49+ QUALITY_INPUTS += -benchmark-baseline $(BENCHMARK_BASELINE )
50+ endif
51+ ifneq ($(strip $(FUZZ_REPORT ) ) ,)
52+ QUALITY_INPUTS += -fuzz-report $(FUZZ_REPORT )
53+ endif
54+ ifneq ($(strip $(MUTATION_REPORT ) ) ,)
55+ QUALITY_INPUTS += -mutation-report $(MUTATION_REPORT )
56+ endif
57+ QUALITY_INPUTS += -benchmark-regression $(BENCHMARK_REGRESSION )
58+
59+ .PHONY : default all build deps tidy lint format test test_all test_integration test_neo4j test_pg test_update complexity complexity_check crap crap_check quality quality_check quality_backend quality_bench metrics metrics_check generate clean help
1560
1661# Default target
1762default : help
@@ -41,9 +86,11 @@ format:
4186 @find ./ -name ' *.go' -print0 | xargs -P 12 -0 -I ' {}' goimports -w ' {}'
4287
4388# Test targets
44- test :
89+ test : $( METRICS_DIR )
4590 @echo " Running tests..."
46- @$(GO_CMD ) test -race -cover -count=1 -parallel=10 $(MAIN_PACKAGES )
91+ @$(GO_CMD ) test -race -covermode=atomic -coverprofile=$(COVERAGE_PROFILE ) -coverpkg=$(COVERPKG ) -count=1 -parallel=10 $(MAIN_PACKAGES )
92+ @$(GO_CMD ) tool cover -func=$(COVERAGE_PROFILE ) > $(COVERAGE_FUNC_REPORT )
93+ @echo " Coverage report written to $( COVERAGE_FUNC_REPORT) "
4794
4895test_all : test test_integration
4996
@@ -76,6 +123,78 @@ test_update:
76123 @cp -fv cypher/models/pgsql/test/updated_cases/* cypher/models/pgsql/test/translation_cases
77124 @rm -rf cypher/models/pgsql/test/updated_cases
78125
126+ # Metric targets
127+ $(METRICS_DIR ) :
128+ @mkdir -p $(METRICS_DIR )
129+
130+ complexity : $(METRICS_DIR )
131+ @echo " Measuring cyclomatic complexity..."
132+ @$(GO_CMD ) tool gocyclo -top $(CYCLO_TOP ) -ignore ' $(METRICS_IGNORE)' . | tee $(CYCLO_REPORT )
133+ @echo " Cyclomatic complexity report written to $( CYCLO_REPORT) "
134+
135+ complexity_check : $(METRICS_DIR )
136+ @echo " Checking cyclomatic complexity..."
137+ @if [ " $( METRICS_ENFORCE) " = " 1" ]; then \
138+ $(GO_CMD ) tool gocyclo -over $(CYCLO_OVER ) -ignore ' $(METRICS_IGNORE)' . | tee $(CYCLO_REPORT ) ; \
139+ else \
140+ $(GO_CMD ) tool gocyclo -top $(CYCLO_TOP ) -ignore ' $(METRICS_IGNORE)' . | tee $(CYCLO_REPORT ) ; \
141+ echo " METRICS_ENFORCE=0; cyclomatic complexity threshold $( CYCLO_OVER) is report-only." ; \
142+ fi
143+
144+ crap : test
145+ @echo " Calculating CRAP metrics..."
146+ @$(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -text $(CRAP_TEXT_REPORT ) -json $(CRAP_JSON_REPORT ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT )
147+ @echo " CRAP and quality reports written to $( CRAP_TEXT_REPORT) , $( CRAP_JSON_REPORT) , $( QUALITY_TEXT_REPORT) , $( QUALITY_JSON_REPORT) , and $( METRICS_HTML_REPORT) "
148+
149+ crap_check : test
150+ @echo " Checking CRAP metrics..."
151+ @if [ " $( METRICS_ENFORCE) " = " 1" ]; then \
152+ $(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -text $(CRAP_TEXT_REPORT ) -json $(CRAP_JSON_REPORT ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) -fail-over $(CRAP_OVER ) -fail-quality; \
153+ else \
154+ $(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -text $(CRAP_TEXT_REPORT ) -json $(CRAP_JSON_REPORT ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) ; \
155+ echo " METRICS_ENFORCE=0; CRAP threshold $( CRAP_OVER) is report-only." ; \
156+ fi
157+
158+ quality : test
159+ @echo " Calculating quality metrics..."
160+ @$(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) -stdout=false
161+ @echo " Quality reports written to $( QUALITY_TEXT_REPORT) , $( QUALITY_JSON_REPORT) , and $( METRICS_HTML_REPORT) "
162+
163+ quality_check : test
164+ @echo " Checking quality metrics..."
165+ @if [ " $( METRICS_ENFORCE) " = " 1" ]; then \
166+ $(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) -stdout=false -fail-quality; \
167+ else \
168+ $(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) $(QUALITY_INPUTS ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) -stdout=false; \
169+ echo " METRICS_ENFORCE=0; quality watch signals are report-only." ; \
170+ fi
171+
172+ quality_backend : test
173+ @echo " Running backend equivalence test captures..."
174+ @if [ -z " $( PG_CONNECTION_STRING) " ] || [ -z " $( NEO4J_CONNECTION_STRING) " ]; then \
175+ echo " PG_CONNECTION_STRING and NEO4J_CONNECTION_STRING are required." ; \
176+ exit 1; \
177+ fi
178+ @set +e; \
179+ CONNECTION_STRING=" $( PG_CONNECTION_STRING) " $(GO_CMD ) test -json -tags ' manual_integration integration' -race -cover -count=1 -p=1 -parallel=1 $(MAIN_PACKAGES ) > $(BACKEND_PG_REPORT ) ; \
180+ pg_status=$$? ; \
181+ CONNECTION_STRING=" $( NEO4J_CONNECTION_STRING) " $(GO_CMD ) test -json -tags ' manual_integration integration' -race -cover -count=1 -p=1 -parallel=1 $(MAIN_PACKAGES ) > $(BACKEND_NEO4J_REPORT ) ; \
182+ neo4j_status=$$? ; \
183+ set -e; \
184+ $(GO_CMD ) tool dawgs-metrics -source-root . -coverprofile $(COVERAGE_PROFILE ) -ignore ' $(METRICS_IGNORE)' -top $(CRAP_TOP ) -over $(CRAP_OVER ) -cyclo-over $(CYCLO_OVER ) -backend-result pg=$(BACKEND_PG_REPORT ) -backend-result neo4j=$(BACKEND_NEO4J_REPORT ) $(QUALITY_INPUTS ) -quality-text $(QUALITY_TEXT_REPORT ) -quality-json $(QUALITY_JSON_REPORT ) -html $(METRICS_HTML_REPORT ) -stdout=false; \
185+ if [ $$ pg_status -ne 0 ]; then exit $$ pg_status; fi ; \
186+ if [ $$ neo4j_status -ne 0 ]; then exit $$ neo4j_status; fi
187+
188+ quality_bench : $(METRICS_DIR )
189+ @echo " Running benchmark capture..."
190+ @$(GO_CMD ) run ./cmd/benchmark -output $(QUALITY_BENCHMARK_MARKDOWN ) -json-output $(QUALITY_BENCHMARK_REPORT )
191+ @echo " Benchmark reports written to $( QUALITY_BENCHMARK_MARKDOWN) and $( QUALITY_BENCHMARK_REPORT) "
192+
193+ metrics : complexity crap
194+
195+ metrics_check : METRICS_ENFORCE = 1
196+ metrics_check : complexity_check crap_check
197+
79198# Utility targets
80199generate :
81200 @echo " Running code generation..."
@@ -87,6 +206,7 @@ clean:
87206
88207 @rm -rf cypher/analyzer/updated_cases/
89208 @rm -rf cypher/models/pgsql/test/updated_cases
209+ @rm -rf $(METRICS_DIR)
90210
91211help :
92212 @echo " Available targets:"
@@ -114,6 +234,13 @@ help:
114234 @echo " test_neo4j - Run Neo4j integration tests"
115235 @echo " test_pg - Run PostgreSQL integration tests"
116236 @echo " test_update - Update test cases"
237+ @echo " complexity - Report cyclomatic complexity"
238+ @echo " crap - Report CRAP scores from unit test coverage"
239+ @echo " quality - Report drift, equivalence, invariant, fuzz, mutation, and benchmark signals"
240+ @echo " quality_backend - Capture backend equivalence test results"
241+ @echo " quality_bench - Capture benchmark markdown and JSON reports"
242+ @echo " metrics - Run cyclomatic complexity, CRAP, and quality reports"
243+ @echo " metrics_check - Enforce cyclomatic complexity, CRAP, and quality thresholds"
117244 @echo " "
118245 @echo " Utility:"
119246 @echo " clean - Clean build artifacts"
0 commit comments