// Copyright 2020 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 dep_test import ( "fmt" "io" "strings" "testing" "text/tabwriter" "cuelang.org/go/cue" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/debug" "cuelang.org/go/internal/core/dep" "cuelang.org/go/internal/core/eval" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/value" ) type visitFunc func(*adt.OpContext, *adt.ImportReference, *adt.Vertex, dep.VisitFunc) error func TestVisit(t *testing.T) { test := cuetxtar.TxTarTest{ Root: "./testdata", Name: "dependencies", } test.Run(t, func(t *cuetxtar.Test) { val := cuecontext.New().BuildInstance(t.Instance()) if val.Err() != nil { t.Fatal(val.Err()) } ctxt := eval.NewContext(value.ToInternal(val)) testCases := []struct { name string root string cfg *dep.Config }{{ name: "field", root: "a.b", cfg: nil, }, { name: "all", root: "a", cfg: &dep.Config{Descend: true}, }, { name: "dynamic", root: "a", cfg: &dep.Config{Dynamic: true}, }} for _, tc := range testCases { v := val.LookupPath(cue.ParsePath(tc.root)) _, n := value.ToInternal(v) w := t.Writer(tc.name) t.Run(tc.name, func(sub *testing.T) { testVisit(sub, w, ctxt, n, tc.cfg) }) } }) } func testVisit(t *testing.T, w io.Writer, ctxt *adt.OpContext, v *adt.Vertex, cfg *dep.Config) { t.Helper() tw := tabwriter.NewWriter(w, 0, 4, 1, ' ', 0) defer tw.Flush() fmt.Fprintf(tw, "line \vreference\v path of resulting vertex\n") dep.Visit(cfg, ctxt, v, func(d dep.Dependency) error { if d.Reference == nil { t.Fatal("no reference") } src := d.Reference.Source() line := src.Pos().Line() b, _ := format.Node(src) ref := string(b) str := value.Make(ctxt, d.Node).Path().String() if i := d.Import(); i != nil { path := i.ImportPath.StringValue(ctxt) str = fmt.Sprintf("%q.%s", path, str) } else if !d.Node.Rooted() { str = "**non-rooted**" } fmt.Fprintf(tw, "%d:\v%s\v=> %s\n", line, ref, str) return nil }) } // DO NOT REMOVE: for Testing purposes. func TestX(t *testing.T) { cfg := &dep.Config{ Dynamic: true, // Recurse: true, } in := ` ` if strings.TrimSpace(in) == "" { t.Skip() } rt := cue.Runtime{} inst, err := rt.Compile("", in) if err != nil { t.Fatal(err) } v := inst.Lookup("a") r, n := value.ToInternal(v) ctxt := eval.NewContext(r, n) for _, c := range n.Conjuncts { str := debug.NodeString(ctxt, c.Elem(), nil) t.Log(str) } w := &strings.Builder{} fmt.Fprintln(w) testVisit(t, w, ctxt, n, cfg) t.Error(w.String()) }