github.com/k14s/starlark-go@v0.0.0-20200720175618-3a5c849cc368/starlarkstruct/struct_test.go (about) 1 // Copyright 2018 The Bazel Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package starlarkstruct_test 6 7 import ( 8 "fmt" 9 "path/filepath" 10 "testing" 11 12 "github.com/k14s/starlark-go/resolve" 13 "github.com/k14s/starlark-go/starlark" 14 "github.com/k14s/starlark-go/starlarkstruct" 15 "github.com/k14s/starlark-go/starlarktest" 16 ) 17 18 func init() { 19 // The tests make extensive use of these not-yet-standard features. 20 resolve.AllowLambda = true 21 resolve.AllowNestedDef = true 22 resolve.AllowFloat = true 23 resolve.AllowSet = true 24 } 25 26 func Test(t *testing.T) { 27 testdata := starlarktest.DataFile("starlarkstruct", ".") 28 thread := &starlark.Thread{Load: load} 29 starlarktest.SetReporter(thread, t) 30 filename := filepath.Join(testdata, "testdata/struct.star") 31 predeclared := starlark.StringDict{ 32 "struct": starlark.NewBuiltin("struct", starlarkstruct.Make), 33 "gensym": starlark.NewBuiltin("gensym", gensym), 34 } 35 if _, err := starlark.ExecFile(thread, filename, nil, predeclared); err != nil { 36 if err, ok := err.(*starlark.EvalError); ok { 37 t.Fatal(err.Backtrace()) 38 } 39 t.Fatal(err) 40 } 41 } 42 43 // load implements the 'load' operation as used in the evaluator tests. 44 func load(thread *starlark.Thread, module string) (starlark.StringDict, error) { 45 if module == "assert.star" { 46 return starlarktest.LoadAssertModule() 47 } 48 return nil, fmt.Errorf("load not implemented") 49 } 50 51 // gensym is a built-in function that generates a unique symbol. 52 func gensym(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 53 var name string 54 if err := starlark.UnpackArgs("gensym", args, kwargs, "name", &name); err != nil { 55 return nil, err 56 } 57 return &symbol{name: name}, nil 58 } 59 60 // A symbol is a distinct value that acts as a constructor of "branded" 61 // struct instances, like a class symbol in Python or a "provider" in Bazel. 62 type symbol struct{ name string } 63 64 var _ starlark.Callable = (*symbol)(nil) 65 66 func (sym *symbol) Name() string { return sym.name } 67 func (sym *symbol) String() string { return sym.name } 68 func (sym *symbol) Type() string { return "symbol" } 69 func (sym *symbol) Freeze() {} // immutable 70 func (sym *symbol) Truth() starlark.Bool { return starlark.True } 71 func (sym *symbol) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", sym.Type()) } 72 73 func (sym *symbol) CallInternal(thread *starlark.Thread, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 74 if len(args) > 0 { 75 return nil, fmt.Errorf("%s: unexpected positional arguments", sym) 76 } 77 return starlarkstruct.FromKeywords(sym, kwargs), nil 78 }