Test that what is well-formed and means one thing loads: ignored parts, constant samples, any JSON value, weight 0, an unread name, a stray rows file, a tagless struct and flags with no effect
This commit is contained in:
+5
-14
@@ -271,25 +271,19 @@ func TestBuiltinDateAndTime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestBuiltinDateArgs pins the New-time checks: bounds are calendar dates in order,
|
// TestBuiltinDateArgs pins the New-time checks: bounds are calendar dates in order, and the
|
||||||
// the layout is quoted, names a field, and for time names no date field.
|
// layout is quoted.
|
||||||
func TestBuiltinDateArgs(t *testing.T) {
|
func TestBuiltinDateArgs(t *testing.T) {
|
||||||
for tmpl, want := range map[string]string{
|
for tmpl, want := range map[string]string{
|
||||||
`"{date(1990-13-01,1990-12-31,'2006-01-02')}"`: "1990-13-01",
|
`"{date(1990-13-01,1990-12-31,'2006-01-02')}"`: "1990-13-01",
|
||||||
`"{date(1990-12-31,1990-01-01,'2006-01-02')}"`: "is after",
|
`"{date(1990-12-31,1990-01-01,'2006-01-02')}"`: "is after",
|
||||||
`"{date(1990-01-01,1990-01-01,'2006-01-02')}"`: "write it as text",
|
|
||||||
`"{date(1990-01-01,1990-12-31,2006-01-02)}"`: "'2006-01-02'",
|
`"{date(1990-01-01,1990-12-31,2006-01-02)}"`: "'2006-01-02'",
|
||||||
`"{date(1990-01-01,1990-12-31,'January 2, 2006)}"`: "'",
|
`"{date(1990-01-01,1990-12-31,'January 2, 2006)}"`: "'",
|
||||||
`"{date(1990-01-01,1990-12-31,\"January 2, 2006\")}"`: "quoted: 'January 2, 2006'",
|
`"{date(1990-01-01,1990-12-31,\"January 2, 2006\")}"`: "quoted: 'January 2, 2006'",
|
||||||
`"{date(1990-01-01,1990-12-31,'x')}"`: "text",
|
|
||||||
`"{date(1990-01-01,1990-12-31,'')}"`: "text",
|
|
||||||
`"{date(1990-01-01,1990-12-31)}"`: "3 arguments",
|
`"{date(1990-01-01,1990-12-31)}"`: "3 arguments",
|
||||||
`"{date(1990-01-01,1990-12-31,January 2, 2006)}"`: "'January 2, 2006'",
|
`"{date(1990-01-01,1990-12-31,January 2, 2006)}"`: "'January 2, 2006'",
|
||||||
`"{time(3:04 PM, Mon)}"`: "'3:04 PM, Mon'",
|
`"{time(3:04 PM, Mon)}"`: "'3:04 PM, Mon'",
|
||||||
`"{time(15:04)}"`: "'15:04'",
|
`"{time(15:04)}"`: "'15:04'",
|
||||||
`"{time('2006-01-02 15:04')}"`: "date(",
|
|
||||||
`"{time('x')}"`: "text",
|
|
||||||
`"{date(1990-01-01,1990-12-31,'15:04')}"`: "time('15:04')",
|
|
||||||
} {
|
} {
|
||||||
_, err := resolved(t, tmpl)
|
_, err := resolved(t, tmpl)
|
||||||
if err == nil || !strings.Contains(err.Error(), want) {
|
if err == nil || !strings.Contains(err.Error(), want) {
|
||||||
@@ -327,7 +321,7 @@ func TestBuiltinLayoutErrorsNameARunnableSpelling(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TestBuiltinDateSpansOneDay pins that from == to is a day: with a clock layout it
|
// TestBuiltinDateSpansOneDay pins that from == to is a day: with a clock layout it
|
||||||
// draws every second of it, and without one it could only emit one value.
|
// draws every second of it, and without one it prints that day.
|
||||||
func TestBuiltinDateSpansOneDay(t *testing.T) {
|
func TestBuiltinDateSpansOneDay(t *testing.T) {
|
||||||
f := engine(1)
|
f := engine(1)
|
||||||
seen := map[string]bool{}
|
seen := map[string]bool{}
|
||||||
@@ -341,9 +335,8 @@ func TestBuiltinDateSpansOneDay(t *testing.T) {
|
|||||||
if len(seen) < 400 {
|
if len(seen) < 400 {
|
||||||
t.Fatalf("date over one day drew %d distinct seconds in 500, want the whole day", len(seen))
|
t.Fatalf("date over one day drew %d distinct seconds in 500, want the whole day", len(seen))
|
||||||
}
|
}
|
||||||
_, err := compile(parse(t, `"{date(2026-01-01,2026-01-01,'2006-01-02')}"`))
|
if got := mustRender(t, f, `"{date(2026-01-01,2026-01-01,'2006-01-02')}"`); got != "2026-01-01" {
|
||||||
if err == nil || !strings.Contains(err.Error(), "write it as text") {
|
t.Fatalf("one day in a date-only layout = %q, want that day", got)
|
||||||
t.Fatalf("one day in a date-only layout = %v, want it named a constant", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,8 +391,6 @@ func TestBuiltinCompileErrors(t *testing.T) {
|
|||||||
`"{float(Inf,Inf,2)}"`, // same-sign infinities
|
`"{float(Inf,Inf,2)}"`, // same-sign infinities
|
||||||
`"{float(1,NaN,2)}"`, // one NaN bound
|
`"{float(1,NaN,2)}"`, // one NaN bound
|
||||||
`"{float(-Inf,1,2)}"`, // one infinite bound
|
`"{float(-Inf,1,2)}"`, // one infinite bound
|
||||||
`"{int(5,5)}"`, // a constant is written as text
|
|
||||||
`"{float(1,1,2)}"`, // a constant is written as text
|
|
||||||
`"{iban(US)}"`, // unsupported country
|
`"{iban(US)}"`, // unsupported country
|
||||||
`"{seq(a,b)}"`, // seq takes at most one name
|
`"{seq(a,b)}"`, // seq takes at most one name
|
||||||
} {
|
} {
|
||||||
|
|||||||
+18
-13
@@ -492,11 +492,6 @@ func TestRunTemplateMisuse(t *testing.T) {
|
|||||||
"{bad": "unterminated",
|
"{bad": "unterminated",
|
||||||
"name: {/no.such.path}": "no entry",
|
"name: {/no.such.path}": "no entry",
|
||||||
"a } b": "}}",
|
"a } b": "}}",
|
||||||
"42": "number",
|
|
||||||
"42\n": "number",
|
|
||||||
"true\n": "boolean",
|
|
||||||
"null\n": "jq",
|
|
||||||
" null ": "jq",
|
|
||||||
"{//sv_SE.person}": "write {/sv_SE.person}",
|
"{//sv_SE.person}": "write {/sv_SE.person}",
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut(stdin, "--seed", "1")
|
code, out, errb := runOut(stdin, "--seed", "1")
|
||||||
@@ -548,11 +543,24 @@ func TestRunRepeatIsBounded(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunListTakesNoRepeatOrSeparator(t *testing.T) {
|
func TestRunIgnoresAFlagWithNoEffect(t *testing.T) {
|
||||||
for _, args := range [][]string{{"--list", "-n", "3"}, {"--list", "--separator", ","}} {
|
for _, args := range [][]string{{"--list", "-n", "3"}, {"--list", "--separator", ","}, {"--list", "--format", "json"}, {"--list", "--table", "t"}} {
|
||||||
code, _, errb := runOut("", args...)
|
if code, out, errb := runOut("", args...); code != 0 || !strings.Contains(out, "sv_SE.person\n") {
|
||||||
if code != 2 || !strings.Contains(errb, "--list takes no") {
|
t.Errorf("run(%v) = %d, stderr %q, want the list", args, code, errb)
|
||||||
t.Errorf("run(%v) = %d, %q, want misuse", args, code, errb)
|
}
|
||||||
|
}
|
||||||
|
dir := recordDir(t)
|
||||||
|
for _, args := range [][]string{{"--format", "json", "--separator", ","}, {"--table", "t"}, {"--format", "json", "--table", "t"}} {
|
||||||
|
if code, out, errb := runOut("{/users}", append(args, "--data-path", dir)...); code != 0 || out == "" {
|
||||||
|
t.Errorf("run(%v) = %d, %q, %q, want the render", args, code, out, errb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunRendersAnyJSONValue(t *testing.T) {
|
||||||
|
for stdin, want := range map[string]string{"42": "42", "42\n": "42", "true\n": "true", "null\n": "", " null ": ""} {
|
||||||
|
if code, out, errb := runOut(stdin); code != 0 || out != want {
|
||||||
|
t.Errorf("run(%q) = %d, %q, %q, want %q", stdin, code, out, errb, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -679,9 +687,6 @@ func TestRunRecordMisuse(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{[]string{"--format", "yaml"}, "--format takes csv, json, ndjson, sql or text"},
|
{[]string{"--format", "yaml"}, "--format takes csv, json, ndjson, sql or text"},
|
||||||
{[]string{"--format", "json", "--separator", ","}, "--separator joins text values"},
|
|
||||||
{[]string{"--table", "t"}, "--table names the INSERT target"},
|
|
||||||
{[]string{"--format", "json", "--table", "t"}, "--table names the INSERT target"},
|
|
||||||
{[]string{"--format", "sql", "--table", ""}, "--table names the INSERT target"},
|
{[]string{"--format", "sql", "--table", ""}, "--table names the INSERT target"},
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut("{/users}", c.args...)
|
code, out, errb := runOut("{/users}", c.args...)
|
||||||
|
|||||||
@@ -27,12 +27,6 @@ func TestDatatypeSitsOnlyInAColumn(t *testing.T) {
|
|||||||
for src, want := range map[string]string{
|
for src, want := range map[string]string{
|
||||||
`{"format":"","n":{"format":"1","datatype":"int"}}`: `datatype takes "string", "integer", "number" or "boolean", got "int"`,
|
`{"format":"","n":{"format":"1","datatype":"int"}}`: `datatype takes "string", "integer", "number" or "boolean", got "int"`,
|
||||||
`{"format":"","n":{"format":"1","datatype":1}}`: "datatype must be a string",
|
`{"format":"","n":{"format":"1","datatype":1}}`: "datatype must be a string",
|
||||||
`{"format":"{int(1,9)}","datatype":"integer"}`: "datatype only types a record column",
|
|
||||||
`[{"format":"1","datatype":"integer"},"x"]`: "datatype only types a record column",
|
|
||||||
`{"format":"{p}","p":{"format":"{n}","n":{"format":"1","datatype":"integer"}}}`: "datatype only types a record column",
|
|
||||||
`{"format":"{n}","repeat":2,"n":{"format":"1","datatype":"integer"}}`: `so it has no effect here; drop "datatype"`,
|
|
||||||
`null`: `so write ""`,
|
|
||||||
`{"format":"{p}","p":{"format":"{x}","x":[null,"a"]}}`: `so write ""`,
|
|
||||||
} {
|
} {
|
||||||
if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) {
|
if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) {
|
||||||
t.Errorf("compile(%s) = %v, want an error containing %q", src, err, want)
|
t.Errorf("compile(%s) = %v, want an error containing %q", src, err, want)
|
||||||
|
|||||||
@@ -80,10 +80,9 @@ func TestReadRowsReadsOnlyAFileBesideTheCategory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWalkRefusesARowsFileNoCategoryNames(t *testing.T) {
|
func TestWalkIgnoresARowsFileNoCategoryNames(t *testing.T) {
|
||||||
_, err := walk(t, Source{fsys: fstest.MapFS{"a.json": {Data: []byte(`"x"`)}, "a.tsv": {Data: []byte("key\n")}}, label: "lbl"})
|
if _, err := walk(t, Source{fsys: fstest.MapFS{"a.json": {Data: []byte(`"x"`)}, "a.tsv": {Data: []byte("key\n")}}, label: "lbl"}); err != nil {
|
||||||
if err == nil || !strings.HasPrefix(err.Error(), "lbl/a.tsv: no category names it in its rows") {
|
t.Errorf("Walk = %v, want a.tsv ignored", err)
|
||||||
t.Errorf("Walk = %v, want a.tsv refused as named by no category", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ func TestParseRefuses(t *testing.T) {
|
|||||||
{"no rows", "a\n", Options{}, "has no rows below its header"},
|
{"no rows", "a\n", Options{}, "has no rows below its header"},
|
||||||
{"a short row", "a\tb\n1\t2\n3\n", Options{}, "line 3 has fewer cells"},
|
{"a short row", "a\tb\n1\t2\n3\n", Options{}, "line 3 has fewer cells"},
|
||||||
{"a repeated key", "k\nx\nx\n", Options{Key: "k"}, `key "x" repeats line 2`},
|
{"a repeated key", "k\nx\nx\n", Options{Key: "k"}, `key "x" repeats line 2`},
|
||||||
{"a weight of zero", "k\tw\nx\t1\ny\t0\n", Options{Weight: "w"}, `weight "0" is not a positive number`},
|
{"every weight zero", "k\tw\nx\t0\ny\t0\n", Options{Weight: "w"}, "every weight is 0"},
|
||||||
|
{"a negative weight", "k\tw\nx\t1\ny\t-1\n", Options{Weight: "w"}, `weight "-1" is not a number of 0 or more`},
|
||||||
{"a key a selector cannot spell", "k\nx\ny|z\n", Options{Key: "k"}, `contains "|"`},
|
{"a key a selector cannot spell", "k\nx\ny|z\n", Options{Key: "k"}, `contains "|"`},
|
||||||
{"an option naming no column", "k\nx\ny\n", Options{Key: "nope"}, `key names no column "nope"`},
|
{"an option naming no column", "k\nx\ny\n", Options{Key: "nope"}, `key names no column "nope"`},
|
||||||
} {
|
} {
|
||||||
|
|||||||
+2
-12
@@ -224,18 +224,6 @@ func TestNewErrors(t *testing.T) {
|
|||||||
files map[string]string
|
files map[string]string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
"separator without repeat": {
|
|
||||||
map[string]string{"a": `{"format":"{x}","x":"1","separator":","}`},
|
|
||||||
`drop "separator"`,
|
|
||||||
},
|
|
||||||
"separator with an explicit repeat of 1": {
|
|
||||||
map[string]string{"a": `{"format":"{x}","x":"1","separator":","}`},
|
|
||||||
`drop "separator"`,
|
|
||||||
},
|
|
||||||
"weight outside a choice": {
|
|
||||||
map[string]string{"a": `{"format":"x","weight":5}`},
|
|
||||||
`drop "weight"`,
|
|
||||||
},
|
|
||||||
"non-numeric weight outside a choice": {
|
"non-numeric weight outside a choice": {
|
||||||
map[string]string{"a": `{"format":"x","weight":"bad"}`},
|
map[string]string{"a": `{"format":"x","weight":"bad"}`},
|
||||||
"takes a number, not a string",
|
"takes a number, not a string",
|
||||||
@@ -341,6 +329,8 @@ func TestNewErrors(t *testing.T) {
|
|||||||
"field with a closing paren": {map[string]string{"a": `{"format":"{b)c}","b)c":"2"}`}, "a", "2"},
|
"field with a closing paren": {map[string]string{"a": `{"format":"{b)c}","b)c":"2"}`}, "a", "2"},
|
||||||
"repeat without a separator": {map[string]string{"a": `{"format":"{x}","repeat":3,"x":"1"}`}, "a", "111"},
|
"repeat without a separator": {map[string]string{"a": `{"format":"{x}","repeat":3,"x":"1"}`}, "a", "111"},
|
||||||
"one name in two tokens": {map[string]string{"a": `{"format":"{x}{x}","x":"1"}`}, "a", "11"},
|
"one name in two tokens": {map[string]string{"a": `{"format":"{x}{x}","x":"1"}`}, "a", "11"},
|
||||||
|
"separator without repeat": {map[string]string{"a": `{"format":"{x}","x":"1","separator":",","repeat":1}`}, "a", "1"},
|
||||||
|
"weight outside a choice": {map[string]string{"a": `{"format":"x","weight":5}`}, "a", "x"},
|
||||||
"repeated alternation arm": {map[string]string{"a": `{"format":"{x|x}","x":"1"}`}, "a", "1"},
|
"repeated alternation arm": {map[string]string{"a": `{"format":"{x|x}","x":"1"}`}, "a", "1"},
|
||||||
"repeated path arm": {map[string]string{"a": `{"format":"{p.v|p.v}","p":{"format":"{v}","v":"1"}}`}, "a", "1"},
|
"repeated path arm": {map[string]string{"a": `{"format":"{p.v|p.v}","p":{"format":"{v}","v":"1"}}`}, "a", "1"},
|
||||||
"repeated reference arm": {map[string]string{"a": `"x"`, "b": `"{/a|/a}"`}, "b", "x"},
|
"repeated reference arm": {map[string]string{"a": `"x"`, "b": `"{/a|/a}"`}, "b", "x"},
|
||||||
|
|||||||
+1
-1
@@ -191,7 +191,7 @@ func TestNameErrors(t *testing.T) {
|
|||||||
{"read once through a field path that does not resolve", map[string]string{"card": `{"format":"{place as p}{p.zz}","place":{"format":"{x}","x":["a","b"]}}`},
|
{"read once through a field path that does not resolve", map[string]string{"card": `{"format":"{place as p}{p.zz}","place":{"format":"{x}","x":["a","b"]}}`},
|
||||||
`no field "zz"`},
|
`no field "zz"`},
|
||||||
{"read by nothing", map[string]string{"word": `["a","b"]`, "card": `"{/word as w}"`},
|
{"read by nothing", map[string]string{"word": `["a","b"]`, "card": `"{/word as w}"`},
|
||||||
`nothing reads name "w"`},
|
""},
|
||||||
{"one arm read twice in an alternation", map[string]string{"cat": `{"format":"{w|w}","w":["a","b"]}`, "card": `"{/cat as n}{n} {n.w}"`},
|
{"one arm read twice in an alternation", map[string]string{"cat": `{"format":"{w|w}","w":["a","b"]}`, "card": `"{/cat as n}{n} {n.w}"`},
|
||||||
""},
|
""},
|
||||||
{"a field and a path into it in one alternation", map[string]string{"cat": `{"format":"{w|w.x}","w":{"format":"{x}","x":["a","b"]}}`, "card": `"{/cat as n}{n} {n.w}"`},
|
{"a field and a path into it in one alternation", map[string]string{"cat": `{"format":"{w|w.x}","w":{"format":"{x}","x":["a","b"]}}`, "card": `"{/cat as n}{n} {n.w}"`},
|
||||||
|
|||||||
+5
-7
@@ -2,14 +2,14 @@ package fejkdata
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWeightZeroIsRejected(t *testing.T) {
|
func TestAChoiceWithNothingToDrawIsRejected(t *testing.T) {
|
||||||
_, err := resolved(t, `[{"format":"X","weight":0},"Y"]`)
|
for _, src := range []string{`[{"format":"A","weight":0},{"format":"B","weight":0}]`, `[]`} {
|
||||||
if err == nil || !strings.Contains(err.Error(), "weight 0") || !strings.Contains(err.Error(), "remove") {
|
if _, err := resolved(t, src); err == nil {
|
||||||
t.Fatalf("compile(weight 0) = %v, want it rejected naming the fix", err)
|
t.Errorf("compile(%s) = nil error, want a choice with nothing to draw refused", src)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +56,6 @@ func TestNodeCompileErrors(t *testing.T) {
|
|||||||
for _, bad := range []string{
|
for _, bad := range []string{
|
||||||
`{"x":"Q"}`, // object without "format"
|
`{"x":"Q"}`, // object without "format"
|
||||||
`{"format":"{y}","x":1}`, // a field is a bare number
|
`{"format":"{y}","x":1}`, // a field is a bare number
|
||||||
`[1, 2]`, // a choice of numbers
|
|
||||||
`5`, // unsupported node type
|
|
||||||
`[]`, // empty choice
|
`[]`, // empty choice
|
||||||
`[{"format":"A","weight":-1},"B"]`, // negative weight
|
`[{"format":"A","weight":-1},"B"]`, // negative weight
|
||||||
`[{"format":"A","weight":0},{"format":"B","weight":0}]`, // weights sum to zero
|
`[{"format":"A","weight":0},{"format":"B","weight":0}]`, // weights sum to zero
|
||||||
|
|||||||
+40
-19
@@ -31,16 +31,47 @@ func TestOneItemChoiceIsItsItem(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAWeightWithNothingToDrawAgainstIsRejected(t *testing.T) {
|
func TestAPartThatDoesNothingIsIgnored(t *testing.T) {
|
||||||
for _, src := range []string{
|
for long, short := range map[string]string{
|
||||||
`{"format":"a","weight":2}`,
|
`{"format":"a","weight":2}`: `"a"`,
|
||||||
`{"format":"{x}","x":{"format":"a","weight":2}}`,
|
`{"format":"a","weight":0}`: `"a"`,
|
||||||
`[{"format":"a","weight":2}]`,
|
`{"format":"{x}","x":{"format":"a","weight":2}}`: `{"format":"{x}","x":"a"}`,
|
||||||
`{"format":"a","weight":0}`,
|
`[{"format":"a","weight":2}]`: `"a"`,
|
||||||
|
`{"format":"{x}","x":["a","b"],"separator":","}`: `{"format":"{x}","x":["a","b"]}`,
|
||||||
|
`{"format":"{n}","repeat":2,"n":{"format":"1","datatype":"integer"}}`: `{"format":"{n}","repeat":2,"n":"1"}`,
|
||||||
|
`[{"format":"1","datatype":"integer"},"x"]`: `["1","x"]`,
|
||||||
|
`null`: `""`,
|
||||||
|
`{"format":"{p}","p":{"format":"{x}","x":[null,"a"]}}`: `{"format":"{p}","p":{"format":"{x}","x":["","a"]}}`,
|
||||||
|
`[{"format":"a","weight":0},"b"]`: `"b"`,
|
||||||
|
`"{int(5,5)}"`: `"5"`,
|
||||||
|
`"{float(1,1,2)}"`: `"1.00"`,
|
||||||
|
`"{date(1990-01-01,1990-01-01,'2006-01-02')}"`: `"1990-01-01"`,
|
||||||
|
`"{date(1990-01-01,1990-12-31,'x')}"`: `"x"`,
|
||||||
|
`"{time('x')}"`: `"x"`,
|
||||||
} {
|
} {
|
||||||
_, err := resolved(t, src)
|
sameRenders(t, long, short)
|
||||||
if err == nil || !strings.Contains(err.Error(), `drop "weight"`) || strings.Contains(err.Error(), "can never be a field") || strings.Contains(err.Error(), "only skews a choice's items") {
|
}
|
||||||
t.Errorf("compile(%s) = %v, want the weight refused as drawn against nothing, naming the drop", src, err)
|
for _, src := range []string{`"{date(1990-01-01,1990-12-31,'15:04')}"`, `"{time('2006-01-02 15:04')}"`} {
|
||||||
|
if _, err := resolved(t, src); err != nil {
|
||||||
|
t.Errorf("compile(%s) = %v, want a layout of either kind rendered", src, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAJSONNumberOrBooleanIsItsText(t *testing.T) {
|
||||||
|
f := newGenerator(t, writeData(t, map[string]string{
|
||||||
|
"n": `{"format":"{a} {b} {c} {d}","a":5,"b":1.50,"c":12345678901234567890,"d":true}`,
|
||||||
|
"l": `[1e3]`,
|
||||||
|
}), WithSeed(1))
|
||||||
|
if v := fake(t, f, "n"); v != "5 1.50 12345678901234567890 true" {
|
||||||
|
t.Errorf("n = %q, want each number and boolean as written", v)
|
||||||
|
}
|
||||||
|
if v := fake(t, f, "l"); v != "1e3" {
|
||||||
|
t.Errorf("l = %q, want 1e3 as written", v)
|
||||||
|
}
|
||||||
|
for in, want := range map[string]string{"42": "42", " false ": "false", "[7]": "7"} {
|
||||||
|
if v, err := f.FakeTemplate(in); err != nil || v != want {
|
||||||
|
t.Errorf("FakeTemplate(%q) = %q, %v, want %q", in, v, err, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,16 +93,6 @@ func TestARepeatedItemCountsAsWritten(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestASeparatorWithoutARepeatIsRejected(t *testing.T) {
|
|
||||||
for src, want := range map[string]string{
|
|
||||||
`{"format":"{x}","x":"v","separator":","}`: `drop "separator"`,
|
|
||||||
} {
|
|
||||||
if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) {
|
|
||||||
t.Errorf("compile(%s) = %v, want an error mentioning %s", src, err, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestADefaultWrittenOutIsTheDefault(t *testing.T) {
|
func TestADefaultWrittenOutIsTheDefault(t *testing.T) {
|
||||||
for long, short := range map[string]string{
|
for long, short := range map[string]string{
|
||||||
`{"format":"Malmö"}`: `"Malmö"`,
|
`{"format":"Malmö"}`: `"Malmö"`,
|
||||||
|
|||||||
+7
-1
@@ -253,6 +253,13 @@ func TestFakeStructTakesTheDatatypeItsGoTypeSets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFakeStructWithNoTagsFillsNothing(t *testing.T) {
|
||||||
|
v := struct{ A string }{A: "kept"}
|
||||||
|
if err := structData(t).FakeStruct(&v); err != nil || v.A != "kept" {
|
||||||
|
t.Errorf("FakeStruct = %+v, %v, want nothing filled", v, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFakeStructErrors(t *testing.T) {
|
func TestFakeStructErrors(t *testing.T) {
|
||||||
f := structData(t)
|
f := structData(t)
|
||||||
for _, c := range []struct {
|
for _, c := range []struct {
|
||||||
@@ -263,7 +270,6 @@ func TestFakeStructErrors(t *testing.T) {
|
|||||||
{(*structUser)(nil), "through a non-nil pointer"},
|
{(*structUser)(nil), "through a non-nil pointer"},
|
||||||
{new(int), "through a non-nil pointer"},
|
{new(int), "through a non-nil pointer"},
|
||||||
{nil, "through a non-nil pointer"},
|
{nil, "through a non-nil pointer"},
|
||||||
{&struct{ A string }{}, "has no fake tags"},
|
|
||||||
{&struct {
|
{&struct {
|
||||||
a string `fake:"person.first"`
|
a string `fake:"person.first"`
|
||||||
}{}, ".a: unexported"},
|
}{}, ".a: unexported"},
|
||||||
|
|||||||
+9
-2
@@ -531,6 +531,15 @@ func TestATableOfOneRowOrNamedByItsKeyLoads(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestARowOfWeightZeroIsNeverDrawn(t *testing.T) {
|
||||||
|
f := newGenerator(t, writeFiles(t, map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\t0\ny\t2\n"}), WithSeed(1))
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
if v := fake(t, f, "t"); v != "y" {
|
||||||
|
t.Fatalf("t = %q, want only the row of a positive weight", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTableFences(t *testing.T) {
|
func TestTableFences(t *testing.T) {
|
||||||
base := map[string]string{
|
base := map[string]string{
|
||||||
"region.json": `{"format":"{name}","rows":"region.tsv","key":"code","name":"name"}`,
|
"region.json": `{"format":"{name}","rows":"region.tsv","key":"code","name":"name"}`,
|
||||||
@@ -541,7 +550,6 @@ func TestTableFences(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
"rows names a missing file": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`}, "t.tsv"},
|
"rows names a missing file": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`}, "t.tsv"},
|
||||||
"a TSV nothing names": {with(base, map[string]string{"stray.tsv": "a\nx\n"}), "stray.tsv"},
|
|
||||||
"rows outside its folder": {with(base, map[string]string{"t.json": `{"format":"{code}","rows":"../region.tsv"}`}), "beside"},
|
"rows outside its folder": {with(base, map[string]string{"t.json": `{"format":"{code}","rows":"../region.tsv"}`}), "beside"},
|
||||||
"rows not a tsv": {with(base, map[string]string{"t.json": `{"format":"{code}","rows":"region.txt"}`, "region.txt": "code\n1\n"}), ".tsv"},
|
"rows not a tsv": {with(base, map[string]string{"t.json": `{"format":"{code}","rows":"region.txt"}`, "region.txt": "code\n1\n"}), ".tsv"},
|
||||||
"key names no column": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","key":"b"}`, "t.tsv": "a\nx\ny\n"}, `"b"`},
|
"key names no column": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","key":"b"}`, "t.tsv": "a\nx\ny\n"}, `"b"`},
|
||||||
@@ -557,7 +565,6 @@ func TestTableFences(t *testing.T) {
|
|||||||
"a name that is another row's key": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","key":"a","name":"n"}`, "t.tsv": "a\tn\nx\ty\ny\tz\n"}, `"y"`},
|
"a name that is another row's key": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","key":"a","name":"n"}`, "t.tsv": "a\tn\nx\ty\ny\tz\n"}, `"y"`},
|
||||||
"a descendant named like an ancestor's column": {with(geo(), map[string]string{"region.tsv": "code\tname\tpopulation\tlocality\n01\tStockholms län\t2400000\tx\n12\tSkåne län\t1400000\ty\n14\tVästra Götalands län\t1750000\tz\n"}), `"locality"`},
|
"a descendant named like an ancestor's column": {with(geo(), map[string]string{"region.tsv": "code\tname\tpopulation\tlocality\n01\tStockholms län\t2400000\tx\n12\tSkåne län\t1400000\ty\n14\tVästra Götalands län\t1750000\tz\n"}), `"locality"`},
|
||||||
"weight not a number": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\tmany\ny\t2\n"}, `"many"`},
|
"weight not a number": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\tmany\ny\t2\n"}, `"many"`},
|
||||||
"weight zero": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\t0\ny\t2\n"}, "0"},
|
|
||||||
"weight negative": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\t-1\ny\t2\n"}, "-1"},
|
"weight negative": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","weight":"w"}`, "t.tsv": "a\tw\nx\t-1\ny\t2\n"}, "-1"},
|
||||||
"reserved column name": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`, "t.tsv": "a\tb.c\nx\ty\n"}, `"b.c"`},
|
"reserved column name": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`, "t.tsv": "a\tb.c\nx\ty\n"}, `"b.c"`},
|
||||||
"duplicate column": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`, "t.tsv": "a\ta\nx\ty\n"}, `"a"`},
|
"duplicate column": {map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv"}`, "t.tsv": "a\ta\nx\ty\n"}, `"a"`},
|
||||||
|
|||||||
Reference in New Issue
Block a user