Name the tests' held reads held, keeping bound for a numeric bound
This commit is contained in:
+8
-8
@@ -57,29 +57,29 @@ func BenchmarkRepeat(b *testing.B) {
|
||||
benchPath(b, dir, "many")
|
||||
}
|
||||
|
||||
// BenchmarkBound measures a format that binds a head and reads two paths from it —
|
||||
// what a correlated pair costs against BenchmarkUnbound, the same output drawn from
|
||||
// BenchmarkHeld measures a format that holds a head and reads two paths from it —
|
||||
// what a correlated pair costs against BenchmarkUnheld, the same output drawn from
|
||||
// two independent fields.
|
||||
func BenchmarkBound(b *testing.B) {
|
||||
func BenchmarkHeld(b *testing.B) {
|
||||
dir := tmpData(b, "addr", `{"format":"{place.postal-code} {place.locality}","place":[{"format":"{locality}","locality":"Stockholm","postal-code":"1{digits(2)} {digits(2)}"},{"format":"{locality}","locality":"Tranås","postal-code":"573 {digits(2)}"}]}`)
|
||||
benchPath(b, dir, "addr")
|
||||
}
|
||||
|
||||
func BenchmarkUnbound(b *testing.B) {
|
||||
func BenchmarkUnheld(b *testing.B) {
|
||||
dir := tmpData(b, "addr", `{"format":"{postal-code} {locality}","postal-code":["1{digits(2)} {digits(2)}","573 {digits(2)}"],"locality":["Stockholm","Tranås"]}`)
|
||||
benchPath(b, dir, "addr")
|
||||
}
|
||||
|
||||
// BenchmarkBoundDeep reads two paths through an intermediate level, the shape the
|
||||
// BenchmarkHeldDeep reads two paths through an intermediate level, the shape the
|
||||
// depth question is about.
|
||||
func BenchmarkBoundDeep(b *testing.B) {
|
||||
func BenchmarkHeldDeep(b *testing.B) {
|
||||
dir := tmpData(b, "addr", `{"format":"{p.addr.city} {p.addr.zip}","p":{"format":"{addr}","addr":{"format":"{city}","city":["Stockholm","Tranås"],"zip":"1{digits(2)} {digits(2)}"}}}`)
|
||||
benchPath(b, dir, "addr")
|
||||
}
|
||||
|
||||
// BenchmarkBoundWide reads ten paths from one row: the point where the maps an
|
||||
// BenchmarkHeldWide reads ten paths from one row: the point where the maps an
|
||||
// expansion holds outgrow a single bucket.
|
||||
func BenchmarkBoundWide(b *testing.B) {
|
||||
func BenchmarkHeldWide(b *testing.B) {
|
||||
dir := tmpData(b, "row", `{"format":"{r.a}{r.b}{r.c}{r.d}{r.e}{r.f}{r.g}{r.h}{r.i}{r.j}","r":[
|
||||
{"format":"x","a":"1","b":"2","c":"3","d":"4","e":"5","f":"6","g":"7","h":"8","i":"9","j":"0"},
|
||||
{"format":"y","a":"A","b":"B","c":"C","d":"D","e":"E","f":"F","g":"G","h":"H","i":"I","j":"J"}]}`)
|
||||
|
||||
+13
-13
@@ -68,8 +68,8 @@ func TestRenderingALevelAndReadingIntoItIsRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalcOperandNamingABoundLevelIsRejected(t *testing.T) {
|
||||
// A calc operand renders its field, so naming a bound level in one is the same
|
||||
func TestCalcOperandNamingAHeldLevelIsRejected(t *testing.T) {
|
||||
// A calc operand renders its field, so naming a held level in one is the same
|
||||
// overlap as a bare token: {calc(item * 1)} renders what {item.price} reads a
|
||||
// path into, and the two disagree.
|
||||
_, err := New(WithoutShippedData(), WithDataPath(writeData(t, map[string]string{
|
||||
@@ -87,8 +87,8 @@ func TestCalcOperandNamingABoundLevelIsRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferenceNamingABoundLevelIsRejected(t *testing.T) {
|
||||
// A reference can name a bound level from the data root, which renders it
|
||||
func TestReferenceNamingAHeldLevelIsRejected(t *testing.T) {
|
||||
// A reference can name a held level from the data root, which renders it
|
||||
// afresh beside the path that reads its held draw — the same overlap by
|
||||
// another spelling.
|
||||
// A category never references itself, so each reference back into cat sits in a
|
||||
@@ -102,7 +102,7 @@ func TestReferenceNamingABoundLevelIsRejected(t *testing.T) {
|
||||
"cat": `{"format":"{p.addr}|{/hop}","p":{"format":"x","addr":["A","B","C","D"]}}`,
|
||||
"hop": `"{/cat.p.addr}"`,
|
||||
},
|
||||
// The reference need not sit in the format that binds: any field it renders
|
||||
// The reference need not sit in the format that holds the level: any field it renders
|
||||
// reaches the level just the same, however deep.
|
||||
"reference from a sibling field": {
|
||||
"cat": `{"format":"{p.first}|{inner}","p":[` +
|
||||
@@ -122,7 +122,7 @@ func TestReferenceNamingABoundLevelIsRejected(t *testing.T) {
|
||||
"cat": `{"format":"{p.first} {/surname}","p":{"format":"{first}","first":["Anna","Bo"]}}`,
|
||||
"surname": `["Eriksson","Lindqvist"]`,
|
||||
}))); err != nil {
|
||||
t.Errorf("New = %v, want a reference outside the bound level accepted", err)
|
||||
t.Errorf("New = %v, want a reference outside the held level accepted", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ func TestACalcOperandIsHeldAgainstEveryRoute(t *testing.T) {
|
||||
},
|
||||
`{q} renders "net"`,
|
||||
},
|
||||
// A reference ending at the operand binds the choice itself, not a variant,
|
||||
// A reference ending at the operand holds the choice itself, not a variant,
|
||||
// so wrapping the operand in one changes nothing.
|
||||
"a reference to an operand wrapped in a choice": {
|
||||
map[string]string{
|
||||
@@ -344,7 +344,7 @@ func TestALevelAPathNeverRendersIsAccepted(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestADeepDiamondChainLoads(t *testing.T) {
|
||||
// A diamond chain is 2^n routes through n nodes. The search past a bound level
|
||||
// A diamond chain is 2^n routes through n nodes. The search past a held level
|
||||
// must walk each node once, not once per route, or a deep chain never loads.
|
||||
files := map[string]string{"l0": `"x"`}
|
||||
for i := 1; i <= 30; i++ {
|
||||
@@ -359,7 +359,7 @@ func TestADeepDiamondChainLoads(t *testing.T) {
|
||||
|
||||
func TestASharedNodeIsWalkedOnce(t *testing.T) {
|
||||
// Two fields reaching one node make the render graph a diamond, not a tree.
|
||||
// The search past a bound level must take that in its stride rather than walk
|
||||
// The search past a held level must take that in its stride rather than walk
|
||||
// the shared node once per route.
|
||||
f, err := New(WithoutShippedData(), WithDataPath(writeData(t, map[string]string{
|
||||
"cat": `{"format":"{p.first}|{q}","p":{"format":"{first}","first":["Anna","Bo"]},` +
|
||||
@@ -399,7 +399,7 @@ func TestReferenceToAMatchingStringIsAccepted(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNestedChoiceDrawsOneVariant(t *testing.T) {
|
||||
// A choice item may itself be a choice, so drawing a bound head unwraps until
|
||||
// A choice item may itself be a choice, so drawing a held head unwraps until
|
||||
// it reaches a value. Stopping at one level leaves a choice where the walk
|
||||
// expects a template.
|
||||
f := engine(21)
|
||||
@@ -478,7 +478,7 @@ func TestFieldWithoutAPathTokenStillDrawsEachTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTwoBoundHeadsDrawIndependently(t *testing.T) {
|
||||
func TestTwoHeldHeadsDrawIndependently(t *testing.T) {
|
||||
// Binding is per head, so two correlated sets in one format compose instead
|
||||
// of needing a cross product of variants.
|
||||
f := engine(4)
|
||||
@@ -538,7 +538,7 @@ func TestNestedTemplateKeepsItsOwnBinding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoundDrawIsSeedStable(t *testing.T) {
|
||||
func TestHeldDrawIsSeedStable(t *testing.T) {
|
||||
tmpl := places("{place.postal-code} {place.locality}")
|
||||
a := mustRender(t, engine(42), tmpl)
|
||||
b := mustRender(t, engine(42), tmpl)
|
||||
@@ -721,7 +721,7 @@ func TestCycleThroughAPathTokenIsRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoundPathIsReachableByFake(t *testing.T) {
|
||||
func TestHeldPathIsReachableByFake(t *testing.T) {
|
||||
// Binding changes how a format reads a sibling, not what List and Fake offer:
|
||||
// the sub-fields stay addressable on their own.
|
||||
dir := writeData(t, map[string]string{"address": places("{place.postal-code} {place.locality}")})
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ func TestList(t *testing.T) {
|
||||
"person": `{"format":"{first} {last}","first":"A","last":"B"}`,
|
||||
"word": `["x", "y"]`,
|
||||
"geo/city": `"Z"`,
|
||||
// A bound {/path} reference is a render edge, not an addressable field.
|
||||
// A {/path} reference is a render edge, not an addressable field.
|
||||
"greeting": `{"format":"hej {/person.first} and {own}","own":"x"}`,
|
||||
// Only the fields every variant carries are addressable, so "extra" is not.
|
||||
"coin": `[{"format":"{code}","code":"A","name":"Aa"},{"format":"{code}","code":"B","name":"Bb","extra":"x"}]`,
|
||||
|
||||
+2
-2
@@ -102,7 +102,7 @@ func TestReferenceErrors(t *testing.T) {
|
||||
"a category in a subfolder referencing itself": {"sv_SE/a": `"x{/sv_SE.a}"`},
|
||||
"mutual cycle within a subfolder": {"sv_SE/a": `"{/sv_SE.b}"`, "sv_SE/b": `"{/sv_SE.a}"`},
|
||||
"mutual cycle across two folders": {"en_US/a": `"{/sv_SE.b}"`, "sv_SE/b": `"{/en_US.a}"`},
|
||||
// ".." is reserved for bound references, so an authored key using it would
|
||||
// ".." is reserved for references, so an authored key using it would
|
||||
// name a node nothing can reach and nothing would validate.
|
||||
"field key using the reference prefix": {"cat": `{"format":"hi","..x":"{/nope}"}`},
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func TestNewErrorIsDeterministic(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestNewErrorPathIsCanonical pins the node path a load error names: a choice arm
|
||||
// adds no segment, and a bound {/path} reference is not a containment segment at
|
||||
// adds no segment, and a {/path} reference is not a containment segment at
|
||||
// all, so a bad reference is reported against the node that holds it.
|
||||
func TestNewErrorPathIsCanonical(t *testing.T) {
|
||||
cases := []struct {
|
||||
|
||||
Reference in New Issue
Block a user