Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion csv_golden_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"testing"
)

var updateGolden = flag.Bool("update-golden", false, "rewrite testdata/experimental_csv/*.golden files")
var updateGolden = flag.Bool("update-golden", false, "rewrite testdata/experimental_csv/*.golden, testdata/yaml_output/*.golden, and profile YAML goldens")

func TestExperimentalCsvGolden(t *testing.T) {
for name, rs := range csvGoldenFixtures() {
Expand Down
109 changes: 109 additions & 0 deletions params/fixtures_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package params

import (
"path/filepath"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestLoadParamFileFixtures(t *testing.T) {
t.Parallel()

tests := []struct {
file string
want map[string]string
}{
{
file: "testdata/readme_example.yaml",
want: map[string]string{
"arr": "ARRAY<STRING>",
"names": `[STRUCT<FirstName STRING, LastName STRING>("John", "Doe"), ("Mary", "Sue")]`,
},
},
{
file: "testdata/spanner_literals.yml",
want: map[string]string{
"b": "TRUE",
"bs": `b"foo"`,
"i64": "1",
"f64": "1.0",
"f32": "CAST(1.0 AS FLOAT32)",
"n": `NUMERIC "1"`,
"s": "'foo'",
"js": `JSON "{}"`,
"ts": `TIMESTAMP "2000-01-01T00:00:00Z"`,
"ival_single": "INTERVAL 3 DAY",
"n_b": "CAST(NULL AS BOOL)",
},
},
{
file: "testdata/multiline_literal.yaml",
want: map[string]string{
"query": "SELECT SingerId, FirstName\nFROM Singers\nWHERE SingerId = @id\n",
"id": "42",
},
},
{
file: "testdata/large_int.yaml",
want: map[string]string{
"id": "1234567890123456789",
},
},
{
file: "testdata/scalars_extra.yaml",
want: map[string]string{
"id": "123",
"enabled": "FALSE",
"price": "1.0",
"ratio": "0.25",
"tag": "yes",
"label": "ARRAY<INT64>",
"created_at": `TIMESTAMP "2023-01-01T00:00:00Z"`,
},
},
}

for _, tc := range tests {
tc := tc
t.Run(filepath.Base(tc.file), func(t *testing.T) {
t.Parallel()
got, err := LoadParamFile(tc.file)
Comment thread
apstndb marked this conversation as resolved.
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatalf("(-want +got)\n%s", diff)
}
})
}
}

func TestLoadParamFileFixtureErrors(t *testing.T) {
t.Parallel()

if _, err := LoadParamFile("testdata/nested_map.yaml"); err == nil {
t.Fatal("expected error for nested map")
}
if _, err := LoadParamFile("testdata/nested_array.yaml"); err == nil {
t.Fatal("expected error for nested array")
}
}

func TestMergeParamsWithFixture(t *testing.T) {
t.Parallel()

file, err := LoadParamFile("testdata/readme_example.yaml")
if err != nil {
t.Fatal(err)
}
got := MergeParams(file, map[string]string{"arr": "ARRAY<INT64>", "extra": "1"})
want := map[string]string{
"arr": "ARRAY<INT64>",
"names": `[STRUCT<FirstName STRING, LastName STRING>("John", "Doe"), ("Mary", "Sue")]`,
"extra": "1",
}
if diff := cmp.Diff(want, got); diff != "" {
t.Fatalf("(-want +got)\n%s", diff)
}
}
41 changes: 1 addition & 40 deletions params/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,49 +63,18 @@ func TestLoadParamFile(t *testing.T) {

dir := t.TempDir()

yamlPath := filepath.Join(dir, "params.yaml")
if err := os.WriteFile(yamlPath, []byte("arr: ARRAY<STRING>\nname: \"42\"\n"), 0o644); err != nil {
t.Fatal(err)
}
got, err := LoadParamFile(yamlPath)
if err != nil {
t.Fatal(err)
}
want := map[string]string{"arr": "ARRAY<STRING>", "name": "42"}
if diff := cmp.Diff(want, got); diff != "" {
t.Fatalf("(-want +got)\n%s", diff)
}

jsonPath := filepath.Join(dir, "params.json")
if err := os.WriteFile(jsonPath, []byte(`{"arr":"ARRAY<STRING>"}`), 0o644); err != nil {
t.Fatal(err)
}
got, err = LoadParamFile(jsonPath)
got, err := LoadParamFile(jsonPath)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(map[string]string{"arr": "ARRAY<STRING>"}, got); diff != "" {
t.Fatalf("(-want +got)\n%s", diff)
}

yamlScalarsPath := filepath.Join(dir, "params-scalars.yaml")
if err := os.WriteFile(yamlScalarsPath, []byte("id: 123\nenabled: true\nprice: 1.0\ncreated_at: 2023-01-01T00:00:00Z\n"), 0o644); err != nil {
t.Fatal(err)
}
got, err = LoadParamFile(yamlScalarsPath)
if err != nil {
t.Fatal(err)
}
wantScalars := map[string]string{
"id": "123",
"enabled": "TRUE",
"price": "1.0",
"created_at": `TIMESTAMP "2023-01-01T00:00:00Z"`,
}
if diff := cmp.Diff(wantScalars, got); diff != "" {
t.Fatalf("(-want +got)\n%s", diff)
}

jsonLargeIntPath := filepath.Join(dir, "params-large-int.json")
if err := os.WriteFile(jsonLargeIntPath, []byte(`{"id":1234567890123456789}`), 0o644); err != nil {
t.Fatal(err)
Expand All @@ -118,14 +87,6 @@ func TestLoadParamFile(t *testing.T) {
t.Fatalf("got id=%q, want exact integer string", got["id"])
}

nestedPath := filepath.Join(dir, "params-nested.yaml")
if err := os.WriteFile(nestedPath, []byte("arr: [1, 2]\n"), 0o644); err != nil {
t.Fatal(err)
}
if _, err := LoadParamFile(nestedPath); err == nil {
t.Fatal("expected error for nested array in param file")
}

emptyPath := filepath.Join(dir, "params-empty.yaml")
if err := os.WriteFile(emptyPath, []byte(" \n"), 0o644); err != nil {
t.Fatal(err)
Expand Down
1 change: 1 addition & 0 deletions params/testdata/large_int.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
id: 1234567890123456789
5 changes: 5 additions & 0 deletions params/testdata/multiline_literal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: |
SELECT SingerId, FirstName
FROM Singers
WHERE SingerId = @id
id: "42"
1 change: 1 addition & 0 deletions params/testdata/nested_array.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
arr: [1, 2]
2 changes: 2 additions & 0 deletions params/testdata/nested_map.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
opts:
key: value
3 changes: 3 additions & 0 deletions params/testdata/readme_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# params.yaml from README (--param-file example)
arr: ARRAY<STRING>
names: '[STRUCT<FirstName STRING, LastName STRING>("John", "Doe"), ("Mary", "Sue")]'
7 changes: 7 additions & 0 deletions params/testdata/scalars_extra.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
id: 123
enabled: false
price: 1.0
ratio: 0.25
tag: yes
label: "ARRAY<INT64>"
created_at: 2023-01-01T00:00:00Z
12 changes: 12 additions & 0 deletions params/testdata/spanner_literals.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Common Spanner parameter literal strings for --param-file
b: "TRUE"
bs: 'b"foo"'
i64: "1"
f64: "1.0"
f32: "CAST(1.0 AS FLOAT32)"
n: 'NUMERIC "1"'
s: "'foo'"
js: 'JSON "{}"'
ts: 'TIMESTAMP "2000-01-01T00:00:00Z"'
ival_single: "INTERVAL 3 DAY"
n_b: "CAST(NULL AS BOOL)"
109 changes: 109 additions & 0 deletions profile_yaml_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"os"
"path/filepath"
"testing"

sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
"google.golang.org/protobuf/encoding/protojson"
)

func loadProfileJSONFixture(path string) (*sppb.ResultSet, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var rs sppb.ResultSet
if err := protojson.Unmarshal(b, &rs); err != nil {
return nil, err
}
return &rs, nil
}

type profileYAMLGoldenCase struct {
jsonFile string
filter string
golden string
}

func profileYAMLGoldenCases() []profileYAMLGoldenCase {
return []profileYAMLGoldenCase{
{
jsonFile: "testdata/profile/param_scalar.json",
filter: ".",
golden: "profile_param_scalar",
},
{
jsonFile: "testdata/profile/albums_by_singer.json",
filter: ".",
golden: "profile_albums_by_singer",
},
{
jsonFile: "testdata/profile/singers_limit3.json",
filter: ".",
golden: "profile_singers_limit3",
},
{
jsonFile: "testdata/profile/singers_limit3.json",
filter: `{rowType: .metadata.rowType, rows: .rows}`,
golden: "profile_singers_limit3_rowtype_rows",
},
{
jsonFile: "testdata/profile/singers_limit3.json",
filter: `.rows[]`,
golden: "profile_singers_limit3_rows_stream",
},
{
jsonFile: "testdata/profile/singers_limit3.json",
filter: `.metadata.rowType.fields | map(.name)`,
golden: "profile_singers_limit3_field_names",
},
}
}

func TestProfileJSONToYamlGolden(t *testing.T) {
for _, tc := range profileYAMLGoldenCases() {
tc := tc
t.Run(tc.golden, func(t *testing.T) {
Comment thread
apstndb marked this conversation as resolved.
rs, err := loadProfileJSONFixture(tc.jsonFile)
if err != nil {
t.Fatal(err)
}
if rs.GetMetadata() == nil || rs.GetMetadata().GetRowType() == nil {
t.Fatal("missing metadata.rowType")
}
if rs.GetStats() == nil {
t.Fatal("missing stats")
}
if rs.GetStats().GetQueryPlan() == nil && rs.GetStats().GetQueryStats() == nil {
t.Fatal("missing query plan or query stats")
}

got, err := encodeResultSetYAML(tc.filter, rs)
if err != nil {
t.Fatalf("encodeResultSetYAML() error = %v", err)
}

goldenPath := filepath.Join("testdata", "yaml_output", tc.golden+".golden")
if *updateGolden {
if err := os.MkdirAll(filepath.Dir(goldenPath), 0o755); err != nil {
t.Fatalf("MkdirAll() error = %v", err)
}
if err := os.WriteFile(goldenPath, got, 0o644); err != nil {
t.Fatalf("WriteFile() error = %v", err)
}
t.Logf("updated %s", goldenPath)
return
}

want, err := os.ReadFile(goldenPath)
if err != nil {
t.Fatalf("ReadFile(%q) error = %v (run: go test -update-golden -run TestProfileJSONToYamlGolden)", goldenPath, err)
}
if string(got) != string(want) {
t.Fatalf("PROFILE JSON → YAML mismatch for %s\n\ngot:\n%s\n\nwant:\n%s", tc.golden, got, want)
}
})
}
}
Loading
Loading