// Copyright 2023 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 runtime_test import ( "fmt" "strconv" "testing" "cuelang.org/go/cue" "cuelang.org/go/cue/ast" "cuelang.org/go/cue/build" "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal/core/adt" "cuelang.org/go/internal/core/runtime" "cuelang.org/go/internal/cuetxtar" "cuelang.org/go/internal/value" ) func Test(t *testing.T) { test := cuetxtar.TxTarTest{ Root: "testdata/", Name: "extern", } test.Run(t, func(t *cuetxtar.Test) { inj := &injectionFake{files: map[string]int{}} ctx := cuecontext.New(cuecontext.WithInjection(inj)) b := t.Instance() v := ctx.BuildInstance(b) if err := v.Err(); err != nil { t.WriteErrors(errors.Promote(err, "test")) return } fmt.Fprintf(t, "%v\n", v) }) } type injectionFake struct { files map[string]int } func (i *injectionFake) Kind() string { return "testfn" } func (i *injectionFake) InjectorForInstance(b *build.Instance, r *runtime.Runtime) (runtime.Injector, errors.Error) { switch b.PkgName { case "failinit": return nil, errors.Newf(token.NoPos, "TEST: fail initialization") case "nullinit": return nil, nil case "scopetest": return newInjectorFake(b, r) } return i, nil } func (i *injectionFake) InjectedValue(attr *runtime.ExternAttr, _ *adt.Vertex) (adt.Expr, errors.Error) { a := attr.Attr if ok, _ := a.Flag(1, "fail"); ok { return nil, errors.Newf(token.NoPos, "TEST: fail compilation") } str, ok, err := a.Lookup(1, "err") if err != nil { return nil, errors.Promote(err, "test") } if ok { return nil, errors.Newf(token.NoPos, "%s", str) } if str, err = a.String(0); err != nil { return nil, errors.Promote(err, "test") } if _, ok := i.files[str]; !ok { i.files[str] = len(i.files) + 1 } // Derive the function name from the parent field label, // with an explicit name= attribute taking precedence. var funcName string if f, ok := attr.Parent.(*ast.Field); ok { funcName, _, _ = ast.LabelName(f.Label) } if name, ok, _ := a.Lookup(1, "name"); ok { funcName = name } return &adt.Builtin{ Name: "impl" + funcName + strconv.Itoa(i.files[str]), Params: []adt.Param{{Value: &adt.BasicType{K: adt.IntKind}}}, Result: adt.IntKind, }, nil } type injectorFake struct { runtime *runtime.Runtime b *build.Instance } func newInjectorFake(b *build.Instance, r *runtime.Runtime) (runtime.Injector, errors.Error) { return &injectorFake{ runtime: r, b: b, }, nil } func (c *injectorFake) InjectedValue(attr *runtime.ExternAttr, scope *adt.Vertex) (adt.Expr, errors.Error) { a := attr.Attr typStr, err := a.String(0) if err != nil { return nil, errors.Promote(err, "test") } call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, Func: func(call adt.BuiltinCallContext) adt.Expr { opctx := call.OpContext() cuectx := (*cue.Context)(c.runtime) scope := value.Make(opctx, scope) typ := cuectx.CompileString(typStr, cue.Scope(scope)) _, ityp := value.ToInternal(typ) return ityp }, }} return call, nil }