Example #1
0
func TestNewSliceType(t *testing.T) {

	capSize := 2 * unsafe.Sizeof(reflect.SliceHeader{}.Cap)

	s_t, err := ffi.NewStructType("s_0", []ffi.Field{{"a", ffi.C_int32}})
	if err != nil {
		t.Errorf(err.Error())
	}

	p_s_t, err := ffi.NewPointerType(s_t)
	if err != nil {
		t.Errorf(err.Error())
	}

	for _, table := range []struct {
		name string
		elem ffi.Type
	}{
		{"uint8[]", ffi.C_uint8},
		{"uint16[]", ffi.C_uint16},
		{"uint32[]", ffi.C_uint32},
		{"uint64[]", ffi.C_uint64},
		{"int8[]", ffi.C_int8},
		{"int16[]", ffi.C_int16},
		{"int32[]", ffi.C_int32},
		{"int64[]", ffi.C_int64},

		{"float[]", ffi.C_float},
		{"double[]", ffi.C_double},

		{"s_0[]", s_t},
		{"s_0*[]", p_s_t},
	} {
		typ, err := ffi.NewSliceType(table.elem)
		if err != nil {
			t.Errorf(err.Error())
		}
		eq(t, table.name, typ.Name())
		eq(t, table.elem, typ.Elem())
		eq(t, capSize+ffi.C_pointer.Size(), typ.Size())
		//eq(t, table.n, typ.Len())
		eq(t, ffi.Slice, typ.Kind())
	}
}
Example #2
0
func TestEncoderDecoder(t *testing.T) {
	arr_10, _ := ffi.NewArrayType(10, ffi.C_int32)
	sli_10, _ := ffi.NewSliceType(ffi.C_int32)

	const sz = 10
	{
		const val = 42
		for _, v := range []interface{}{
			int(val),
			int8(val),
			int16(val),
			int32(val),
			int64(val),
		} {
			ct := ffi.TypeOf(v)
			cv := ffi.New(ct)
			enc := ffi.NewEncoder(cv)
			err := enc.Encode(v)
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, int64(val), cv.Int())

			// now decode back
			vv := reflect.New(reflect.TypeOf(v))
			dec := ffi.NewDecoder(cv)
			err = dec.Decode(vv.Interface())
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, vv.Elem().Int(), cv.Int())
		}
	}

	{
		const val = 42
		for _, v := range []interface{}{
			uint(val),
			uint8(val),
			uint16(val),
			uint32(val),
			uint64(val),
		} {
			ct := ffi.TypeOf(v)
			cv := ffi.New(ct)
			enc := ffi.NewEncoder(cv)
			err := enc.Encode(v)
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, uint64(val), cv.Uint())

			// now decode back
			vv := reflect.New(reflect.TypeOf(v))
			dec := ffi.NewDecoder(cv)
			err = dec.Decode(vv.Interface())
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, vv.Elem().Uint(), cv.Uint())
		}
	}
	{
		const val = 42.0
		for _, v := range []interface{}{
			float32(val),
			float64(val),
		} {
			ct := ffi.TypeOf(v)
			cv := ffi.New(ct)
			enc := ffi.NewEncoder(cv)
			err := enc.Encode(v)
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, float64(val), cv.Float())

			// now decode back
			vv := reflect.New(reflect.TypeOf(v))
			dec := ffi.NewDecoder(cv)
			err = dec.Decode(vv.Interface())
			if err != nil {
				t.Errorf(err.Error())
			}
			eq(t, vv.Elem().Float(), cv.Float())
		}
	}
	{
		const val = 42
		ctyp, err := ffi.NewStructType(
			"struct_ints",
			[]ffi.Field{
				{"F1", ffi.C_int8},
				{"F2", ffi.C_int16},
				{"F3", ffi.C_int32},
				{"F4", ffi.C_int64},
			})
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.New(ctyp)
		gval := struct {
			F1 int8
			F2 int16
			F3 int32
			F4 int64
		}{val + 1, val + 1, val + 1, val + 1}
		err = ffi.Associate(ctyp, reflect.TypeOf(gval))
		if err != nil {
			t.Errorf(err.Error())
		}

		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}

		rval := reflect.ValueOf(gval)
		for i := 0; i < ctyp.NumField(); i++ {
			eq(t, rval.Field(i).Int(), cval.Field(i).Int())
		}

		// now decode back
		vv := reflect.New(rval.Type())
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		rval = vv.Elem()
		for i := 0; i < ctyp.NumField(); i++ {
			eq(t, rval.Field(i).Int(), cval.Field(i).Int())
		}
	}
	{
		const val = 42
		ctyp, err := ffi.NewStructType(
			"struct_ints_arr10",
			[]ffi.Field{
				{"F1", ffi.C_int8},
				{"F2", ffi.C_int16},
				{"A1", arr_10},
				{"F3", ffi.C_int32},
				{"F4", ffi.C_int64},
			})
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.New(ctyp)
		gval := struct {
			F1 int8
			F2 int16
			A1 [sz]int32
			F3 int32
			F4 int64
		}{
			val + 1, val + 1,
			[sz]int32{
				val, val, val, val, val,
				val, val, val, val, val,
			},
			val + 1, val + 1,
		}
		err = ffi.Associate(ctyp, reflect.TypeOf(gval))
		if err != nil {
			t.Errorf(err.Error())
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}

		rval := reflect.ValueOf(gval)
		eq(t, rval.Field(0).Int(), cval.Field(0).Int())
		eq(t, rval.Field(1).Int(), cval.Field(1).Int())
		eq(t, rval.Field(3).Int(), cval.Field(3).Int())
		eq(t, rval.Field(4).Int(), cval.Field(4).Int())
		rfield := cval.Field(2)
		cfield := cval.Field(2)
		eq(t, rfield.Len(), cfield.Len())
		for i := 0; i < cfield.Len(); i++ {
			eq(t, rfield.Index(i).Int(), cfield.Index(i).Int())
		}

		// now decode back
		vv := reflect.New(rval.Type())
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		rval = vv.Elem()
		eq(t, rval.Field(0).Int(), cval.Field(0).Int())
		eq(t, rval.Field(1).Int(), cval.Field(1).Int())
		eq(t, rval.Field(3).Int(), cval.Field(3).Int())
		eq(t, rval.Field(4).Int(), cval.Field(4).Int())
		rfield = cval.Field(2)
		cfield = cval.Field(2)
		eq(t, rfield.Len(), cfield.Len())
		for i := 0; i < cfield.Len(); i++ {
			eq(t, rfield.Index(i).Int(), cfield.Index(i).Int())
		}
	}
	{
		const val = 42
		ctyp, err := ffi.NewStructType(
			"struct_ints_sli10",
			[]ffi.Field{
				{"F1", ffi.C_int8},
				{"F2", ffi.C_int16},
				{"S1", sli_10},
				{"F3", ffi.C_int32},
				{"F4", ffi.C_int64},
			})
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.New(ctyp)
		gval := struct {
			F1 int8
			F2 int16
			S1 []int32
			F3 int32
			F4 int64
		}{
			val + 1, val + 1,
			[]int32{
				val, val, val, val, val,
				val, val, val, val, val,
			},
			val + 1, val + 1,
		}
		err = ffi.Associate(ctyp, reflect.TypeOf(gval))
		if err != nil {
			t.Errorf(err.Error())
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}

		rval := reflect.ValueOf(gval)
		eq(t, rval.Field(0).Int(), cval.Field(0).Int())
		eq(t, rval.Field(1).Int(), cval.Field(1).Int())
		eq(t, rval.Field(3).Int(), cval.Field(3).Int())
		eq(t, rval.Field(4).Int(), cval.Field(4).Int())
		rfield := cval.Field(2)
		cfield := cval.Field(2)
		eq(t, rfield.Len(), cfield.Len())
		for i := 0; i < cfield.Len(); i++ {
			eq(t, rfield.Index(i).Int(), cfield.Index(i).Int())
		}

		// now decode back
		vv := reflect.New(rval.Type())
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		rval = vv.Elem()
		eq(t, rval.Field(0).Int(), cval.Field(0).Int())
		eq(t, rval.Field(1).Int(), cval.Field(1).Int())
		eq(t, rval.Field(3).Int(), cval.Field(3).Int())
		eq(t, rval.Field(4).Int(), cval.Field(4).Int())
		rfield = cval.Field(2)
		cfield = cval.Field(2)
		eq(t, rfield.Len(), cfield.Len())
		for i := 0; i < cfield.Len(); i++ {
			eq(t, rfield.Index(i).Int(), cfield.Index(i).Int())
		}
	}
	{
		const val = 42
		ctyp, err := ffi.NewArrayType(sz, ffi.C_int32)
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.New(ctyp)
		gval := [sz]int32{
			val, val, val, val, val,
			val, val, val, val, val,
		}
		err = ffi.Associate(ctyp, reflect.TypeOf(gval))
		if err != nil {
			t.Errorf(err.Error())
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Type().Len(); i++ {
			eq(t, int64(val), cval.Index(i).Int())
		}

		// now decode back
		vv := reflect.New(reflect.TypeOf(gval))
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Type().Len(); i++ {
			eq(t, vv.Elem().Index(i).Int(), cval.Index(i).Int())
		}

	}

	{
		const val = 42
		ctyp, err := ffi.NewArrayType(sz, ffi.C_float)
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.New(ctyp)
		gval := [sz]float32{
			val, val, val, val, val,
			val, val, val, val, val,
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Type().Len(); i++ {
			eq(t, float64(val), cval.Index(i).Float())
		}
		// now decode back
		vv := reflect.New(reflect.TypeOf(gval))
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Type().Len(); i++ {
			eq(t, vv.Elem().Index(i).Float(), cval.Index(i).Float())
		}

	}

	{
		const val = 42
		ctyp, err := ffi.NewSliceType(ffi.C_int32)
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.MakeSlice(ctyp, sz, sz)
		gval := []int32{
			val, val, val, val, val,
			val, val, val, val, val,
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Len(); i++ {
			eq(t, int64(val), cval.Index(i).Int())
		}
		// now decode back
		vv := reflect.New(reflect.TypeOf(gval))
		dec := ffi.NewDecoder(cval)
		err = dec.Decode(vv.Interface())
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Len(); i++ {
			eq(t, vv.Elem().Index(i).Int(), cval.Index(i).Int())
		}
	}
	{
		const val = 42
		ctyp, err := ffi.NewSliceType(ffi.C_float)
		if err != nil {
			t.Errorf(err.Error())
		}
		cval := ffi.MakeSlice(ctyp, sz, sz)
		gval := []float32{
			val, val, val, val, val,
			val, val, val, val, val,
		}
		enc := ffi.NewEncoder(cval)
		err = enc.Encode(gval)
		if err != nil {
			t.Errorf(err.Error())
		}
		for i := 0; i < cval.Len(); i++ {
			eq(t, float64(val), cval.Index(i).Float())
		}
		{
			// now decode back
			vv := reflect.New(reflect.TypeOf(gval))
			dec := ffi.NewDecoder(cval)
			err = dec.Decode(vv.Interface())
			if err != nil {
				t.Errorf(err.Error())
			}
			for i := 0; i < cval.Len(); i++ {
				eq(t, vv.Elem().Index(i).Float(), cval.Index(i).Float())
			}
		}
	}
}
Example #3
0
func TestGetSetSliceValue(t *testing.T) {

	const sz = 10
	{
		const val = 42
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"uint8[]", ffi.C_uint8, make([]uint8, sz)},
			{"uint16[]", ffi.C_uint16, make([]uint16, sz)},
			{"uint32[]", ffi.C_uint32, make([]uint32, sz)},
			{"uint64[]", ffi.C_uint64, make([]uint64, sz)},
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, sz, sz)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, gval.Len(), cval.Len())
			eq(t, int(sz), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Uint(), cval.Index(i).Uint())
				gval.Index(i).SetUint(val)
				cval.Index(i).SetUint(val)
				eq(t, gval.Index(i).Uint(), cval.Index(i).Uint())
			}
		}
	}

	{
		const val = 42
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"int8[]", ffi.C_int8, make([]int8, sz)},
			{"int16[]", ffi.C_int16, make([]int16, sz)},
			{"int32[]", ffi.C_int32, make([]int32, sz)},
			{"int64[]", ffi.C_int64, make([]int64, sz)},
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, sz, sz)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, gval.Len(), cval.Len())
			eq(t, int(sz), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Int(), cval.Index(i).Int())
				gval.Index(i).SetInt(val)
				cval.Index(i).SetInt(val)
				eq(t, gval.Index(i).Int(), cval.Index(i).Int())
			}
		}
	}

	{
		const val = -66.2
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"float[]", ffi.C_float, make([]float32, sz)},
			{"double[]", ffi.C_double, make([]float64, sz)},
			// FIXME: go has no long double equivalent
			//{"long double[]", ffi.C_longdouble, make([]float128, sz)}
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, sz, sz)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, gval.Len(), cval.Len())
			eq(t, int(sz), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Float(), cval.Index(i).Float())
				gval.Index(i).SetFloat(val)
				cval.Index(i).SetFloat(val)
				eq(t, gval.Index(i).Float(), cval.Index(i).Float())
			}
		}
	}

	// now test if slices can automatically grow...
	{
		const val = 42
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"uint8[]", ffi.C_uint8, make([]uint8, sz)},
			{"uint16[]", ffi.C_uint16, make([]uint16, sz)},
			{"uint32[]", ffi.C_uint32, make([]uint32, sz)},
			{"uint64[]", ffi.C_uint64, make([]uint64, sz)},
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, 0, 0)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, int(0), cval.Len())
			cval.SetValue(gval) // <---------
			eq(t, int(sz), cval.Len())
			eq(t, gval.Len(), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Uint(), cval.Index(i).Uint())
				gval.Index(i).SetUint(val)
				cval.Index(i).SetUint(val)
				eq(t, gval.Index(i).Uint(), cval.Index(i).Uint())
			}
		}
	}

	{
		const val = 42
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"int8[]", ffi.C_int8, make([]int8, sz)},
			{"int16[]", ffi.C_int16, make([]int16, sz)},
			{"int32[]", ffi.C_int32, make([]int32, sz)},
			{"int64[]", ffi.C_int64, make([]int64, sz)},
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, 0, 0)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, int(0), cval.Len())
			cval.SetValue(gval) // <---------
			eq(t, int(sz), cval.Len())
			eq(t, gval.Len(), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Int(), cval.Index(i).Int())
				gval.Index(i).SetInt(val)
				cval.Index(i).SetInt(val)
				eq(t, gval.Index(i).Int(), cval.Index(i).Int())
			}
		}
	}

	{
		const val = -66.2
		for _, tt := range []struct {
			n   string
			t   ffi.Type
			val interface{}
		}{
			{"float[]", ffi.C_float, make([]float32, sz)},
			{"double[]", ffi.C_double, make([]float64, sz)},
			// FIXME: go has no long double equivalent
			//{"long double[]", ffi.C_longdouble, make([]float128, sz)}
		} {
			ctyp, err := ffi.NewSliceType(tt.t)
			if err != nil {
				t.Errorf(err.Error())
			}
			cval := ffi.MakeSlice(ctyp, 0, 0)
			eq(t, tt.n, cval.Type().Name())
			eq(t, ctyp.Kind(), cval.Kind())
			gtyp := reflect.TypeOf(tt.val)
			gval := reflect.MakeSlice(gtyp, sz, sz)
			eq(t, int(0), cval.Len())
			cval.SetValue(gval) // <---------
			eq(t, int(sz), cval.Len())
			eq(t, gval.Len(), cval.Len())
			for i := 0; i < gval.Len(); i++ {
				eq(t, gval.Index(i).Float(), cval.Index(i).Float())
				gval.Index(i).SetFloat(val)
				cval.Index(i).SetFloat(val)
				eq(t, gval.Index(i).Float(), cval.Index(i).Float())
			}
		}
	}
}
Example #4
0
func TestGetSetStructWithSliceValue(t *testing.T) {

	const val = 42
	arr10, err := ffi.NewArrayType(10, ffi.C_int32)
	if err != nil {
		t.Errorf(err.Error())
	}
	slityp, err := ffi.NewSliceType(ffi.C_int32)
	if err != nil {
		t.Errorf(err.Error())
	}

	ctyp, err := ffi.NewStructType(
		"struct_sswsv",
		[]ffi.Field{
			{"F1", ffi.C_uint16},
			{"F2", arr10},
			{"F3", ffi.C_int32},
			{"F4", ffi.C_uint16},
			{"F5", slityp},
		})
	eq(t, "struct_sswsv", ctyp.Name())
	eq(t, ffi.Struct, ctyp.Kind())
	eq(t, 5, ctyp.NumField())

	cval := ffi.New(ctyp)
	eq(t, ctyp.Kind(), cval.Kind())
	eq(t, ctyp.NumField(), cval.NumField())
	eq(t, uint64(0), cval.Field(0).Uint())
	for i := 0; i < arr10.Len(); i++ {
		eq(t, int64(0), cval.Field(1).Index(i).Int())
	}
	eq(t, int64(0), cval.Field(2).Int())
	eq(t, uint64(0), cval.Field(3).Uint())
	eq(t, int(0), cval.Field(4).Len())
	eq(t, int(0), cval.Field(4).Len())

	goval := struct {
		F1 uint16
		F2 [10]int32
		F3 int32
		F4 uint16
		F5 []int32
	}{
		F1: val,
		F2: [10]int32{val, val, val, val, val,
			val, val, val, val, val},
		F3: val,
		F4: val,
		F5: make([]int32, 2, 3),
	}
	goval.F5[0] = val
	goval.F5[1] = val

	cval.SetValue(reflect.ValueOf(goval))

	eq(t, uint64(val), cval.Field(0).Uint())
	for i := 0; i < arr10.Len(); i++ {
		eq(t, int64(val), cval.Field(1).Index(i).Int())
	}
	eq(t, int64(val), cval.Field(2).Int())
	eq(t, uint64(val), cval.Field(3).Uint())
	eq(t, int(2), cval.Field(4).Len())
	// FIXME: should we get the 'cap' from go ?
	eq(t, int( /*3*/ 2), cval.Field(4).Cap())
	eq(t, int64(val), cval.Field(4).Index(0).Int())
	eq(t, int64(val), cval.Field(4).Index(1).Int())
}