Compare commits

...

1 Commits

3 changed files with 52 additions and 11 deletions
+15
View File
@@ -245,3 +245,18 @@ func TestCalcOverANeverNumericOperandIsRejected(t *testing.T) {
} }
} }
} }
func TestCalcConstantZeroDivisorIsRejected(t *testing.T) {
for _, bad := range []string{`"{calc(1/0)}"`, `"{calc(2/(1-1))}"`, `{"format":"{calc(x/y)}","x":"1","y":"0"}`, `{"format":"{calc(x/(y*2))}","x":"1","y":" 0 "}`} {
if _, err := compile(parse(t, bad)); err == nil || !strings.Contains(err.Error(), "zero") {
t.Errorf("compile(%s) = %v, want the constant zero divisor rejected", bad, err)
}
}
f := engine(1)
for i := 0; i < 50; i++ {
if got := mustRender(t, f, `{"format":"{calc(x/y)}","x":"1","y":["0","1"]}`); got == "+Inf" {
return
}
}
t.Fatal("a sometimes-zero divisor never printed +Inf in 50 draws")
}
+14
View File
@@ -136,3 +136,17 @@ func TestMissingFieldNamesItself(t *testing.T) {
t.Errorf("Fake(person.typo) = %v, want it to name the missing field", err) t.Errorf("Fake(person.typo) = %v, want it to name the missing field", err)
} }
} }
func TestBindingKeyIsNotAPathSegment(t *testing.T) {
dir := writeData(t, map[string]string{
"color": `["red","blue"]`,
"name": `{"format":"{/color} {w}","w":"x"}`,
})
f := newGenerator(t, dir, WithSeed(1))
if slices.Contains(f.List(), "name./color") {
t.Error("List() advertises a binding key")
}
if _, err := f.Fake("name./color"); err == nil || !strings.Contains(err.Error(), `no field "/color"`) {
t.Errorf("Fake(name./color) = %v, want a no-field error", err)
}
}
+23 -11
View File
@@ -227,17 +227,29 @@ func TestCompileErrors(t *testing.T) {
`{"format":"x","repeat":1.5}`, // non-integer repeat `{"format":"x","repeat":1.5}`, // non-integer repeat
`{"format":"x","repeat":"two"}`, // non-numeric repeat `{"format":"x","repeat":"two"}`, // non-numeric repeat
`{"format":"x","repeat":2,"separator":5}`, // non-string separator `{"format":"x","repeat":2,"separator":5}`, // non-string separator
`"{nope()}"`, // unknown function `"{nope()}"`, // unknown function
`"{luhn(x)}"`, // function given args it takes none of `"{luhn(x)}"`, // function given args it takes none of
`"{luhn(}"`, // malformed function token `"{luhn(}"`, // malformed function token
`"{int(1)}"`, // wrong arity `"{int(1)}"`, // wrong arity
`"{int(a,b)}"`, // non-integer args `"{int(a,b)}"`, // non-integer args
`"{int(5,1)}"`, // min > max `"{int(5,1)}"`, // min > max
`"{hex(0)}"`, // count must be positive `"{hex(0)}"`, // count must be positive
`"{nanoid(-1)}"`, // negative count `"{nanoid(-1)}"`, // negative count
`"{base64(0)}"`, // count must be positive `"{base64(0)}"`, // count must be positive
`"{float(1,2)}"`, // wrong arity `"{float(1,2)}"`, // wrong arity
`"{float(1,2,-1)}"`, // negative decimals `"{float(1,2,-1)}"`, // negative decimals
`"{float(NaN,NaN,2)}"`, // bounds must be finite
`"{float(Inf,Inf,2)}"`, // same-sign infinities
`"{float(1,NaN,2)}"`, // one NaN bound
`"{float(-Inf,1,2)}"`, // one infinite bound
`"{digits(+5)}"`, // a count is a plain integer
`"{digits(05)}"`, // no leading zero
`"{int(+1,5)}"`, // a bound is a plain integer
`"{int(5,5)}"`, // a constant is written as text
`"{float(1,1,2)}"`, // a constant is written as text
`{"format":"{x}","x":"v","repeat":2,"separator":""}`, // separator "" is the default
`"{calc(1/0)}"`, // a constant zero divisor
`{"format":"{calc(x/y)}","x":"1","y":"0"}`, // a fixed zero divisor
`"{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
`"{calc()}"`, // calc needs an expression `"{calc()}"`, // calc needs an expression