cue: allow Len for invalid objects
Fixes #51.
Change-Id: I64cd6e782c8806724590fc4073ef8b7eb0c7affa
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2181
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/types.go b/cue/types.go
index a4a5c85..75637da 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -80,6 +80,9 @@
// Len reports the number of fields in this struct.
func (o *structValue) Len() int {
+ if o.n == nil {
+ return 0
+ }
return len(o.n.arcs)
}
@@ -95,12 +98,13 @@
func (o *structValue) Lookup(key string) Value {
f := o.ctx.strLabel(key)
i := 0
- for ; i < len(o.n.arcs); i++ {
+ len := o.Len()
+ for ; i < len; i++ {
if o.n.arcs[i].feature == f {
break
}
}
- if i == len(o.n.arcs) {
+ if i == len {
// TODO: better message.
return newValueRoot(o.ctx, o.ctx.mkErr(o.n, codeNotExist,
"value %q not found", key))
diff --git a/cue/types_test.go b/cue/types_test.go
index 895df3c..4df1cc3 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -993,6 +993,67 @@
}
}
+func TestValidate(t *testing.T) {
+ testCases := []struct {
+ desc string
+ in string
+ err bool
+ opts []Option
+ }{{
+ desc: "issue #51",
+ in: `
+ a <Name>: foo
+ a b: {}
+ `,
+ err: true,
+ }, {
+ desc: "concrete",
+ in: `
+ a: 1
+ b: { c: 2, d: 3 }
+ c d e f: 5
+ `,
+ opts: []Option{Concrete(true)},
+ }, {
+ desc: "disjunction",
+ in: `a: 1 | 2`,
+ }, {
+ desc: "disjunction concrete",
+ in: `a: 1 | 2`,
+ opts: []Option{Concrete(true)},
+ err: true,
+ }, {
+ desc: "incomplete concrete",
+ in: `a: string`,
+ }, {
+ desc: "incomplete",
+ in: `a: string`,
+ opts: []Option{Concrete(true)},
+ err: true,
+ }, {
+ desc: "list",
+ in: `a: [{b: string}, 3]`,
+ }, {
+ desc: "list concrete",
+ in: `a: [{b: string}, 3]`,
+ opts: []Option{Concrete(true)},
+ err: true,
+ }}
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ r := Runtime{}
+ inst, err := r.Parse("validate", tc.in)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = inst.Value().Validate(tc.opts...)
+ if gotErr := err != nil; gotErr != tc.err {
+ t.Errorf("got %v; want %v", err, tc.err)
+ }
+ })
+ }
+}
+
func TestValueLookup(t *testing.T) {
config := `
a: {