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 <[email protected]>
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"

Reply via email to