func Test_PythonCallable_callPython(t *testing.T) { plugin, err := NewPythonPlugin() testutils.NoError(t, err) // Setup: define a Python function and make sure that Run() finds // it, so it can be added to a Fubsy namespace and used from Fubsy // code. pycode := ` def reverse_strings(*args): '''takes N strings, reverses each one, then returns the reversed strings concatenated into a single string with + between each one''' return '+'.join(''.join(reversed(arg)) for arg in args)` values, err := plugin.Run(pycode) testutils.NoError(t, err) value, ok := values.Lookup("reverse_strings") assert.True(t, ok) pycallable := value.(PythonCallable) assert.Equal(t, "reverse_strings", pycallable.Name()) // Call the Python function with 3 strings. args := types.MakeStringList("foo", "blob", "pingpong").List() argsource := types.MakeBasicArgs(nil, args, nil) value, errs := pycallable.callPython(argsource) testutils.NoErrors(t, errs) // And test the returned value. expect := types.MakeFuString("oof+bolb+gnopgnip") assert.True(t, expect.Equal(value), "expected %s, but got %s", expect, value) }
func Test_mkdir(t *testing.T) { cleanup := testutils.Chtemp() defer cleanup() // mkdir() happily accepts an empty argument list, to allow for // cases where a user-defined list becomes the arg list, and it // just happens to be empty pargs := []types.FuObject{} args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, pargs, nil), } result, errs := fn_mkdir(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) assert.Equal(t, []string{}, dirContents(".")) // easiest case: create a single dir pargs = types.MakeStringList("foo").List() args.SetArgs(pargs) result, errs = fn_mkdir(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) assert.Equal(t, []string{"foo"}, dirContents(".")) assert.True(t, isDir("foo")) // create multiple dirs, including "foo" which already exists pargs = types.MakeStringList("meep/meep/meep", "foo", "meep/beep").List() args.SetArgs(pargs) result, errs = fn_mkdir(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) assert.Equal(t, []string{"foo", "meep"}, dirContents(".")) assert.True(t, isDir("foo")) assert.True(t, isDir("meep/meep")) assert.True(t, isDir("meep/meep/meep")) assert.True(t, isDir("meep/beep")) // now with an error in the middle of the list (*but* we still // create the other requested dirs!) testutils.TouchFiles("meep/zap") pargs = types.MakeStringList("meep/bap", "meep/zap/zip", "foo/bar").List() args.SetArgs(pargs) result, errs = fn_mkdir(args) assert.Nil(t, result) assert.Equal(t, 1, len(errs)) assert.Equal(t, "mkdir meep/zap: not a directory", errs[0].Error()) assert.True(t, isDir("meep/bap")) assert.True(t, isDir("foo/bar")) // finally, with multiple errors pargs = append(pargs, types.MakeFuString("meep/zap/blop")) args.SetArgs(pargs) result, errs = fn_mkdir(args) assert.Nil(t, result) assert.Equal(t, 2, len(errs)) assert.Equal(t, "mkdir meep/zap: not a directory", errs[0].Error()) assert.Equal(t, "mkdir meep/zap: not a directory", errs[1].Error()) }
func Test_println(t *testing.T) { cleanup1 := testutils.Chtemp() defer cleanup1() rfile, err := os.Create("stdout") if err != nil { panic(err) } // save a copy of stdout in another fd stdout_fd := int(os.Stdout.Fd()) save_stdout, err := syscall.Dup(stdout_fd) if err != nil { panic(err) } // redirect stdout to rfile err = syscall.Dup2(int(rfile.Fd()), stdout_fd) if err != nil { panic(err) } cleanup2 := func() { rfile.Close() err = syscall.Dup2(save_stdout, stdout_fd) if err != nil { panic(err) } syscall.Close(save_stdout) } defer cleanup2() args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, []types.FuObject{}, nil), } result, errs := fn_println(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) data, err := ioutil.ReadFile("stdout") assert.Nil(t, err) assert.Equal(t, "\n", string(data)) rfile.Truncate(0) rfile.Seek(0, 0) args.SetArgs(types.MakeStringList("hello", "world").List()) fn_println(args) data, err = ioutil.ReadFile("stdout") assert.Nil(t, err) assert.Equal(t, "hello world\n", string(data)) rfile.Truncate(0) rfile.Seek(0, 0) }
func Test_ActionNode(t *testing.T) { args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, types.MakeStringList("test/x").List(), nil), runtime: minimalRuntime(), } node0, errs := fn_ActionNode(args) assert.Equal(t, 0, len(errs)) _ = node0.(*dag.ActionNode) assert.Equal(t, "test/x:action", node0.ValueString()) assert.Equal(t, "test/x:action", node0.(dag.Node).Name()) node1, errs := fn_ActionNode(args) assert.True(t, node0 == node1) }
func Test_remove(t *testing.T) { cleanup := testutils.Chtemp() defer cleanup() args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, []types.FuObject{}, nil), } // remove() doesn't care about empty arg list (same reason as mkdir()) result, errs := fn_remove(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) // remove() ignores non-existent files args.SetArgs(types.MakeStringList("foo", "bar/bleep/meep", "qux").List()) result, errs = fn_remove(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) // remove() removes regular files testutils.TouchFiles("foo", "bar/bleep/meep", "bar/bleep/feep", "qux") args.SetArgs(types.MakeStringList("foo", "bar/bleep/meep", "bogus").List()) result, errs = fn_remove(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) assert.Equal(t, []string{"bar", "qux"}, dirContents(".")) assert.Equal(t, []string{"bleep"}, dirContents("bar")) assert.Equal(t, []string{"feep"}, dirContents("bar/bleep")) // remove() removes files and directories too testutils.TouchFiles("foo", "bar/bleep/meep", "qux") args.SetArgs(types.MakeStringList("bogus", "bar", "morebogus", "qux").List()) result, errs = fn_remove(args) assert.Nil(t, result) assert.Equal(t, 0, len(errs)) assert.Equal(t, []string{"foo"}, dirContents(".")) // remove() fails if it tries to delete from an unwriteable directory testutils.TouchFiles("bar/bong", "qux/bip") testutils.ChmodRO("bar") defer testutils.ChmodOwnerAll("bar") args.SetArgs(types.MakeStringList("bar", "qux").List()) result, errs = fn_remove(args) assert.Nil(t, result) assert.Equal(t, "remove bar/bong: permission denied", errs[0].Error()) }
func (self *Runtime) expandArgs(argsource RuntimeArgs) (RuntimeArgs, []error) { var errs []error var err error // XXX ignoring kwargs args := argsource.Args() xargs := make([]types.FuObject, len(args)) for i, arg := range args { xargs[i], err = arg.ActionExpand(self.stack, nil) if err != nil { errs = append(errs, err) } } result := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(argsource.Receiver(), xargs, nil), runtime: argsource.runtime, } return result, errs }
func Test_FileNode(t *testing.T) { args := RuntimeArgs{ BasicArgs: types.MakeBasicArgs(nil, types.MakeStringList("a.txt").List(), nil), runtime: minimalRuntime(), } node0, errs := fn_FileNode(args) assert.Equal(t, 0, len(errs)) node1, errs := fn_FileNode(args) assert.Equal(t, 0, len(errs)) // panic on unexpected type _ = node0.(*dag.FileNode) _ = node1.(*dag.FileNode) assert.Equal(t, "a.txt", node0.(dag.Node).Name()) assert.True(t, node0.Equal(node1)) // FileNode is a factory: it will return existing node objects // rather than create new ones assert.True(t, node0 == node1) }
//export callBuiltin func callBuiltin( pfunc unsafe.Pointer, numargs C.int, cargs unsafe.Pointer) ( *C.char, *C.char) { log.Debug(log.PLUGINS, "callBuiltin: calling Go function at %p", pfunc) var fn types.FuCode fuargs := make([]types.FuObject, numargs) for i := uintptr(0); i < uintptr(numargs); i++ { // cargs is really a C char **, i.e. a pointer to an array of // char *. argp is a pointer to the i'th member of cargs. This // is just C-style array lookup with pointer arithmetic, but // in Go syntax. argp := unsafe.Pointer(uintptr(cargs) + i*unsafe.Sizeof(cargs)) arg := C.GoString(*(**C.char)(argp)) fuargs[i] = types.MakeFuString(arg) } args := types.MakeBasicArgs(nil, fuargs, nil) fn = *(*types.FuCode)(unsafe.Pointer(&pfunc)) log.Debug(log.PLUGINS, "followed unsafe.Pointer to get %p", fn) result, err := fn(args) if len(err) > 0 { errmsgs := make([]string, len(err)) for i, err := range err { errmsgs[i] = err.Error() } return nil, C.CString(strings.Join(errmsgs, "\n")) } var cresult *C.char if result != nil { cresult = C.CString(result.String()) } return cresult, nil }