more tests, additional methods for fields

This commit is contained in:
Fatih Arslan 2014-08-10 16:42:04 +03:00
parent d5c544c4f6
commit 84a0f611c7
3 changed files with 72 additions and 9 deletions

View File

@ -30,3 +30,17 @@ func (f *Field) IsEmbedded() bool {
func (f *Field) IsExported() bool { func (f *Field) IsExported() bool {
return f.field.PkgPath == "" return f.field.PkgPath == ""
} }
// IsZero returns true if the given field is not initalized (has a zero value).
// It panics if the field is not exported.
func (f *Field) IsZero() bool {
zero := reflect.Zero(f.value.Type()).Interface()
current := f.Value()
return reflect.DeepEqual(current, zero)
}
// Name returns the name of the given field
func (f *Field) Name() string {
return f.field.Name
}

View File

@ -8,6 +8,7 @@ type Foo struct {
B int `structure:"y"` B int `structure:"y"`
C bool `json:"c"` C bool `json:"c"`
d string // not exported d string // not exported
x string `xml:"x"` // not exported, with tag
*Bar // embedded *Bar // embedded
} }
@ -24,9 +25,9 @@ func newStruct() *Struct {
g: []string{"zeynep", "fatih"}, g: []string{"zeynep", "fatih"},
} }
// B and x is not initialized for testing
f := &Foo{ f := &Foo{
A: "gopher", A: "gopher",
B: 1,
C: true, C: true,
d: "small", d: "small",
} }
@ -47,3 +48,56 @@ func TestField(t *testing.T) {
_ = s.Field("no-field") _ = s.Field("no-field")
} }
func TestField_Tag(t *testing.T) {
s := newStruct()
v := s.Field("B").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a non existing tag should return empty, got: %s", v)
}
v = s.Field("C").Tag("json")
if v != "c" {
t.Errorf("Field's tag value of the existing field C should return 'c', got: %s", v)
}
v = s.Field("d").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a non exported field should return empty, got: %s", v)
}
v = s.Field("x").Tag("xml")
if v != "x" {
t.Errorf("Field's tag value of a non exported field with a tag should return 'x', got: %s", v)
}
v = s.Field("A").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a existing field without a tag should return empty, got: %s", v)
}
}
func TestField_Value(t *testing.T) {
s := newStruct()
v := s.Field("A").Value()
val, ok := v.(string)
if !ok {
t.Errorf("Field's value of a A should be string")
}
if val != "gopher" {
t.Errorf("Field's value of a existing tag should return 'gopher', got: %s", val)
}
defer func() {
err := recover()
if err == nil {
t.Error("Value of a non exported field from the field should panic")
}
}()
// should panic
_ = s.Field("d").Value()
}

View File

@ -32,8 +32,7 @@ func (s *Struct) Fields() []string {
} }
// Field returns a new Field struct that provides several high level functions // Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. It panics if the field is not found or // around a single struct field entitiy. It panics if the field is not found.
// is unexported.
func (s *Struct) Field(name string) *Field { func (s *Struct) Field(name string) *Field {
f, ok := s.FieldOk(name) f, ok := s.FieldOk(name)
if !ok { if !ok {
@ -44,8 +43,8 @@ func (s *Struct) Field(name string) *Field {
} }
// Field returns a new Field struct that provides several high level functions // Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy and a boolean indicating if the field // around a single struct field entitiy. The boolean returns true if the field
// was found. It panics if the or is unexported. // was found.
func (s *Struct) FieldOk(name string) (*Field, bool) { func (s *Struct) FieldOk(name string) (*Field, bool) {
v := strctVal(s.raw) v := strctVal(s.raw)
t := v.Type() t := v.Type()
@ -55,10 +54,6 @@ func (s *Struct) FieldOk(name string) (*Field, bool) {
return nil, false return nil, false
} }
if field.PkgPath != "" {
panic("unexported field access is not allowed")
}
return &Field{ return &Field{
field: field, field: field,
value: v.FieldByName(name), value: v.FieldByName(name),