Skip to content

Commit 37202e1

Browse files
authored
Test golang ci compat (#31)
1 parent cb090a4 commit 37202e1

File tree

4 files changed

+306
-0
lines changed

4 files changed

+306
-0
lines changed

.github/workflows/golangci-compat.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: GolangCI-Lint Compatibility
2+
3+
on:
4+
push:
5+
branches: ["master"]
6+
pull_request:
7+
branches: ["master"]
8+
schedule:
9+
- cron: "0 0 * * 0" # Run weekly on Sundays at midnight
10+
11+
jobs:
12+
test-golangci-compat:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Go
18+
uses: actions/setup-go@v5
19+
with:
20+
go-version: "1.21"
21+
check-latest: true
22+
23+
- name: Make script executable
24+
run: chmod +x ./scripts/test-golangci-compat.sh
25+
26+
- name: Run compatibility tests
27+
run: ./scripts/test-golangci-compat.sh

compat/compat_integration_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package compat
2+
3+
import (
4+
"go/ast"
5+
"go/parser"
6+
"go/token"
7+
"testing"
8+
9+
goconstAPI "github.com/jgautheron/goconst"
10+
)
11+
12+
func TestGolangCIIntegration(t *testing.T) {
13+
const testCode = `package example
14+
15+
const ExistingConst = "test-const"
16+
17+
func example() {
18+
// This should be detected as it matches ExistingConst
19+
str1 := "test-const"
20+
str2 := "test-const"
21+
22+
// This should be detected as a duplicate without matching constant
23+
dup1 := "duplicate"
24+
dup2 := "duplicate"
25+
26+
// This should be ignored as it's in a function call
27+
println("ignored-in-call")
28+
println("ignored-in-call")
29+
30+
// This should be ignored as it's too short
31+
x := "a"
32+
y := "a"
33+
34+
// This should be ignored due to IgnoreStrings
35+
skip := "test-ignore"
36+
skip2 := "test-ignore"
37+
}
38+
`
39+
40+
// Parse the test code
41+
fset := token.NewFileSet()
42+
f, err := parser.ParseFile(fset, "example.go", testCode, 0)
43+
if err != nil {
44+
t.Fatalf("Failed to parse test code: %v", err)
45+
}
46+
47+
// Configure exactly as golangci-lint does
48+
cfg := &goconstAPI.Config{
49+
IgnoreStrings: "test-ignore",
50+
MatchWithConstants: true,
51+
MinStringLength: 3,
52+
MinOccurrences: 2,
53+
ParseNumbers: false,
54+
ExcludeTypes: map[goconstAPI.Type]bool{
55+
goconstAPI.Call: true,
56+
},
57+
IgnoreTests: false,
58+
}
59+
60+
// Run the analysis
61+
issues, err := goconstAPI.Run([]*ast.File{f}, fset, cfg)
62+
if err != nil {
63+
t.Fatalf("Run() error = %v", err)
64+
}
65+
66+
// Verify we get exactly the issues we expect
67+
expectedIssues := map[string]struct {
68+
count int
69+
matchingConst string
70+
}{
71+
"test-const": {2, "ExistingConst"},
72+
"duplicate": {2, ""},
73+
}
74+
75+
if len(issues) != len(expectedIssues) {
76+
t.Errorf("Got %d issues, want %d", len(issues), len(expectedIssues))
77+
for _, issue := range issues {
78+
t.Logf("Found issue: %q matches constant %q with %d occurrences",
79+
issue.Str, issue.MatchingConst, issue.OccurrencesCount)
80+
}
81+
}
82+
83+
for _, issue := range issues {
84+
expected, ok := expectedIssues[issue.Str]
85+
if !ok {
86+
t.Errorf("Unexpected issue found: %q", issue.Str)
87+
continue
88+
}
89+
90+
if issue.OccurrencesCount != expected.count {
91+
t.Errorf("String %q: got %d occurrences, want %d",
92+
issue.Str, issue.OccurrencesCount, expected.count)
93+
}
94+
95+
if issue.MatchingConst != expected.matchingConst {
96+
t.Errorf("String %q: got matching const %q, want %q",
97+
issue.Str, issue.MatchingConst, expected.matchingConst)
98+
}
99+
}
100+
}

compat/compat_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package compat
2+
3+
import (
4+
"go/token"
5+
"testing"
6+
7+
goconstAPI "github.com/jgautheron/goconst"
8+
)
9+
10+
// TestGolangCICompatibility verifies that our API remains compatible
11+
// with how golangci-lint uses it
12+
func TestGolangCICompatibility(t *testing.T) {
13+
// This test mimics how golangci-lint configures and uses goconst
14+
// See: https://github.com/golangci/golangci-lint/blob/main/pkg/golinters/goconst/goconst.go
15+
16+
cfg := goconstAPI.Config{
17+
IgnoreStrings: "test",
18+
MatchWithConstants: true,
19+
MinStringLength: 3,
20+
MinOccurrences: 2,
21+
ParseNumbers: true,
22+
NumberMin: 100,
23+
NumberMax: 1000,
24+
ExcludeTypes: map[goconstAPI.Type]bool{
25+
goconstAPI.Call: true,
26+
},
27+
IgnoreTests: false,
28+
}
29+
30+
// Create a simple test file
31+
fset := token.NewFileSet()
32+
33+
// Verify that the API call signature matches what golangci-lint expects
34+
_, err := goconstAPI.Run(nil, fset, &cfg)
35+
if err != nil {
36+
// We expect an error since we passed nil files
37+
// but the important part is that the function signature matches
38+
t.Log("Expected error from nil files:", err)
39+
}
40+
41+
// Verify that the Issue struct has all fields golangci-lint expects
42+
issue := goconstAPI.Issue{
43+
Pos: token.Position{},
44+
OccurrencesCount: 2,
45+
Str: "test",
46+
MatchingConst: "TEST",
47+
}
48+
49+
// Verify we can access all fields golangci-lint uses
50+
_ = issue.Pos
51+
_ = issue.OccurrencesCount
52+
_ = issue.Str
53+
_ = issue.MatchingConst
54+
}

scripts/test-golangci-compat.sh

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# This script tests compatibility of goconst with golangci-lint
5+
# using the command line interface rather than importing the package
6+
7+
echo "Testing compatibility with golangci-lint..."
8+
9+
# Get current directory
10+
REPO_ROOT="$(pwd)"
11+
echo "Using repository at: $REPO_ROOT"
12+
13+
# Set up test directory
14+
TEST_DIR=$(mktemp -d)
15+
echo "Created test directory: $TEST_DIR"
16+
17+
# Clean up on exit
18+
cleanup() {
19+
echo "Cleaning up test directory..."
20+
rm -rf "$TEST_DIR"
21+
}
22+
trap cleanup EXIT
23+
24+
# Build goconst CLI
25+
echo "Building goconst CLI..."
26+
GOCONST_BIN="$TEST_DIR/goconst"
27+
go build -o "$GOCONST_BIN" ./cmd/goconst
28+
29+
# Create test files
30+
echo "Creating test files..."
31+
mkdir -p "$TEST_DIR/testpkg"
32+
33+
# Create a file with constants and strings
34+
cat > "$TEST_DIR/testpkg/main.go" << 'EOF'
35+
package testpkg
36+
37+
const ExistingConst = "test-const"
38+
39+
func example() {
40+
// This should be detected as it matches ExistingConst
41+
str1 := "test-const"
42+
str2 := "test-const"
43+
44+
// This should be detected as a duplicate without matching constant
45+
dup1 := "duplicate"
46+
dup2 := "duplicate"
47+
48+
// This should be ignored due to ignore-strings
49+
skip := "test-ignore"
50+
skip2 := "test-ignore"
51+
}
52+
EOF
53+
54+
# Test 1: Basic functionality
55+
echo "Test 1: Basic functionality (without match-with-constants)..."
56+
"$GOCONST_BIN" -ignore-strings "test-ignore" -match-constant=false "$TEST_DIR/testpkg" > "$TEST_DIR/output1.txt"
57+
if ! grep -q "duplicate" "$TEST_DIR/output1.txt"; then
58+
echo "Failed: Should detect 'duplicate' string"
59+
cat "$TEST_DIR/output1.txt"
60+
exit 1
61+
fi
62+
if ! grep -q "test-const" "$TEST_DIR/output1.txt"; then
63+
echo "Failed: Should detect 'test-const' string"
64+
cat "$TEST_DIR/output1.txt"
65+
exit 1
66+
fi
67+
if grep -q "test-ignore" "$TEST_DIR/output1.txt"; then
68+
echo "Failed: Should NOT detect 'test-ignore' string"
69+
cat "$TEST_DIR/output1.txt"
70+
exit 1
71+
fi
72+
73+
# Test 2: Match with constants
74+
echo "Test 2: Testing match-with-constants functionality..."
75+
"$GOCONST_BIN" -ignore-strings "test-ignore" -match-constant "$TEST_DIR/testpkg" > "$TEST_DIR/output2.txt"
76+
if ! grep -q "matching constant.*ExistingConst" "$TEST_DIR/output2.txt"; then
77+
echo "Failed: Should match 'test-const' with 'ExistingConst'"
78+
cat "$TEST_DIR/output2.txt"
79+
exit 1
80+
fi
81+
if ! grep -q "duplicate" "$TEST_DIR/output2.txt"; then
82+
echo "Failed: Should detect 'duplicate' string"
83+
cat "$TEST_DIR/output2.txt"
84+
exit 1
85+
fi
86+
if grep -q "test-ignore" "$TEST_DIR/output2.txt"; then
87+
echo "Failed: Should NOT detect 'test-ignore' string"
88+
cat "$TEST_DIR/output2.txt"
89+
exit 1
90+
fi
91+
92+
# Test 3: Create another test file with multiple constants
93+
cat > "$TEST_DIR/testpkg/multi_const.go" << 'EOF'
94+
package testpkg
95+
96+
const (
97+
FirstConst = "duplicate-value"
98+
SecondConst = "duplicate-value"
99+
)
100+
101+
func multipleConstants() {
102+
x := "duplicate-value"
103+
y := "duplicate-value"
104+
}
105+
EOF
106+
107+
echo "Test 3: Testing multiple constants with same value..."
108+
"$GOCONST_BIN" -match-constant "$TEST_DIR/testpkg/multi_const.go" > "$TEST_DIR/output3.txt"
109+
if ! grep -q "matching constant.*FirstConst" "$TEST_DIR/output3.txt"; then
110+
echo "Failed: Should match 'duplicate-value' with 'FirstConst'"
111+
cat "$TEST_DIR/output3.txt"
112+
exit 1
113+
fi
114+
115+
# Test 4: Test with JSON output (golangci-lint compatibility)
116+
echo "Test 4: Testing JSON output format..."
117+
"$GOCONST_BIN" -ignore-strings "test-ignore" -match-constant -output json "$TEST_DIR/testpkg/main.go" > "$TEST_DIR/output4.json"
118+
# Check that the JSON has the correct structure: strings + constants sections
119+
if ! grep -q '"constants":{"test-const":\[.*"Name":"ExistingConst"' "$TEST_DIR/output4.json"; then
120+
echo "Failed: JSON output should include constants with ExistingConst"
121+
cat "$TEST_DIR/output4.json"
122+
exit 1
123+
fi
124+
125+
echo "All compatibility tests PASSED!"

0 commit comments

Comments
 (0)