Support multiple locations for diagnostics (#1610)

## Changes
This PR changes `diag.Diagnostics` to allow including multiple locations
associated with the diagnostic message. The diagnostics that now return
multiple locations with this PR are:
1. Warning for unknown keys in config.
2. Use of experimental.run_as
3. Accidental sync.exludes that exclude all files.

## Tests
Existing unit tests pass. New unit test case to assert on error message
when multiple locations are included.

Example output:
```
➜  bundle-playground-2 ~/cli2/cli/cli bundle validate              
Warning: You are using the legacy mode of run_as. The support for this mode is experimental and might be removed in a future release of the CLI. In order to run the DLT pipelines in your DAB as the run_as user this mode changes the owners of the pipelines to the run_as identity, which requires the user deploying the bundle to be a workspace admin, and also a Metastore admin if the pipeline target is in UC.
  at experimental.use_legacy_run_as
  in resources.yml:10:22
     databricks.yml:13:22

Name: fix run_if
Target: default
Workspace:
  User: shreyas.goenka@databricks.com
  Path: /Users/shreyas.goenka@databricks.com/.bundle/fix run_if/default

Found 1 warning
```
This commit is contained in:
shreyas-goenka 2024-07-23 22:50:11 +05:30 committed by GitHub
parent 52ca599cd5
commit 4bf88b4209
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 276 additions and 218 deletions

View File

@ -55,12 +55,18 @@ func parsePythonDiagnostics(input io.Reader) (diag.Diagnostics, error) {
return nil, fmt.Errorf("failed to parse path: %s", err)
}
var locations []dyn.Location
location := convertPythonLocation(parsedLine.Location)
if location != (dyn.Location{}) {
locations = append(locations, location)
}
diag := diag.Diagnostic{
Severity: severity,
Summary: parsedLine.Summary,
Detail: parsedLine.Detail,
Location: convertPythonLocation(parsedLine.Location),
Path: path,
Severity: severity,
Summary: parsedLine.Summary,
Detail: parsedLine.Detail,
Locations: locations,
Path: path,
}
diags = diags.Append(diag)

View File

@ -39,10 +39,12 @@ func TestParsePythonDiagnostics(t *testing.T) {
{
Severity: diag.Error,
Summary: "error summary",
Location: dyn.Location{
File: "src/examples/file.py",
Line: 1,
Column: 2,
Locations: []dyn.Location{
{
File: "src/examples/file.py",
Line: 1,
Column: 2,
},
},
},
},

View File

@ -97,11 +97,14 @@ func TestPythonMutator_load(t *testing.T) {
assert.Equal(t, 1, len(diags))
assert.Equal(t, "job doesn't have any tasks", diags[0].Summary)
assert.Equal(t, dyn.Location{
File: "src/examples/file.py",
Line: 10,
Column: 5,
}, diags[0].Location)
assert.Equal(t, []dyn.Location{
{
File: "src/examples/file.py",
Line: 10,
Column: 5,
},
}, diags[0].Locations)
}
func TestPythonMutator_load_disallowed(t *testing.T) {

View File

@ -178,10 +178,10 @@ func (m *setRunAs) Apply(_ context.Context, b *bundle.Bundle) diag.Diagnostics {
setRunAsForJobs(b)
return diag.Diagnostics{
{
Severity: diag.Warning,
Summary: "You are using the legacy mode of run_as. The support for this mode is experimental and might be removed in a future release of the CLI. In order to run the DLT pipelines in your DAB as the run_as user this mode changes the owners of the pipelines to the run_as identity, which requires the user deploying the bundle to be a workspace admin, and also a Metastore admin if the pipeline target is in UC.",
Path: dyn.MustPathFromString("experimental.use_legacy_run_as"),
Location: b.Config.GetLocation("experimental.use_legacy_run_as"),
Severity: diag.Warning,
Summary: "You are using the legacy mode of run_as. The support for this mode is experimental and might be removed in a future release of the CLI. In order to run the DLT pipelines in your DAB as the run_as user this mode changes the owners of the pipelines to the run_as identity, which requires the user deploying the bundle to be a workspace admin, and also a Metastore admin if the pipeline target is in UC.",
Path: dyn.MustPathFromString("experimental.use_legacy_run_as"),
Locations: b.Config.GetLocations("experimental.use_legacy_run_as"),
},
}
}

View File

@ -524,6 +524,17 @@ func (r Root) GetLocation(path string) dyn.Location {
return v.Location()
}
// Get all locations of the configuration value at the specified path. We need both
// this function and it's singular version (GetLocation) because some diagnostics just need
// the primary location and some need all locations associated with a configuration value.
func (r Root) GetLocations(path string) []dyn.Location {
v, err := dyn.Get(r.value, path)
if err != nil {
return []dyn.Location{}
}
return v.Locations()
}
// Value returns the dynamic configuration value of the root object. This value
// is the source of truth and is kept in sync with values in the typed configuration.
func (r Root) Value() dyn.Value {

View File

@ -45,8 +45,10 @@ func (v *filesToSync) Apply(ctx context.Context, rb bundle.ReadOnlyBundle) diag.
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: "There are no files to sync, please check your .gitignore and sync.exclude configuration",
Location: loc.Location(),
Path: loc.Path(),
// Show all locations where sync.exclude is defined, since merging
// sync.exclude is additive.
Locations: loc.Locations(),
Path: loc.Path(),
})
}

View File

@ -6,6 +6,7 @@ import (
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/cli/libs/dyn"
)
func JobClusterKeyDefined() bundle.ReadOnlyMutator {
@ -41,8 +42,11 @@ func (v *jobClusterKeyDefined) Apply(ctx context.Context, rb bundle.ReadOnlyBund
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("job_cluster_key %s is not defined", task.JobClusterKey),
Location: loc.Location(),
Path: loc.Path(),
// Show only the location where the job_cluster_key is defined.
// Other associated locations are not relevant since they are
// overridden during merging.
Locations: []dyn.Location{loc.Location()},
Path: loc.Path(),
})
}
}

View File

@ -20,6 +20,10 @@ func (l location) Location() dyn.Location {
return l.rb.Config().GetLocation(l.path)
}
func (l location) Locations() []dyn.Location {
return l.rb.Config().GetLocations(l.path)
}
func (l location) Path() dyn.Path {
return dyn.MustPathFromString(l.path)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/fileset"
"golang.org/x/sync/errgroup"
)
@ -64,10 +65,10 @@ func checkPatterns(patterns []string, path string, rb bundle.ReadOnlyBundle) (di
loc := location{path: fmt.Sprintf("%s[%d]", path, index), rb: rb}
mu.Lock()
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("Pattern %s does not match any files", p),
Location: loc.Location(),
Path: loc.Path(),
Severity: diag.Warning,
Summary: fmt.Sprintf("Pattern %s does not match any files", p),
Locations: []dyn.Location{loc.Location()},
Path: loc.Path(),
})
mu.Unlock()
}

View File

@ -32,8 +32,8 @@ const errorTemplate = `{{ "Error" | red }}: {{ .Summary }}
{{- if .Path.String }}
{{ "at " }}{{ .Path.String | green }}
{{- end }}
{{- if .Location.File }}
{{ "in " }}{{ .Location.String | cyan }}
{{- range $index, $element := .Locations }}
{{ if eq $index 0 }}in {{else}} {{ end}}{{ $element.String | cyan }}
{{- end }}
{{- if .Detail }}
@ -46,8 +46,8 @@ const warningTemplate = `{{ "Warning" | yellow }}: {{ .Summary }}
{{- if .Path.String }}
{{ "at " }}{{ .Path.String | green }}
{{- end }}
{{- if .Location.File }}
{{ "in " }}{{ .Location.String | cyan }}
{{- range $index, $element := .Locations }}
{{ if eq $index 0 }}in {{else}} {{ end}}{{ $element.String | cyan }}
{{- end }}
{{- if .Detail }}
@ -141,12 +141,18 @@ func renderDiagnostics(out io.Writer, b *bundle.Bundle, diags diag.Diagnostics)
t = warningT
}
// Make file relative to bundle root
if d.Location.File != "" && b != nil {
out, err := filepath.Rel(b.RootPath, d.Location.File)
// if we can't relativize the path, just use path as-is
if err == nil {
d.Location.File = out
for i := range d.Locations {
if b == nil {
break
}
// Make location relative to bundle root
if d.Locations[i].File != "" {
out, err := filepath.Rel(b.RootPath, d.Locations[i].File)
// if we can't relativize the path, just use path as-is
if err == nil {
d.Locations[i].File = out
}
}
}

View File

@ -88,34 +88,22 @@ func TestRenderTextOutput(t *testing.T) {
bundle: loadingBundle,
diags: diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: "error (1)",
Detail: "detail (1)",
Location: dyn.Location{
File: "foo.py",
Line: 1,
Column: 1,
},
Severity: diag.Error,
Summary: "error (1)",
Detail: "detail (1)",
Locations: []dyn.Location{{File: "foo.py", Line: 1, Column: 1}},
},
diag.Diagnostic{
Severity: diag.Error,
Summary: "error (2)",
Detail: "detail (2)",
Location: dyn.Location{
File: "foo.py",
Line: 2,
Column: 1,
},
Severity: diag.Error,
Summary: "error (2)",
Detail: "detail (2)",
Locations: []dyn.Location{{File: "foo.py", Line: 2, Column: 1}},
},
diag.Diagnostic{
Severity: diag.Warning,
Summary: "warning (3)",
Detail: "detail (3)",
Location: dyn.Location{
File: "foo.py",
Line: 3,
Column: 1,
},
Severity: diag.Warning,
Summary: "warning (3)",
Detail: "detail (3)",
Locations: []dyn.Location{{File: "foo.py", Line: 3, Column: 1}},
},
},
opts: RenderOptions{RenderSummaryTable: true},
@ -174,24 +162,16 @@ func TestRenderTextOutput(t *testing.T) {
bundle: nil,
diags: diag.Diagnostics{
diag.Diagnostic{
Severity: diag.Error,
Summary: "error (1)",
Detail: "detail (1)",
Location: dyn.Location{
File: "foo.py",
Line: 1,
Column: 1,
},
Severity: diag.Error,
Summary: "error (1)",
Detail: "detail (1)",
Locations: []dyn.Location{{File: "foo.py", Line: 1, Column: 1}},
},
diag.Diagnostic{
Severity: diag.Warning,
Summary: "warning (2)",
Detail: "detail (2)",
Location: dyn.Location{
File: "foo.py",
Line: 3,
Column: 1,
},
Severity: diag.Warning,
Summary: "warning (2)",
Detail: "detail (2)",
Locations: []dyn.Location{{File: "foo.py", Line: 3, Column: 1}},
},
},
opts: RenderOptions{RenderSummaryTable: false},
@ -252,17 +232,42 @@ func TestRenderDiagnostics(t *testing.T) {
Severity: diag.Error,
Summary: "failed to load xxx",
Detail: "'name' is required",
Location: dyn.Location{
Locations: []dyn.Location{{
File: "foo.yaml",
Line: 1,
Column: 2,
},
Column: 2}},
},
},
expected: "Error: failed to load xxx\n" +
" in foo.yaml:1:2\n\n" +
"'name' is required\n\n",
},
{
name: "error with multiple source locations",
diags: diag.Diagnostics{
{
Severity: diag.Error,
Summary: "failed to load xxx",
Detail: "'name' is required",
Locations: []dyn.Location{
{
File: "foo.yaml",
Line: 1,
Column: 2,
},
{
File: "bar.yaml",
Line: 3,
Column: 4,
},
},
},
},
expected: "Error: failed to load xxx\n" +
" in foo.yaml:1:2\n" +
" bar.yaml:3:4\n\n" +
"'name' is required\n\n",
},
{
name: "error with path",
diags: diag.Diagnostics{

View File

@ -9,6 +9,7 @@ import (
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/config/validate"
"github.com/databricks/cli/libs/diag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -21,11 +22,13 @@ func TestSyncIncludeExcludeNoMatchesTest(t *testing.T) {
require.Equal(t, diags[0].Severity, diag.Warning)
require.Equal(t, diags[0].Summary, "Pattern dist does not match any files")
require.Equal(t, diags[0].Location.File, filepath.Join("sync", "override", "databricks.yml"))
require.Equal(t, diags[0].Location.Line, 17)
require.Equal(t, diags[0].Location.Column, 11)
require.Equal(t, diags[0].Path.String(), "sync.exclude[0]")
assert.Len(t, diags[0].Locations, 1)
require.Equal(t, diags[0].Locations[0].File, filepath.Join("sync", "override", "databricks.yml"))
require.Equal(t, diags[0].Locations[0].Line, 17)
require.Equal(t, diags[0].Locations[0].Column, 11)
summaries := []string{
fmt.Sprintf("Pattern %s does not match any files", filepath.Join("src", "*")),
fmt.Sprintf("Pattern %s does not match any files", filepath.Join("tests", "*")),

View File

@ -17,9 +17,9 @@ type Diagnostic struct {
// This may be multiple lines and may be nil.
Detail string
// Location is a source code location associated with the diagnostic message.
// It may be zero if there is no associated location.
Location dyn.Location
// Locations are the source code locations associated with the diagnostic message.
// It may be empty if there are no associated locations.
Locations []dyn.Location
// Path is a path to the value in a configuration tree that the diagnostic is associated with.
// It may be nil if there is no associated path.

View File

@ -65,19 +65,19 @@ func (n normalizeOptions) normalizeType(typ reflect.Type, src dyn.Value, seen []
func nullWarning(expected dyn.Kind, src dyn.Value, path dyn.Path) diag.Diagnostic {
return diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("expected a %s value, found null", expected),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf("expected a %s value, found null", expected),
Locations: []dyn.Location{src.Location()},
Path: path,
}
}
func typeMismatch(expected dyn.Kind, src dyn.Value, path dyn.Path) diag.Diagnostic {
return diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("expected %s, found %s", expected, src.Kind()),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf("expected %s, found %s", expected, src.Kind()),
Locations: []dyn.Location{src.Location()},
Path: path,
}
}
@ -98,8 +98,9 @@ func (n normalizeOptions) normalizeStruct(typ reflect.Type, src dyn.Value, seen
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("unknown field: %s", pk.MustString()),
Location: pk.Location(),
Path: path,
// Show all locations the unknown field is defined at.
Locations: pk.Locations(),
Path: path,
})
}
continue
@ -320,10 +321,10 @@ func (n normalizeOptions) normalizeInt(typ reflect.Type, src dyn.Value, path dyn
out = int64(src.MustFloat())
if src.MustFloat() != float64(out) {
return dyn.InvalidValue, diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf(`cannot accurately represent "%g" as integer due to precision loss`, src.MustFloat()),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf(`cannot accurately represent "%g" as integer due to precision loss`, src.MustFloat()),
Locations: []dyn.Location{src.Location()},
Path: path,
})
}
case dyn.KindString:
@ -336,10 +337,10 @@ func (n normalizeOptions) normalizeInt(typ reflect.Type, src dyn.Value, path dyn
}
return dyn.InvalidValue, diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("cannot parse %q as an integer", src.MustString()),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf("cannot parse %q as an integer", src.MustString()),
Locations: []dyn.Location{src.Location()},
Path: path,
})
}
case dyn.KindNil:
@ -363,10 +364,10 @@ func (n normalizeOptions) normalizeFloat(typ reflect.Type, src dyn.Value, path d
out = float64(src.MustInt())
if src.MustInt() != int64(out) {
return dyn.InvalidValue, diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf(`cannot accurately represent "%d" as floating point number due to precision loss`, src.MustInt()),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf(`cannot accurately represent "%d" as floating point number due to precision loss`, src.MustInt()),
Locations: []dyn.Location{src.Location()},
Path: path,
})
}
case dyn.KindString:
@ -379,10 +380,10 @@ func (n normalizeOptions) normalizeFloat(typ reflect.Type, src dyn.Value, path d
}
return dyn.InvalidValue, diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: fmt.Sprintf("cannot parse %q as a floating point number", src.MustString()),
Location: src.Location(),
Path: path,
Severity: diag.Warning,
Summary: fmt.Sprintf("cannot parse %q as a floating point number", src.MustString()),
Locations: []dyn.Location{src.Location()},
Path: path,
})
}
case dyn.KindNil:

View File

@ -40,10 +40,10 @@ func TestNormalizeStructElementDiagnostic(t *testing.T) {
vout, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected string, found map`,
Location: dyn.Location{},
Path: dyn.NewPath(dyn.Key("bar")),
Severity: diag.Warning,
Summary: `expected string, found map`,
Locations: []dyn.Location{{}},
Path: dyn.NewPath(dyn.Key("bar")),
}, err[0])
// Elements that encounter an error during normalization are dropped.
@ -58,23 +58,33 @@ func TestNormalizeStructUnknownField(t *testing.T) {
}
var typ Tmp
vin := dyn.V(map[string]dyn.Value{
"foo": dyn.V("bar"),
"bar": dyn.V("baz"),
})
m := dyn.NewMapping()
m.Set(dyn.V("foo"), dyn.V("val-foo"))
// Set the unknown field, with location information.
m.Set(dyn.NewValue("bar", []dyn.Location{
{File: "hello.yaml", Line: 1, Column: 1},
{File: "world.yaml", Line: 2, Column: 2},
}), dyn.V("var-bar"))
vin := dyn.V(m)
vout, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `unknown field: bar`,
Location: vin.Get("foo").Location(),
Path: dyn.EmptyPath,
// Assert location of the unknown field is included in the diagnostic.
Locations: []dyn.Location{
{File: "hello.yaml", Line: 1, Column: 1},
{File: "world.yaml", Line: 2, Column: 2},
},
Path: dyn.EmptyPath,
}, err[0])
// The field that can be mapped to the struct field is retained.
assert.Equal(t, map[string]any{
"foo": "bar",
"foo": "val-foo",
}, vout.AsAny())
}
@ -100,10 +110,10 @@ func TestNormalizeStructError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found string`,
Location: vin.Get("foo").Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found string`,
Locations: []dyn.Location{vin.Get("foo").Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -245,10 +255,10 @@ func TestNormalizeStructRandomStringError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -262,10 +272,10 @@ func TestNormalizeStructIntError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found int`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found int`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -291,10 +301,10 @@ func TestNormalizeMapElementDiagnostic(t *testing.T) {
vout, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected string, found map`,
Location: dyn.Location{},
Path: dyn.NewPath(dyn.Key("bar")),
Severity: diag.Warning,
Summary: `expected string, found map`,
Locations: []dyn.Location{{}},
Path: dyn.NewPath(dyn.Key("bar")),
}, err[0])
// Elements that encounter an error during normalization are dropped.
@ -317,10 +327,10 @@ func TestNormalizeMapError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -372,10 +382,10 @@ func TestNormalizeMapRandomStringError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -385,10 +395,10 @@ func TestNormalizeMapIntError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected map, found int`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected map, found int`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -415,10 +425,10 @@ func TestNormalizeSliceElementDiagnostic(t *testing.T) {
vout, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected string, found map`,
Location: dyn.Location{},
Path: dyn.NewPath(dyn.Index(2)),
Severity: diag.Warning,
Summary: `expected string, found map`,
Locations: []dyn.Location{{}},
Path: dyn.NewPath(dyn.Index(2)),
}, err[0])
// Elements that encounter an error during normalization are dropped.
@ -439,10 +449,10 @@ func TestNormalizeSliceError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected sequence, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected sequence, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -494,10 +504,10 @@ func TestNormalizeSliceRandomStringError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected sequence, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected sequence, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -507,10 +517,10 @@ func TestNormalizeSliceIntError(t *testing.T) {
_, err := Normalize(typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected sequence, found int`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected sequence, found int`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -528,10 +538,10 @@ func TestNormalizeStringNil(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected a string value, found null`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected a string value, found null`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -565,10 +575,10 @@ func TestNormalizeStringError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected string, found map`,
Location: dyn.Location{},
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected string, found map`,
Locations: []dyn.Location{{}},
Path: dyn.EmptyPath,
}, err[0])
}
@ -586,10 +596,10 @@ func TestNormalizeBoolNil(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected a bool value, found null`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected a bool value, found null`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -628,10 +638,10 @@ func TestNormalizeBoolFromStringError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected bool, found string`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected bool, found string`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -641,10 +651,10 @@ func TestNormalizeBoolError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected bool, found map`,
Location: dyn.Location{},
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected bool, found map`,
Locations: []dyn.Location{{}},
Path: dyn.EmptyPath,
}, err[0])
}
@ -662,10 +672,10 @@ func TestNormalizeIntNil(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected a int value, found null`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected a int value, found null`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -683,10 +693,10 @@ func TestNormalizeIntFromFloatError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `cannot accurately represent "1.5" as integer due to precision loss`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `cannot accurately represent "1.5" as integer due to precision loss`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -712,10 +722,10 @@ func TestNormalizeIntFromStringError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `cannot parse "abc" as an integer`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `cannot parse "abc" as an integer`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -725,10 +735,10 @@ func TestNormalizeIntError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected int, found map`,
Location: dyn.Location{},
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected int, found map`,
Locations: []dyn.Location{{}},
Path: dyn.EmptyPath,
}, err[0])
}
@ -746,10 +756,10 @@ func TestNormalizeFloatNil(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected a float value, found null`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected a float value, found null`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -771,10 +781,10 @@ func TestNormalizeFloatFromIntError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `cannot accurately represent "9007199254740993" as floating point number due to precision loss`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `cannot accurately represent "9007199254740993" as floating point number due to precision loss`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -800,10 +810,10 @@ func TestNormalizeFloatFromStringError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `cannot parse "abc" as a floating point number`,
Location: vin.Location(),
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `cannot parse "abc" as a floating point number`,
Locations: []dyn.Location{vin.Location()},
Path: dyn.EmptyPath,
}, err[0])
}
@ -813,10 +823,10 @@ func TestNormalizeFloatError(t *testing.T) {
_, err := Normalize(&typ, vin)
assert.Len(t, err, 1)
assert.Equal(t, diag.Diagnostic{
Severity: diag.Warning,
Summary: `expected float, found map`,
Location: dyn.Location{},
Path: dyn.EmptyPath,
Severity: diag.Warning,
Summary: `expected float, found map`,
Locations: []dyn.Location{{}},
Path: dyn.EmptyPath,
}, err[0])
}