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()) } }
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()) } } } }
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()) } } } }
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()) }