func defaultNodeAdd(self Node, other types.FuObject) (types.FuObject, error) { otherlist := other.List() values := make([]types.FuObject, 0, 1+len(otherlist)) values = append(values, self) values = append(values, otherlist...) return types.MakeFuList(values...), nil }
func assertEvaluateOK( t *testing.T, rt *Runtime, expect types.FuObject, input dsl.ASTExpression) { obj, err := rt.evaluate(input) assert.Nil(t, err) if !expect.Equal(obj) { t.Errorf("expected\n%#v\nbut got\n%#v", expect, obj) } }
func assertExpand( t *testing.T, ns types.Namespace, expect []string, obj types.FuObject) { if ns == nil { ns = types.NewValueMap() } actualobj, err := obj.ActionExpand(ns, nil) assert.Nil(t, err) // convert FuList of FileNode to slice of string actualstr := make([]string, len(actualobj.List())) for i, obj := range actualobj.List() { actualstr[i] = obj.ValueString() } assert.Equal(t, expect, actualstr) }
func (self *ListNode) Add(other types.FuObject) (types.FuObject, error) { values := self.List() otherlist := other.List() result := make([]types.FuObject, len(values)+len(otherlist)) for i, obj := range values { result[i] = obj } j := len(values) for i, obj := range otherlist { if _, ok := obj.(Node); !ok { return types.UnsupportedAdd( self, other, "second operand contains "+obj.Typename()) } result[j+i] = obj } return newListNode(result...), nil }
func Test_FileNode_Add(t *testing.T) { node0 := NewFileNode("foo/bar") node1 := NewFileNode("foo/baz") obj0 := types.MakeFuString(".c") obj1 := types.MakeStringList("a", "b") var err error var expect types.FuObject var actual types.FuObject // node + node = list of nodes expect = types.MakeFuList(node0, node1) actual, err = node0.Add(node1) assert.Nil(t, err) assert.True(t, expect.Equal(actual)) // node + string = new node expect = NewFileNode("foo/bar.c") actual, err = node0.Add(obj0) assert.Nil(t, err) assert.True(t, expect.Equal(actual)) // node + list = flattened list expect = types.MakeFuList( node0, types.MakeFuString("a"), types.MakeFuString("b")) actual, err = node0.Add(obj1) assert.Nil(t, err) assert.True(t, expect.Equal(actual)) }
func Test_evaluateCall_no_expand(t *testing.T) { calls := 0 fn_foo := func(argsource types.ArgSource) (types.FuObject, []error) { calls++ return types.MakeFuString("arg: " + argsource.Args()[0].ValueString()), nil } foo := types.NewFixedFunction("foo", 1, fn_foo) rt := minimalRuntime() args := RuntimeArgs{runtime: rt} // call bar() with an arg that needs to be expanded to test that // expansion does *not* happen -- evaluateCall() doesn't know // which phase it's in, so it has to rely on someone else to // ActionExpand() each value in the build phase args.SetArgs([]types.FuObject{types.MakeFuString(">$src<")}) result, errs := rt.evaluateCall(foo, args, nil) assert.Equal(t, 1, calls) assert.Equal(t, types.MakeFuString("arg: >$src<"), result) if len(errs) != 0 { t.Errorf("expected no errors, but got: %v", errs) } // now make a value that expands to three values expansion := types.MakeStringList("a", "b", "c") var val types.FuObject = types.NewStubObject("val", expansion) valexp, _ := val.ActionExpand(nil, nil) assert.Equal(t, expansion, valexp) // this actually tests StubObject // call foo() with that expandable value, and make sure it is // really called with the unexpanded value args.SetArgs([]types.FuObject{val}) result, errs = rt.evaluateCall(foo, args, nil) assert.Equal(t, 2, calls) assert.Equal(t, types.MakeFuString("arg: val"), result) if len(errs) != 0 { t.Errorf("expected no errors, but got: %v", errs) } }
// Convert a single FuObject (possibly a FuList) to a list of Nodes and // add them to the DAG. func (self *Runtime) nodify(values types.FuObject) []dag.Node { // Blecchh: specially handling every type here limits the // extensibility of the type system. But I don't want each type to // know how it becomes a node, because then the 'types' package // depends on 'dag', which seems backwards to me. Hmmmm. var result []dag.Node switch values := values.(type) { case types.FuString: result = []dag.Node{dag.MakeFileNode(self.dag, values.ValueString())} case types.FuList: result = make([]dag.Node, 0, len(values.List())) for _, val := range values.List() { result = append(result, self.nodify(val)...) } case *dag.ListNode: result = values.Nodes() for i, node := range result { result[i] = self.dag.AddNode(node) } case dag.Node: result = []dag.Node{self.dag.AddNode(values)} } return result }
func Test_BuildRule_setLocals(t *testing.T) { targets := []dag.Node{dag.NewStubNode("foo")} sources := []dag.Node{dag.NewStubNode("bar"), dag.NewStubNode("qux")} ns := types.NewValueMap() rule := NewBuildRule(nil, targets, sources) rule.setLocals(ns) var val types.FuObject var ok bool val, ok = ns.Lookup("whatever") assert.False(t, ok) val, ok = ns.Lookup("target") assert.False(t, ok) val, ok = ns.Lookup("targets") assert.False(t, ok) val, ok = ns.Lookup("TARGET") assert.True(t, ok) assert.Equal(t, "foo", val.ValueString()) assert.Equal(t, "foo", val.(*dag.StubNode).Name()) val, ok = ns.Lookup("SOURCE") assert.True(t, ok) assert.Equal(t, "bar", val.ValueString()) assert.Equal(t, "bar", val.(*dag.StubNode).Name()) val, ok = ns.Lookup("TARGETS") assert.True(t, ok) assert.Equal(t, 1, len(val.List())) assert.Equal(t, `["foo"]`, val.String()) val, ok = ns.Lookup("SOURCES") assert.True(t, ok) assert.Equal(t, 2, len(val.List())) assert.Equal(t, `["bar", "qux"]`, val.String()) }
func Test_FinderNode_CommandString(t *testing.T) { var finder types.FuObject finder = &FinderNode{includes: []string{"*.c", "blurp/blop", "**/*.h"}} assert.Equal(t, "'*.c' blurp/blop '**/*.h'", finder.CommandString()) }
func Test_FinderNode_String(t *testing.T) { var finder types.FuObject finder = &FinderNode{includes: []string{"*.c", "**/*.h"}} assert.Equal(t, "<*.c **/*.h>", finder.String()) }