// Copyright 2021 CUE Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cue_test import ( "bytes" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/diff" "golang.org/x/tools/txtar" ) func TestLookupPath(t *testing.T) { r := &cue.Runtime{} testCases := []struct { in string path cue.Path out string `test:"update"` // :nerdSnipe: err string `test:"update"` // :nerdSnipe: }{{ in: ` #V: { x: int } #X: { [string]: int64 } & #V v: #X `, path: cue.ParsePath("v.x"), out: `int64`, }, { in: `#foo: 3`, path: cue.ParsePath("#foo"), out: `3`, }, { in: `_foo: 3`, path: cue.MakePath(cue.Def("_foo")), err: `field not found: #_foo`, }, { in: `_#foo: 3`, path: cue.MakePath(cue.Def("_#foo")), err: `field not found: _#foo`, }, { in: `"foo", #foo: 3`, path: cue.ParsePath("#foo"), out: `3`, }, { in: ` a: [...int] `, path: cue.MakePath(cue.Str("a"), cue.AnyIndex), out: `int`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.AnyString, cue.Str("a")), out: `string`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.Str("b").Optional(), cue.Str("a")), out: `"b"`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.AnyString), out: `{a: string}`, }, { in: ` a: [Foo=string]: [Bar=string]: { b: Foo+Bar } `, path: cue.MakePath(cue.Str("a"), cue.Str("b"), cue.Str("c")).Optional(), out: `{b: "bc"}`, }, { in: ` a: [Foo=string]: b: [Bar=string]: { c: Foo } a: foo: b: [Bar=string]: { d: Bar } `, path: cue.MakePath(cue.Str("a"), cue.Str("foo"), cue.Str("b"), cue.AnyString), out: `{c: "foo", d: string}`, }, { in: ` [Name=string]: { a: Name } `, path: cue.MakePath(cue.Str("a")), err: `field not found: a`, }} for _, tc := range testCases { t.Run(tc.path.String(), func(t *testing.T) { v := compileT(t, r, tc.in) v = v.LookupPath(tc.path) if err := v.Err(); err != nil || tc.err != "" { if got := err.Error(); got != tc.err { t.Errorf("error: got %v; want %v", got, tc.err) } } if exists := v.Exists(); exists != (tc.err == "") { t.Fatalf("exists: got %v; want: %v", exists, tc.err == "") } else if !exists { return } w := compileT(t, r, tc.out) if k, d := diff.Diff(v, w); k != diff.Identity { b := &bytes.Buffer{} diff.Print(b, d) t.Error(b) } }) } } func compileT(t *testing.T, r *cue.Runtime, s string) cue.Value { t.Helper() inst, err := r.Compile("", s) if err != nil { t.Fatal(err) } return inst.Value() } func TestHidden(t *testing.T) { in := ` -- cue.mod/module.cue -- module: "mod.test" -- in.cue -- import "mod.test/foo" a: foo.C b: _c _c: 2 -- foo/foo.cue -- package foo C: _d _d: 3 ` a := txtar.Parse([]byte(in)) instance := cuetxtar.Load(a, t.TempDir())[0] if instance.Err != nil { t.Fatal(instance.Err) } v := cuecontext.New().BuildInstance(instance) testCases := []struct { path cue.Path pkg string }{{ path: cue.ParsePath("a"), pkg: "mod.test/foo", }, { path: cue.ParsePath("b"), pkg: "_", }} for _, tc := range testCases { t.Run(tc.path.String(), func(t *testing.T) { v := v.LookupPath(tc.path) p := cue.Dereference(cue.Dereference(v)).Path().Selectors() if got := p[len(p)-1].PkgPath(); got != tc.pkg { t.Errorf("got %v; want %v", got, tc.pkg) } }) } }