From 086f3382db1117819e3829c27bccd52aa26296ae Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 5 Aug 2026 22:15:46 +0900 Subject: [PATCH 1/5] refactor: streamline Makefile and add diff functionality with tests --- Makefile | 10 +++-- diff.go | 80 +++++++++++++++++++++++++++++++++++++++ diff_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++ main.go | 103 ++++++++++----------------------------------------- main_test.go | 89 +++----------------------------------------- 5 files changed, 199 insertions(+), 171 deletions(-) create mode 100644 diff.go create mode 100644 diff_test.go diff --git a/Makefile b/Makefile index a73fb5f..ab32b6c 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,14 @@ all: check-diff .PHONY: check-diff -check-diff: main.go open_unix.go open_windows.go - go build $(LDFLAGS) -o check-diff . +check-diff: *.go + go build $(LDFLAGS) -o check-diff -linux: main.go open_unix.go - GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o check-diff open_unix.go main.go +linux: *.go + GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o check-diff check: go test -v ./... +lint: + golangci-lint run ./... \ No newline at end of file diff --git a/diff.go b/diff.go new file mode 100644 index 0000000..194644f --- /dev/null +++ b/diff.go @@ -0,0 +1,80 @@ +package main + +import ( + "bufio" + "fmt" + "strings" + + "github.com/cubicdaiya/gonp" +) + +func getLines(filename string) ([]string, error) { + file, err := openRD(filename) + if err != nil { + return nil, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + scanner.Buffer(make([]byte, 64*1024), 10*1024*1024) + lines := make([]string, 0) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + if err := scanner.Err(); err != nil { + return nil, err + } + return lines, nil +} + +func diff(prev, new string) (string, error) { + prevLines, err := getLines(prev) + if err != nil { + return "", err + } + newLines, err := getLines(new) + if err != nil { + return "", err + } + + diff := gonp.New(prevLines, newLines) + diff.Compose() + + return diff.SprintUniHunks(diff.UnifiedHunks()), nil +} + +func buildNoDifferenceMsg(filename string) (string, error) { + file, err := openRD(filename) + if err != nil { + return "", err + } + defer file.Close() + + fileinfo, err := file.Stat() + if err != nil { + return "", err + } + b := make([]byte, 128) + count, err := file.Read(b) + if err != nil { + return "", err + } + o := string(strings.TrimRight(string(b[0:count]), "\r\n")) + if fileinfo.Size() > 128 { + return fmt.Sprintf("no difference: ```%s...```", o), nil + } + return fmt.Sprintf("no difference: ```%s```", o), nil +} + +func buildDiffMsg(diff string) string { + o := diff + if len(diff) > 512 { + o = diff[0:512] + } + o = strings.TrimRight(o, "\r\n") + + if len(diff) > 512 { + return fmt.Sprintf("found difference: ```%s...```", o) + } + return fmt.Sprintf("found difference: ```%s```", o) +} diff --git a/diff_test.go b/diff_test.go new file mode 100644 index 0000000..4c40987 --- /dev/null +++ b/diff_test.go @@ -0,0 +1,88 @@ +package main + +import ( + "strings" + "testing" +) + +func TestDiff(t *testing.T) { + file1, cleanup1 := createTempFile(t, "Hello, World!\n") + defer cleanup1() + + file2, cleanup2 := createTempFile(t, "Hello, Go!\n") + defer cleanup2() + + diffResult, err := diff(file1.Name(), file2.Name()) + if err != nil { + t.Fatalf("diff failed: %v", err) + } + if diffResult == "" { + t.Errorf("Expected a diff result, got empty string") + } + if !strings.Contains(diffResult, "Hello, World!") || !strings.Contains(diffResult, "Hello, Go!") { + t.Errorf("Diff result does not contain expected content: %q", diffResult) + } +} + +func TestBuildNoDifferenceMsg(t *testing.T) { + shortMsg := "This is a test message." + file, cleanup := createTempFile(t, shortMsg+"\n") + defer cleanup() + expected := "no difference: ```" + shortMsg + "```" + result, err := buildNoDifferenceMsg(file.Name()) + if err != nil { + t.Fatalf("buildNoDifferenceMsg failed: %v", err) + } + if result != expected { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func TestBuildNoDifferenceMsgLargeResult(t *testing.T) { + largeMsg := strings.Repeat("A", 600) + file, cleanup := createTempFile(t, largeMsg+"\n") + defer cleanup() + + expected := "no difference: ```" + largeMsg[:128] + "...```" + result, err := buildNoDifferenceMsg(file.Name()) + if err != nil { + t.Fatalf("buildNoDifferenceMsg failed: %v", err) + } + if result != expected { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func TestBuildDiffMsg(t *testing.T) { + diff := "This is a test diff message.\nThis is the second line of the diff.\n" + expected := "found difference: ```This is a test diff message.\nThis is the second line of the diff.```" + result := buildDiffMsg(diff) + if result != expected { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func TestBuildDiffMsgLargeResult(t *testing.T) { + diff := strings.Repeat("A", 600) + expected := "found difference: ```" + diff[:512] + "...```" + result := buildDiffMsg(diff) + if result != expected { + t.Errorf("Expected %q, got %q", expected, result) + } +} + +func TestDiffNoDifference(t *testing.T) { + file1, cleanup1 := createTempFile(t, "Hello, World!\n") + defer cleanup1() + + file2, cleanup2 := createTempFile(t, "Hello, World!\n") + defer cleanup2() + + diffResult, err := diff(file1.Name(), file2.Name()) + if err != nil { + t.Fatalf("diff failed: %v", err) + } + if diffResult != "" { + t.Errorf("Expected no diff result, got: %q", diffResult) + } +} diff --git a/main.go b/main.go index e4408f1..46dcfdc 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "bufio" "bytes" "crypto/sha256" "fmt" @@ -12,7 +11,6 @@ import ( "runtime" "strings" - "github.com/cubicdaiya/gonp" "github.com/jessevdk/go-flags" "github.com/mackerelio/checkers" "github.com/mackerelio/golib/pluginutil" @@ -21,6 +19,13 @@ import ( var version string var commit string +const ( + OK = iota + WARNING + CRITICAL + UNKNOWN +) + type Opt struct { Args []string Command string @@ -40,7 +45,7 @@ func (opt *Opt) cmd(file *os.File) error { } err := cmd.Wait() if err != nil { - return fmt.Errorf("%s - %s", err, stderr.String()) + return fmt.Errorf("%w - %s", err, stderr.String()) } return nil } @@ -69,7 +74,7 @@ func (opt *Opt) run() *checkers.Checker { err = opt.cmd(newFile) if err != nil { newFile.Close() - os.Remove(newFile.Name()) + _ = os.Remove(newFile.Name()) return checkers.Critical(err.Error()) } @@ -114,77 +119,6 @@ func (opt *Opt) run() *checkers.Checker { return checkers.Critical(diffMsg) } -func buildNoDifferenceMsg(filename string) (string, error) { - file, err := openRD(filename) - if err != nil { - return "", err - } - defer file.Close() - - fileinfo, err := file.Stat() - if err != nil { - return "", err - } - b := make([]byte, 128) - count, err := file.Read(b) - if err != nil { - return "", err - } - o := string(strings.TrimRight(string(b[0:count]), "\r\n")) - if fileinfo.Size() > 128 { - return fmt.Sprintf("no difference: ```%s...```", o), nil - } - return fmt.Sprintf("no difference: ```%s```", o), nil -} - -func buildDiffMsg(diff string) string { - o := diff - if len(diff) > 512 { - o = diff[0:512] - } - o = strings.TrimRight(o, "\r\n") - - if len(diff) > 512 { - return fmt.Sprintf("found difference: ```%s...```", o) - } - return fmt.Sprintf("found difference: ```%s```", o) -} - -func getLines(filename string) ([]string, error) { - file, err := openRD(filename) - if err != nil { - return nil, err - } - defer file.Close() - - scanner := bufio.NewScanner(file) - scanner.Buffer(make([]byte, 64*1024), 10*1024*1024) - lines := make([]string, 0) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - if err := scanner.Err(); err != nil { - return nil, err - } - return lines, nil -} - -func diff(prev, new string) (string, error) { - prevLines, err := getLines(prev) - if err != nil { - return "", err - } - newLines, err := getLines(new) - if err != nil { - return "", err - } - - diff := gonp.New(prevLines, newLines) - diff.Compose() - - return diff.SprintUniHunks(diff.UnifiedHunks()), nil -} - func fileExists(filename string) bool { _, err := os.Stat(filename) return err == nil @@ -207,16 +141,19 @@ func main() { runtime.GOARCH, runtime.Version(), commit) - os.Exit(0) - } - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } - if len(args) == 0 { + os.Exit(OK) + } else if flags.WroteHelp(err) { + fmt.Fprintf(os.Stdout, "%v\n", err) + os.Exit(OK) + } else if len(args) == 0 { + fmt.Fprintf(os.Stderr, "command is required\n") psr.WriteHelp(os.Stderr) - os.Exit(1) + os.Exit(UNKNOWN) + } else if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(UNKNOWN) } + opt.Args = []string{} opt.Command = args[0] if len(args) > 1 { diff --git a/main_test.go b/main_test.go index 7356404..220f1bb 100644 --- a/main_test.go +++ b/main_test.go @@ -35,7 +35,10 @@ func TestCmd(t *testing.T) { t.Fatalf("cmd failed: %v", err) } - file.Seek(0, 0) // Reset file pointer to the beginning + _, err := file.Seek(0, 0) // Reset file pointer to the beginning + if err != nil { + t.Fatalf("Failed to seek file: %v", err) + } scanner := bufio.NewScanner(file) if scanner.Scan() { output := scanner.Text() @@ -77,89 +80,7 @@ func createTempFile(t *testing.T, content string) (*os.File, func()) { t.Fatalf("Failed to close temp file: %v", err) } return tmpfile, func() { - os.Remove(tmpfile.Name()) - } -} - -func TestBuildNoDifferenceMsg(t *testing.T) { - shortMsg := "This is a test message." - file, cleanup := createTempFile(t, shortMsg+"\n") - defer cleanup() - expected := "no difference: ```" + shortMsg + "```" - result, err := buildNoDifferenceMsg(file.Name()) - if err != nil { - t.Fatalf("buildNoDifferenceMsg failed: %v", err) - } - if result != expected { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func TestBuildNoDifferenceMsgLargeResult(t *testing.T) { - largeMsg := strings.Repeat("A", 600) - file, cleanup := createTempFile(t, largeMsg+"\n") - defer cleanup() - - expected := "no difference: ```" + largeMsg[:128] + "...```" - result, err := buildNoDifferenceMsg(file.Name()) - if err != nil { - t.Fatalf("buildNoDifferenceMsg failed: %v", err) - } - if result != expected { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func TestBuildDiffMsg(t *testing.T) { - diff := "This is a test diff message.\nThis is the second line of the diff.\n" - expected := "found difference: ```This is a test diff message.\nThis is the second line of the diff.```" - result := buildDiffMsg(diff) - if result != expected { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func TestBuildDiffMsgLargeResult(t *testing.T) { - diff := strings.Repeat("A", 600) - expected := "found difference: ```" + diff[:512] + "...```" - result := buildDiffMsg(diff) - if result != expected { - t.Errorf("Expected %q, got %q", expected, result) - } -} - -func TestDiff(t *testing.T) { - file1, cleanup1 := createTempFile(t, "Hello, World!\n") - defer cleanup1() - - file2, cleanup2 := createTempFile(t, "Hello, Go!\n") - defer cleanup2() - - diffResult, err := diff(file1.Name(), file2.Name()) - if err != nil { - t.Fatalf("diff failed: %v", err) - } - if diffResult == "" { - t.Errorf("Expected a diff result, got empty string") - } - if !strings.Contains(diffResult, "Hello, World!") || !strings.Contains(diffResult, "Hello, Go!") { - t.Errorf("Diff result does not contain expected content: %q", diffResult) - } -} - -func TestDiffNoDifference(t *testing.T) { - file1, cleanup1 := createTempFile(t, "Hello, World!\n") - defer cleanup1() - - file2, cleanup2 := createTempFile(t, "Hello, World!\n") - defer cleanup2() - - diffResult, err := diff(file1.Name(), file2.Name()) - if err != nil { - t.Fatalf("diff failed: %v", err) - } - if diffResult != "" { - t.Errorf("Expected no diff result, got: %q", diffResult) + _ = os.Remove(tmpfile.Name()) } } From 8c4c517b9225a0df5220f2d707b9c6397986f289 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 5 Aug 2026 22:23:28 +0900 Subject: [PATCH 2/5] Update diff.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- diff.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff.go b/diff.go index 194644f..b8a10f3 100644 --- a/diff.go +++ b/diff.go @@ -56,7 +56,7 @@ func buildNoDifferenceMsg(filename string) (string, error) { } b := make([]byte, 128) count, err := file.Read(b) - if err != nil { + if err != nil && err != io.EOF { return "", err } o := string(strings.TrimRight(string(b[0:count]), "\r\n")) From ac9ed4a63ac47aca95fb91ebbeb860c630a6ff0a Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 5 Aug 2026 22:26:50 +0900 Subject: [PATCH 3/5] Update diff.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- diff.go | 1 + 1 file changed, 1 insertion(+) diff --git a/diff.go b/diff.go index b8a10f3..d31c412 100644 --- a/diff.go +++ b/diff.go @@ -3,6 +3,7 @@ package main import ( "bufio" "fmt" + "io" "strings" "github.com/cubicdaiya/gonp" From b51bdf6d0f022e8c2349c1bc2c7f121b892f1f85 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 5 Aug 2026 22:38:38 +0900 Subject: [PATCH 4/5] fix: handle error case for missing command in main function --- main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 46dcfdc..d13fc97 100644 --- a/main.go +++ b/main.go @@ -145,13 +145,13 @@ func main() { } else if flags.WroteHelp(err) { fmt.Fprintf(os.Stdout, "%v\n", err) os.Exit(OK) + } else if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(UNKNOWN) } else if len(args) == 0 { fmt.Fprintf(os.Stderr, "command is required\n") psr.WriteHelp(os.Stderr) os.Exit(UNKNOWN) - } else if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(UNKNOWN) } opt.Args = []string{} From 8a2b0ea201a0e23c9ad499b06127a590754475aa Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 5 Aug 2026 22:43:11 +0900 Subject: [PATCH 5/5] Update diff.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- diff.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/diff.go b/diff.go index d31c412..0422ee9 100644 --- a/diff.go +++ b/diff.go @@ -28,20 +28,20 @@ func getLines(filename string) ([]string, error) { return lines, nil } -func diff(prev, new string) (string, error) { - prevLines, err := getLines(prev) - if err != nil { - return "", err - } - newLines, err := getLines(new) - if err != nil { - return "", err - } +func diff(prev, current string) (string, error) { + prevLines, err := getLines(prev) + if err != nil { + return "", err + } + newLines, err := getLines(current) + if err != nil { + return "", err + } - diff := gonp.New(prevLines, newLines) - diff.Compose() + d := gonp.New(prevLines, newLines) + d.Compose() - return diff.SprintUniHunks(diff.UnifiedHunks()), nil + return d.SprintUniHunks(d.UnifiedHunks()), nil } func buildNoDifferenceMsg(filename string) (string, error) {