-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlint_test.go
More file actions
122 lines (105 loc) · 4.13 KB
/
Copy pathlint_test.go
File metadata and controls
122 lines (105 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package cli
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/block/pg-sprite/pkg/lint"
)
func TestLintCleanScriptPrintsNothing(t *testing.T) {
var out strings.Builder
cmd := LintCmd{}
err := cmd.runLint(strings.NewReader("CREATE TABLE t (id int)"), &out)
require.NoError(t, err)
assert.Empty(t, out.String())
}
// Warning findings are reported but do not fail the command; only
// error-severity findings flip the exit code.
func TestLintWarningsPassErrorsFail(t *testing.T) {
var out strings.Builder
cmd := LintCmd{JSON: true}
err := cmd.runLint(strings.NewReader("CREATE INDEX t_c_idx ON t (c)"), &out)
require.NoError(t, err)
out.Reset()
err = cmd.runLint(strings.NewReader(
"ALTER TABLE t ADD CONSTRAINT no_overlap EXCLUDE USING gist (room WITH =)"), &out)
require.ErrorIs(t, err, ErrLintFindings)
var report lint.Report
require.NoError(t, json.Unmarshal([]byte(out.String()), &report))
assert.Equal(t, lint.FormatVersion, report.FormatVersion)
assert.Equal(t, 1, report.Errors)
require.Len(t, report.Findings, 1)
assert.Equal(t, lint.CodeUnsupportedOperation, report.Findings[0].Code)
}
func TestLintReadsFromFile(t *testing.T) {
path := filepath.Join(t.TempDir(), "change.sql")
require.NoError(t, os.WriteFile(path,
[]byte("ALTER TABLE t DROP COLUMN legacy"), 0o600))
var out strings.Builder
cmd := LintCmd{Path: path, JSON: true}
require.NoError(t, cmd.runLint(strings.NewReader(""), &out))
var report lint.Report
require.NoError(t, json.Unmarshal([]byte(out.String()), &report))
require.Len(t, report.Findings, 1)
assert.Equal(t, lint.CodeDestructive, report.Findings[0].Code)
assert.Equal(t, 1, report.Warnings)
}
// The text renderer leads each flagged statement with the conventional
// name:line:column: label so a reader can jump to the finding, and renders
// the findings in the same diagnostic grammar as the dry-run report. This
// is the renderer's own unit test — everything else asserts typed fields.
func TestLintTextFindingsCarryPositions(t *testing.T) {
var out strings.Builder
cmd := LintCmd{}
err := cmd.runLint(strings.NewReader(
"CREATE TABLE ok (id int);\nALTER TABLE t DROP COLUMN legacy;\n"), &out)
require.NoError(t, err)
assert.Equal(t, `<stdin>:2:1:
ALTER TABLE t DROP COLUMN legacy;
warning[destructive]:
DROP COLUMN legacy — discards live data or structure
docs:
`+onlineDDLReferenceURL+`#destructive
lint:
<stdin> — 1 finding, 0 errors, 1 warning
`, out.String())
}
// Two findings on the same statement share one statement header — the
// flagged SQL prints once, each finding as its own labeled entry beneath
// it. This is the renderer's own unit test — everything else asserts
// typed fields.
func TestLintTextGroupsFindingsByStatement(t *testing.T) {
var out strings.Builder
cmd := LintCmd{}
err := cmd.runLint(strings.NewReader(
"ALTER TABLE t DROP COLUMN a, DROP COLUMN b;\n"), &out)
require.NoError(t, err)
assert.Equal(t, 1,
strings.Count(out.String(), "ALTER TABLE t DROP COLUMN a, DROP COLUMN b;"),
"the flagged statement prints once per group, not once per finding")
assert.Equal(t, 2, strings.Count(out.String(), "warning[destructive]:"))
}
// The suggestion block must leave an operator who runs the safer form by
// hand with a reachable reference and the recovery check they take on.
// This is the renderer's own unit test — everything else asserts typed
// fields.
func TestLintTextSuggestionCarriesExecutionCaveat(t *testing.T) {
var out strings.Builder
cmd := LintCmd{}
err := cmd.runLint(strings.NewReader("CREATE INDEX i ON t (c);\n"), &out)
require.NoError(t, err)
assert.Contains(t, out.String(), onlineDDLReferenceURL,
"the reference must be reachable from an installed build, not a repo path")
assert.Contains(t, out.String(), "pg_index.indisvalid",
"the caveat names the recovery check a manual run takes on")
}
func TestLintParseFailureIsErrorNotFinding(t *testing.T) {
var out strings.Builder
cmd := LintCmd{}
err := cmd.runLint(strings.NewReader("CREATE TABEL t (id int)"), &out)
require.Error(t, err)
assert.NotErrorIs(t, err, ErrLintFindings)
}