Test that a calc over digits(0) or a repeat of 0 is refused, that an option of the wrong kind names its JSON kind, and that the root scope is the category

This commit is contained in:
2026-10-07 23:58:22 +02:00
committed by Lillem4n
parent 924ba07c1c
commit ba2ae41ffe
6 changed files with 41 additions and 6 deletions
+12 -3
View File
@@ -309,6 +309,15 @@ func TestCalcRefusesABadOperand(t *testing.T) {
}
}
func TestATypedColumnRefusesACalcOverNoDigits(t *testing.T) {
_, err := New(WithoutShippedData(), WithDataPath(writeData(t, map[string]string{
"row": `{"format":"","x":{"format":"{calc(d + 1)}","d":"{digits(0)}","datatype":"integer"}}`,
})))
if err == nil || !strings.Contains(err.Error(), "{digits(0)} prints nothing, which is no number") {
t.Fatalf("New = %v, want a calc over {digits(0)} refused in a typed column", err)
}
}
func TestATypedColumnProvesACalcOverAName(t *testing.T) {
dir := writeData(t, map[string]string{
"n": `"{int(1,9)}"`,
@@ -334,8 +343,8 @@ func TestATypedColumnProvesACalcOverAName(t *testing.T) {
}
}
func TestARepeatOfZeroIsNoConstant(t *testing.T) {
if got := mustRender(t, engine(1), `{"format":"{calc(x / y)}","x":"1","y":{"format":"0","repeat":0}}`); got != "NaN" {
t.Errorf("a divisor rendering nothing = %q, want NaN", got)
func TestARepeatOfZeroIsNeverANumber(t *testing.T) {
if _, err := resolved(t, `{"format":"{calc(x / y)}","x":"1","y":{"format":"0","repeat":0}}`); err == nil || !strings.Contains(err.Error(), `operand "y" is never a number: it renders ""`) {
t.Errorf("a calc over a repeat of 0 = %v, want the operand refused as never a number", err)
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ func TestDatatypeSitsOnlyInAColumn(t *testing.T) {
}
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":1}}`: "datatype must be a string",
`{"format":"","n":{"format":"1","datatype":1}}`: "datatype must be a string, not a number",
} {
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)
+3 -2
View File
@@ -29,14 +29,15 @@ func TestPackageImports(t *testing.T) {
}
checked := 0
allowed := map[string][]string{
".": {"internal/builtinfunc", "internal/datafiles", "internal/datatype", "internal/drawstate", "internal/grammar", "internal/invariant", "internal/proven", "internal/rows"},
".": {"internal/builtinfunc", "internal/datafiles", "internal/datatype", "internal/drawstate", "internal/grammar", "internal/invariant", "internal/jsonvalue", "internal/proven", "internal/rows"},
"cmd/fejkdata": {"."},
"internal/builtinfunc": {"internal/datatype", "internal/drawstate", "internal/grammar", "internal/invariant", "internal/proven"},
"internal/datafiles": {"internal/grammar"},
"internal/datafiles": {"internal/grammar", "internal/jsonvalue"},
"internal/datatype": nil,
"internal/drawstate": nil,
"internal/grammar": nil,
"internal/invariant": nil,
"internal/jsonvalue": nil,
"internal/proven": {"internal/datatype", "internal/grammar", "internal/invariant"},
"internal/rows": {"internal/drawstate", "internal/grammar", "internal/invariant"},
}
+11
View File
@@ -1,6 +1,7 @@
package fejkdata
import (
"fmt"
"strings"
"testing"
)
@@ -182,6 +183,16 @@ func TestAChoiceItemKeepsTheNamesItBinds(t *testing.T) {
}
}
func TestTheRootScopeIsTheCategory(t *testing.T) {
root := compiled(t, `{"format":"{x as n}{n}{y}","x":"a","y":{"format":"{z as m}{m}","z":"b","repeat":2}}`).(*template)
if k := fmt.Sprint(root.nameScope.kind()); k != "category" {
t.Errorf("root scope kind = %q, want category", k)
}
if k := fmt.Sprint(root.fields["y"].(*template).nameScope.kind()); k != "repeat" {
t.Errorf("repeat scope kind = %q, want repeat", k)
}
}
func TestNameErrors(t *testing.T) {
cases := []struct {
name string
+11
View File
@@ -2,9 +2,20 @@ package fejkdata
import (
"regexp"
"strings"
"testing"
)
func TestAnOptionOfTheWrongKindIsNamedByItsJSONKind(t *testing.T) {
if _, err := resolved(t, `{"format":"x","repeat":2,"separator":5}`); err == nil || !strings.Contains(err.Error(), "separator must be a string, not a number") {
t.Errorf("separator 5 = %v, want the kind named", err)
}
_, err := New(WithoutShippedData(), WithDataPath(writeFiles(t, map[string]string{"t.json": `{"format":"{a}","rows":"t.tsv","key":5}`, "t.tsv": "a\nx\n"})))
if err == nil || !strings.Contains(err.Error(), "key must be a string, not a number") {
t.Errorf("key 5 = %v, want the kind named", err)
}
}
func TestWeightSkewsDistribution(t *testing.T) {
f := engine(9)
heavy := 0
+3
View File
@@ -309,6 +309,9 @@ func TestFakeStructErrors(t *testing.T) {
{&struct {
A int `fake:"person.first"`
}{}, `"Ada" is not an integer`},
{&struct {
A int `fake:"{\"format\":\"{calc(d + 1)}\",\"d\":\"{digits(0)}\"}"`
}{}, "{digits(0)} prints nothing, which is no number"},
{&struct {
A int8 `fake:"{int(0,300)}"`
}{}, `"{int(0,300)}" is not proven within int8; narrow it to that range, or make the field int64`},