Permalink
Browse files

unmap struct with slices, prepare for full un/map testing

  • Loading branch information...
1 parent 62692ca commit 42a6efb297118aea316ec89ba86e423d7b5f927b @carloscm committed Mar 21, 2012
Showing with 78 additions and 52 deletions.
  1. +39 −25 src/gossie/struct.go
  2. +39 −27 src/gossie/struct_test.go
View
@@ -377,10 +377,10 @@ func Unmap(row *Row, destination interface{}) os.Error {
// always work with a pointer to struct
vp := reflect.ValueOf(destination)
if vp.Kind() != reflect.Ptr {
- return os.NewError("Passed destination is not a pointer to a struct")
+ return os.NewError("Passed destination is not a pointer")
}
if vp.IsNil() {
- return os.NewError("Passed destination is not a pointer to a struct")
+ return os.NewError("Passed destination is a nil pointer")
}
v := reflect.Indirect(vp)
if v.Kind() != reflect.Struct {
@@ -404,8 +404,11 @@ func Unmap(row *Row, destination interface{}) os.Error {
}
// unmarshal col/values
- setField := func(fm *fieldMapping, b []byte) os.Error {
+ setField := func(fm *fieldMapping, b []byte, index int) os.Error {
vfield := v.Field(fm.position)
+ if index >= 0 {
+ vfield = vfield.Index(index)
+ }
if !vfield.CanAddr() {
return os.NewError(fmt.Sprint("Cannot obtain pointer to field ", vfield.Type().Name(), " in struct ", v.Type().Name()))
}
@@ -417,7 +420,15 @@ func Unmap(row *Row, destination interface{}) os.Error {
return nil
}
- for _, column := range row.Columns {
+ prepareSlice := func(fm *fieldMapping, n int) {
+ vfield := v.Field(fm.position)
+ t := vfield.Type().Elem()
+ s := reflect.MakeSlice(t, n, n)
+ vfield.Set(s)
+ }
+
+ rowLength := len(row.Columns)
+ for i, column := range row.Columns {
var components [][]byte
if sm.isCompositeColumn {
components = unpackComposite(column.Name)
@@ -427,46 +438,49 @@ func Unmap(row *Row, destination interface{}) os.Error {
if len(components) != len(sm.columns) {
return os.NewError(fmt.Sprint("Returned number of components in composite column name does not match struct col: component in struct ", v.Type().Name()))
}
+
+ // prepare slice components and value
+ for _, fm := range sm.columns {
+ if fm.fieldKind == baseTypeSliceField {
+ prepareSlice(fm, rowLength)
+ }
+ }
+ if sm.value.fieldKind == baseTypeSliceField {
+ prepareSlice(sm.value, rowLength)
+ }
+
+ // iterate over column name components and set them, plus values
for j, b := range components {
fm := sm.columns[j]
switch fm.fieldKind {
+
case baseTypeField:
- if err = setField(fm, b); err != nil {
+ if err = setField(fm, b, -1); err != nil {
return err
}
+
case starNameField:
var name string
err = Unmarshal(b, UTF8Type, &name)
if err != nil {
return os.NewError(fmt.Sprint("Error unmarshaling composite field as UTF8Type for *name in struct ", v.Type().Name(), ", error: ", err))
}
if valueFM, found := sm.others[name]; found {
- if err = setField(valueFM, column.Value); err != nil {
+ if err = setField(valueFM, column.Value, -1); err != nil {
return err
}
}
- //case baseTypeSliceField:
+
+ case baseTypeSliceField:
+ if err = setField(fm, b, i); err != nil {
+ return err
+ }
+ if err = setField(sm.value, column.Value, -1); err != nil {
+ return err
+ }
}
}
}
-/*
- for each row.Columns
- for each sm.columns
- case baseTypeField
- (potentially not the last component of a composite)
- set struct field value to unmarshaled row column component
- case baseTypeSliceField:
- (this is for sure the last component of a composite)
- append struct field slice value to unmarshaled row column component
- --> call field setter based on val:
- case starNameField:
- (this is for sure the last component of a composite)
- lookup filed named unmarshaled row column component as string
- --> call field setter based on val:
-
-
-*/
return nil
}
-
View
@@ -10,7 +10,7 @@ import (
todo:
- basically everything. real unit testing for all struct funcs
+ much more testing on struct mapping
more test for name: and type:
@@ -216,39 +216,51 @@ func TestStructMapping(t *testing.T) {
}
-func TestMap(t *testing.T) {
- ec := &everythingComp{"a", []byte{1, 2}, true, 3, 4, 5, 6, 7, 8.0, 9.0, "b",
- [16]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, "c"}
- row, err := Map(ec)
+func checkMap(t *testing.T, expectedStruct interface{}, expectedRow *Row) {
+ resultRow, err := Map(expectedStruct)
if err != nil {
- t.Fatal("Unexpected error in test map:", err)
- }
- if !reflect.DeepEqual([]byte{97}, row.Key) {
- t.Error("Invalid key for test row")
- }
- if len(row.Columns) != 1 {
- t.Error("Expected number of columns is 1, got ", len(row.Columns))
+ t.Error("Error mapping struct: ", err)
}
- name := []byte{0, 2, 1, 2, 0, 0, 1, 1, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 8, 0, 0, 0,
- 0, 0, 0, 0, 5, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 65, 0, 0, 0, 0, 0,
- 8, 64, 34, 0, 0, 0, 0, 0, 0, 0, 0, 1, 98, 0, 0, 16, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204,
- 221, 238, 255, 0, 0, 3, 86, 97, 108, 0}
- value := []byte{99}
- if !reflect.DeepEqual(name, row.Columns[0].Name) {
- t.Error("Invalid composite column name in for test row")
- }
- if !reflect.DeepEqual(value, row.Columns[0].Value) {
- t.Error("Invalid value in test row")
+ if !reflect.DeepEqual(resultRow, expectedRow) {
+ t.Error("Mapped struct does not match expected ", expectedRow, " actual ", resultRow)
}
+}
- destEC := &everythingComp{}
- err = Unmap(row, destEC)
+func checkUnmap(t *testing.T, expectedRow *Row, resultStruct interface{}, expectedStruct interface{}) {
+ err := Unmap(expectedRow, resultStruct)
if err != nil {
- t.Fatal("Unexpected error in test unmap:", err)
+ t.Error("Error umapping struct: ", err)
}
+ if !reflect.DeepEqual(resultStruct, expectedStruct) {
+ t.Error("Unmapped struct does not match expected ", expectedStruct, " actual ", resultStruct)
+ }
+}
- if !reflect.DeepEqual(ec, destEC) {
- t.Error("Original and unmapped struct does not match")
+func checkFullMap(t *testing.T, expectedRow *Row, resultStruct interface{}, expectedStruct interface{}) {
+ checkMap(t, expectedStruct, expectedRow)
+ checkUnmap(t, expectedRow, resultStruct, expectedStruct)
+ checkMap(t, resultStruct, expectedRow)
+}
+
+func TestMap(t *testing.T) {
+
+ expectedStruct := &everythingComp{"a", []byte{1, 2}, true, 3, 4, 5, 6, 7, 8.0, 9.0, "b",
+ [16]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, "c"}
+
+ resultStruct := &everythingComp{}
+
+ expectedRow := &Row{
+ Key: []byte{97},
+ Columns: []*Column{
+ &Column{
+ Name: []byte{0, 2, 1, 2, 0, 0, 1, 1, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 65, 0, 0, 0, 0, 0,
+ 8, 64, 34, 0, 0, 0, 0, 0, 0, 0, 0, 1, 98, 0, 0, 16, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204,
+ 221, 238, 255, 0, 0, 3, 86, 97, 108, 0},
+ Value: []byte{99},
+ },
+ },
}
+ checkFullMap(t, expectedRow, resultStruct, expectedStruct)
}

0 comments on commit 42a6efb

Please sign in to comment.