Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
+204
-142
@@ -17,14 +17,21 @@ const (
|
|||||||
misc = "../../data/misc"
|
misc = "../../data/misc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runOut(args ...string) (int, string, string) {
|
func runOut(stdin string, args ...string) (int, string, string) {
|
||||||
var out, errb bytes.Buffer
|
var out, errb bytes.Buffer
|
||||||
code := run(args, &out, &errb)
|
code := run(args, strings.NewReader(stdin), &out, &errb)
|
||||||
|
return code, out.String(), errb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// runTerminal runs as from a shell with nothing piped in.
|
||||||
|
func runTerminal(args ...string) (int, string, string) {
|
||||||
|
var out, errb bytes.Buffer
|
||||||
|
code := run(args, nil, &out, &errb)
|
||||||
return code, out.String(), errb.String()
|
return code, out.String(), errb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunOutputsValue(t *testing.T) {
|
func TestRunOutputsValue(t *testing.T) {
|
||||||
code, out, errb := runOut("--data-path", svSE, "person")
|
code, out, errb := runOut("{/person}", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -37,11 +44,11 @@ func TestRunOutputsValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunDotPath(t *testing.T) {
|
func TestRunDotPath(t *testing.T) {
|
||||||
code, full, _ := runOut("--seed", "7", "--data-path", svSE, "person")
|
code, full, _ := runOut("{/person}", "--seed", "7", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("person run = %d", code)
|
t.Fatalf("person run = %d", code)
|
||||||
}
|
}
|
||||||
code, last, errb := runOut("--seed", "7", "--data-path", svSE, "person.last")
|
code, last, errb := runOut("{/person.last}", "--seed", "7", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("person.last run = %d, stderr=%q", code, errb)
|
t.Fatalf("person.last run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -54,13 +61,13 @@ func TestRunDotPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunSeedSpellings(t *testing.T) {
|
func TestRunSeedSpellings(t *testing.T) {
|
||||||
_, want, _ := runOut("--seed", "42", "--data-path", svSE, "address")
|
_, want, _ := runOut("{/address}", "--seed", "42", "--data-path", svSE)
|
||||||
for _, args := range [][]string{
|
for _, args := range [][]string{
|
||||||
{"--seed=42", "--data-path", svSE, "address"},
|
{"--seed=42", "--data-path", svSE},
|
||||||
{"-s", "42", "-d", svSE, "address"},
|
{"-s", "42", "-d", svSE},
|
||||||
{"--data-path", svSE, "address", "--seed", "42"},
|
{"--data-path", svSE, "--seed", "42"},
|
||||||
} {
|
} {
|
||||||
code, got, errb := runOut(args...)
|
code, got, errb := runOut("{/address}", args...)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run(%v) = %d, stderr=%q", args, code, errb)
|
t.Fatalf("run(%v) = %d, stderr=%q", args, code, errb)
|
||||||
}
|
}
|
||||||
@@ -71,13 +78,13 @@ func TestRunSeedSpellings(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunShortFlagValues(t *testing.T) {
|
func TestRunShortFlagValues(t *testing.T) {
|
||||||
_, want, _ := runOut("--seed", "42", "--data-path", svSE, "address")
|
_, want, _ := runOut("{/address}", "--seed", "42", "--data-path", svSE)
|
||||||
for _, args := range [][]string{
|
for _, args := range [][]string{
|
||||||
{"-s42", "-d", svSE, "address"},
|
{"-s42", "-d", svSE},
|
||||||
{"-s", "42", "-d" + svSE, "address"},
|
{"-s", "42", "-d" + svSE},
|
||||||
{"-d", svSE, "address", "-s42"},
|
{"-d", svSE, "-s42"},
|
||||||
} {
|
} {
|
||||||
code, got, errb := runOut(args...)
|
code, got, errb := runOut("{/address}", args...)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run(%v) = %d, stderr=%q", args, code, errb)
|
t.Fatalf("run(%v) = %d, stderr=%q", args, code, errb)
|
||||||
}
|
}
|
||||||
@@ -85,7 +92,7 @@ func TestRunShortFlagValues(t *testing.T) {
|
|||||||
t.Errorf("run(%v) = %q, want %q", args, got, want)
|
t.Errorf("run(%v) = %q, want %q", args, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, three, _ := runOut("-s", "1", "-n3", "-d", svSE, "word")
|
_, three, _ := runOut("{/word}", "-s", "1", "-n3", "-d", svSE)
|
||||||
if lines := strings.Split(strings.TrimRight(three, "\n"), "\n"); len(lines) != 3 {
|
if lines := strings.Split(strings.TrimRight(three, "\n"), "\n"); len(lines) != 3 {
|
||||||
t.Errorf("-n3 gave %d lines: %q", len(lines), three)
|
t.Errorf("-n3 gave %d lines: %q", len(lines), three)
|
||||||
}
|
}
|
||||||
@@ -93,13 +100,13 @@ func TestRunShortFlagValues(t *testing.T) {
|
|||||||
args []string
|
args []string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{[]string{"-s=42", "-d", svSE, "address"}, "-s42"},
|
{[]string{"-s=42", "-d", svSE}, "-s42"},
|
||||||
{[]string{"-s=42", "-d", svSE, "address"}, "--seed=42"},
|
{[]string{"-s=42", "-d", svSE}, "--seed=42"},
|
||||||
{[]string{"-d=" + svSE, "address"}, "--data-path="},
|
{[]string{"-d=" + svSE}, "--data-path="},
|
||||||
{[]string{"-nd", "3", "-d", svSE, "word"}, `--repeat needs an integer in 1..1048576, got "d"`},
|
{[]string{"-nd", "3", "-d", svSE}, `--repeat needs an integer in 1..1048576, got "d"`},
|
||||||
{[]string{"--seed=", "-d", svSE, "word"}, `--seed needs an unsigned integer, got ""`},
|
{[]string{"--seed=", "-d", svSE}, `--seed needs an unsigned integer, got ""`},
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut(c.args...)
|
code, out, errb := runOut("{/word}", c.args...)
|
||||||
if code != 2 || out != "" {
|
if code != 2 || out != "" {
|
||||||
t.Errorf("run(%v) = %d, stdout %q, want misuse", c.args, code, out)
|
t.Errorf("run(%v) = %d, stdout %q, want misuse", c.args, code, out)
|
||||||
}
|
}
|
||||||
@@ -107,20 +114,20 @@ func TestRunShortFlagValues(t *testing.T) {
|
|||||||
t.Errorf("run(%v) stderr = %q, want %q", c.args, errb, c.want)
|
t.Errorf("run(%v) stderr = %q, want %q", c.args, errb, c.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code, out, _ := runOut("-hd", svSE)
|
code, out, _ := runOut("", "-hd", svSE)
|
||||||
if code != 0 || !strings.Contains(out, "Usage") {
|
if code != 0 || !strings.Contains(out, "Usage") {
|
||||||
t.Errorf("-hd (bundled help) = %d, %q, want usage", code, out)
|
t.Errorf("-hd (bundled help) = %d, %q, want usage", code, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunDoubleDashEndsFlags(t *testing.T) {
|
func TestRunDoubleDashEndsFlags(t *testing.T) {
|
||||||
code, out, errb := runOut("--data-path", svSE, "--", "person")
|
code, out, errb := runOut("{/person}", "--data-path", svSE, "--")
|
||||||
if code != 0 || strings.TrimSpace(out) == "" {
|
if code != 0 || strings.TrimSpace(out) == "" {
|
||||||
t.Fatalf("run = %d, out=%q, stderr=%q", code, out, errb)
|
t.Fatalf("run = %d, out=%q, stderr=%q", code, out, errb)
|
||||||
}
|
}
|
||||||
code, _, errb = runOut("--data-path", svSE, "--", "--list")
|
code, _, errb = runOut("{/person}", "--data-path", svSE, "--", "--list")
|
||||||
if code != 1 || !strings.Contains(errb, "--list") {
|
if code != 2 || !strings.Contains(errb, "stdin") {
|
||||||
t.Errorf("after --, --list should be a path: code %d, stderr %q", code, errb)
|
t.Errorf("after --, --list should be an argument: code %d, stderr %q", code, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,14 +136,14 @@ func TestRunSingleDashLongIsRejected(t *testing.T) {
|
|||||||
args []string
|
args []string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{[]string{"-seed", "42", "-d", svSE, "person"}, "use --seed"},
|
{[]string{"-seed", "42", "-d", svSE}, "use --seed"},
|
||||||
{[]string{"-seed=42", "-d", svSE, "person"}, "use --seed"},
|
{[]string{"-seed=42", "-d", svSE}, "use --seed"},
|
||||||
{[]string{"-data-path", svSE, "person"}, "use --data-path"},
|
{[]string{"-data-path", svSE}, "use --data-path"},
|
||||||
{[]string{"-list", "-d", svSE}, "use --list"},
|
{[]string{"-list", "-d", svSE}, "use --list"},
|
||||||
{[]string{"--nope", "-d", svSE, "person"}, "unknown flag --nope"},
|
{[]string{"--nope", "-d", svSE}, "unknown flag --nope"},
|
||||||
{[]string{"-x", "-d", svSE, "person"}, "unknown flag -x"},
|
{[]string{"-x", "-d", svSE}, "unknown flag -x"},
|
||||||
} {
|
} {
|
||||||
code, _, errb := runOut(c.args...)
|
code, _, errb := runOut("{/person}", c.args...)
|
||||||
if code != 2 {
|
if code != 2 {
|
||||||
t.Errorf("run(%v) = %d, want 2", c.args, code)
|
t.Errorf("run(%v) = %d, want 2", c.args, code)
|
||||||
}
|
}
|
||||||
@@ -151,14 +158,14 @@ func TestRunFlagValues(t *testing.T) {
|
|||||||
args []string
|
args []string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{[]string{"--seed", "-d", svSE, "person"}, `--seed needs an unsigned integer, got "-d"`},
|
{[]string{"--seed", "-d", svSE}, `--seed needs an unsigned integer, got "-d"`},
|
||||||
{[]string{"-d", svSE, "person", "--seed"}, "--seed needs a value"},
|
{[]string{"-d", svSE, "--seed"}, "--seed needs a value"},
|
||||||
{[]string{"--seed", "x", "-d", svSE, "person"}, "--seed"},
|
{[]string{"--seed", "x", "-d", svSE}, "--seed"},
|
||||||
{[]string{"--list=1", "-d", svSE}, "--list takes no value"},
|
{[]string{"--list=1", "-d", svSE}, "--list takes no value"},
|
||||||
{[]string{"--repeat", "0", "-d", svSE, "person"}, "--repeat"},
|
{[]string{"--repeat", "0", "-d", svSE}, "--repeat"},
|
||||||
{[]string{"-n", "-1", "-d", svSE, "person"}, "--repeat"},
|
{[]string{"-n", "-1", "-d", svSE}, "--repeat"},
|
||||||
} {
|
} {
|
||||||
code, _, errb := runOut(c.args...)
|
code, _, errb := runOut("{/person}", c.args...)
|
||||||
if code != 2 {
|
if code != 2 {
|
||||||
t.Errorf("run(%v) = %d, want 2", c.args, code)
|
t.Errorf("run(%v) = %d, want 2", c.args, code)
|
||||||
}
|
}
|
||||||
@@ -169,7 +176,7 @@ func TestRunFlagValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRepeat(t *testing.T) {
|
func TestRunRepeat(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--repeat", "3", "--data-path", svSE, "word")
|
code, out, errb := runOut("{/word}", "--seed", "1", "--repeat", "3", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -177,14 +184,14 @@ func TestRunRepeat(t *testing.T) {
|
|||||||
if len(lines) != 3 {
|
if len(lines) != 3 {
|
||||||
t.Errorf("repeat=3 gave %d lines: %q", len(lines), out)
|
t.Errorf("repeat=3 gave %d lines: %q", len(lines), out)
|
||||||
}
|
}
|
||||||
_, short, _ := runOut("--seed", "1", "-n", "3", "-d", svSE, "word")
|
_, short, _ := runOut("{/word}", "--seed", "1", "-n", "3", "-d", svSE)
|
||||||
if short != out {
|
if short != out {
|
||||||
t.Errorf("-n 3 = %q, want the same as --repeat 3 %q", short, out)
|
t.Errorf("-n 3 = %q, want the same as --repeat 3 %q", short, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunSeparator(t *testing.T) {
|
func TestRunSeparator(t *testing.T) {
|
||||||
code, out, errb := runOut("--repeat", "3", "--separator", ",", "--data-path", svSE, "word")
|
code, out, errb := runOut("{/word}", "--repeat", "3", "--separator", ",", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -197,7 +204,7 @@ func TestRunSeparator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRepeatAdvancesRNG(t *testing.T) {
|
func TestRunRepeatAdvancesRNG(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--repeat", "5", "--data-path", svSE, "person")
|
code, out, errb := runOut("{/person}", "--seed", "1", "--repeat", "5", "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -211,30 +218,102 @@ func TestRunRepeatAdvancesRNG(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunMisuse(t *testing.T) {
|
func TestRunMisuse(t *testing.T) {
|
||||||
for _, args := range [][]string{{}, {"--data-path", svSE}, {"-d", svSE, "person", "word"}, {"-d", svSE, "--list", "person"}, {"--no-shipped-data", "sv_SE.person"}} {
|
for _, c := range []struct {
|
||||||
code, out, errb := runOut(args...)
|
stdin string
|
||||||
|
args []string
|
||||||
|
}{
|
||||||
|
{"", nil},
|
||||||
|
{"", []string{"--data-path", svSE}},
|
||||||
|
{"\n", []string{"--data-path", svSE}},
|
||||||
|
{"{/person}", []string{"-d", svSE, "word"}},
|
||||||
|
{"", []string{"-d", svSE, "--list", "person"}},
|
||||||
|
{"{/sv_SE.person}", []string{"--no-shipped-data"}},
|
||||||
|
} {
|
||||||
|
code, out, errb := runOut(c.stdin, c.args...)
|
||||||
if code != 2 {
|
if code != 2 {
|
||||||
t.Errorf("run(%v) = %d, want 2", args, code)
|
t.Errorf("run(%q, %v) = %d, want 2", c.stdin, c.args, code)
|
||||||
}
|
}
|
||||||
if !strings.Contains(errb, "try 'fejkdata --help'") {
|
if !strings.Contains(errb, "try 'fejkdata --help'") {
|
||||||
t.Errorf("run(%v) stderr = %q, want a pointer to --help", args, errb)
|
t.Errorf("run(%q, %v) stderr = %q, want a pointer to --help", c.stdin, c.args, errb)
|
||||||
}
|
}
|
||||||
if out != "" {
|
if out != "" {
|
||||||
t.Errorf("run(%v) stdout = %q, want nothing", args, out)
|
t.Errorf("run(%q, %v) stdout = %q, want nothing", c.stdin, c.args, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// A template a shell split names both quotings, since which one cures it turns
|
}
|
||||||
// on whether the argument carries a double-quoted JSON.
|
|
||||||
_, _, errb := runOut("{date(1990-01-01,2010-12-31,", "January", "2,", "2006)}")
|
// TestRunTakesNoArgument pins the way from the old spelling, a template or a path as
|
||||||
for _, want := range []string{`wrap the whole argument in "…"`, `or in '…'`} {
|
// an argument, to the one that runs: the template on stdin.
|
||||||
if !strings.Contains(errb, want) {
|
func TestRunTakesNoArgument(t *testing.T) {
|
||||||
t.Errorf("a split template stderr = %q, want it to name %s", errb, want)
|
for _, args := range [][]string{{"sv_SE.person"}, {"{/sv_SE.person}"}, {"name:", "{/sv_SE.person.last}"}} {
|
||||||
|
code, out, errb := runOut("", args...)
|
||||||
|
if code != 2 || out != "" || !strings.Contains(errb, "stdin") || !strings.Contains(errb, "| fejkdata") {
|
||||||
|
t.Errorf("run(%v) = %d, %q, %q; want misuse showing a template piped to fejkdata", args, code, out, errb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTerminalStdinIsMisuse(t *testing.T) {
|
||||||
|
code, out, errb := runTerminal("--seed", "1")
|
||||||
|
if code != 2 || out != "" || !strings.Contains(errb, "| fejkdata") {
|
||||||
|
t.Errorf("run with nothing piped = %d, %q, %q; want misuse showing a template piped to fejkdata", code, out, errb)
|
||||||
|
}
|
||||||
|
for _, args := range [][]string{{"--list"}, {"--help"}, {"--version"}} {
|
||||||
|
if code, out, errb := runTerminal(args...); code != 0 || out == "" {
|
||||||
|
t.Errorf("run(%v) with nothing piped = %d, %q, %q; want it to run, reading no stdin", args, code, out, errb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunDropsOneTrailingNewline(t *testing.T) {
|
||||||
|
for stdin, want := range map[string]string{
|
||||||
|
"hihi": "hihi\n",
|
||||||
|
"hihi\n": "hihi\n",
|
||||||
|
"hihi\n\n": "hihi\n\n",
|
||||||
|
"a\nb\n": "a\nb\n",
|
||||||
|
" hihi \n": " hihi \n",
|
||||||
|
"hihi\r\n": "hihi\r\n",
|
||||||
|
"{{x}}\n": "{x}\n",
|
||||||
|
"x: {/sv_SE.person.last}\n\n": "",
|
||||||
|
} {
|
||||||
|
code, out, errb := runOut(stdin, "--seed", "1")
|
||||||
|
if want == "" {
|
||||||
|
if code != 0 || !strings.HasPrefix(out, "x: ") || !strings.HasSuffix(out, "\n\n") || strings.Count(out, "\n") != 2 {
|
||||||
|
t.Errorf("run(%q) = %d, %q, %q; want the template's own newline, then the line's", stdin, code, out, errb)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if code != 0 || out != want {
|
||||||
|
t.Errorf("run(%q) = %d, %q, %q; want %q", stdin, code, out, errb, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTextPrintsAsWritten(t *testing.T) {
|
||||||
|
for _, stdin := range []string{"sv_SE.person", "42", "null", "true", "[Skåne län]", "x[1]y", `say "hi"`} {
|
||||||
|
code, out, errb := runOut(stdin)
|
||||||
|
if code != 0 || out != stdin+"\n" {
|
||||||
|
t.Errorf("run(%q) = %d, %q, %q; want the text as written", stdin, code, out, errb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTrimsWhitespaceAroundJSON(t *testing.T) {
|
||||||
|
for _, stdin := range []string{
|
||||||
|
"{\"format\":\"{x}\",\"x\":[\"a\",\"b\"]}\n",
|
||||||
|
" {\"format\":\"{x}\",\"x\":[\"a\",\"b\"]}\n\n",
|
||||||
|
"\t[\"a\",\"b\"]\r\n",
|
||||||
|
" \"a\" \n",
|
||||||
|
} {
|
||||||
|
code, out, errb := runOut(stdin, "--seed", "1")
|
||||||
|
if code != 0 || (out != "a\n" && out != "b\n") {
|
||||||
|
t.Errorf("run(%q) = %d, %q, %q; want a or b", stdin, code, out, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunMultipleDataPaths(t *testing.T) {
|
func TestRunMultipleDataPaths(t *testing.T) {
|
||||||
code, out, errb := runOut("-d", enUS, "--data-path", svSE, "person")
|
code, out, errb := runOut("{/person}", "-d", enUS, "--data-path", svSE)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run(multi-dir) = %d, stderr=%q", code, errb)
|
t.Fatalf("run(multi-dir) = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -244,7 +323,7 @@ func TestRunMultipleDataPaths(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunUnknownCategoryFails(t *testing.T) {
|
func TestRunUnknownCategoryFails(t *testing.T) {
|
||||||
code, _, errb := runOut("--data-path", svSE, "nope")
|
code, _, errb := runOut("{/nope}", "--data-path", svSE)
|
||||||
if code != 1 {
|
if code != 1 {
|
||||||
t.Fatalf("run = %d, want 1", code)
|
t.Fatalf("run = %d, want 1", code)
|
||||||
}
|
}
|
||||||
@@ -254,7 +333,7 @@ func TestRunUnknownCategoryFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunList(t *testing.T) {
|
func TestRunList(t *testing.T) {
|
||||||
code, out, errb := runOut("--data-path", svSE, "--list")
|
code, out, errb := runOut("", "--data-path", svSE, "--list")
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -267,7 +346,7 @@ func TestRunList(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunHelpOnStdout(t *testing.T) {
|
func TestRunHelpOnStdout(t *testing.T) {
|
||||||
for _, h := range []string{"-h", "--help"} {
|
for _, h := range []string{"-h", "--help"} {
|
||||||
code, out, errb := runOut(h)
|
code, out, errb := runOut("", h)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Errorf("%s = %d, want 0", h, code)
|
t.Errorf("%s = %d, want 0", h, code)
|
||||||
}
|
}
|
||||||
@@ -278,7 +357,7 @@ func TestRunHelpOnStdout(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunVersion(t *testing.T) {
|
func TestRunVersion(t *testing.T) {
|
||||||
code, out, errb := runOut("--version")
|
code, out, errb := runOut("", "--version")
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("--version = %d, stderr=%q", code, errb)
|
t.Fatalf("--version = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -289,7 +368,7 @@ func TestRunVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunMissingDirFails(t *testing.T) {
|
func TestRunMissingDirFails(t *testing.T) {
|
||||||
code, _, errb := runOut("--data-path", "../../data/nope", "person")
|
code, _, errb := runOut("{/person}", "--data-path", "../../data/nope")
|
||||||
if code != 1 {
|
if code != 1 {
|
||||||
t.Fatalf("run = %d, want 1", code)
|
t.Fatalf("run = %d, want 1", code)
|
||||||
}
|
}
|
||||||
@@ -299,34 +378,20 @@ func TestRunMissingDirFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunShippedDataByDefault(t *testing.T) {
|
func TestRunShippedDataByDefault(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "sv_SE.person")
|
code, out, errb := runOut("{/sv_SE.person}", "--seed", "1")
|
||||||
if code != 0 || strings.TrimSpace(out) == "" {
|
if code != 0 || strings.TrimSpace(out) == "" {
|
||||||
t.Fatalf("run = %d, out=%q, stderr=%q", code, out, errb)
|
t.Fatalf("run = %d, out=%q, stderr=%q", code, out, errb)
|
||||||
}
|
}
|
||||||
code, list, _ := runOut("--list")
|
code, list, _ := runOut("", "--list")
|
||||||
if code != 0 || !strings.Contains(list, "en_US.person\n") || !strings.Contains(list, "misc.uuid\n") {
|
if code != 0 || !strings.Contains(list, "en_US.person\n") || !strings.Contains(list, "misc.uuid\n") {
|
||||||
t.Errorf("--list without --data-path = %d, %q", code, list)
|
t.Errorf("--list without --data-path = %d, %q", code, list)
|
||||||
}
|
}
|
||||||
code, _, errb = runOut("person")
|
code, _, errb = runOut("{/person}")
|
||||||
if code != 1 || !strings.Contains(errb, "person") {
|
if code != 1 || !strings.Contains(errb, "person") {
|
||||||
t.Errorf("a category outside the shipped tree: code %d, stderr %q", code, errb)
|
t.Errorf("a category outside the shipped tree: code %d, stderr %q", code, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClassify(t *testing.T) {
|
|
||||||
for arg, want := range map[string]argKind{"sv_SE.person": argPath, "name: {x}": argTemplate} {
|
|
||||||
if got, err := classify(arg); err != nil || got != want {
|
|
||||||
t.Errorf("classify(%q) = %v, %v; want %v", arg, got, err, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := classify("[abc]"); err == nil || !strings.Contains(err.Error(), `"["`) || !strings.Contains(err.Error(), "JSON") {
|
|
||||||
t.Errorf("classify([abc]) = %v; want it rejected naming the leading bracket", err)
|
|
||||||
}
|
|
||||||
if got, err := classify("geo.SE.municipality[St. Louis].name"); err != nil || got != argPath {
|
|
||||||
t.Errorf("classify(a selecting path) = %v, %v; want a path", got, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunSelectsATableRow(t *testing.T) {
|
func TestRunSelectsATableRow(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
for name, content := range map[string]string{
|
for name, content := range map[string]string{
|
||||||
@@ -337,95 +402,92 @@ func TestRunSelectsATableRow(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if code, out, errb := runOut("--no-shipped-data", "-d", dir, "region[12]"); code != 0 || out != "Skåne län\n" {
|
if code, out, errb := runOut("{/region[12]}", "--no-shipped-data", "-d", dir); code != 0 || out != "Skåne län\n" {
|
||||||
t.Fatalf("region[12] = %d, %q, stderr=%q", code, out, errb)
|
t.Fatalf("{/region[12]} = %d, %q, stderr=%q", code, out, errb)
|
||||||
}
|
}
|
||||||
if code, out, _ := runOut("--no-shipped-data", "-d", dir, "region[Skåne län].code"); code != 0 || out != "12\n" {
|
if code, out, _ := runOut("{/region[Skåne län].code}", "--no-shipped-data", "-d", dir); code != 0 || out != "12\n" {
|
||||||
t.Fatalf("region[Skåne län].code = %d, %q", code, out)
|
t.Fatalf("{/region[Skåne län].code} = %d, %q", code, out)
|
||||||
}
|
}
|
||||||
if code, out, _ := runOut("--no-shipped-data", "-d", dir, "--format", "sql", "region[12]"); code != 0 || out != `INSERT INTO "region" ("code", "name") VALUES ('12', 'Skåne län');`+"\n" {
|
if code, out, _ := runOut("{/region[12]}", "--no-shipped-data", "-d", dir, "--format", "sql"); code != 0 || out != `INSERT INTO "region" ("code", "name") VALUES ('12', 'Skåne län');`+"\n" {
|
||||||
t.Fatalf("--format sql region[12] = %d, %q, want the table named without its selector", code, out)
|
t.Fatalf("--format sql {/region[12]} = %d, %q, want the table named without its selector", code, out)
|
||||||
}
|
}
|
||||||
if code, _, errb := runOut("--no-shipped-data", "-d", dir, "region[99]"); code != 1 || !strings.Contains(errb, `"99"`) {
|
if code, _, errb := runOut("{/region[99]}", "--no-shipped-data", "-d", dir); code != 1 || !strings.Contains(errb, `"99"`) {
|
||||||
t.Fatalf("region[99] = %d, stderr=%q, want a runtime error naming the row", code, errb)
|
t.Fatalf("{/region[99]} = %d, stderr=%q, want a runtime error naming the row", code, errb)
|
||||||
}
|
}
|
||||||
if code, _, errb := runOut("--no-shipped-data", "-d", dir, "[Skåne län]"); code != 2 || !strings.Contains(errb, "JSON") {
|
if code, out, _ := runOut("{/misc.territory[SE]}", "--seed", "1", "--format", "csv"); code != 0 || !strings.HasPrefix(out, "alpha2,") || !strings.Contains(out, "\nSE,SWE,") {
|
||||||
t.Fatalf("[Skåne län] = %d, stderr=%q, want misuse: a leading bracket that is no JSON names nothing", code, errb)
|
t.Fatalf("--format csv {/misc.territory[SE]} = %d, %q", code, out)
|
||||||
}
|
|
||||||
if code, out, _ := runOut("--seed", "1", "--format", "csv", "misc.territory[SE]"); code != 0 || !strings.HasPrefix(out, "alpha2,") || !strings.Contains(out, "\nSE,SWE,") {
|
|
||||||
t.Fatalf("--format csv misc.territory[SE] = %d, %q", code, out)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUsageReferencesResolve(t *testing.T) {
|
func TestUsageReferencesResolve(t *testing.T) {
|
||||||
for _, token := range regexp.MustCompile(`\{/[^}]+\}`).FindAllString(usage, -1) {
|
for _, token := range regexp.MustCompile(`\{/[^}]+\}`).FindAllString(usage, -1) {
|
||||||
path := token[2 : len(token)-1]
|
code, out, errb := runOut(token, "--seed", "1")
|
||||||
code, out, errb := runOut("--seed", "1", path)
|
|
||||||
if code != 0 || strings.TrimSpace(out) == "" {
|
if code != 0 || strings.TrimSpace(out) == "" {
|
||||||
t.Errorf("usage advertises %s: run %s = %d, %q, stderr %q", token, path, code, out, errb)
|
t.Errorf("usage advertises %s: run = %d, %q, stderr %q", token, code, out, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunShapeMisuseBeforeLoad(t *testing.T) {
|
func TestRunArgumentMisuseBeforeLoad(t *testing.T) {
|
||||||
code, _, errb := runOut("--no-shipped-data", "[abc]")
|
code, _, errb := runOut("", "--no-shipped-data", "x")
|
||||||
if code != 2 || !strings.Contains(errb, "[abc]") || strings.Contains(errb, "--data-path") {
|
if code != 2 || !strings.Contains(errb, "stdin") || strings.Contains(errb, "--data-path") {
|
||||||
t.Fatalf("shape misuse with no data = %d, %q; want the shape error before any load", code, errb)
|
t.Fatalf("an argument with no data = %d, %q; want the argument refused before any load", code, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunInlineTemplate(t *testing.T) {
|
func TestRunInlineTemplate(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "name: {/sv_SE.person.last}")
|
code, out, errb := runOut("name: {/sv_SE.person.last}", "--seed", "1")
|
||||||
if code != 0 || !strings.HasPrefix(out, "name: ") || strings.Contains(out, "{") {
|
if code != 0 || !strings.HasPrefix(out, "name: ") || strings.Contains(out, "{") {
|
||||||
t.Fatalf("inline format string = %d, %q, stderr %q", code, out, errb)
|
t.Fatalf("inline format string = %d, %q, stderr %q", code, out, errb)
|
||||||
}
|
}
|
||||||
code, out, errb = runOut("--seed", "1", `{"format":"name: {x}","x":["bosse","lina"]}`)
|
code, out, errb = runOut(`{"format":"name: {x}","x":["bosse","lina"]}`, "--seed", "1")
|
||||||
if code != 0 || (out != "name: bosse\n" && out != "name: lina\n") {
|
if code != 0 || (out != "name: bosse\n" && out != "name: lina\n") {
|
||||||
t.Fatalf("inline JSON template = %d, %q, want one name, stderr %q", code, out, errb)
|
t.Fatalf("inline JSON template = %d, %q, want one name, stderr %q", code, out, errb)
|
||||||
}
|
}
|
||||||
code, out, errb = runOut("--seed", "1", `"name: {/sv_SE.person.last}"`)
|
code, out, errb = runOut(`"name: {/sv_SE.person.last}"`, "--seed", "1")
|
||||||
if code != 0 || !strings.HasPrefix(out, "name: ") || strings.Contains(out, "{") {
|
if code != 0 || !strings.HasPrefix(out, "name: ") || strings.Contains(out, "{") {
|
||||||
t.Fatalf("inline JSON string = %d, %q, stderr %q", code, out, errb)
|
t.Fatalf("inline JSON string = %d, %q, stderr %q", code, out, errb)
|
||||||
}
|
}
|
||||||
code, out, errb = runOut("--seed", "1", "-n", "2", `{digits(1)}`)
|
code, out, errb = runOut(`{digits(1)}`, "--seed", "1", "-n", "2")
|
||||||
if code != 0 || len(strings.Split(strings.TrimRight(out, "\n"), "\n")) != 2 {
|
if code != 0 || len(strings.Split(strings.TrimRight(out, "\n"), "\n")) != 2 {
|
||||||
t.Fatalf("inline template with --repeat = %d, %q, stderr %q", code, out, errb)
|
t.Fatalf("inline template with --repeat = %d, %q, stderr %q", code, out, errb)
|
||||||
}
|
}
|
||||||
|
code, out, errb = runOut("{/sv_SE.person} hihi", "--seed", "1")
|
||||||
|
if code != 0 || !strings.HasSuffix(out, " hihi\n") || strings.Contains(out, "{") {
|
||||||
|
t.Fatalf("a reference and text = %d, %q, stderr %q", code, out, errb)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunTemplateMisuse(t *testing.T) {
|
func TestRunTemplateMisuse(t *testing.T) {
|
||||||
for arg, want := range map[string]string{
|
for stdin, want := range map[string]string{
|
||||||
"{bad": "unterminated",
|
"{bad": "unterminated",
|
||||||
"[red,green]": `starts with "["`,
|
|
||||||
`{"format":"x"}`: "is a string",
|
`{"format":"x"}`: "is a string",
|
||||||
"name: {/no.such.path}": "no entry",
|
"name: {/no.such.path}": "no entry",
|
||||||
"{/sv_SE.person}": "write sv_SE.person",
|
"a } b": "}}",
|
||||||
"x[1]y": `"]"`,
|
|
||||||
` ["a","b"] `: "may not be padded",
|
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut("--seed", "1", arg)
|
code, out, errb := runOut(stdin, "--seed", "1")
|
||||||
if code != 2 || out != "" || !strings.Contains(errb, "try 'fejkdata --help'") || !strings.Contains(errb, want) {
|
if code != 2 || out != "" || !strings.Contains(errb, "try 'fejkdata --help'") || !strings.Contains(errb, want) {
|
||||||
t.Errorf("run(%q) = %d, %q, %q; want misuse naming %q and --help", arg, code, out, errb, want)
|
t.Errorf("run(%q) = %d, %q, %q; want misuse naming %q and --help", stdin, code, out, errb, want)
|
||||||
}
|
}
|
||||||
if strings.Contains(errb, "fejkdata: fejkdata:") {
|
if strings.Contains(errb, "fejkdata: fejkdata:") {
|
||||||
t.Errorf("run(%q) doubled the program prefix: %q", arg, errb)
|
t.Errorf("run(%q) doubled the program prefix: %q", stdin, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunNoShippedData(t *testing.T) {
|
func TestRunNoShippedData(t *testing.T) {
|
||||||
code, list, errb := runOut("--no-shipped-data", "-d", misc, "--list")
|
code, list, errb := runOut("", "--no-shipped-data", "-d", misc, "--list")
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
if strings.Contains(list, "sv_SE") || !strings.Contains(list, "uuid\n") {
|
if strings.Contains(list, "sv_SE") || !strings.Contains(list, "uuid\n") {
|
||||||
t.Errorf("--no-shipped-data --list = %q, want only the given dir", list)
|
t.Errorf("--no-shipped-data --list = %q, want only the given dir", list)
|
||||||
}
|
}
|
||||||
code, out, _ := runOut("--no-shipped-data", "-d", misc, "-s", "3", "uuid")
|
code, out, _ := runOut("{/uuid}", "--no-shipped-data", "-d", misc, "-s", "3")
|
||||||
if code != 0 || strings.TrimSpace(out) == "" {
|
if code != 0 || strings.TrimSpace(out) == "" {
|
||||||
t.Errorf("run = %d, out=%q", code, out)
|
t.Errorf("run = %d, out=%q", code, out)
|
||||||
}
|
}
|
||||||
code, _, errb = runOut("--no-shipped-data", "sv_SE.person")
|
code, _, errb = runOut("{/sv_SE.person}", "--no-shipped-data")
|
||||||
if code != 2 || !strings.Contains(errb, "--no-shipped-data needs at least one --data-path") {
|
if code != 2 || !strings.Contains(errb, "--no-shipped-data needs at least one --data-path") {
|
||||||
t.Errorf("--no-shipped-data alone = %d, %q, want misuse naming --data-path", code, errb)
|
t.Errorf("--no-shipped-data alone = %d, %q, want misuse naming --data-path", code, errb)
|
||||||
}
|
}
|
||||||
@@ -433,11 +495,11 @@ func TestRunNoShippedData(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunRepeatIsBounded(t *testing.T) {
|
func TestRunRepeatIsBounded(t *testing.T) {
|
||||||
for _, args := range [][]string{
|
for _, args := range [][]string{
|
||||||
{"--repeat", "9223372036854775807", "sv_SE.word"},
|
{"--repeat", "9223372036854775807"},
|
||||||
{"--repeat", "1048577", "sv_SE.word"},
|
{"--repeat", "1048577"},
|
||||||
{"-n", "99999999999", "sv_SE.word"},
|
{"-n", "99999999999"},
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut(args...)
|
code, out, errb := runOut("{/sv_SE.word}", args...)
|
||||||
if code != 2 || out != "" || !strings.Contains(errb, "1..1048576") {
|
if code != 2 || out != "" || !strings.Contains(errb, "1..1048576") {
|
||||||
t.Errorf("run(%v) = %d, %q, %q, want misuse naming the range", args, code, out, errb)
|
t.Errorf("run(%v) = %d, %q, %q, want misuse naming the range", args, code, out, errb)
|
||||||
}
|
}
|
||||||
@@ -446,7 +508,7 @@ func TestRunRepeatIsBounded(t *testing.T) {
|
|||||||
if err := os.WriteFile(filepath.Join(dir, "x.json"), []byte(`"x"`), 0o644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, "x.json"), []byte(`"x"`), 0o644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
code, out, errb := runOut("--no-shipped-data", "-d", dir, "--repeat", "1048576", "--separator", "", "x")
|
code, out, errb := runOut("{/x}", "--no-shipped-data", "-d", dir, "--repeat", "1048576", "--separator", "")
|
||||||
if code != 0 || len(out) != 1048576+1 {
|
if code != 0 || len(out) != 1048576+1 {
|
||||||
t.Errorf("repeat at the cap = %d, %d bytes, stderr %q; want every render streamed", code, len(out), errb)
|
t.Errorf("repeat at the cap = %d, %d bytes, stderr %q; want every render streamed", code, len(out), errb)
|
||||||
}
|
}
|
||||||
@@ -454,7 +516,7 @@ func TestRunRepeatIsBounded(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunListTakesNoRepeatOrSeparator(t *testing.T) {
|
func TestRunListTakesNoRepeatOrSeparator(t *testing.T) {
|
||||||
for _, args := range [][]string{{"--list", "-n", "3"}, {"--list", "--separator", ","}} {
|
for _, args := range [][]string{{"--list", "-n", "3"}, {"--list", "--separator", ","}} {
|
||||||
code, _, errb := runOut(args...)
|
code, _, errb := runOut("", args...)
|
||||||
if code != 2 || !strings.Contains(errb, "--list takes no") {
|
if code != 2 || !strings.Contains(errb, "--list takes no") {
|
||||||
t.Errorf("run(%v) = %d, %q, want misuse", args, code, errb)
|
t.Errorf("run(%v) = %d, %q, want misuse", args, code, errb)
|
||||||
}
|
}
|
||||||
@@ -462,14 +524,14 @@ func TestRunListTakesNoRepeatOrSeparator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunUnknownFlagIsNamedByRune(t *testing.T) {
|
func TestRunUnknownFlagIsNamedByRune(t *testing.T) {
|
||||||
code, _, errb := runOut("-ä", "sv_SE.word")
|
code, _, errb := runOut("{/sv_SE.word}", "-ä")
|
||||||
if code != 2 || !strings.Contains(errb, "unknown flag -ä") {
|
if code != 2 || !strings.Contains(errb, "unknown flag -ä") {
|
||||||
t.Errorf("run(-ä) = %d, %q, want the flag named whole", code, errb)
|
t.Errorf("run(-ä) = %d, %q, want the flag named whole", code, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunEmptyDataPathIsNamed(t *testing.T) {
|
func TestRunEmptyDataPathIsNamed(t *testing.T) {
|
||||||
code, _, errb := runOut("--data-path=", "sv_SE.word")
|
code, _, errb := runOut("{/sv_SE.word}", "--data-path=")
|
||||||
if code != 1 || !strings.Contains(errb, "empty") {
|
if code != 1 || !strings.Contains(errb, "empty") {
|
||||||
t.Errorf("run(--data-path=) = %d, %q, want the empty path named", code, errb)
|
t.Errorf("run(--data-path=) = %d, %q, want the empty path named", code, errb)
|
||||||
}
|
}
|
||||||
@@ -486,7 +548,7 @@ func recordDir(t *testing.T) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordJSON(t *testing.T) {
|
func TestRunRecordJSON(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "json", "--repeat", "2", "--data-path", recordDir(t), "users")
|
code, out, errb := runOut("{/users}", "--seed", "1", "--format", "json", "--repeat", "2", "--data-path", recordDir(t))
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -500,7 +562,7 @@ func TestRunRecordJSON(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordNDJSON(t *testing.T) {
|
func TestRunRecordNDJSON(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "ndjson", "--repeat", "2", "--data-path", recordDir(t), "users")
|
code, out, errb := runOut("{/users}", "--seed", "1", "--format", "ndjson", "--repeat", "2", "--data-path", recordDir(t))
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -517,7 +579,7 @@ func TestRunRecordNDJSON(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordCSVRoundTrips(t *testing.T) {
|
func TestRunRecordCSVRoundTrips(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "csv", "--repeat", "3", "--data-path", recordDir(t), "users")
|
code, out, errb := runOut("{/users}\n", "--seed", "1", "--format", "csv", "--repeat", "3", "--data-path", recordDir(t))
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -538,7 +600,7 @@ func TestRunRecordCSVRoundTrips(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordSQL(t *testing.T) {
|
func TestRunRecordSQL(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "sql", "--repeat", "2", "--table", "people", "--data-path", recordDir(t), "users")
|
code, out, errb := runOut("{/users}", "--seed", "1", "--format", "sql", "--repeat", "2", "--table", "people", "--data-path", recordDir(t))
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("run = %d, stderr=%q", code, errb)
|
t.Fatalf("run = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -549,14 +611,14 @@ func TestRunRecordSQL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordDefaultTable(t *testing.T) {
|
func TestRunRecordDefaultTable(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "sql", "--data-path", recordDir(t), "users")
|
code, out, errb := runOut("{/users}", "--seed", "1", "--format", "sql", "--data-path", recordDir(t))
|
||||||
if code != 0 || !strings.HasPrefix(out, `INSERT INTO "users" (`) {
|
if code != 0 || !strings.HasPrefix(out, `INSERT INTO "users" (`) {
|
||||||
t.Fatalf("default table = %d, %q, want the path's last segment; stderr %q", code, out, errb)
|
t.Fatalf("default table = %d, %q, want the reference's last segment; stderr %q", code, out, errb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRecordInlineTemplate(t *testing.T) {
|
func TestRunRecordInlineTemplate(t *testing.T) {
|
||||||
code, out, errb := runOut("--seed", "1", "--format", "json", `{"format":"{x}","x":["a","b"]}`)
|
code, out, errb := runOut(`{"format":"{x}","x":["a","b"]}`, "--seed", "1", "--format", "json")
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("inline record = %d, stderr=%q", code, errb)
|
t.Fatalf("inline record = %d, stderr=%q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -571,13 +633,13 @@ func TestRunRecordMisuse(t *testing.T) {
|
|||||||
args []string
|
args []string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{[]string{"--format", "yaml", "users"}, "--format takes csv, json, ndjson, sql or text"},
|
{[]string{"--format", "yaml"}, "--format takes csv, json, ndjson, sql or text"},
|
||||||
{[]string{"--format", "json", "--separator", ",", "users"}, "--separator joins text values"},
|
{[]string{"--format", "json", "--separator", ","}, "--separator joins text values"},
|
||||||
{[]string{"--table", "t", "users"}, "--table names the INSERT target"},
|
{[]string{"--table", "t"}, "--table names the INSERT target"},
|
||||||
{[]string{"--format", "json", "--table", "t", "users"}, "--table names the INSERT target"},
|
{[]string{"--format", "json", "--table", "t"}, "--table names the INSERT target"},
|
||||||
{[]string{"--format", "sql", "--table", "", "users"}, "--table names the INSERT target"},
|
{[]string{"--format", "sql", "--table", ""}, "--table names the INSERT target"},
|
||||||
} {
|
} {
|
||||||
code, out, errb := runOut(c.args...)
|
code, out, errb := runOut("{/users}", c.args...)
|
||||||
if code != 2 || out != "" || !strings.Contains(errb, c.want) {
|
if code != 2 || out != "" || !strings.Contains(errb, c.want) {
|
||||||
t.Errorf("run(%v) = %d, %q, %q; want misuse naming %q", c.args, code, out, errb, c.want)
|
t.Errorf("run(%v) = %d, %q, %q; want misuse naming %q", c.args, code, out, errb, c.want)
|
||||||
}
|
}
|
||||||
@@ -589,7 +651,7 @@ func TestRunRecordOnABareValueIsRuntimeError(t *testing.T) {
|
|||||||
if err := os.WriteFile(filepath.Join(dir, "word.json"), []byte(`["a","b"]`), 0o644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, "word.json"), []byte(`["a","b"]`), 0o644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
code, _, errb := runOut("--format", "json", "--data-path", dir, "word")
|
code, _, errb := runOut("{/word}", "--format", "json", "--data-path", dir)
|
||||||
if code != 1 {
|
if code != 1 {
|
||||||
t.Fatalf("record on a choice = %d, want exit 1 (runtime error), stderr %q", code, errb)
|
t.Fatalf("record on a choice = %d, want exit 1 (runtime error), stderr %q", code, errb)
|
||||||
}
|
}
|
||||||
@@ -601,22 +663,22 @@ func TestRunRecordRejectsATopLevelRepeat(t *testing.T) {
|
|||||||
if err := os.WriteFile(filepath.Join(dir, "rep.json"), []byte(content), 0o644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, "rep.json"), []byte(content), 0o644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
code, _, errb := runOut("--format", "json", "--data-path", dir, "rep")
|
code, _, errb := runOut("{/rep}", "--format", "json", "--data-path", dir)
|
||||||
if code != 1 || !strings.Contains(errb, "carries repeat 3") {
|
if code != 1 || !strings.Contains(errb, "carries repeat 3") {
|
||||||
t.Errorf("record on a repeating path = %d, %q; want exit 1 naming the repeat", code, errb)
|
t.Errorf("record on a repeating path = %d, %q; want exit 1 naming the repeat", code, errb)
|
||||||
}
|
}
|
||||||
code, _, errb = runOut("--format", "json", content)
|
code, _, errb = runOut(content, "--format", "json")
|
||||||
if code != 2 || !strings.Contains(errb, "carries repeat 3") {
|
if code != 2 || !strings.Contains(errb, "carries repeat 3") {
|
||||||
t.Errorf("record on a repeating inline template = %d, %q; want exit 2 naming the repeat", code, errb)
|
t.Errorf("record on a repeating inline template = %d, %q; want exit 2 naming the repeat", code, errb)
|
||||||
}
|
}
|
||||||
if code, out, _ := runOut("--seed", "1", "--data-path", dir, "rep"); code != 0 || strings.TrimSpace(out) != "x-|x-|x-" {
|
if code, out, _ := runOut("{/rep}", "--seed", "1", "--data-path", dir); code != 0 || strings.TrimSpace(out) != "x-|x-|x-" {
|
||||||
t.Errorf("text view = %d, %q; want the repeat still composed", code, out)
|
t.Errorf("text view = %d, %q; want the repeat still composed", code, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunNumbersFollowTheShell(t *testing.T) {
|
func TestRunNumbersFollowTheShell(t *testing.T) {
|
||||||
_, want, _ := runOut("--seed", "7", "--repeat", "3", "sv_SE.word")
|
_, want, _ := runOut("{/sv_SE.word}", "--seed", "7", "--repeat", "3")
|
||||||
code, got, errb := runOut("--seed", "007", "--repeat", "+3", "sv_SE.word")
|
code, got, errb := runOut("{/sv_SE.word}", "--seed", "007", "--repeat", "+3")
|
||||||
if code != 0 || got != want {
|
if code != 0 || got != want {
|
||||||
t.Errorf("run(--seed 007 --repeat +3) = %d, %q, stderr %q; want the same as --seed 7 --repeat 3 %q", code, got, errb, want)
|
t.Errorf("run(--seed 007 --repeat +3) = %d, %q, stderr %q; want the same as --seed 7 --repeat 3 %q", code, got, errb, want)
|
||||||
}
|
}
|
||||||
@@ -624,11 +686,11 @@ func TestRunNumbersFollowTheShell(t *testing.T) {
|
|||||||
|
|
||||||
// TestRunRecordOfAFieldlessPath pins the way out of asking a category of one value
|
// TestRunRecordOfAFieldlessPath pins the way out of asking a category of one value
|
||||||
// for columns: the record to write, and the quoting a shell needs to take it. The
|
// for columns: the record to write, and the quoting a shell needs to take it. The
|
||||||
// argument is well-formed and only the data cannot serve it, so the code is 1.
|
// template is well-formed and only the data cannot serve it, so the code is 1.
|
||||||
func TestRunRecordOfAFieldlessPath(t *testing.T) {
|
func TestRunRecordOfAFieldlessPath(t *testing.T) {
|
||||||
code, out, errb := runOut("--format", "csv", "sv_SE.personnummer")
|
code, out, errb := runOut("{/sv_SE.personnummer}", "--format", "csv")
|
||||||
if code != 1 {
|
if code != 1 {
|
||||||
t.Fatalf("run(--format csv sv_SE.personnummer) = %d, want 1", code)
|
t.Fatalf("run(--format csv) of {/sv_SE.personnummer} = %d, want 1", code)
|
||||||
}
|
}
|
||||||
for _, want := range []string{`{"format":"","personnummer":"{/sv_SE.personnummer}"}`, "single quotes"} {
|
for _, want := range []string{`{"format":"","personnummer":"{/sv_SE.personnummer}"}`, "single quotes"} {
|
||||||
if !strings.Contains(errb, want) {
|
if !strings.Contains(errb, want) {
|
||||||
|
|||||||
Reference in New Issue
Block a user