You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2026/05/21 13:28:49 UTC

(skywalking-banyandb) branch main updated: fix(test/cases/measure): preserve Apache license header on captured want fixtures and gate the capture loop (#1137)

This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git


The following commit(s) were added to refs/heads/main by this push:
     new 349a41316 fix(test/cases/measure): preserve Apache license header on captured want fixtures and gate the capture loop (#1137)
349a41316 is described below

commit 349a4131690de0bff7bebc81d94cb260f240caf4
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Thu May 21 21:28:43 2026 +0800

    fix(test/cases/measure): preserve Apache license header on captured want fixtures and gate the capture loop (#1137)
---
 .gitignore                                     |  1 +
 Makefile                                       |  5 ++-
 test/cases/measure/cmd/capture/capture_test.go | 27 ++++++++++++++--
 test/cases/measure/cmd/generate/capture.go     |  9 +++++-
 test/cases/measure/cmd/generate/types.go       | 18 ++---------
 test/cases/measure/data/license_header.go      | 43 ++++++++++++++++++++++++++
 6 files changed, 83 insertions(+), 20 deletions(-)

diff --git a/.gitignore b/.gitignore
index 336e73309..ca1ab487a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,6 +77,7 @@ gomock_reflect*
 # Claude
 .claude/
 .omc/
+.omx/
 
 # eBPF generated files and binaries
 fodc/agent/internal/ktm/iomonitor/ebpf/generated/vmlinux.h
diff --git a/Makefile b/Makefile
index cd62b858f..806d24366 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,9 @@ generate: default  ## Generate API codes
 generate-test-cases:  ## Regenerate measure query test cases (input/*.ql, input/*.yaml)
 	go run ./test/cases/measure/cmd/generate generate test/cases/measure/data
 
+capture-test-cases:  ## Capture measure query want fixtures (data/want/*.yaml) by running queries against a standalone server
+	CAPTURE_WANT_FIXTURES=1 go test -count=1 -timeout 5m -run TestCapture ./test/cases/measure/cmd/capture/
+
 build: TARGET=all
 build: default  ## Build all projects
 
@@ -270,7 +273,7 @@ release-push-candidate: ## Push release candidate
 	${PUSH_RELEASE_SCRIPTS}
 	
 .PHONY: all $(PROJECTS) clean build  default nuke
-.PHONY: lint check tidy format pre-push generate-test-cases check-import-boundaries
+.PHONY: lint check tidy format pre-push generate-test-cases capture-test-cases check-import-boundaries
 .PHONY: test test-race test-coverage test-ci test-docker
 .PHONY: license-check license-fix license-dep
 .PHONY: release release-binary release-source release-sign release-assembly
diff --git a/test/cases/measure/cmd/capture/capture_test.go b/test/cases/measure/cmd/capture/capture_test.go
index d5d80a85d..a7c36241d 100644
--- a/test/cases/measure/cmd/capture/capture_test.go
+++ b/test/cases/measure/cmd/capture/capture_test.go
@@ -18,9 +18,19 @@
 // Package capture_test runs a standalone server, loads seed data, executes
 // generated queries, and writes responses as want/*.yaml files.
 //
+// The capture loop is gated behind the CAPTURE_WANT_FIXTURES=1 environment
+// variable so a routine `make test` (or any `./...` discovery) cannot
+// silently re-baseline the golden fixtures from whatever branch the
+// developer happens to be on. Without the env var the test calls
+// t.Skip and returns instantly.
+//
 // Usage:
 //
-//	go test -run TestCapture ./test/cases/measure/cmd/capture/ -args [output-dir]
+//	make capture-test-cases
+//
+// or directly:
+//
+//	CAPTURE_WANT_FIXTURES=1 go test -run TestCapture ./test/cases/measure/cmd/capture/ -args [output-dir]
 //
 // output-dir defaults to ../../data (i.e. test/cases/measure/data).
 package capture_test
@@ -49,6 +59,12 @@ import (
 )
 
 func TestCapture(t *testing.T) {
+	if os.Getenv("CAPTURE_WANT_FIXTURES") != "1" {
+		t.Skip("skipped: set CAPTURE_WANT_FIXTURES=1 (or run `make capture-test-cases`) " +
+			"to re-baseline data/want/*.yaml. This test starts a live server and rewrites " +
+			"the golden fixtures with whatever the current build produces, so it must be " +
+			"opt-in and only run against a trusted baseline.")
+	}
 	gomega.RegisterTestingT(t)
 
 	// Initialize logger
@@ -97,6 +113,10 @@ func TestCapture(t *testing.T) {
 	entries, readErr := os.ReadDir(inputDirPath)
 	gomega.Expect(readErr).NotTo(gomega.HaveOccurred())
 
+	// Precompute the header bytes once so each fixture write is a single
+	// make+copy, not a per-iteration string→[]byte conversion + append.
+	headerBytes := []byte(casesMeasureData.LicenseHeader)
+
 	capturedCount := 0
 	for _, entry := range entries {
 		if entry.IsDir() {
@@ -169,7 +189,10 @@ func TestCapture(t *testing.T) {
 		}
 
 		wantPath := filepath.Join(wantDirPath, testName+".yaml")
-		if writeErr := os.WriteFile(wantPath, respYAML, 0o600); writeErr != nil {
+		wantContent := make([]byte, len(headerBytes)+len(respYAML))
+		copy(wantContent, headerBytes)
+		copy(wantContent[len(headerBytes):], respYAML)
+		if writeErr := os.WriteFile(wantPath, wantContent, 0o600); writeErr != nil {
 			t.Errorf("  [ERROR] %s: write failed: %v", testName, writeErr)
 			continue
 		}
diff --git a/test/cases/measure/cmd/generate/capture.go b/test/cases/measure/cmd/generate/capture.go
index f4b79dc0a..1226c2e9b 100644
--- a/test/cases/measure/cmd/generate/capture.go
+++ b/test/cases/measure/cmd/generate/capture.go
@@ -76,6 +76,10 @@ func runCapture(outputDir, serverAddr string) {
 	skippedCount := 0
 	errorCount := 0
 
+	// Precompute the header bytes once so each fixture write is a single
+	// make+copy, not a per-iteration string→[]byte conversion + append.
+	headerBytes := []byte(licenseHeader)
+
 	for _, entry := range entries {
 		if entry.IsDir() {
 			continue
@@ -165,7 +169,10 @@ func runCapture(outputDir, serverAddr string) {
 		}
 
 		wantPath := filepath.Join(wantDirPath, testName+".yaml")
-		if writeErr := os.WriteFile(wantPath, respYAML, 0o600); writeErr != nil {
+		wantContent := make([]byte, len(headerBytes)+len(respYAML))
+		copy(wantContent, headerBytes)
+		copy(wantContent[len(headerBytes):], respYAML)
+		if writeErr := os.WriteFile(wantPath, wantContent, 0o600); writeErr != nil {
 			fmt.Fprintf(os.Stderr, "  [ERROR] %s: write failed: %v\n", testName, writeErr)
 			errorCount++
 			continue
diff --git a/test/cases/measure/cmd/generate/types.go b/test/cases/measure/cmd/generate/types.go
index 20f11fc1e..9eecaf6de 100644
--- a/test/cases/measure/cmd/generate/types.go
+++ b/test/cases/measure/cmd/generate/types.go
@@ -23,6 +23,7 @@ import (
 
 	measurev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/measure/v1"
 	modelv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v1"
+	"github.com/apache/skywalking-banyandb/test/cases/measure/data"
 )
 
 // TestCase represents a generated test case with all its artifacts.
@@ -37,22 +38,7 @@ type TestCase struct {
 	DisOrder  bool
 }
 
-const licenseHeader = "# Licensed to Apache Software Foundation (ASF) under one or more contributor\n" +
-	"# license agreements. See the NOTICE file distributed with\n" +
-	"# this work for additional information regarding copyright\n" +
-	"# ownership. Apache Software Foundation (ASF) licenses this file to you under\n" +
-	"# the Apache License, Version 2.0 (the \"License\"); you may\n" +
-	"# not use this file except in compliance with the License.\n" +
-	"# You may obtain a copy of the License at\n" +
-	"#\n" +
-	"#     http://www.apache.org/licenses/LICENSE-2.0\n" +
-	"#\n" +
-	"# Unless required by applicable law or agreed to in writing,\n" +
-	"# software distributed under the License is distributed on an\n" +
-	"# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
-	"# KIND, either express or implied.  See the License for the\n" +
-	"# specific language governing permissions and limitations\n" +
-	"# under the License.\n\n"
+const licenseHeader = data.LicenseHeader
 
 // QLFileContent returns the .ql file content with license header.
 func (tc *TestCase) QLFileContent() []byte {
diff --git a/test/cases/measure/data/license_header.go b/test/cases/measure/data/license_header.go
new file mode 100644
index 000000000..59b7e52a4
--- /dev/null
+++ b/test/cases/measure/data/license_header.go
@@ -0,0 +1,43 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package data
+
+// LicenseHeader is the Apache 2.0 header (in YAML/properties comment form,
+// trailing blank line included) that generated fixture files must carry so
+// they pass the repo-wide license-eye scan. Both the generator and the
+// response-capture writer prepend this to every file they produce; without
+// it, regenerating the fixtures locally silently strips the header and
+// would break `make license-check` (the bug uncovered by the
+// vectorized-query branch's full `make test` run, which exercises the
+// `./test/cases/...` path that CI normally skips).
+const LicenseHeader = "# Licensed to Apache Software Foundation (ASF) under one or more contributor\n" +
+	"# license agreements. See the NOTICE file distributed with\n" +
+	"# this work for additional information regarding copyright\n" +
+	"# ownership. Apache Software Foundation (ASF) licenses this file to you under\n" +
+	"# the Apache License, Version 2.0 (the \"License\"); you may\n" +
+	"# not use this file except in compliance with the License.\n" +
+	"# You may obtain a copy of the License at\n" +
+	"#\n" +
+	"#     http://www.apache.org/licenses/LICENSE-2.0\n" +
+	"#\n" +
+	"# Unless required by applicable law or agreed to in writing,\n" +
+	"# software distributed under the License is distributed on an\n" +
+	"# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
+	"# KIND, either express or implied.  See the License for the\n" +
+	"# specific language governing permissions and limitations\n" +
+	"# under the License.\n\n"