[feat] new package nazareflect

pull/2/head
q191201771 5 years ago
parent 1663c4464b
commit c35f398d57

@ -9,10 +9,7 @@
// package assert 提供了单元测试时的断言功能,减少一些模板代码
package assert
import (
"bytes"
"reflect"
)
import "github.com/q191201771/naza/pkg/nazareflect"
// 单元测试中的 *testing.T 和 *testing.B 都满足该接口
type TestingT interface {
@ -27,7 +24,7 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msg ...string)
if h, ok := t.(tHelper); ok {
h.Helper()
}
if !equal(expected, actual) {
if !nazareflect.Equal(expected, actual) {
t.Errorf("%s expected=%+v, actual=%+v", msg, expected, actual)
}
return
@ -38,37 +35,8 @@ func IsNotNil(t TestingT, actual interface{}, msg ...string) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if isNil(actual) {
if nazareflect.IsNil(actual) {
t.Errorf("%s expected not nil, but actual=%+v", msg, actual)
}
return
}
func isNil(actual interface{}) bool {
if actual == nil {
return true
}
v := reflect.ValueOf(actual)
k := v.Kind()
if k == reflect.Chan || k == reflect.Map || k == reflect.Ptr || k == reflect.Interface || k == reflect.Slice {
return v.IsNil()
}
return false
}
func equal(expected, actual interface{}) bool {
if expected == nil {
return isNil(actual)
}
exp, ok := expected.([]byte)
if !ok {
return reflect.DeepEqual(expected, actual)
}
act, ok := actual.([]byte)
if !ok {
return false
}
return bytes.Equal(exp, act)
}

@ -11,6 +11,8 @@ package nazalog
import (
"fmt"
"github.com/q191201771/naza/pkg/nazareflect"
"github.com/q191201771/naza/pkg/fake"
)
@ -93,7 +95,7 @@ func Panicln(v ...interface{}) {
}
func Assert(expected interface{}, actual interface{}) {
if !equal(expected, actual) {
if !nazareflect.Equal(expected, actual) {
err := fmt.Sprintf("assert failed. excepted=%+v, but actual=%+v", expected, actual)
switch global.core.option.AssertBehavior {
case AssertError:

@ -13,11 +13,12 @@ import (
"fmt"
"os"
"path/filepath"
"reflect"
"runtime"
"sync"
"time"
"github.com/q191201771/naza/pkg/nazareflect"
"github.com/q191201771/naza/pkg/fake"
)
@ -153,7 +154,7 @@ func (l *logger) Panicln(v ...interface{}) {
}
func (l *logger) Assert(expected interface{}, actual interface{}) {
if !equal(expected, actual) {
if !nazareflect.Equal(expected, actual) {
err := fmt.Sprintf("assert failed. excepted=%+v, but actual=%+v", expected, actual)
switch l.core.option.AssertBehavior {
case AssertError:
@ -320,34 +321,6 @@ func validate(option Option) error {
}
return nil
}
func isNil(actual interface{}) bool {
if actual == nil {
return true
}
v := reflect.ValueOf(actual)
k := v.Kind()
if k == reflect.Chan || k == reflect.Map || k == reflect.Ptr || k == reflect.Interface || k == reflect.Slice {
return v.IsNil()
}
return false
}
func equal(expected, actual interface{}) bool {
if expected == nil {
return isNil(actual)
}
exp, ok := expected.([]byte)
if !ok {
return reflect.DeepEqual(expected, actual)
}
act, ok := actual.([]byte)
if !ok {
return false
}
return bytes.Equal(exp, act)
}
func writeTime(buf *bytes.Buffer, t time.Time) {
year, month, day := t.Date()

@ -0,0 +1,118 @@
// Copyright 2020, Chef. All rights reserved.
// https://github.com/q191201771/naza
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package nazareflect
import (
"bytes"
"reflect"
)
func IsNil(actual interface{}) bool {
if actual == nil {
return true
}
v := reflect.ValueOf(actual)
k := v.Kind()
if k == reflect.Chan || k == reflect.Map || k == reflect.Ptr || k == reflect.Interface || k == reflect.Slice {
return v.IsNil()
}
return false
}
// TODO chef: 考虑是否将EqualInteger放入Equal中但是需考虑会给Equal带来额外的性能开销
func Equal(expected, actual interface{}) bool {
if expected == nil {
return IsNil(actual)
}
exp, ok := expected.([]byte)
if ok {
act, ok := actual.([]byte)
if !ok {
return false
}
return bytes.Equal(exp, act)
}
return reflect.DeepEqual(expected, actual)
}
// 用于判断不同类型的整型的值是否相等比如int8(1)和int32(1)做比较结果为true
// 注意如果a或b不是整型则直接返回false
func EqualInteger(a, b interface{}) bool {
// a有3种状态有符号整型无符号整型非整型
// b同理也是3种状态
// 那么总共有3*3种组合需要判断
aiv, aiok := tryInt(a)
biv, biok := tryInt(b)
if aiok && biok { // a,b都是有符号整型 (1)
return aiv == biv
}
auv, auok := tryUint(a)
buv, buok := tryUint(b)
if auok && buok { // a,b都是无符号整型 (1)
return auv == auv
}
if aiok && buok { // a是有符号整型b是无符号整型 (1)
if aiv < 0 {
return false
}
return uint64(aiv) == buv
}
if auok && biok { // a是无符号整型b是有符号整型 (1)
if biv < 0 {
return false
}
return uint64(biv) == auv
}
// 剩下的情况,至少有一个不是整型 (5)
return false
}
func tryInt(actual interface{}) (int64, bool) {
v := reflect.ValueOf(actual)
k := v.Kind()
switch k {
case reflect.Int:
fallthrough
case reflect.Int8:
fallthrough
case reflect.Int16:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
return v.Int(), true
}
return 0, false
}
func tryUint(actual interface{}) (uint64, bool) {
v := reflect.ValueOf(actual)
k := v.Kind()
switch k {
case reflect.Uint:
fallthrough
case reflect.Uint8:
fallthrough
case reflect.Uint16:
fallthrough
case reflect.Uint32:
fallthrough
case reflect.Uint64:
fallthrough
case reflect.Uintptr:
return v.Uint(), true
}
return 0, false
}

@ -0,0 +1,70 @@
// Copyright 2020, Chef. All rights reserved.
// https://github.com/q191201771/naza
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package nazareflect
import (
"errors"
"testing"
)
func BenchmarkEqualInteger(b *testing.B) {
for i := 0; i < b.N; i++ {
EqualInteger("a", 1)
}
}
func TestIsNil(t *testing.T) {
sure(t, IsNil(nil))
sure(t, !IsNil(1))
}
func TestEqual(t *testing.T) {
sure(t, Equal(nil, nil))
sure(t, Equal(1, 1))
sure(t, Equal("aaa", "aaa"))
var ch chan struct{}
sure(t, Equal(nil, ch))
var m map[string]string
sure(t, Equal(nil, m))
var p *int
sure(t, Equal(nil, p))
var i interface{}
sure(t, Equal(nil, i))
var b []byte
sure(t, Equal(nil, b))
sure(t, Equal([]byte{}, []byte{}))
sure(t, Equal([]byte{0, 1, 2}, []byte{0, 1, 2}))
sure(t, !Equal(nil, 1))
sure(t, !Equal([]byte{}, "aaa"))
sure(t, !Equal(nil, errors.New("mock error")))
}
func TestEqualInteger(t *testing.T) {
sure(t, EqualInteger(0, 0))
sure(t, EqualInteger(1, uint(1)))
sure(t, EqualInteger(uint32(1), int16(1)))
sure(t, EqualInteger(uint(1), uint8(1)))
sure(t, !EqualInteger(1, 0))
sure(t, !EqualInteger(0, "aaa"))
sure(t, !EqualInteger(-1, uint(0)))
sure(t, !EqualInteger(uint16(0), int32(-1)))
}
// 因为naza assert package引用了naza value package如果这里再使用assert就造成package循环引用了
// 所以这里写个简单的帮助测试的函数
func sure(t *testing.T, actual bool) {
t.Helper()
if !actual {
t.Error()
}
}
Loading…
Cancel
Save