Skip to content

Instantly share code, notes, and snippets.

@Code-Hex
Last active August 10, 2018 13:17
Show Gist options
  • Save Code-Hex/71d48d14b7fec37527d3202689dd8d7f to your computer and use it in GitHub Desktop.
Save Code-Hex/71d48d14b7fec37527d3202689dd8d7f to your computer and use it in GitHub Desktop.

Revisions

  1. Code-Hex revised this gist Aug 10, 2018. 2 changed files with 164 additions and 1 deletion.
    163 changes: 163 additions & 0 deletions validaion_test.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,163 @@
    package main

    import (
    "reflect"
    "testing"
    )

    type TS struct {
    id int
    name string
    }

    type TestStruct struct {
    Str string
    Int int
    Float64 float64
    Slice []complex128
    Bool bool
    Uint uint
    Ary [2]string
    Value TS
    Pointer *TS
    SliceTestStruct []*TS
    MapTestStruct map[string][]*TS
    }

    func TestValidateEmptyStructValue(t *testing.T) {
    testcases := []struct {
    name string
    typ interface{}
    wantErr string
    unexpectedErr bool
    }{
    {
    name: "valid struct pointer",
    typ: &TestStruct{},
    },
    {
    name: "struct value",
    typ: &TestStruct{},
    wantErr: "must pass a empty struct pointer",
    },
    {
    name: "int",
    typ: 10,
    wantErr: "must pass a empty struct pointer",
    },
    {
    name: "string",
    typ: "10",
    wantErr: "must pass a empty struct pointer",
    },
    {
    name: "nil",
    typ: nil,
    wantErr: "must pass a empty struct pointer",
    },
    {
    name: "non empty struct (string)",
    typ: &TestStruct{Str: "Hello"},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (int)",
    typ: &TestStruct{Int: 10},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (float64)",
    typ: &TestStruct{Float64: 30.5},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct ([]complex128])",
    typ: &TestStruct{Slice: []complex128{-23, 1i}},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (bool)",
    typ: &TestStruct{Bool: true},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (array)",
    typ: &TestStruct{Ary: [2]string{}},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (struct value)",
    typ: &TestStruct{Value: TS{id: 1}},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (struct pointer)",
    typ: &TestStruct{Pointer: &TS{}},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (slice of struct pointer)",
    typ: &TestStruct{SliceTestStruct: make([]*TS, 1)},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    {
    name: "non empty struct (map of slice of struct pointer)",
    typ: &TestStruct{MapTestStruct: make(map[string][]*TS, 1)},
    wantErr: "must pass a empty struct pointer, you passed containing values",
    },
    }
    for _, testcase := range testcases {
    t.Run(testcase.name, func(t *testing.T) {
    v := reflect.ValueOf(testcase.typ)
    err := validateEmptyStructValue(v)
    if err != nil {
    if err.Error() != testcase.wantErr {
    t.Fatalf(`expected "%s", but got "%s"`, testcase.wantErr, err)
    }
    }
    })
    }
    }

    func Test_validateSendChannel(t *testing.T) {
    testcases := []struct {
    name string
    typ interface{}
    wantErr string
    }{
    {
    name: "channel",
    typ: make(chan struct{}),
    },
    {
    name: "send channel",
    typ: make(chan<- struct{}),
    },
    {
    name: "another type",
    typ: 10,
    wantErr: `must pass a channel which is send direction (got "int")`,
    },
    {
    name: "nil",
    typ: nil,
    wantErr: `must pass a channel which is send direction (got "nil")`,
    },
    {
    name: "recv channel",
    typ: make(<-chan struct{}),
    wantErr: "must pass a channel which is send direction",
    },
    }
    for _, testcase := range testcases {
    t.Run(testcase.name, func(t *testing.T) {
    v := reflect.ValueOf(testcase.typ)
    err := validateSendChannel(v)
    if err != nil {
    if err.Error() != testcase.wantErr {
    t.Fatalf(`expected "%s", but got "%s"`, testcase.wantErr, err)
    }
    }
    })
    }
    }
    2 changes: 1 addition & 1 deletion validation.go
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    package fetcher
    package main

    import (
    "errors"
  2. Code-Hex revised this gist Aug 10, 2018. No changes.
  3. Code-Hex created this gist Aug 10, 2018.
    74 changes: 74 additions & 0 deletions validation.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    package fetcher

    import (
    "errors"
    "fmt"
    "reflect"
    )

    func validateEmptyStructValue(v reflect.Value) error {
    if !v.IsValid() || v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
    return errors.New("must pass a empty struct pointer")
    }
    if !isZero(v) {
    return errors.New("must pass a empty struct pointer, you passed containing values")
    }
    return nil
    }

    func validateSendChannel(chrv reflect.Value) error {
    if !chrv.IsValid() || chrv.Kind() != reflect.Chan {
    typ := "nil"
    if chrv.IsValid() {
    typ = chrv.Type().String()
    }
    return fmt.Errorf(`must pass a channel which is send direction (got "%s")`, typ)
    }
    if (chrv.Type().ChanDir() & reflect.SendDir) == 0 {
    return errors.New(`must pass a channel which is send direction`)
    }
    return nil
    }

    func isZero(v reflect.Value) bool {
    switch v.Kind() {
    case reflect.Bool:
    return v.Bool() == false

    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    return v.Int() == 0

    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
    reflect.Uint64, reflect.Uintptr:
    return v.Uint() == 0

    case reflect.Float32, reflect.Float64:
    return v.Float() == 0

    case reflect.Complex64, reflect.Complex128:
    return v.Complex() == 0

    case reflect.Ptr, reflect.Interface:
    return !v.IsNil()

    case reflect.Array:
    for i := 0; i < v.Len(); i++ {
    if !isZero(v.Index(i)) {
    return false
    }
    }
    return true

    case reflect.Slice, reflect.String, reflect.Map:
    return v.Len() == 0

    case reflect.Struct:
    for i, n := 0, v.NumField(); i < n; i++ {
    if !isZero(v.Field(i)) {
    return false
    }
    }
    return true
    }
    return false
    }