Skip to content

Commit

Permalink
update with more tests and feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroshade committed Aug 14, 2023
1 parent b2ec016 commit 3b0772a
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 6 deletions.
2 changes: 2 additions & 0 deletions go/iceberg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
14 changes: 13 additions & 1 deletion go/iceberg/go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4 changes: 2 additions & 2 deletions go/iceberg/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ func TestNestedFieldToString(t *testing.T) {
{2, "3: baz: optional boolean"},
{3, "4: qux: required list<string>"},
{4, "6: quux: required map<string, map<string, int>>"},
{5, "11: location: required list<struct<latitude: float, longitude: float>>"},
{6, "15: person: optional struct<name: string, age: int>"},
{5, "11: location: required list<struct<13: latitude: float, 14: longitude: float>>"},
{6, "15: person: optional struct<16: name: string, 17: age: required int>"},
}

for _, tt := range tests {
Expand Down
12 changes: 10 additions & 2 deletions go/iceberg/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,17 @@ func (s *StructType) String() string {
if i != 0 {
b.WriteString(", ")
}
b.WriteString(f.Name)
b.WriteString(": ")
fmt.Fprintf(&b, "%d: %s: ",
f.ID, f.Name)
if f.Required {
b.WriteString("required ")
}
b.WriteString(f.Type.String())
if f.Doc != "" {
b.WriteString(" (")
b.WriteString(f.Doc)
b.WriteByte(')')
}
}
b.WriteString(">")

Expand Down
174 changes: 173 additions & 1 deletion go/iceberg/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ import (
"github.com/stretchr/testify/require"
)

func TestRemainingTypes(t *testing.T) {
func TestTypesBasic(t *testing.T) {
tests := []struct {
expected string
typ iceberg.Type
}{
{"boolean", iceberg.PrimitiveTypes.Bool},
{"int", iceberg.PrimitiveTypes.Int32},
{"long", iceberg.PrimitiveTypes.Int64},
{"float", iceberg.PrimitiveTypes.Float32},
{"double", iceberg.PrimitiveTypes.Float64},
{"date", iceberg.PrimitiveTypes.Date},
{"time", iceberg.PrimitiveTypes.Time},
Expand Down Expand Up @@ -62,3 +65,172 @@ func TestRemainingTypes(t *testing.T) {
})
}
}

func TestFixedType(t *testing.T) {
typ := iceberg.FixedTypeOf(5)
assert.Equal(t, 5, typ.Len())
assert.Equal(t, "fixed[5]", typ.String())
assert.True(t, typ.Equals(iceberg.FixedTypeOf(5)))
assert.False(t, typ.Equals(iceberg.FixedTypeOf(6)))
}

func TestDecimalType(t *testing.T) {
typ := iceberg.DecimalTypeOf(9, 2)
assert.Equal(t, 9, typ.Precision())
assert.Equal(t, 2, typ.Scale())
assert.Equal(t, "decimal(9, 2)", typ.String())
assert.True(t, typ.Equals(iceberg.DecimalTypeOf(9, 2)))
assert.False(t, typ.Equals(iceberg.DecimalTypeOf(9, 3)))
}

func TestStructType(t *testing.T) {
typ := &iceberg.StructType{
FieldList: []iceberg.NestedField{
{ID: 1, Name: "required_field", Type: iceberg.PrimitiveTypes.Int32, Required: true},
{ID: 2, Name: "optional_field", Type: iceberg.FixedTypeOf(5), Required: false},
{ID: 3, Name: "required_field", Type: &iceberg.StructType{
FieldList: []iceberg.NestedField{
{ID: 4, Name: "optional_field", Type: iceberg.DecimalTypeOf(8, 2), Required: false},
{ID: 5, Name: "required_field", Type: iceberg.PrimitiveTypes.Int64, Required: false},
},
}, Required: false},
},
}

assert.Len(t, typ.FieldList, 3)
assert.False(t, typ.Equals(&iceberg.StructType{FieldList: []iceberg.NestedField{{ID: 1, Name: "optional_field", Type: iceberg.PrimitiveTypes.Int32, Required: true}}}))
out, err := json.Marshal(typ)
require.NoError(t, err)

var actual iceberg.StructType
require.NoError(t, json.Unmarshal(out, &actual))
assert.True(t, typ.Equals(&actual))
}

func TestListType(t *testing.T) {
typ := &iceberg.ListType{
ElementID: 1,
ElementRequired: false,
Element: &iceberg.StructType{
FieldList: []iceberg.NestedField{
{ID: 2, Name: "required_field", Type: iceberg.DecimalTypeOf(8, 2), Required: true},
{ID: 3, Name: "optional_field", Type: iceberg.PrimitiveTypes.Int64, Required: false},
},
},
}

assert.IsType(t, (*iceberg.StructType)(nil), typ.ElementField().Type)
assert.Len(t, typ.ElementField().Type.(iceberg.NestedType).Fields(), 2)
assert.Equal(t, 1, typ.ElementField().ID)
assert.False(t, typ.Equals(&iceberg.ListType{
ElementID: 1,
ElementRequired: true,
Element: &iceberg.StructType{
FieldList: []iceberg.NestedField{
{ID: 2, Name: "required_field", Type: iceberg.DecimalTypeOf(8, 2), Required: true},
},
},
}))

out, err := json.Marshal(typ)
require.NoError(t, err)

var actual iceberg.ListType
require.NoError(t, json.Unmarshal(out, &actual))
assert.True(t, typ.Equals(&actual))
}

func TestMapType(t *testing.T) {
typ := &iceberg.MapType{
KeyID: 1,
KeyType: iceberg.PrimitiveTypes.Float64,
ValueID: 2,
ValueType: iceberg.PrimitiveTypes.UUID,
ValueRequired: false,
}

assert.IsType(t, iceberg.PrimitiveTypes.Float64, typ.KeyField().Type)
assert.Equal(t, 1, typ.KeyField().ID)
assert.IsType(t, iceberg.PrimitiveTypes.UUID, typ.ValueField().Type)
assert.Equal(t, 2, typ.ValueField().ID)
assert.False(t, typ.Equals(&iceberg.MapType{
KeyID: 1, KeyType: iceberg.PrimitiveTypes.Int64,
ValueID: 2, ValueType: iceberg.PrimitiveTypes.UUID, ValueRequired: false,
}))
assert.False(t, typ.Equals(&iceberg.MapType{
KeyID: 1, KeyType: iceberg.PrimitiveTypes.Float64,
ValueID: 2, ValueType: iceberg.PrimitiveTypes.String, ValueRequired: true,
}))

out, err := json.Marshal(typ)
require.NoError(t, err)

var actual iceberg.MapType
require.NoError(t, json.Unmarshal(out, &actual))
assert.True(t, typ.Equals(&actual))
}

var (
NonParameterizedTypes = []iceberg.Type{
iceberg.PrimitiveTypes.Bool,
iceberg.PrimitiveTypes.Int32,
iceberg.PrimitiveTypes.Int64,
iceberg.PrimitiveTypes.Float32,
iceberg.PrimitiveTypes.Float64,
iceberg.PrimitiveTypes.Date,
iceberg.PrimitiveTypes.Time,
iceberg.PrimitiveTypes.Timestamp,
iceberg.PrimitiveTypes.TimestampTz,
iceberg.PrimitiveTypes.String,
iceberg.PrimitiveTypes.Binary,
iceberg.PrimitiveTypes.UUID,
}
)

func TestNonParameterizedTypeEquality(t *testing.T) {
for i, in := range NonParameterizedTypes {
for j, check := range NonParameterizedTypes {
if i == j {
assert.Truef(t, in.Equals(check), "expected %s == %s", in, check)
} else {
assert.Falsef(t, in.Equals(check), "expected %s != %s", in, check)
}
}
}
}

func TestTypeStrings(t *testing.T) {
tests := []struct {
typ iceberg.Type
str string
}{
{iceberg.PrimitiveTypes.Bool, "boolean"},
{iceberg.PrimitiveTypes.Int32, "int"},
{iceberg.PrimitiveTypes.Int64, "long"},
{iceberg.PrimitiveTypes.Float32, "float"},
{iceberg.PrimitiveTypes.Float64, "double"},
{iceberg.PrimitiveTypes.Date, "date"},
{iceberg.PrimitiveTypes.Time, "time"},
{iceberg.PrimitiveTypes.Timestamp, "timestamp"},
{iceberg.PrimitiveTypes.TimestampTz, "timestamptz"},
{iceberg.PrimitiveTypes.String, "string"},
{iceberg.PrimitiveTypes.UUID, "uuid"},
{iceberg.PrimitiveTypes.Binary, "binary"},
{iceberg.FixedTypeOf(22), "fixed[22]"},
{iceberg.DecimalTypeOf(19, 25), "decimal(19, 25)"},
{&iceberg.StructType{
FieldList: []iceberg.NestedField{
{ID: 1, Name: "required_field", Type: iceberg.PrimitiveTypes.String, Required: true, Doc: "this is a doc"},
{ID: 2, Name: "optional_field", Type: iceberg.PrimitiveTypes.Int32, Required: true},
},
}, "struct<1: required_field: required string (this is a doc), 2: optional_field: required int>"},
{&iceberg.ListType{
ElementID: 22, Element: iceberg.PrimitiveTypes.String}, "list<string>"},
{&iceberg.MapType{KeyID: 19, KeyType: iceberg.PrimitiveTypes.String, ValueID: 25, ValueType: iceberg.PrimitiveTypes.Float64},
"map<string, double>"},
}

for _, tt := range tests {
assert.Equal(t, tt.str, tt.typ.String())
}
}

0 comments on commit 3b0772a

Please sign in to comment.