Example #1
0
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)
}
Example #2
0
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())
}
Example #3
0
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)
}
Example #4
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)
}
Example #5
0
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())
}
Example #6
0
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
}
Example #7
0
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)
}
Example #8
0
//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
}