open-code-review/internal/diff/hunk_test.go
kite 533b526b4c
Some checks are pending
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
chore: add SPDX license headers and automated verification (#740)
* chore: add SPDX license headers to all source files

Add Apache-2.0 SPDX license identifiers and copyright notices to all
tracked .go, .sh, .js, .mjs, .ts, and .tsx source files.

Introduce scripts/verify-license.sh and scripts/add-license.sh for
automated verification and bulk addition of license headers. Integrate
the check into CI (ci.yml) and the Makefile (license-check target as
a prerequisite of the existing check target).

This satisfies the OpenSSF Best Practices Badge requirements for
copyright_per_file and license_per_file.

* fix: restore execute permissions on scripts

* docs: add license header instructions to CONTRIBUTING guides

* docs: add license header instructions to pages contributing guides

* fix(pages): strip unclosed HTML comment markers to satisfy CodeQL

* fix: apply code review suggestions for license scripts

- Fix portability: detect macOS vs Linux stat for permission copy
- Fix has_header: check both SPDX and copyright (match verify logic)
- Fix is_ignored: match on path boundaries to avoid false positives
- Fix year extraction: use consistent pipeline across both scripts
- Fix Bash 3.2 compat: quote array length expansion for set -u

* fix(pages): use loop-until-clean for HTML comment stripping (CodeQL)

* fix(pages): use split/join instead of replace to avoid CodeQL false positive

CodeQL's js/incomplete-multi-character-sanitization rule flags any
.replace() that removes multi-character sequences like '<!--...-->',
regardless of context. The data here comes from readFileSync on the
project's own index.html (no untrusted input), making this a false
positive. Using split(regex).join('') achieves the same result without
triggering the taint-tracking rule.
2026-08-05 21:26:27 +08:00

123 lines
3 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 alibaba/open-code-review Contributors
package diff
import (
"testing"
)
func TestParseHunks_SingleHunk(t *testing.T) {
raw := `diff --git a/pkg/example/handler.go b/pkg/example/handler.go
--- a/pkg/example/handler.go
+++ b/pkg/example/handler.go
@@ -10,7 +10,7 @@ func HandleRequest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
- log.Print("handling request")
+ log.Printf("handling request: %s", r.URL.Path)
err := process(ctx)`
hunks := ParseHunks(raw)
if len(hunks) != 1 {
t.Fatalf("expected 1 hunk, got %d", len(hunks))
}
h := hunks[0]
if h.OldStart != 10 || h.OldCount != 7 {
t.Errorf("OldStart/OldCount: expected 10,7 got %d,%d", h.OldStart, h.OldCount)
}
if h.NewStart != 10 || h.NewCount != 7 {
t.Errorf("NewStart/NewCount: expected 10,7 got %d,%d", h.NewStart, h.NewCount)
}
if len(h.Lines) != 4 {
t.Fatalf("expected 4 lines, got %d", len(h.Lines))
}
// Check line types in order
expected := []HunkLineType{HunkContext, HunkDeleted, HunkAdded, HunkContext}
for i, lt := range expected {
if h.Lines[i].Type != lt {
t.Errorf("line[%d]: type %d expected %d", i, h.Lines[i].Type, lt)
}
}
}
func TestParseHunks_MultipleHunks(t *testing.T) {
raw := `diff --git a/pkg/example/handler.go b/pkg/example/handler.go
--- a/pkg/example/handler.go
+++ b/pkg/example/handler.go
@@ -10,3 +10,3 @@ func foo() {
a := 1
- b := 2
+ b := 3
c := 4
@@ -25,6 +25,8 @@ func bar() {
if err != nil {
return err
}
+ log.Print("ok")
+ log.Print("done")
return nil`
hunks := ParseHunks(raw)
if len(hunks) != 2 {
t.Fatalf("expected 2 hunks, got %d", len(hunks))
}
h1 := hunks[0]
if h1.OldStart != 10 || h1.NewStart != 10 {
t.Errorf("hunk 0: OldStart=%d NewStart=%d", h1.OldStart, h1.NewStart)
}
h2 := hunks[1]
if h2.OldStart != 25 || h2.NewStart != 25 {
t.Errorf("hunk 1: OldStart=%d NewStart=%d", h2.OldStart, h2.NewStart)
}
if h2.OldCount != 6 || h2.NewCount != 8 {
t.Errorf("hunk 1 counts: OldCount=%d NewCount=%d", h2.OldCount, h2.NewCount)
}
}
func TestParseHunks_NoNewlineMarker(t *testing.T) {
raw := `@@ -1,2 +1,2 @@
- old line
\ No newline at end of file
+ new line`
hunks := ParseHunks(raw)
if len(hunks) != 1 {
t.Fatalf("expected 1 hunk, got %d", len(hunks))
}
if len(hunks[0].Lines) != 2 {
t.Errorf("expected 2 lines (excluding no-newline marker), got %d", len(hunks[0].Lines))
}
}
func TestParseHunks_EmptyInput(t *testing.T) {
hunks := ParseHunks("")
if len(hunks) != 0 {
t.Errorf("expected 0 hunks, got %d", len(hunks))
}
}
func TestParseHunks_NewFileAllAdditions(t *testing.T) {
raw := `diff --git a/pkg/new.go b/pkg/new.go
new file mode 100644
--- /dev/null
+++ b/pkg/new.go
@@ -0,0 +1,3 @@
+package pkg
+
+func New() {}`
hunks := ParseHunks(raw)
if len(hunks) != 1 {
t.Fatalf("expected 1 hunk, got %d", len(hunks))
}
h := hunks[0]
for _, l := range h.Lines {
if l.Type != HunkAdded {
t.Errorf("expected all lines to be HunkAdded, got %d", l.Type)
}
}
}