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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 14a8bf414 fix(rmqctl): hash the parsed source in single-file 
cataloggen (#5837)
14a8bf414 is described below

commit 14a8bf414be81f4665f43d79e68cd15ea3e38fce
Author: 0 <[email protected]>
AuthorDate: Mon Oct 12 16:15:16 2026 +0800

    fix(rmqctl): hash the parsed source in single-file cataloggen (#5837)
    
    The catalog generator's single-file mode hashed and rendered bytes it never 
read.
    
    - #5837 in `rmqctl/internal/catalog/generate/main.go`, `:315` wrote 
`source, err := os.ReadFile(inputPath)` inside the `else` block, and that `:=` 
declared a new block-scoped `source` shadowing the outer `var source []byte` at 
`:302`, so under `-input` the outer variable stayed nil: `digest := 
sha256.Sum256(source)` at `:326` always produced `e3b0c442…` — the SHA-256 of 
the empty input — and `renderSDKContract(source)` at `:340` always emitted 
`null`, while the `yaml.Unmarshal(source, [...]
    
    Tests: `TestRunSingleFileModeDigestMatchesSource` runs the generator over a 
single-file input and compares the emitted `Digest` against a `crypto/sha256` 
sum the test computes from the input file itself rather than from the code 
under test, and asserts the rendered SDK contract is not `null`; reverting the 
assignment turns both assertions red. No `tool-catalog/tools/*.yaml` change, so 
nothing needs regenerating and `make catalog-verify` stays a no-op check.
---
 rmqctl/internal/catalog/generate/main.go      |  5 +++-
 rmqctl/internal/catalog/generate/main_test.go | 37 +++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/rmqctl/internal/catalog/generate/main.go 
b/rmqctl/internal/catalog/generate/main.go
index 3e209bf87..54cde5b71 100644
--- a/rmqctl/internal/catalog/generate/main.go
+++ b/rmqctl/internal/catalog/generate/main.go
@@ -312,10 +312,13 @@ func run(arguments []string) error {
                        return fmt.Errorf("parse merged catalog: %w", err)
                }
        } else {
-               source, err := os.ReadFile(inputPath)
+               // Assign to the outer source instead of declaring a new 
variable:
+               // the digest and the SDK contract are derived from it below.
+               fileSource, err := os.ReadFile(inputPath)
                if err != nil {
                        return fmt.Errorf("read catalog: %w", err)
                }
+               source = fileSource
                if err := yaml.Unmarshal(source, &document); err != nil {
                        return fmt.Errorf("parse catalog: %w", err)
                }
diff --git a/rmqctl/internal/catalog/generate/main_test.go 
b/rmqctl/internal/catalog/generate/main_test.go
index bcf3a3f5f..b40bbb87f 100644
--- a/rmqctl/internal/catalog/generate/main_test.go
+++ b/rmqctl/internal/catalog/generate/main_test.go
@@ -17,6 +17,9 @@
 package main
 
 import (
+       "crypto/sha256"
+       "encoding/hex"
+       "fmt"
        "os"
        "path/filepath"
        "strings"
@@ -281,3 +284,37 @@ func TestRunRejectsReservedInstanceIDFlag(t *testing.T) {
                t.Fatalf("err = %v, want nested instanceId rejection", err)
        }
 }
+
+// TestRunSingleFileModeDigestMatchesSource pins the single-file (-input) mode
+// contract: the catalog digest must be the SHA-256 of the input document, and
+// the SDK contract must be rendered from the same source. Both previously fell
+// back to the zero value of a shadowed source variable.
+func TestRunSingleFileModeDigestMatchesSource(t *testing.T) {
+       input, output := writeCatalogSource(t, platformToolSource)
+       sdk := filepath.Join(t.TempDir(), "rmq-tools.json")
+
+       if err := run([]string{"-input", input, "-output", output, "-sdk", 
sdk}); err != nil {
+               t.Fatalf("generate catalog: %v", err)
+       }
+       source, err := os.ReadFile(input)
+       if err != nil {
+               t.Fatal(err)
+       }
+       digest := sha256.Sum256(source)
+       generated, err := os.ReadFile(output)
+       if err != nil {
+               t.Fatal(err)
+       }
+       expected := fmt.Sprintf("%q", hex.EncodeToString(digest[:]))
+       if !strings.Contains(string(generated), "Digest:") ||
+               !strings.Contains(string(generated), expected) {
+               t.Fatalf("generated digest does not match SHA-256 of the source 
%s\n", expected)
+       }
+       contract, err := os.ReadFile(sdk)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if strings.TrimSpace(string(contract)) == "null" || 
!strings.Contains(string(contract), `"rmq.cluster.list"`) {
+               t.Fatalf("SDK contract was not rendered from the source: %s", 
contract)
+       }
+}

Reply via email to