Permalink
Browse files

more composite work and testing

  • Loading branch information...
carloscm committed Mar 16, 2012
1 parent b46e8fa commit 506e19c158728cb690ccdb69de12e67648c183df
Showing with 169 additions and 61 deletions.
  1. +2 −2 README.md
  2. +23 −12 src/gossie/connection_test.go
  3. +12 −2 src/gossie/struct.go
  4. +122 −45 src/gossie/struct_test.go
  5. +10 −0 src/gossie/types.go
View
@@ -1,6 +1,6 @@
# About
-Gossie is (for now) a Go library with a low level wrapper for the Cassandra 1.0 thrift bidings with with utilities for connection pooling, primitive type marshalling and easy query building (much easier to use than the generated thrift bindings). A higher level layer will be implemented on top of the current code to allow for struct marshalling into rows and composites, among other things.
+Gossie is (for now) a Go library with a low level wrapper for the Cassandra 1.0 thrift bidings with with utilities for connection pooling, primitive type marshaling and easy query building (much easier to use than the generated thrift bindings). A higher level layer will be implemented on top of the current code to allow for struct marshalling into rows and composites, among other things.
# Requeriments
@@ -29,7 +29,7 @@ Launch a Cassandra instance in localhost:9160, create a keyspace named TestGossi
# Example
-I will provide a full example once the higher level marshalling is implemented. For examples of the low level layer check src/gossie/query_test.go
+I will provide a full example once the higher level marshaling is implemented. For examples of the low level layer check src/gossie/query_test.go
# License
@@ -9,12 +9,14 @@ import (
func TestConnection(t *testing.T) {
- c, err := newConnection("127.0.0.1:9999", "NotExists", 3000)
- if err == nil {
- t.Fatal("Invalid connection parameters did not return error")
- }
-
- c, err = newConnection("127.0.0.1:9160", "NotExists", 1000)
+ /* kind of pointless
+ c, err := newConnection("127.0.0.1:9999", "NotExists", 3000)
+ if err == nil {
+ t.Fatal("Invalid connection parameters did not return error")
+ }
+ */
+
+ c, err := newConnection("127.0.0.1:9160", "NotExists", 1000)
if err == nil {
t.Fatal("Invalid keyspace did not return error")
}
@@ -33,17 +35,26 @@ func TestConnection(t *testing.T) {
func TestNewConnectionPool(t *testing.T) {
- cp, err := NewConnectionPool([]string{"127.0.0.1:9999"}, "NotExists", PoolOptions{Size: 50, Timeout: 3000})
- if err == nil {
- t.Fatal("Invalid connection parameters did not return error")
- }
+ /* kind of pointless
+ cp, err := NewConnectionPool([]string{"127.0.0.1:9999"}, "NotExists", PoolOptions{Size: 50, Timeout: 3000})
+ if err == nil {
+ t.Fatal("Invalid connection parameters did not return error")
+ }
+ */
- cp, err = NewConnectionPool([]string{"127.0.0.1:9160"}, "NotExists", PoolOptions{Size: 50, Timeout: 3000})
+ cp, err := NewConnectionPool([]string{"127.0.0.1:9160"}, "NotExists", PoolOptions{Size: 50, Timeout: 3000})
if err == nil {
t.Fatal("Invalid keyspace did not return error")
}
- cp, err = NewConnectionPool([]string{"127.0.0.1:9160", "127.0.0.1:9170", "127.0.0.1:9180"}, "TestGossie", PoolOptions{Size: 50, Timeout: 3000})
+ /* kind of pointless
+ cp, err = NewConnectionPool([]string{"127.0.0.1:9160", "127.0.0.1:9170", "127.0.0.1:9180"}, "TestGossie", PoolOptions{Size: 50, Timeout: 3000})
+ if err != nil {
+ t.Fatal("Error connecting to Cassandra:", err)
+ }
+ */
+
+ cp, err = NewConnectionPool([]string{"127.0.0.1:9160"}, "TestGossie", PoolOptions{Size: 50, Timeout: 3000})
if err != nil {
t.Fatal("Error connecting to Cassandra:", err)
}
View
@@ -17,6 +17,18 @@ todo:
support composite key, not just composite column (is this actually in use by anybody???)
name: and type: tag field modifiers to override default naming and marshaling
+ go maps support for things like
+ type s struct {
+ a int `cf:"cfname" key:"a" col:"atts" val:"atts"`
+ atts map[string]string
+ }
+ type s2 struct {
+ a int `cf:"cfname" key:"a" col:"b,atts" val:"atts"`
+ b UUID
+ atts map[string]string
+ }
+ --> then think about slicing/pagging this, oops
+
unmap
---
@@ -90,7 +102,6 @@ type fieldMapping struct {
fieldKind int
position int
name string
- goType reflect.Type
cassandraType TypeDesc
}
type structMapping struct {
@@ -152,7 +163,6 @@ func newFieldMapping(pos int, sf reflect.StructField) *fieldMapping {
fm.cassandraType, fm.fieldKind = defaultCassandraType(sf.Type)
fm.position = pos
fm.name = sf.Name
- fm.goType = sf.Type
return fm
}
View
@@ -57,6 +57,32 @@ type noErrC struct {
b int
c int
}
+type noErrD struct {
+ a int `cf:"cfname" key:"a" col:"b" val:"c"`
+ b []int
+ c []int
+}
+type noErrE struct {
+ a int `cf:"cfname" key:"a" col:"b,c" val:"d"`
+ b int
+ c []int
+ d []int
+}
+type everythingComp struct {
+ Key string `cf:"cfname" key:"Key" col:"FBytes,FBool,FInt8,FInt16,FInt32,FInt,FInt64,FFloat32,FFloat64,FString,FUUID,*name" val:"*value"`
+ FBytes []byte
+ FBool bool
+ FInt8 int8
+ FInt16 int16
+ FInt32 int32
+ FInt int
+ FInt64 int64
+ FFloat32 float32
+ FFloat64 float64
+ FString string
+ FUUID UUID
+ Val string
+}
func buildMappingFromPtr(instance interface{}) (*structMapping, os.Error) {
valuePtr := reflect.ValueOf(instance)
@@ -72,10 +98,13 @@ func structMapMustError(t *testing.T, instance interface{}) {
}
}
-func TestStructMapping(t *testing.T) {
- var sampleInt int
- sampleIntT := reflect.TypeOf(sampleInt)
+func checkMapping(t *testing.T, expected, actual interface{}, name string) {
+ if !reflect.DeepEqual(expected, actual) {
+ t.Error("Mapping for struct sample", name, "does not match expected output")
+ }
+}
+func TestStructMapping(t *testing.T) {
structMapMustError(t, &errNoMeta{})
structMapMustError(t, &errNoMetaKeyColVal{})
structMapMustError(t, &errNoMetaColVal{})
@@ -87,77 +116,125 @@ func TestStructMapping(t *testing.T) {
mapA, _ := buildMappingFromPtr(&noErrA{1, 2, 3})
goodA := &structMapping{
cf: "cfname",
- key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", goType: sampleIntT, cassandraType: LongType},
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", cassandraType: LongType},
columns: []*fieldMapping{
- &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", goType: sampleIntT, cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", cassandraType: LongType},
},
- value: &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", goType: sampleIntT, cassandraType: LongType},
+ value: &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", cassandraType: LongType},
others: nil,
isCompositeColumn: false,
}
- if !reflect.DeepEqual(mapA, goodA) {
- t.Error("Mapping for struct sample A does not match expected output, ", mapA, " vs ", goodA)
- }
+ checkMapping(t, goodA, mapA, "mapA")
mapB, _ := buildMappingFromPtr(&noErrB{1, 2, 3})
goodB := &structMapping{
cf: "cfname",
- key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", goType: sampleIntT, cassandraType: LongType},
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", cassandraType: LongType},
columns: []*fieldMapping{
- &fieldMapping{fieldKind: starNameField, position: 0, name: "", goType: nil, cassandraType: 0},
+ &fieldMapping{fieldKind: starNameField, position: 0, name: "", cassandraType: 0},
},
- value: &fieldMapping{fieldKind: starValueField, position: 0, name: "", goType: nil, cassandraType: 0},
+ value: &fieldMapping{fieldKind: starValueField, position: 0, name: "", cassandraType: 0},
others: map[string]*fieldMapping{
- "b": &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", goType: sampleIntT, cassandraType: LongType},
- "c": &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", goType: sampleIntT, cassandraType: LongType},
+ "b": &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", cassandraType: LongType},
+ "c": &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", cassandraType: LongType},
},
isCompositeColumn: false,
}
- if !reflect.DeepEqual(mapB, goodB) {
- t.Error("Mapping for struct sample B does not match expected output, ", mapB, " vs ", goodB)
- }
+ checkMapping(t, goodB, mapB, "mapB")
mapC, _ := buildMappingFromPtr(&noErrC{1, 2, 3})
goodC := &structMapping{
cf: "cfname",
- key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", goType: sampleIntT, cassandraType: LongType},
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", cassandraType: LongType},
columns: []*fieldMapping{
- &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", goType: sampleIntT, cassandraType: LongType},
- &fieldMapping{fieldKind: starNameField, position: 0, name: "", goType: nil, cassandraType: 0},
+ &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", cassandraType: LongType},
+ &fieldMapping{fieldKind: starNameField, position: 0, name: "", cassandraType: 0},
},
- value: &fieldMapping{fieldKind: starValueField, position: 0, name: "", goType: nil, cassandraType: 0},
+ value: &fieldMapping{fieldKind: starValueField, position: 0, name: "", cassandraType: 0},
others: map[string]*fieldMapping{
- "c": &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", goType: sampleIntT, cassandraType: LongType},
+ "c": &fieldMapping{fieldKind: baseTypeField, position: 2, name: "c", cassandraType: LongType},
},
isCompositeColumn: true,
}
- if !reflect.DeepEqual(mapC, goodC) {
- t.Error("Mapping for struct sample C does not match expected output, ", mapC, " vs ", goodC)
- }
-}
-
-type timeline struct {
- UserId string `cf:"Timelines" key:"UserId" col:"TweetId,*name" val:"*value"`
- TweetId int
- Author string
- Body string
-}
-
-func TestMap(t *testing.T) {
-
- tweet := &timeline{UserId: "abc", TweetId: 3, Author: "xyz", Body: "hello world"}
+ checkMapping(t, goodC, mapC, "mapC")
- row, _ := Map(tweet)
+ mapD, _ := buildMappingFromPtr(&noErrD{1, []int{2, 3}, []int{4, 5}})
+ goodD := &structMapping{
+ cf: "cfname",
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", cassandraType: LongType},
+ columns: []*fieldMapping{
+ &fieldMapping{fieldKind: baseTypeSliceField, position: 1, name: "b", cassandraType: LongType},
+ },
+ value: &fieldMapping{fieldKind: baseTypeSliceField, position: 2, name: "c", cassandraType: LongType},
+ others: nil,
+ isCompositeColumn: false,
+ }
+ checkMapping(t, goodD, mapD, "mapD")
- if len(row.Columns) != 2 {
- t.Error("Expected number of columns is 2, got ", len(row.Columns))
+ mapE, _ := buildMappingFromPtr(&noErrE{1, 2, []int{3, 4}, []int{5, 6}})
+ goodE := &structMapping{
+ cf: "cfname",
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "a", cassandraType: LongType},
+ columns: []*fieldMapping{
+ &fieldMapping{fieldKind: baseTypeField, position: 1, name: "b", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeSliceField, position: 2, name: "c", cassandraType: LongType},
+ },
+ value: &fieldMapping{fieldKind: baseTypeSliceField, position: 3, name: "d", cassandraType: LongType},
+ others: nil,
+ isCompositeColumn: true,
}
+ checkMapping(t, goodE, mapE, "mapE")
- t.Log(row.Columns[0].Name)
- t.Log(row.Columns[0].Value)
- t.Log(row.Columns[1].Name)
- t.Log(row.Columns[1].Value)
+ eComp, _ := buildMappingFromPtr(&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"})
+ goodEComp := &structMapping{
+ cf: "cfname",
+ key: &fieldMapping{fieldKind: baseTypeField, position: 0, name: "Key", cassandraType: UTF8Type},
+ columns: []*fieldMapping{
+ &fieldMapping{fieldKind: baseTypeField, position: 1, name: "FBytes", cassandraType: BytesType},
+ &fieldMapping{fieldKind: baseTypeField, position: 2, name: "FBool", cassandraType: BooleanType},
+ &fieldMapping{fieldKind: baseTypeField, position: 3, name: "FInt8", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 4, name: "FInt16", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 5, name: "FInt32", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 6, name: "FInt", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 7, name: "FInt64", cassandraType: LongType},
+ &fieldMapping{fieldKind: baseTypeField, position: 8, name: "FFloat32", cassandraType: FloatType},
+ &fieldMapping{fieldKind: baseTypeField, position: 9, name: "FFloat64", cassandraType: DoubleType},
+ &fieldMapping{fieldKind: baseTypeField, position: 10, name: "FString", cassandraType: UTF8Type},
+ &fieldMapping{fieldKind: baseTypeField, position: 11, name: "FUUID", cassandraType: UUIDType},
+ &fieldMapping{fieldKind: starNameField, position: 0, name: "", cassandraType: 0},
+ },
+ value: &fieldMapping{fieldKind: starValueField, position: 0, name: "", cassandraType: 0},
+ others: map[string]*fieldMapping{
+ "Val": &fieldMapping{fieldKind: baseTypeField, position: 12, name: "Val", cassandraType: UTF8Type},
+ },
+ isCompositeColumn: true,
+ }
+ t.Log(goodEComp.key)
+ t.Log(eComp.key)
+ checkMapping(t, goodEComp, eComp, "eComp")
- //t.Fatal("heh")
+}
+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)
+ if err != nil {
+ t.Fatal("Unexpected error in test map:", err)
+ }
+ if len(row.Columns) != 1 {
+ t.Error("Expected number of columns is 1, got ", len(row.Columns))
+ }
+ 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")
+ }
}
View
@@ -641,3 +641,13 @@ func packComposite(current, component []byte, comparator, sliceStart, inclusive
r = append(r, component...)
return append(r, eoc)
}
+
+func unpackComposite(composite []byte) [][]byte {
+ components := make([][]byte, 0)
+ for len(composite) > 0 {
+ l := enc.BigEndian.Uint16(composite[:2])
+ components = append(components, composite[2:2+l])
+ composite = composite[3+l:]
+ }
+ return components
+}

0 comments on commit 506e19c

Please sign in to comment.