blob: 4c739cd94b777d6ef9a27d395a7c43d5e1dc917c [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package staticanalysis
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestFindingNormalize(t *testing.T) {
tests := []struct {
name string
finding Finding
expected Finding
wantErr bool
}{
{
name: "valid finding",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
},
},
{
name: "no category",
finding: Finding{
Category: "",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
},
wantErr: true,
},
{
name: "no message",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "",
Path: "src/foo/bar.cc",
},
wantErr: true,
},
{
name: "relative path",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "../../src/foo/bar.cc",
},
wantErr: true,
},
{
name: "absolute path",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "/usr/local/home/me/fuchsia/src/foo/bar.cc",
},
wantErr: true,
},
{
name: "bad end_line",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
EndLine: 4,
},
wantErr: true,
},
{
name: "bad end_char",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
EndLine: 5,
StartChar: 14,
EndChar: 1,
},
wantErr: true,
},
{
name: "start_line unset",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 0,
EndLine: 5,
StartChar: 14,
EndChar: 20,
},
wantErr: true,
},
{
name: "unclosed span with suggestions",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
// Span is not fully specified so suggestions should not be
// allowed.
StartLine: 1,
EndLine: 1,
Suggestions: []Suggestion{
{
Description: "try this instead",
Replacements: []Replacement{
{
Replacement: "foo",
StartLine: 1,
EndLine: 1,
StartChar: 5,
EndChar: 8,
},
},
},
},
},
wantErr: true,
},
{
name: "suggested replacement without full span",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 1,
EndLine: 1,
StartChar: 5,
EndChar: 8,
Suggestions: []Suggestion{
{
Description: "try this instead",
Replacements: []Replacement{
{
Replacement: "foo",
// Replacement span is not fully specified
// (missing an EndLine) and should be rejected.
StartLine: 1,
EndLine: 0,
StartChar: 5,
EndChar: 6,
},
},
},
},
},
wantErr: true,
},
{
name: "invalid replacement span",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 1,
EndLine: 1,
StartChar: 5,
EndChar: 8,
Suggestions: []Suggestion{
{
Description: "try this instead",
Replacements: []Replacement{
{
Replacement: "foo",
// Span is not valid and should be rejected.
StartLine: 1,
EndLine: 1,
StartChar: 100,
EndChar: 15,
},
},
},
},
},
wantErr: true,
},
{
name: "valid replacement span with equal start and end chars",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 1,
EndLine: 1,
StartChar: 5,
EndChar: 8,
Suggestions: []Suggestion{
{
Description: "try this instead",
Replacements: []Replacement{
{
Replacement: "foo",
// This should be allowed - the suggestion is to
// replace an empty span with a non-empty
// string, i.e. just insert text without
// deleting anything.
StartLine: 1,
EndLine: 1,
StartChar: 15,
EndChar: 15,
},
},
},
},
},
},
{
name: "sets end_line if unset",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
},
expected: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
EndLine: 5,
},
},
{
name: "increments end_char if equal to start_char",
finding: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
EndLine: 5,
StartChar: 10,
EndChar: 10,
},
expected: Finding{
Category: "somelint/warning/not_defined",
Message: "variable foo is not defined",
Path: "src/foo/bar.cc",
StartLine: 5,
EndLine: 5,
StartChar: 10,
EndChar: 11,
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if diff := cmp.Diff(test.expected, Finding{}); diff == "" {
// By default, expect no modifications.
test.expected = test.finding
}
if err := test.finding.Normalize(); (err != nil) != test.wantErr {
t.Errorf("Finding.Normalize() error = %q, wantErr %t", err, test.wantErr)
}
if diff := cmp.Diff(test.expected, test.finding); diff != "" {
t.Errorf("Normalize caused diff (-want +got):\n%s", diff)
}
})
}
}