示例#1
0
文件: value_test.go 项目: rwen/go-ffi
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())
		}
	}
	if true {
		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())
			}
		}
	}
}
示例#2
0
文件: value_test.go 项目: rwen/go-ffi
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())
			}
		}
	}
}