1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-05 05:12:26 +08:00

Compare commits

...

26 Commits

Author SHA1 Message Date
dudaodong
4fd8a18677 release v1.1.6 2022-01-03 15:58:19 +08:00
dudaodong
3de906d7c9 refactor: reduce gocyclo of doHttpRequest func 2022-01-03 15:53:25 +08:00
dudaodong
56fc12c660 refactor: reduce gocyclo of ToString func 2022-01-03 15:15:22 +08:00
dudaodong
7a9b0847f9 fix: fix some go line issue in go report card 2022-01-03 14:57:14 +08:00
dudaodong
9266d99249 add chinese comment for GroupBy func 2022-01-02 22:12:01 +08:00
donutloop
f15131f032 Slice: find nothing case (#11)
The current behavior can result into wired edge cases.

**Current behavior**

if find was unsuccessfully then it will return the first element of the
slice

**Desired behavior**

if find was unsuccessfully then it should return negative ok and a none
value
2022-01-02 22:05:27 +08:00
donutloop
b4a49fccfd Slice: Add GroupBy func (#10)
Group by: split slice into two groups, applies on each slice element a
predicate func to categorize this element.

Changes

* Add groub by func
* Add test case for this func
2022-01-02 21:24:56 +08:00
dudaodong
94b1a1d383 feat: add Reset func for watcher 2022-01-01 20:14:41 +08:00
dudaodong
7db46696f6 release v1.1.5 2022-01-01 20:13:21 +08:00
dudaodong
d4f49af2ad feat: add watcher for record code excution time 2022-01-01 19:56:15 +08:00
dudaodong
ed4acc1c67 feat: add Shuffle func 2022-01-01 19:18:33 +08:00
dudaodong
042a00296f feat: add FlattenDeep func 2022-01-01 18:14:35 +08:00
dudaodong
b42aac53b3 feat: add Drop func 2022-01-01 17:20:41 +08:00
dudaodong
c625a88067 refactor: rename package 'utils' to 'internal' 2021-12-31 11:36:11 +08:00
dudaodong
e15ae9eb98 update: add Md5String func and Md5File func 2021-12-31 11:25:43 +08:00
dudaodong
bb4ac01209 Merge branch 'main' of github.com:duke-git/lancet into main 2021-12-31 10:18:11 +08:00
donutloop
147c1625b5 Slice: Optimize slice func tools (#9)
IntSlice and StringSlice: preallocate memory up front for output slice.
Instead returning a error throw a panic because most likely it's a
programming error.
Contain: rename slice to iterableType and add default case for type
mismatches
2021-12-31 10:15:38 +08:00
dudaodong
2aed55f704 refactor: function in slice.go 2021-12-31 10:12:14 +08:00
dudaodong
051f20caef release: v1.1.4, merge pr7 and pr8 2021-12-30 20:25:20 +08:00
donutloop
613785b07c function: catch earlier programming error (#8)
Place at first line of the function body a function type safe guard
check.
2021-12-30 20:22:00 +08:00
donutloop
0b0eb695e8 datetime: optimized func calls (#7)
Replace time parsing calls with less expensive operations
2021-12-30 10:29:10 +08:00
dudaodong
745082fff1 fix: update api url for http timeout issue in the task of github actions 2021-12-29 11:39:48 +08:00
dudaodong
24b8da360e release: v1.1.3, merge pr5 and pr6 2021-12-29 09:55:42 +08:00
donutloop
b106c428ae Every: use int counter (#6)
Use counter to verify all elements passed the perdicate func.
Replace slice of indexes with int counter.
2021-12-29 09:51:50 +08:00
dudaodong
8b1171d0cb fmt: go fmt for request_test.go 2021-12-28 19:28:55 +08:00
donutloop
ab012f2545 LowerFirst: use slicing and utf8 func tools (#5)
Replace looping with slicing and utf8 func tools operations.
2021-12-28 19:25:44 +08:00
28 changed files with 671 additions and 342 deletions

View File

@@ -6,7 +6,7 @@
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.2-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-1.1.6-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
@@ -21,7 +21,7 @@ English | [简体中文](./README_zh-CN.md)
### Feature
- 👏 Comprehensive, efficient and reusable.
- 💪 100+ common go util functions, support string, slice, datetime, net, crypt...
- 💪 140+ common go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library.
- 🌍 Unit test for exery exported function.
@@ -145,6 +145,8 @@ func HmacMd5(data, key string) string //get hmac md5 value
func HmacSha1(data, key string) string //get hmac sha1 value
func HmacSha256(data, key string) string //get hmac sha256 value
func HmacSha512(data, key string) string //get hmac sha512 value
func Md5String(s string) string //return the md5 value of string
func Md5File(filename string) (string, error) //return the md5 value of file
func Sha1(data string) string //get sha1 value
func Sha256(data string) string //getsha256 value
func Sha512(data string) string //get sha512 value
@@ -276,6 +278,10 @@ func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //make a curr
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //compose the functions from right to left
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //invoke function after delayed time
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //invoke function every duration time, util close the returned bool chan
func (w *Watcher) Start() //start the watch timer.
func (w *Watcher) Stop() //stop the watch timer
func (w *Watcher) Reset() {} //reset the watch timer.
func (w *Watcher) GetElapsedTime() time.Duration //获取代码段运行时间
```
#### 7. netutil is for net process
@@ -386,9 +392,11 @@ func Chunk(slice []interface{}, size int) [][]interface{} //creates an slice of
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //convert originalSlice to newSliceType
func Difference(slice1, slice2 interface{}) interface{} //creates an slice of whose element not included in the other given slice
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //delete the element of slice from start index to end index - 1
func Drop(slice interface{}, n int) interface{} //creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0
func Every(slice, function interface{}) bool //return true if all of the values in the slice pass the predicate function, function signature should be func(index int, value interface{}) bool
func Filter(slice, function interface{}) interface{} //filter slice, function signature should be func(index int, value interface{}) bool
func Find(slice, function interface{}) interface{} //iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool .
func Find(slice, function interface{}) (interface{}, bool) //iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool .
func FlattenDeep(slice interface{}) interface{} //flattens slice recursive
func IntSlice(slice interface{}) ([]int, error) //convert value to int slice
func InterfaceSlice(slice interface{}) []interface{} //convert value to interface{} slice
func Intersection(slices ...interface{}) interface{} //creates a slice of unique values that included by all slices.
@@ -396,6 +404,7 @@ func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}
func Map(slice, function interface{}) interface{} //map lisce, function signature should be func(index int, value interface{}) interface{}
func ReverseSlice(slice interface{}) //revere slice
func Reduce(slice, function, zero interface{}) interface{} //reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}
func Shuffle(slice interface{}) interface{} //creates an slice of shuffled values
func SortByField(slice interface{}, field string, sortType ...string) error //sort struct slice by field
func Some(slice, function interface{}) bool //return true if any of the values in the list pass the predicate function, function signature should be func(index int, value interface{}) bool
func StringSlice(slice interface{}) []string //convert value to string slice
@@ -403,6 +412,7 @@ func Unique(slice interface{}) interface{} //remove duplicate elements in slice
func Union(slices ...interface{}) interface{} //Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //update the slice element at index.
func Without(slice interface{}, values ...interface{}) interface{} //creates a slice excluding all given values
func GroupBy(slice, function interface{}) (interface{}, interface{}) // groups slice into two categories
```
#### 10. strutil is for processing string

View File

@@ -6,7 +6,7 @@
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.2-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-1.1.6-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
@@ -21,7 +21,7 @@
### 特性
- 👏 全面、高效、可复用
- 💪 100+常用go工具函数支持string、slice、datetime、net、crypt...
- 💪 140+常用go工具函数支持string、slice、datetime、net、crypt...
- 💅 只依赖go标准库
- 🌍 所有导出函数单元测试覆盖率100%
@@ -146,6 +146,8 @@ func HmacMd5(data, key string) string //获取hmac md5值
func HmacSha1(data, key string) string //获取hmac sha1值
func HmacSha256(data, key string) string //获取hmac sha256值
func HmacSha512(data, key string) string //获取hmac sha512值
func Md5String(s string) string //获取字符串md5值
func Md5File(filename string) (string, error) //获取文件md5值
func Sha1(data string) string //获取sha1值
func Sha256(data string) string //获取sha256值
func Sha512(data string) string //获取sha512值
@@ -277,6 +279,10 @@ func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //函数柯
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //从右至左组合函数
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //延迟调用函数
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //每隔duration时间调用函数, 关闭返回通道可以停止调用
func (w *Watcher) Start() //开时watcher
func (w *Watcher) Stop() //开时watcher
func (w *Watcher) Reset() {} //重置代码watcher
func (w *Watcher) GetElapsedTime() time.Duration //get code excution elapsed time.
```
#### 7. netutil网络处理包
@@ -387,9 +393,11 @@ func Chunk(slice []interface{}, size int) [][]interface{} //均分slice
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
func Difference(slice1, slice2 interface{}) interface{} //返回
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //删除切片中start到end位置的值
func Drop(slice interface{}, n int) interface{} //创建一个新切片当n大于0时删除原切片前n个元素当n小于0时删除原切片后n个元素
func Every(slice, function interface{}) bool //slice中所有元素都符合函数条件时返回true, 否则返回false. 函数签名func(index int, value interface{}) bool
func Find(slice, function interface{}) interface{} //查找slice中第一个符合条件的元素函数签名func(index int, value interface{}) bool
func Find(slice, function interface{}) (interface{}, bool)//查找slice中第一个符合条件的元素函数签名func(index int, value interface{}) bool
func Filter(slice, function interface{}) interface{} //过滤slice, 函数签名func(index int, value interface{}) bool
func FlattenDeep(slice interface{}) interface{} //将slice递归为一维切片。
func IntSlice(slice interface{}) ([]int, error) //转成int切片
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
func Intersection(slices ...interface{}) interface{} //slice交集去重
@@ -397,6 +405,7 @@ func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名func(index int, value interface{}) interface{}
func ReverseSlice(slice interface{}) //反转切片
func Reduce(slice, function, zero interface{}) interface{} //切片reduce操作 函数签名func(index int, value1, value2 interface{}) interface{}
func Shuffle(slice interface{}) interface{} //创建一个被打乱值的切片
func Some(slice, function interface{}) bool //slice中任意一个元素都符合函数条件时返回true, 否则返回false. 函数签名func(index int, value interface{}) bool
func SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
func StringSlice(slice interface{}) []string //转为string切片
@@ -404,6 +413,7 @@ func Unique(slice interface{}) interface{} //去重切片
func Union(slices ...interface{}) interface{} //slice并集, 去重
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置更新value
func Without(slice interface{}, values ...interface{}) interface{} //slice去除values
func GroupBy(slice, function interface{}) (interface{}, interface{}) //根据函数function的逻辑分slice为两组slice
```
#### 10. strutil字符串处理包

View File

@@ -45,44 +45,34 @@ func ToChar(s string) []string {
// ToString convert value to string
func ToString(value interface{}) string {
var res string
res := ""
if value == nil {
return res
}
switch v := value.(type) {
case float64:
res = strconv.FormatFloat(v, 'f', -1, 64)
case float32:
res = strconv.FormatFloat(float64(v), 'f', -1, 64)
case int:
res = strconv.Itoa(v)
case uint:
res = strconv.Itoa(int(v))
case int8:
res = strconv.Itoa(int(v))
case uint8:
res = strconv.Itoa(int(v))
case int16:
res = strconv.Itoa(int(v))
case uint16:
res = strconv.Itoa(int(v))
case int32:
res = strconv.Itoa(int(v))
case uint32:
res = strconv.Itoa(int(v))
case int64:
res = strconv.FormatInt(v, 10)
case uint64:
res = strconv.FormatUint(v, 10)
v := reflect.ValueOf(value)
switch value.(type) {
case float32, float64:
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
return res
case int, int8, int16, int32, int64:
res = strconv.FormatInt(v.Int(), 10)
return res
case uint, uint8, uint16, uint32, uint64:
res = strconv.FormatUint(v.Uint(), 10)
return res
case string:
res = value.(string)
res = v.String()
return res
case []byte:
res = string(value.([]byte))
res = string(v.Bytes())
return res
default:
newValue, _ := json.Marshal(value)
res = string(newValue)
return res
}
return res
}
// ToJson convert value to a valid json string

View File

@@ -5,7 +5,7 @@ import (
"reflect"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestToChar(t *testing.T) {
@@ -18,7 +18,7 @@ func TestToChar(t *testing.T) {
for i := 0; i < len(cases); i++ {
res := ToChar(cases[i])
if !reflect.DeepEqual(res, expected[i]) {
utils.LogFailedTestInfo(t, "ToChar", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToChar", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -31,7 +31,7 @@ func TestToBool(t *testing.T) {
for i := 0; i < len(cases); i++ {
res, _ := ToBool(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToBool", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToBool", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -52,7 +52,7 @@ func TestToBytes(t *testing.T) {
res, _ := ToBytes(cases[i])
fmt.Println(res)
if !reflect.DeepEqual(res, expected[i]) {
utils.LogFailedTestInfo(t, "ToBytes", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToBytes", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -69,7 +69,7 @@ func TestToInt(t *testing.T) {
for i := 0; i < len(cases); i++ {
res, _ := ToInt(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToInt", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToInt", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -88,7 +88,7 @@ func TestToFloat(t *testing.T) {
for i := 0; i < len(cases); i++ {
res, _ := ToFloat(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToFloat", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToFloat", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -108,20 +108,25 @@ func TestToString(t *testing.T) {
aStruct := TestStruct{Name: "TestStruct"}
cases := []interface{}{
"", nil,
int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float64(12.3), float32(12.3),
true, false,
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111}}
expected := []string{"0", "1", "-1", "123", "123", "123", "123", "123",
"123", "123", "12.3", "12.300000190734863", "true", "false",
expected := []string{
"", "",
"0", "1", "-1",
"123", "123", "123", "123", "123", "123", "123",
"12.3", "12.300000190734863",
"true", "false",
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
for i := 0; i < len(cases); i++ {
res := ToString(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "ToString", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "ToString", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -136,7 +141,7 @@ func TestToJson(t *testing.T) {
mapJson := "{\"a\":1,\"b\":2,\"c\":3}"
r1, _ := ToJson(aMap)
if r1 != mapJson {
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
internal.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
t.FailNow()
}
@@ -148,7 +153,7 @@ func TestToJson(t *testing.T) {
structJson := "{\"Name\":\"TestStruct\"}"
r2, _ := ToJson(aStruct)
if r2 != structJson {
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
internal.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
t.FailNow()
}
}
@@ -170,7 +175,7 @@ func TestStructToMap(t *testing.T) {
//exp1["100"] = 100
if !reflect.DeepEqual(pm1, m1) {
utils.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
internal.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
t.FailNow()
}
@@ -185,7 +190,7 @@ func TestStructToMap(t *testing.T) {
m2["100"] = 100
if reflect.DeepEqual(pm2, m2) {
utils.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
internal.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
t.FailNow()
}
}
@@ -197,7 +202,7 @@ func TestColorHexToRGB(t *testing.T) {
expected := "0,51,102"
if colorRGB != expected {
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
internal.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
t.FailNow()
}
}
@@ -211,7 +216,7 @@ func TestColorRGBToHex(t *testing.T) {
expected := "#003366"
if colorHex != expected {
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
internal.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
t.FailNow()
}
}

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestAesEcbEncrypt(t *testing.T) {
@@ -14,7 +14,7 @@ func TestAesEcbEncrypt(t *testing.T) {
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
if string(aesEcbDecrypt) != data {
utils.LogFailedTestInfo(t, "AesEcbEncrypt/AesEcbDecrypt", data, data, string(aesEcbDecrypt))
internal.LogFailedTestInfo(t, "AesEcbEncrypt/AesEcbDecrypt", data, data, string(aesEcbDecrypt))
t.FailNow()
}
}
@@ -27,7 +27,7 @@ func TestAesCbcEncrypt(t *testing.T) {
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
if string(aesCbcDecrypt) != data {
utils.LogFailedTestInfo(t, "AesCbcEncrypt/AesCbcDecrypt", data, data, string(aesCbcDecrypt))
internal.LogFailedTestInfo(t, "AesCbcEncrypt/AesCbcDecrypt", data, data, string(aesCbcDecrypt))
t.FailNow()
}
}
@@ -40,7 +40,7 @@ func TestAesCtrCrypt(t *testing.T) {
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
if string(aesCtrDeCrypt) != data {
utils.LogFailedTestInfo(t, "AesCtrCrypt", data, data, string(aesCtrDeCrypt))
internal.LogFailedTestInfo(t, "AesCtrCrypt", data, data, string(aesCtrDeCrypt))
t.FailNow()
}
}
@@ -53,7 +53,7 @@ func TestAesCfbEncrypt(t *testing.T) {
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
if string(aesCfbDecrypt) != data {
utils.LogFailedTestInfo(t, "AesCfbEncrypt/AesCfbDecrypt", data, data, string(aesCfbDecrypt))
internal.LogFailedTestInfo(t, "AesCfbEncrypt/AesCfbDecrypt", data, data, string(aesCfbDecrypt))
t.FailNow()
}
}
@@ -66,7 +66,7 @@ func TestAesOfbEncrypt(t *testing.T) {
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
if string(aesOfbDecrypt) != data {
utils.LogFailedTestInfo(t, "AesOfbEncrypt/AesOfbDecrypt", data, data, string(aesOfbDecrypt))
internal.LogFailedTestInfo(t, "AesOfbEncrypt/AesOfbDecrypt", data, data, string(aesOfbDecrypt))
t.FailNow()
}
}

View File

@@ -5,7 +5,7 @@ import (
"os"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestBase64StdEncode(t *testing.T) {
@@ -13,7 +13,7 @@ func TestBase64StdEncode(t *testing.T) {
bs := Base64StdEncode(s)
if bs != "aGVsbG8gd29ybGQ=" {
utils.LogFailedTestInfo(t, "Base64StdEncode", s, "aGVsbG8gd29ybGQ=", bs)
internal.LogFailedTestInfo(t, "Base64StdEncode", s, "aGVsbG8gd29ybGQ=", bs)
t.FailNow()
}
}
@@ -23,7 +23,7 @@ func TestBase64StdDecode(t *testing.T) {
s := Base64StdDecode(bs)
if s != "hello world" {
utils.LogFailedTestInfo(t, "Base64StdDecode", bs, "hello world=", s)
internal.LogFailedTestInfo(t, "Base64StdDecode", bs, "hello world=", s)
t.FailNow()
}
}
@@ -34,7 +34,7 @@ func TestMd5String(t *testing.T) {
expected := "5d41402abc4b2a76b9719d911017c592"
if smd5 != expected {
utils.LogFailedTestInfo(t, "Md5String", s, expected, smd5)
internal.LogFailedTestInfo(t, "Md5String", s, expected, smd5)
t.FailNow()
}
}
@@ -58,7 +58,7 @@ func TestHmacMd5(t *testing.T) {
expected := "5f4c9faaff0a1ad3007d9ddc06abe36d"
if hmacMd5 != expected {
utils.LogFailedTestInfo(t, "HmacMd5", s, expected, hmacMd5)
internal.LogFailedTestInfo(t, "HmacMd5", s, expected, hmacMd5)
t.FailNow()
}
}
@@ -70,7 +70,7 @@ func TestHmacSha1(t *testing.T) {
expected := "3826f812255d8683f051ee97346d1359234d5dbd"
if hmacSha1 != expected {
utils.LogFailedTestInfo(t, "HmacSha1", s, expected, hmacSha1)
internal.LogFailedTestInfo(t, "HmacSha1", s, expected, hmacSha1)
t.FailNow()
}
}
@@ -82,7 +82,7 @@ func TestHmacSha256(t *testing.T) {
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
if hmacSha256 != expected {
utils.LogFailedTestInfo(t, "HmacSha256", s, expected, hmacSha256)
internal.LogFailedTestInfo(t, "HmacSha256", s, expected, hmacSha256)
t.FailNow()
}
}
@@ -94,7 +94,7 @@ func TestHmacSha512(t *testing.T) {
expected := "5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175"
if hmacSha512 != expected {
utils.LogFailedTestInfo(t, "HmacSha512", s, expected, hmacSha512)
internal.LogFailedTestInfo(t, "HmacSha512", s, expected, hmacSha512)
t.FailNow()
}
}
@@ -105,7 +105,7 @@ func TestSha1(t *testing.T) {
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
if sha1 != expected {
utils.LogFailedTestInfo(t, "Sha1", s, expected, sha1)
internal.LogFailedTestInfo(t, "Sha1", s, expected, sha1)
t.FailNow()
}
}
@@ -116,7 +116,7 @@ func TestSha256(t *testing.T) {
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
if sha256 != expected {
utils.LogFailedTestInfo(t, "Sha256", s, expected, sha256)
internal.LogFailedTestInfo(t, "Sha256", s, expected, sha256)
t.FailNow()
}
}
@@ -127,7 +127,7 @@ func TestSha512(t *testing.T) {
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
if sha512 != expected {
utils.LogFailedTestInfo(t, "Sha512", s, expected, sha512)
internal.LogFailedTestInfo(t, "Sha512", s, expected, sha512)
t.FailNow()
}
}

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestDesEcbEncrypt(t *testing.T) {
@@ -14,7 +14,7 @@ func TestDesEcbEncrypt(t *testing.T) {
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
if string(desEcbDecrypt) != data {
utils.LogFailedTestInfo(t, "DesEcbEncrypt/DesEcbDecrypt", data, data, string(desEcbDecrypt))
internal.LogFailedTestInfo(t, "DesEcbEncrypt/DesEcbDecrypt", data, data, string(desEcbDecrypt))
t.FailNow()
}
}
@@ -27,7 +27,7 @@ func TestDesCbcEncrypt(t *testing.T) {
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
if string(desCbcDecrypt) != data {
utils.LogFailedTestInfo(t, "DesCbcEncrypt/DesCbcDecrypt", data, data, string(desCbcDecrypt))
internal.LogFailedTestInfo(t, "DesCbcEncrypt/DesCbcDecrypt", data, data, string(desCbcDecrypt))
t.FailNow()
}
}
@@ -40,7 +40,7 @@ func TestDesCtrCrypt(t *testing.T) {
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
if string(desCtrDeCrypt) != data {
utils.LogFailedTestInfo(t, "DesCtrCrypt", data, data, string(desCtrDeCrypt))
internal.LogFailedTestInfo(t, "DesCtrCrypt", data, data, string(desCtrDeCrypt))
t.FailNow()
}
}
@@ -53,7 +53,7 @@ func TestDesCfbEncrypt(t *testing.T) {
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
if string(desCfbDecrypt) != data {
utils.LogFailedTestInfo(t, "DesCfbEncrypt/DesCfbDecrypt", data, data, string(desCfbDecrypt))
internal.LogFailedTestInfo(t, "DesCfbEncrypt/DesCfbDecrypt", data, data, string(desCfbDecrypt))
t.FailNow()
}
}
@@ -66,7 +66,7 @@ func TestDesOfbEncrypt(t *testing.T) {
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
if string(desOfbDecrypt) != data {
utils.LogFailedTestInfo(t, "DesOfbEncrypt/DesOfbDecrypt", data, data, string(desOfbDecrypt))
internal.LogFailedTestInfo(t, "DesOfbEncrypt/DesOfbDecrypt", data, data, string(desOfbDecrypt))
t.FailNow()
}
}

View File

@@ -3,7 +3,7 @@ package cryptor
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestRsaEncrypt(t *testing.T) {
@@ -13,7 +13,7 @@ func TestRsaEncrypt(t *testing.T) {
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
if string(data) != string(decrypted) {
utils.LogFailedTestInfo(t, "RsaEncrypt/RsaDecrypt", string(data), string(data), string(decrypted))
internal.LogFailedTestInfo(t, "RsaEncrypt/RsaDecrypt", string(data), string(data), string(decrypted))
t.FailNow()
}
}

View File

@@ -25,7 +25,7 @@
package datetime
import (
"strconv"
"fmt"
"time"
)
@@ -56,24 +56,17 @@ func init() {
// AddMinute add or sub minute to the time
func AddMinute(t time.Time, minute int64) time.Time {
s := strconv.FormatInt(minute, 10)
m, _ := time.ParseDuration(s + "m")
return t.Add(m)
return t.Add(time.Minute * time.Duration(minute))
}
// AddHour add or sub hour to the time
func AddHour(t time.Time, hour int64) time.Time {
s := strconv.FormatInt(hour, 10)
h, _ := time.ParseDuration(s + "h")
return t.Add(h)
return t.Add(time.Hour * time.Duration(hour))
}
// AddDay add or sub day to the time
func AddDay(t time.Time, day int64) time.Time {
dayHours := day * 24
d := strconv.FormatInt(dayHours, 10)
h, _ := time.ParseDuration(d + "h")
return t.Add(h)
return t.Add(24 * time.Hour * time.Duration(day))
}
// GetNowDate return format yyyy-mm-dd of current date
@@ -109,7 +102,11 @@ func FormatTimeToStr(t time.Time, format string) string {
}
// FormatStrToTime convert string to time
func FormatStrToTime(str, format string) time.Time {
t, _ := time.Parse(timeFormat[format], str)
return t
func FormatStrToTime(str, format string) (time.Time, error) {
v, ok := timeFormat[format]
if !ok {
return time.Time{}, fmt.Errorf("format %s not found", format)
}
return time.Parse(v, str)
}

View File

@@ -1,7 +1,7 @@
package datetime
import (
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
"testing"
"time"
)
@@ -12,14 +12,14 @@ func TestAddDay(t *testing.T) {
after2Days := AddDay(now, 2)
diff1 := after2Days.Sub(now)
if diff1.Hours() != 48 {
utils.LogFailedTestInfo(t, "AddDay", now, 48, diff1.Hours())
internal.LogFailedTestInfo(t, "AddDay", now, 48, diff1.Hours())
t.FailNow()
}
before2Days := AddDay(now, -2)
diff2 := before2Days.Sub(now)
if diff2.Hours() != -48 {
utils.LogFailedTestInfo(t, "AddDay", now, -48, diff2.Hours())
internal.LogFailedTestInfo(t, "AddDay", now, -48, diff2.Hours())
t.FailNow()
}
@@ -30,14 +30,14 @@ func TestAddHour(t *testing.T) {
after2Hours := AddHour(now, 2)
diff1 := after2Hours.Sub(now)
if diff1.Hours() != 2 {
utils.LogFailedTestInfo(t, "AddHour", now, 2, diff1.Hours())
internal.LogFailedTestInfo(t, "AddHour", now, 2, diff1.Hours())
t.FailNow()
}
before2Hours := AddHour(now, -2)
diff2 := before2Hours.Sub(now)
if diff2.Hours() != -2 {
utils.LogFailedTestInfo(t, "AddHour", now, -2, diff2.Hours())
internal.LogFailedTestInfo(t, "AddHour", now, -2, diff2.Hours())
t.FailNow()
}
}
@@ -48,14 +48,14 @@ func TestAddMinute(t *testing.T) {
after2Minutes := AddMinute(now, 2)
diff1 := after2Minutes.Sub(now)
if diff1.Minutes() != 2 {
utils.LogFailedTestInfo(t, "AddMinute", now, 2, diff1.Minutes())
internal.LogFailedTestInfo(t, "AddMinute", now, 2, diff1.Minutes())
t.FailNow()
}
before2Minutes := AddMinute(now, -2)
diff2 := before2Minutes.Sub(now)
if diff2.Minutes() != -2 {
utils.LogFailedTestInfo(t, "AddMinute", now, -2, diff2.Minutes())
internal.LogFailedTestInfo(t, "AddMinute", now, -2, diff2.Minutes())
t.FailNow()
}
}
@@ -64,7 +64,7 @@ func TestGetNowDate(t *testing.T) {
date := GetNowDate()
expected := time.Now().Format("2006-01-02")
if date != expected {
utils.LogFailedTestInfo(t, "GetNowDate", "", expected, date)
internal.LogFailedTestInfo(t, "GetNowDate", "", expected, date)
t.FailNow()
}
}
@@ -73,7 +73,7 @@ func TestGetNotTime(t *testing.T) {
ts := GetNowTime()
expected := time.Now().Format("15:04:05")
if ts != expected {
utils.LogFailedTestInfo(t, "GetNowTime", "", expected, ts)
internal.LogFailedTestInfo(t, "GetNowTime", "", expected, ts)
t.FailNow()
}
}
@@ -82,7 +82,7 @@ func TestGetNowDateTime(t *testing.T) {
ts := GetNowDateTime()
expected := time.Now().Format("2006-01-02 15:04:05")
if ts != expected {
utils.LogFailedTestInfo(t, "GetNowDateTime", "", expected, ts)
internal.LogFailedTestInfo(t, "GetNowDateTime", "", expected, ts)
t.FailNow()
}
}
@@ -112,7 +112,7 @@ func TestFormatTimeToStr(t *testing.T) {
for i := 0; i < len(cases); i++ {
res := FormatTimeToStr(datetime, cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -135,10 +135,13 @@ func TestFormatStrToTime(t *testing.T) {
"2021/01"}
for i := 0; i < len(cases); i++ {
res := FormatStrToTime(datetimeStr[i], cases[i])
res, err := FormatStrToTime(datetimeStr[i], cases[i])
if err != nil {
t.Fatal(err)
}
expected, _ := time.Parse(formats[i], datetimeStr[i])
if res != expected {
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
internal.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
t.FailNow()
}
}

View File

@@ -5,7 +5,7 @@ import (
"reflect"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestIsExist(t *testing.T) {
@@ -15,7 +15,7 @@ func TestIsExist(t *testing.T) {
for i := 0; i < len(cases); i++ {
res := IsExist(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "IsExist", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "IsExist", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -26,15 +26,15 @@ func TestCreateFile(t *testing.T) {
if CreateFile(f) {
file, err := os.Open(f)
if err != nil {
utils.LogFailedTestInfo(t, "CreateFile", f, f, "create file error: "+err.Error())
internal.LogFailedTestInfo(t, "CreateFile", f, f, "create file error: "+err.Error())
t.FailNow()
}
if file.Name() != f {
utils.LogFailedTestInfo(t, "CreateFile", f, f, file.Name())
internal.LogFailedTestInfo(t, "CreateFile", f, f, file.Name())
t.FailNow()
}
} else {
utils.LogFailedTestInfo(t, "CreateFile", f, f, "create file error")
internal.LogFailedTestInfo(t, "CreateFile", f, f, "create file error")
t.FailNow()
}
}
@@ -46,7 +46,7 @@ func TestIsDir(t *testing.T) {
for i := 0; i < len(cases); i++ {
res := IsDir(cases[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "IsDir", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "IsDir", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -57,11 +57,11 @@ func TestRemoveFile(t *testing.T) {
if CreateFile(f) {
err := RemoveFile(f)
if err != nil {
utils.LogFailedTestInfo(t, "RemoveFile", f, f, err.Error())
internal.LogFailedTestInfo(t, "RemoveFile", f, f, err.Error())
t.FailNow()
}
} else {
utils.LogFailedTestInfo(t, "RemoveFile", f, f, "create file error")
internal.LogFailedTestInfo(t, "RemoveFile", f, f, "create file error")
t.FailNow()
}
}
@@ -76,11 +76,11 @@ func TestCopyFile(t *testing.T) {
if err != nil {
file, err := os.Open(dstFile)
if err != nil {
utils.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, "create file error: "+err.Error())
internal.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, "create file error: "+err.Error())
t.FailNow()
}
if file.Name() != dstFile {
utils.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, file.Name())
internal.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, file.Name())
t.FailNow()
}
}
@@ -93,7 +93,7 @@ func TestListFileNames(t *testing.T) {
}
expected := []string{"datetime.go", "datetime_test.go"}
if !reflect.DeepEqual(filesInCurrentPath, expected) {
utils.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
internal.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
t.FailNow()
}
}
@@ -106,7 +106,7 @@ func TestReadFileToString(t *testing.T) {
res, _ := ReadFileToString(path)
if res != "hello world" {
utils.LogFailedTestInfo(t, "ReadFileToString", path, "hello world", res)
internal.LogFailedTestInfo(t, "ReadFileToString", path, "hello world", res)
}
}
@@ -120,7 +120,7 @@ func TestClearFile(t *testing.T) {
res, _ := ReadFileToString(path)
if res != "" {
utils.LogFailedTestInfo(t, "CreateFile", path, "", res)
internal.LogFailedTestInfo(t, "CreateFile", path, "", res)
}
}
@@ -133,6 +133,6 @@ func TestReadFileByLine(t *testing.T) {
expected := []string{"hello", "world"}
res, _ := ReadFileByLine(path)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "ReadFileByLine", path, expected, res)
internal.LogFailedTestInfo(t, "ReadFileByLine", path, expected, res)
}
}

View File

@@ -3,7 +3,7 @@ package formatter
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestComma(t *testing.T) {
@@ -22,7 +22,7 @@ func TestComma(t *testing.T) {
func comma(t *testing.T, test interface{}, symbol string, expected interface{}) {
res := Comma(test, symbol)
if res != expected {
utils.LogFailedTestInfo(t, "Comma", test, expected, res)
internal.LogFailedTestInfo(t, "Comma", test, expected, res)
t.FailNow()
}
}

View File

@@ -11,10 +11,12 @@ import (
// After creates a function that invokes func once it's called n or more times
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
return func(args ...interface{}) []reflect.Value {
n--
if n < 1 {
return invokeFunc(fn, args...)
return unsafeInvokeFunc(fn, args...)
}
return nil
}
@@ -22,11 +24,12 @@ func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
// Before creates a function that invokes func once it's called less than n times
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
var res []reflect.Value
return func(args ...interface{}) []reflect.Value {
if n > 0 {
res = invokeFunc(fn, args...)
res = unsafeInvokeFunc(fn, args...)
}
if n <= 0 {
fn = nil
@@ -69,11 +72,12 @@ func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
// Schedule invoke function every duration time, util close the returned bool chan
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
// Catch programming error while constructing the closure
mustBeFunction(fn)
quit := make(chan bool)
go func() {
for {
invokeFunc(fn, args...)
unsafeInvokeFunc(fn, args...)
select {
case <-time.After(d):
case <-quit:

View File

@@ -14,6 +14,15 @@ func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
return fv.Call(params)
}
func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
params[i] = reflect.ValueOf(item)
}
return fv.Call(params)
}
func functionValue(function interface{}) reflect.Value {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
@@ -21,3 +30,10 @@ func functionValue(function interface{}) reflect.Value {
}
return v
}
func mustBeFunction(function interface{}) {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
}
}

37
function/watcher.go Normal file
View File

@@ -0,0 +1,37 @@
package function
import "time"
// Watcher is used for record code excution time
type Watcher struct {
startTime int64
stopTime int64
excuting bool
}
// Start the watch timer.
func (w *Watcher) Start() {
w.startTime = time.Now().UnixNano()
w.excuting = true
}
// Stop the watch timer.
func (w *Watcher) Stop() {
w.stopTime = time.Now().UnixNano()
w.excuting = false
}
// GetElapsedTime get excute elapsed time.
func (w *Watcher) GetElapsedTime() time.Duration {
if w.excuting {
return time.Duration(time.Now().UnixNano() - w.startTime)
}
return time.Duration(w.stopTime - w.startTime)
}
// Reset the watch timer.
func (w *Watcher) Reset() {
w.startTime = 0
w.stopTime = 0
w.excuting = false
}

32
function/watcher_test.go Normal file
View File

@@ -0,0 +1,32 @@
package function
import (
"testing"
)
func TestWatcher(t *testing.T) {
w := &Watcher{}
w.Start()
longRunningTask()
if !w.excuting {
t.FailNow()
}
w.Stop()
eapsedTime := w.GetElapsedTime().Milliseconds()
t.Log("Elapsed Time (milsecond)", eapsedTime)
if w.excuting {
t.FailNow()
}
}
func longRunningTask() {
var slice []int64
for i := 0; i < 10000000; i++ {
slice = append(slice, int64(i))
}
}

View File

@@ -1,8 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package utils implements is for internal use.
package utils
// Package internal is for internal use.
package internal
import (
"fmt"

View File

@@ -5,14 +5,14 @@ import (
"net"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestGetInternalIp(t *testing.T) {
internalIp := GetInternalIp()
ip := net.ParseIP(internalIp)
if ip == nil {
utils.LogFailedTestInfo(t, "GetInternalIp", "GetInternalIp", "", ip)
internal.LogFailedTestInfo(t, "GetInternalIp", "GetInternalIp", "", ip)
t.FailNow()
}
}
@@ -40,7 +40,7 @@ func TestIsPublicIP(t *testing.T) {
res := IsPublicIP(ips[i])
if res != expected[i] {
utils.LogFailedTestInfo(t, "IsPublicIP", ips[i], expected[i], res)
internal.LogFailedTestInfo(t, "IsPublicIP", ips[i], expected[i], res)
t.FailNow()
}
}

View File

@@ -22,27 +22,27 @@ import (
//HttpGet send get http request
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
return request(http.MethodGet, url, params...)
return doHttpRequest(http.MethodGet, url, params...)
}
//HttpPost send post http request
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
return request(http.MethodPost, url, params...)
return doHttpRequest(http.MethodPost, url, params...)
}
//HttpPut send put http request
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
return request(http.MethodPut, url, params...)
return doHttpRequest(http.MethodPut, url, params...)
}
//HttpDelete send delete http request
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
return request(http.MethodDelete, url, params...)
return doHttpRequest(http.MethodDelete, url, params...)
}
// HttpPatch send patch http request
func HttpPatch(url string, params ...interface{}) (*http.Response, error) {
return request(http.MethodPatch, url, params...)
return doHttpRequest(http.MethodPatch, url, params...)
}
// ParseHttpResponse decode http response to specified interface

View File

@@ -7,40 +7,37 @@ import (
"log"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestHttpGet(t *testing.T) {
_, e := HttpGet("", nil)
if e == nil {
t.FailNow()
url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{
"Content-Type": "application/json",
}
url := "https://gutendex.com/books?"
queryParams := make(map[string]interface{})
queryParams["ids"] = "1"
resp, err := HttpGet(url, nil, queryParams)
resp, err := HttpGet(url, header)
if err != nil {
fmt.Println("error: ", err)
//t.FailNow()
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response: ", resp.StatusCode, string(body))
}
func TestHttpPost(t *testing.T) {
url := "http://api.postcodes.io/postcodes"
type Postcode struct {
Postcodes []string `json:"postcodes"`
}
postcode := Postcode{[]string{"OX49 5NU"}}
bodyParams, _ := json.Marshal(postcode)
url := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
"Content-Type": "application/json",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, "TestAddToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := HttpPost(url, header, nil, bodyParams)
if err != nil {
log.Fatal(err)
@@ -51,34 +48,55 @@ func TestHttpPost(t *testing.T) {
}
func TestHttpPut(t *testing.T) {
url := "http://public-api-v1.aspirantzhang.com/users/10420"
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
user := User{
"test",
"test@test.com",
}
bodyParams, _ := json.Marshal(user)
url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{
"Content-Type": "application/json",
}
type Todo struct {
Id int `json:"id"`
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, 1, "TestPutToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := HttpPut(url, header, nil, bodyParams)
if err != nil {
fmt.Println("error: ", err)
//t.FailNow()
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response: ", resp.StatusCode, string(body))
}
func TestHttpPatch(t *testing.T) {
url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{
"Content-Type": "application/json",
}
type Todo struct {
Id int `json:"id"`
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, 1, "TestPatchToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := HttpPatch(url, header, nil, bodyParams)
if err != nil {
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response: ", resp.StatusCode, string(body))
}
func TestHttpDelete(t *testing.T) {
url := "http://public-api-v1.aspirantzhang.com/users/10420"
url := "https://jsonplaceholder.typicode.com/todos/1"
resp, err := HttpDelete(url)
if err != nil {
fmt.Println("error: ", err)
//t.FailNow()
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response: ", resp.StatusCode, string(body))
@@ -94,31 +112,35 @@ func TestConvertMapToQueryString(t *testing.T) {
expected := "a=1&b=2&c=3"
r := ConvertMapToQueryString(m)
if r != expected {
utils.LogFailedTestInfo(t, "ConvertMapToQueryString", m, expected, r)
internal.LogFailedTestInfo(t, "ConvertMapToQueryString", m, expected, r)
t.FailNow()
}
}
func TestParseResponse(t *testing.T) {
url := "http://public-api-v1.aspirantzhang.com/users"
type User struct {
Id int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{
"Content-Type": "application/json",
}
type UserResp struct {
Data []User `json:"data"`
}
resp, err := HttpGet(url)
resp, err := HttpGet(url, header)
if err != nil {
log.Fatal(err)
t.FailNow()
}
userResp := &UserResp{}
err = ParseHttpResponse(resp, userResp)
type Todo struct {
Id int `json:"id"`
UserId int `json:"userId"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
toDoResp := &Todo{}
err = ParseHttpResponse(resp, toDoResp)
if err != nil {
log.Fatal(err)
t.FailNow()
}
fmt.Println(userResp.Data)
fmt.Println("response: ", toDoResp)
}

View File

@@ -10,7 +10,7 @@ import (
"strings"
)
func request(method, reqUrl string, params ...interface{}) (*http.Response, error) {
func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response, error) {
if len(reqUrl) == 0 {
return nil, errors.New("url should be specified")
}
@@ -24,53 +24,29 @@ func request(method, reqUrl string, params ...interface{}) (*http.Response, erro
}
client := &http.Client{}
err := setUrl(req, reqUrl)
if err != nil {
return nil, err
}
switch len(params) {
case 0:
err := setUrl(req, reqUrl)
if err != nil {
return nil, err
}
case 1:
err := setUrl(req, reqUrl)
if err != nil {
return nil, err
}
err = setHeader(req, params[0])
if err != nil {
return nil, err
}
case 2:
err := setHeader(req, params[0])
if err != nil {
return nil, err
}
err = setQueryParam(req, reqUrl, params[1])
err := setHeaderAndQueryParam(req, reqUrl, params[0], params[1])
if err != nil {
return nil, err
}
case 3:
err := setHeader(req, params[0])
if err != nil {
return nil, err
}
err = setQueryParam(req, reqUrl, params[1])
if err != nil {
return nil, err
}
err = setBodyByte(req, params[2])
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
if err != nil {
return nil, err
}
case 4:
err := setHeader(req, params[0])
if err != nil {
return nil, err
}
err = setQueryParam(req, reqUrl, params[1])
if err != nil {
return nil, err
}
err = setBodyByte(req, params[2])
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
if err != nil {
return nil, err
}
@@ -78,13 +54,40 @@ func request(method, reqUrl string, params ...interface{}) (*http.Response, erro
if err != nil {
return nil, err
}
}
resp, e := client.Do(req)
return resp, e
}
func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam interface{}) error {
err := setHeader(req, header)
if err != nil {
return err
}
err = setQueryParam(req, reqUrl, queryParam)
if err != nil {
return err
}
return nil
}
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body interface{}) error {
err := setHeader(req, header)
if err != nil {
return err
}
err = setQueryParam(req, reqUrl, queryParam)
if err != nil {
return err
}
err = setBodyByte(req, body)
if err != nil {
return err
}
return nil
}
func setHeader(req *http.Request, header interface{}) error {
if header != nil {
switch v := header.(type) {
@@ -109,6 +112,7 @@ func setHeader(req *http.Request, header interface{}) error {
return nil
}
func setUrl(req *http.Request, reqUrl string) error {
u, err := url.Parse(reqUrl)
if err != nil {
@@ -117,6 +121,7 @@ func setUrl(req *http.Request, reqUrl string) error {
req.URL = u
return nil
}
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
var values url.Values
if queryParam != nil {

View File

@@ -14,7 +14,7 @@ import (
"regexp"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestRandString(t *testing.T) {
@@ -24,7 +24,7 @@ func TestRandString(t *testing.T) {
reg := regexp.MustCompile(pattern)
if len(randStr) != 6 || !reg.MatchString(randStr) {
utils.LogFailedTestInfo(t, "RandString", "RandString(6)", "RandString(6) should be 6 letters ", randStr)
internal.LogFailedTestInfo(t, "RandString", "RandString(6)", "RandString(6) should be 6 letters ", randStr)
t.FailNow()
}
}
@@ -32,19 +32,19 @@ func TestRandString(t *testing.T) {
func TestRandInt(t *testing.T) {
res1 := RandInt(1, 10)
if res1 < 1 || res1 >= 10 {
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", res1)
internal.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", res1)
t.FailNow()
}
res2 := RandInt(1, 1)
if res2 != 1 {
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 1)", "RandInt(1, 1) should be 1 ", res2)
internal.LogFailedTestInfo(t, "RandInt", "RandInt(1, 1)", "RandInt(1, 1) should be 1 ", res2)
t.FailNow()
}
res3 := RandInt(10, 1)
if res3 < 1 || res3 >= 10 {
utils.LogFailedTestInfo(t, "RandInt", "RandInt(10, 1)", "RandInt(10, 1) should between [1, 10) ", res3)
internal.LogFailedTestInfo(t, "RandInt", "RandInt(10, 1)", "RandInt(10, 1) should between [1, 10) ", res3)
t.FailNow()
}
}
@@ -52,19 +52,19 @@ func TestRandInt(t *testing.T) {
func TestRandBytes(t *testing.T) {
randBytes := RandBytes(4)
if len(randBytes) != 4 {
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
internal.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
t.FailNow()
}
v := reflect.ValueOf(randBytes)
et := v.Type().Elem()
if v.Kind() != reflect.Slice || et.Kind() != reflect.Uint8 {
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
internal.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
t.FailNow()
}
randErr := RandBytes(0)
if randErr != nil {
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(0)", "RandBytes(0) should return nil", randErr)
internal.LogFailedTestInfo(t, "RandBytes", "RandBytes(0)", "RandBytes(0) should return nil", randErr)
t.FailNow()
}

View File

@@ -7,16 +7,20 @@ package slice
import (
"errors"
"fmt"
"math"
"math/rand"
"reflect"
"sort"
"strings"
"unsafe"
)
// Contain check if the value is in the slice or not
func Contain(slice interface{}, value interface{}) bool {
v := reflect.ValueOf(slice)
switch reflect.TypeOf(slice).Kind() {
// Contain check if the value is in the iterable type or not
func Contain(iterableType interface{}, value interface{}) bool {
v := reflect.ValueOf(iterableType)
switch kind := reflect.TypeOf(iterableType).Kind(); kind {
case reflect.Slice, reflect.Array:
for i := 0; i < v.Len(); i++ {
if v.Index(i).Interface() == value {
@@ -29,9 +33,15 @@ func Contain(slice interface{}, value interface{}) bool {
return true
}
case reflect.String:
s := fmt.Sprintf("%v", slice)
ss := fmt.Sprintf("%v", value)
s := iterableType.(string)
ss, ok := value.(string)
if !ok {
panic("kind mismatch")
}
return strings.Contains(s, ss)
default:
panic(fmt.Sprintf("kind %s is not support", iterableType))
}
return false
@@ -100,15 +110,15 @@ func Every(slice, function interface{}) bool {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
var indexes []int
var currentLength int
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
indexes = append(indexes, i)
currentLength++
}
}
return len(indexes) == sv.Len()
return currentLength == sv.Len()
}
// Some return true if any of the values in the list pass the predicate function.
@@ -159,9 +169,9 @@ func Filter(slice, function interface{}) interface{} {
return res.Interface()
}
// Find iterates over elements of slice, returning the first one that passes a truth test on function.
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
// The function signature should be func(index int, value interface{}) bool .
func Find(slice, function interface{}) interface{} {
func GroupBy(slice, function interface{}) (interface{}, interface{}) {
sv := sliceValue(slice)
fn := functionValue(function)
@@ -170,7 +180,33 @@ func Find(slice, function interface{}) interface{} {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
var index int
groupB := reflect.MakeSlice(sv.Type(), 0, 0)
groupA := reflect.MakeSlice(sv.Type(), 0, 0)
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
groupA = reflect.Append(groupA, sv.Index(i))
} else {
groupB = reflect.Append(groupB, sv.Index(i))
}
}
return groupA.Interface(), groupB.Interface()
}
// Find iterates over elements of slice, returning the first one that passes a truth test on function.
// The function signature should be func(index int, value interface{}) bool .
func Find(slice, function interface{}) (interface{}, bool) {
sv := sliceValue(slice)
fn := functionValue(function)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
index := -1
for i := 0; i < sv.Len(); i++ {
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
if flag.Bool() {
@@ -178,7 +214,37 @@ func Find(slice, function interface{}) interface{} {
break
}
}
return sv.Index(index).Interface()
if index == -1 {
var none interface{}
return none, false
}
return sv.Index(index).Interface(), true
}
// FlattenDeep flattens slice recursive
func FlattenDeep(slice interface{}) interface{} {
sv := sliceValue(slice)
st := sliceElemType(sv.Type())
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
res := flattenRecursive(sv, tmp)
return res.Interface()
}
func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
for i := 0; i < value.Len(); i++ {
item := value.Index(i)
kind := item.Kind()
if kind == reflect.Slice {
result = flattenRecursive(item, result)
} else {
result = reflect.Append(result, item)
}
}
return result
}
// Map creates an slice of values by running each element of `slice` thru `function`.
@@ -252,32 +318,34 @@ func InterfaceSlice(slice interface{}) []interface{} {
// StringSlice convert param to slice of string.
func StringSlice(slice interface{}) []string {
var res []string
v := sliceValue(slice)
out := make([]string, v.Len())
for i := 0; i < v.Len(); i++ {
res = append(res, fmt.Sprint(v.Index(i)))
v, ok := v.Index(i).Interface().(string)
if !ok {
panic("invalid element type")
}
out[i] = v
}
return res
return out
}
// IntSlice convert param to slice of int.
func IntSlice(slice interface{}) ([]int, error) {
var res []int
func IntSlice(slice interface{}) []int {
sv := sliceValue(slice)
out := make([]int, sv.Len())
for i := 0; i < sv.Len(); i++ {
v := sv.Index(i).Interface()
switch v := v.(type) {
case int:
res = append(res, v)
default:
return nil, errors.New("InvalidSliceElementType")
v, ok := sv.Index(i).Interface().(int)
if !ok {
panic("invalid element type")
}
out[i] = v
}
return res, nil
return out
}
// ConvertSlice convert original slice to new data type element of slice.
@@ -322,6 +390,37 @@ func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error
return v.Interface(), nil
}
// Drop creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0
func Drop(slice interface{}, n int) interface{} {
sv := sliceValue(slice)
if n == 0 {
return slice
}
svLen := sv.Len()
if math.Abs(float64(n)) >= float64(svLen) {
return reflect.MakeSlice(sv.Type(), 0, 0).Interface()
}
if n > 0 {
res := reflect.MakeSlice(sv.Type(), svLen-n, svLen-n)
for i := 0; i < res.Len(); i++ {
res.Index(i).Set(sv.Index(i + n))
}
return res.Interface()
}
res := reflect.MakeSlice(sv.Type(), svLen+n, svLen+n)
for i := 0; i < res.Len(); i++ {
res.Index(i).Set(sv.Index(i))
}
return res.Interface()
}
// InsertByIndex insert the element into slice at index.
// Insert value: s = append(s[:i], append([]T{x}, s[i:]...)...)
// Insert slice: a = append(a[:i], append(b, a[i:]...)...)
@@ -363,6 +462,7 @@ func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}
if index < 0 || index >= v.Len() {
return slice, errors.New("InvalidSliceIndex")
}
if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return slice, errors.New("InvalidValueType")
}
@@ -380,7 +480,7 @@ func Unique(slice interface{}) interface{} {
}
var temp []interface{}
len := 0
for i := 0; i < sv.Len(); i++ {
v := sv.Index(i).Interface()
skip := true
@@ -392,12 +492,11 @@ func Unique(slice interface{}) interface{} {
}
if skip {
temp = append(temp, v)
len++
}
}
res := reflect.MakeSlice(sv.Type(), len, len)
for i := 0; i < len; i++ {
res := reflect.MakeSlice(sv.Type(), len(temp), len(temp))
for i := 0; i < len(temp); i++ {
res.Index(i).Set(reflect.ValueOf(temp[i]))
}
return res.Interface()
@@ -423,21 +522,21 @@ func Union(slices ...interface{}) interface{} {
return nil
}
// append all slices, then unique it
var allSlice []interface{}
var allSlices []interface{}
len := 0
for i := range slices {
sv := sliceValue(slices[i])
len += sv.Len()
for j := 0; j < sv.Len(); j++ {
v := sv.Index(j).Interface()
allSlice = append(allSlice, v)
allSlices = append(allSlices, v)
}
}
sv := sliceValue(slices[0])
res := reflect.MakeSlice(sv.Type(), len, len)
for i := 0; i < len; i++ {
res.Index(i).Set(reflect.ValueOf(allSlice[i]))
res.Index(i).Set(reflect.ValueOf(allSlices[i]))
}
return Unique(res.Interface())
@@ -479,19 +578,32 @@ func Intersection(slices ...interface{}) interface{} {
// ReverseSlice return slice of element order is reversed to the given slice
func ReverseSlice(slice interface{}) {
v := sliceValue(slice)
swp := reflect.Swapper(v.Interface())
for i, j := 0, v.Len()-1; i < j; i, j = i+1, j-1 {
sv := sliceValue(slice)
swp := reflect.Swapper(sv.Interface())
for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 {
swp(i, j)
}
}
// Shuffle creates an slice of shuffled values
func Shuffle(slice interface{}) interface{} {
sv := sliceValue(slice)
length := sv.Len()
res := reflect.MakeSlice(sv.Type(), length, length)
for i, v := range rand.Perm(length) {
res.Index(i).Set(sv.Index(v))
}
return res.Interface()
}
// SortByField return sorted slice by field
// Slice element should be struct, field type should be int, uint, string, or bool
// default sortType is ascending (asc), if descending order, set sortType to desc
func SortByField(slice interface{}, field string, sortType ...string) error {
v := sliceValue(slice)
t := v.Type().Elem()
sv := sliceValue(slice)
t := sv.Type().Elem()
if t.Kind() == reflect.Ptr {
t = t.Elem()
@@ -524,8 +636,8 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
}
sort.Slice(slice, func(i, j int) bool {
a := v.Index(i)
b := v.Index(j)
a := sv.Index(i)
b := sv.Index(j)
if t.Kind() == reflect.Ptr {
a = a.Elem()
b = b.Elem()
@@ -547,6 +659,7 @@ func Without(slice interface{}, values ...interface{}) interface{} {
if sv.Len() == 0 {
return slice
}
var indexes []int
for i := 0; i < sv.Len(); i++ {
v := sv.Index(i).Interface()

View File

@@ -4,7 +4,7 @@ import (
"reflect"
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestContain(t *testing.T) {
@@ -28,7 +28,7 @@ func TestContain(t *testing.T) {
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
res := Contain(test, value)
if res != expected {
utils.LogFailedTestInfo(t, "Contain", test, expected, res)
internal.LogFailedTestInfo(t, "Contain", test, expected, res)
t.FailNow()
}
}
@@ -78,7 +78,7 @@ func TestChunk(t *testing.T) {
func chunk(t *testing.T, test []interface{}, num int, expected [][]interface{}) {
res := Chunk(test, num)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "Chunk", test, expected, res)
internal.LogFailedTestInfo(t, "Chunk", test, expected, res)
t.FailNow()
}
}
@@ -103,7 +103,7 @@ func TestEvery(t *testing.T) {
}
res := Every(nums, isEven)
if res != false {
utils.LogFailedTestInfo(t, "Every", nums, false, res)
internal.LogFailedTestInfo(t, "Every", nums, false, res)
t.FailNow()
}
}
@@ -115,7 +115,7 @@ func TestSome(t *testing.T) {
}
res := Some(nums, isEven)
if res != true {
utils.LogFailedTestInfo(t, "Some", nums, true, res)
internal.LogFailedTestInfo(t, "Some", nums, true, res)
t.FailNow()
}
}
@@ -128,7 +128,7 @@ func TestFilter(t *testing.T) {
e1 := []int{2, 4}
r1 := Filter(nums, even)
if !reflect.DeepEqual(r1, e1) {
utils.LogFailedTestInfo(t, "Filter", nums, e1, r1)
internal.LogFailedTestInfo(t, "Filter", nums, e1, r1)
t.FailNow()
}
@@ -155,20 +155,70 @@ func TestFilter(t *testing.T) {
r2 := Filter(students, filterFunc)
if !reflect.DeepEqual(r2, e2) {
utils.LogFailedTestInfo(t, "Filter", students, e2, r2)
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
t.FailNow()
}
}
func TestGroupBy(t *testing.T) {
nums := []int{1, 2, 3, 4, 5, 6}
evenFunc := func(i, num int) bool {
return (num % 2) == 0
}
expectedEven := []int{2, 4, 6}
even, odd := GroupBy(nums, evenFunc)
t.Log("odd", odd)
t.Log("even", even)
if !reflect.DeepEqual(IntSlice(even), expectedEven) {
internal.LogFailedTestInfo(t, "GroupBy even", nums, expectedEven, even)
t.FailNow()
}
expectedOdd := []int{1, 3, 5}
if !reflect.DeepEqual(IntSlice(odd), expectedOdd) {
internal.LogFailedTestInfo(t, "GroupBy odd", nums, expectedOdd, odd)
t.FailNow()
}
}
func TestFind(t *testing.T) {
nums := []int{1, 2, 3, 4, 5}
even := func(i, num int) bool {
return num%2 == 0
}
res := Find(nums, even)
res, ok := Find(nums, even)
if !ok {
t.Fatal("found nothing")
}
if res != 2 {
utils.LogFailedTestInfo(t, "Find", nums, 2, res)
internal.LogFailedTestInfo(t, "Find", nums, 2, res)
t.FailNow()
}
}
func TestFindFoundNothing(t *testing.T) {
nums := []int{1, 1, 1, 1, 1, 1}
findFunc := func(i, num int) bool {
return num > 1
}
_, ok := Find(nums, findFunc)
if ok {
t.Fatal("found something")
}
}
func TestFlattenDeep(t *testing.T) {
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
expected := []string{"a", "b", "c", "d"}
res := FlattenDeep(input)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "FlattenDeep", input, expected, res)
t.FailNow()
}
}
@@ -181,7 +231,7 @@ func TestMap(t *testing.T) {
e1 := []int{2, 4, 6, 8}
r1 := Map(s1, multiplyTwo)
if !reflect.DeepEqual(r1, e1) {
utils.LogFailedTestInfo(t, "Map", s1, e1, r1)
internal.LogFailedTestInfo(t, "Map", s1, e1, r1)
t.FailNow()
}
@@ -206,7 +256,7 @@ func TestMap(t *testing.T) {
}
r2 := Map(students, mapFunc)
if !reflect.DeepEqual(r2, e2) {
utils.LogFailedTestInfo(t, "Filter", students, e2, r2)
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
t.FailNow()
}
}
@@ -223,7 +273,7 @@ func TestReduce(t *testing.T) {
for i := 0; i < len(cases); i++ {
res := Reduce(cases[i], f, 0)
if res != expected[i] {
utils.LogFailedTestInfo(t, "Reduce", cases[i], expected[i], res)
internal.LogFailedTestInfo(t, "Reduce", cases[i], expected[i], res)
t.FailNow()
}
}
@@ -237,12 +287,10 @@ func TestIntSlice(t *testing.T) {
}
func intSlice(t *testing.T, test interface{}, expected []int) {
res, err := IntSlice(test)
if err != nil {
t.Error("IntSlice Error: " + err.Error())
}
res := IntSlice(test)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "IntSlice", test, expected, res)
internal.LogFailedTestInfo(t, "IntSlice", test, expected, res)
t.FailNow()
}
}
@@ -257,7 +305,7 @@ func TestStringSlice(t *testing.T) {
func stringSlice(t *testing.T, test interface{}, expected []string) {
res := StringSlice(test)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "StringSlice", test, expected, res)
internal.LogFailedTestInfo(t, "StringSlice", test, expected, res)
t.FailNow()
}
}
@@ -271,7 +319,7 @@ func TestInterfaceSlice(t *testing.T) {
func interfaceSlice(t *testing.T, test interface{}, expected []interface{}) {
res := InterfaceSlice(test)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "InterfaceSlice", test, expected, res)
internal.LogFailedTestInfo(t, "InterfaceSlice", test, expected, res)
t.FailNow()
}
}
@@ -323,7 +371,30 @@ func deleteByIndex(t *testing.T, origin, test interface{}, start, end int, expec
}
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "DeleteByIndex", origin, expected, res)
internal.LogFailedTestInfo(t, "DeleteByIndex", origin, expected, res)
t.FailNow()
}
}
func TestDrop(t *testing.T) {
drop(t, []int{}, 0, []int{})
drop(t, []int{}, 1, []int{})
drop(t, []int{}, -1, []int{})
drop(t, []int{1, 2, 3, 4, 5}, 0, []int{1, 2, 3, 4, 5})
drop(t, []int{1, 2, 3, 4, 5}, 1, []int{2, 3, 4, 5})
drop(t, []int{1, 2, 3, 4, 5}, 5, []int{})
drop(t, []int{1, 2, 3, 4, 5}, 6, []int{})
drop(t, []int{1, 2, 3, 4, 5}, -1, []int{1, 2, 3, 4})
drop(t, []int{1, 2, 3, 4, 5}, -5, []int{})
drop(t, []int{1, 2, 3, 4, 5}, -6, []int{})
}
func drop(t *testing.T, test interface{}, n int, expected interface{}) {
res := Drop(test, n)
if !reflect.DeepEqual(res, expected) {
internal.LogFailedTestInfo(t, "Drop", test, expected, res)
t.FailNow()
}
}
@@ -360,7 +431,7 @@ func insertByIndex(t *testing.T, test interface{}, index int, value, expected in
}
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "InsertByIndex", test, expected, res)
internal.LogFailedTestInfo(t, "InsertByIndex", test, expected, res)
t.FailNow()
}
}
@@ -387,7 +458,7 @@ func updateByIndex(t *testing.T, test interface{}, index int, value, expected in
}
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "UpdateByIndex", test, expected, res)
internal.LogFailedTestInfo(t, "UpdateByIndex", test, expected, res)
t.FailNow()
}
}
@@ -397,7 +468,7 @@ func TestUnique(t *testing.T) {
e1 := []int{1, 2, 3}
r1 := Unique(t1)
if !reflect.DeepEqual(r1, e1) {
utils.LogFailedTestInfo(t, "Unique", t1, e1, r1)
internal.LogFailedTestInfo(t, "Unique", t1, e1, r1)
t.FailNow()
}
@@ -405,7 +476,7 @@ func TestUnique(t *testing.T) {
e2 := []string{"a", "b", "c"}
r2 := Unique(t2)
if !reflect.DeepEqual(r2, e2) {
utils.LogFailedTestInfo(t, "Unique", t2, e2, r2)
internal.LogFailedTestInfo(t, "Unique", t2, e2, r2)
t.FailNow()
}
}
@@ -418,14 +489,14 @@ func TestUnion(t *testing.T) {
expected1 := []int{1, 3, 4, 6, 2, 5, 0, 7}
res1 := Union(s1, s2, s3)
if !reflect.DeepEqual(res1, expected1) {
utils.LogFailedTestInfo(t, "Union", s1, expected1, res1)
internal.LogFailedTestInfo(t, "Union", s1, expected1, res1)
t.FailNow()
}
expected2 := []int{1, 3, 4, 6}
res2 := Union(s1)
if !reflect.DeepEqual(res2, expected2) {
utils.LogFailedTestInfo(t, "Union", s1, expected2, res2)
internal.LogFailedTestInfo(t, "Union", s1, expected2, res2)
t.FailNow()
}
}
@@ -450,7 +521,7 @@ func TestIntersection(t *testing.T) {
}
for i := 0; i < len(res); i++ {
if !reflect.DeepEqual(res[i], expected[i]) {
utils.LogFailedTestInfo(t, "Intersection", "Intersection", expected[i], res[i])
internal.LogFailedTestInfo(t, "Intersection", "Intersection", expected[i], res[i])
t.FailNow()
}
}
@@ -462,7 +533,7 @@ func TestReverseSlice(t *testing.T) {
e1 := []int{5, 4, 3, 2, 1}
ReverseSlice(s1)
if !reflect.DeepEqual(s1, e1) {
utils.LogFailedTestInfo(t, "ReverseSlice", s1, e1, s1)
internal.LogFailedTestInfo(t, "ReverseSlice", s1, e1, s1)
t.FailNow()
}
@@ -470,7 +541,7 @@ func TestReverseSlice(t *testing.T) {
e2 := []string{"e", "d", "c", "b", "a"}
ReverseSlice(s2)
if !reflect.DeepEqual(s2, e2) {
utils.LogFailedTestInfo(t, "ReverseSlice", s2, e2, s2)
internal.LogFailedTestInfo(t, "ReverseSlice", s2, e2, s2)
t.FailNow()
}
}
@@ -481,7 +552,7 @@ func TestDifference(t *testing.T) {
e1 := []int{1, 2, 3}
r1 := Difference(s1, s2)
if !reflect.DeepEqual(r1, e1) {
utils.LogFailedTestInfo(t, "Difference", s1, e1, r1)
internal.LogFailedTestInfo(t, "Difference", s1, e1, r1)
t.FailNow()
}
}
@@ -511,7 +582,7 @@ func TestSortByField(t *testing.T) {
}
if !reflect.DeepEqual(students, sortByAge) {
utils.LogFailedTestInfo(t, "SortByField", students, sortByAge, students)
internal.LogFailedTestInfo(t, "SortByField", students, sortByAge, students)
t.FailNow()
}
@@ -523,7 +594,18 @@ func TestWithout(t *testing.T) {
res := Without(s, 1, 2)
if !reflect.DeepEqual(res, expected) {
utils.LogFailedTestInfo(t, "Without", s, expected, res)
internal.LogFailedTestInfo(t, "Without", s, expected, res)
t.FailNow()
}
}
func TestShuffle(t *testing.T) {
s := []int{1, 2, 3, 4, 5}
res := Shuffle(s)
t.Log("Shuffle result: ", res)
if reflect.TypeOf(s) != reflect.TypeOf(res) {
internal.LogFailedTestInfo(t, "Shuffle", s, res, res)
t.FailNow()
}
}

View File

@@ -52,3 +52,14 @@ func checkSliceCallbackFuncSignature(fn reflect.Value, types ...reflect.Type) bo
}
return true
}
// sliceElemType get slice element type
func sliceElemType(reflectType reflect.Type) reflect.Type {
for {
if reflectType.Kind() != reflect.Slice {
return reflectType
}
reflectType = reflectType.Elem()
}
}

View File

@@ -8,6 +8,7 @@ import (
"regexp"
"strings"
"unicode"
"unicode/utf8"
)
// CamelCase covert string to camelCase string.
@@ -59,20 +60,10 @@ func LowerFirst(s string) string {
return ""
}
res := ""
for i, v := range []rune(s) {
if i == 0 {
if v >= 65 && v <= 96 {
v += 32
res += string(v)
} else {
return s
}
} else {
res += string(v)
}
}
return res
r, size := utf8.DecodeRuneInString(s)
r = unicode.ToLower(r)
return string(r) + s[size:]
}
// PadEnd pads string on the right side if it's shorter than size.

View File

@@ -3,7 +3,7 @@ package strutil
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestCamelCase(t *testing.T) {
@@ -16,7 +16,7 @@ func TestCamelCase(t *testing.T) {
func camelCase(t *testing.T, test string, expected string) {
res := CamelCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "CamelCase", test, expected, res)
internal.LogFailedTestInfo(t, "CamelCase", test, expected, res)
t.FailNow()
}
}
@@ -30,7 +30,7 @@ func TestCapitalize(t *testing.T) {
func capitalize(t *testing.T, test string, expected string) {
res := Capitalize(test)
if res != expected {
utils.LogFailedTestInfo(t, "Capitalize", test, expected, res)
internal.LogFailedTestInfo(t, "Capitalize", test, expected, res)
t.FailNow()
}
}
@@ -45,7 +45,7 @@ func TestKebabCase(t *testing.T) {
func kebabCase(t *testing.T, test string, expected string) {
res := KebabCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "KebabCase", test, expected, res)
internal.LogFailedTestInfo(t, "KebabCase", test, expected, res)
t.FailNow()
}
}
@@ -61,7 +61,7 @@ func TestSnakeCase(t *testing.T) {
func snakeCase(t *testing.T, test string, expected string) {
res := SnakeCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "SnakeCase", test, expected, res)
internal.LogFailedTestInfo(t, "SnakeCase", test, expected, res)
t.FailNow()
}
}
@@ -70,12 +70,13 @@ func TestLowerFirst(t *testing.T) {
lowerFirst(t, "foo", "foo")
lowerFirst(t, "BAR", "bAR")
lowerFirst(t, "FOo", "fOo")
lowerFirst(t, "FOo大", "fOo大")
}
func lowerFirst(t *testing.T, test string, expected string) {
res := LowerFirst(test)
if res != expected {
utils.LogFailedTestInfo(t, "LowerFirst", test, expected, res)
internal.LogFailedTestInfo(t, "LowerFirst", test, expected, res)
t.FailNow()
}
}
@@ -91,7 +92,7 @@ func TestPadEnd(t *testing.T) {
func padEnd(t *testing.T, source string, size int, fillString string, expected string) {
res := PadEnd(source, size, fillString)
if res != expected {
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
internal.LogFailedTestInfo(t, "PadEnd", source, expected, res)
t.FailNow()
}
}
@@ -107,7 +108,7 @@ func TestPadStart(t *testing.T) {
func padStart(t *testing.T, source string, size int, fillString string, expected string) {
res := PadStart(source, size, fillString)
if res != expected {
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
internal.LogFailedTestInfo(t, "PadEnd", source, expected, res)
t.FailNow()
}
}
@@ -121,7 +122,7 @@ func TestBefore(t *testing.T) {
func before(t *testing.T, source, char, expected string) {
res := Before(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "Before", source, expected, res)
internal.LogFailedTestInfo(t, "Before", source, expected, res)
t.FailNow()
}
}
@@ -135,7 +136,7 @@ func TestBeforeLast(t *testing.T) {
func beforeLast(t *testing.T, source, char, expected string) {
res := BeforeLast(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "BeforeLast", source, expected, res)
internal.LogFailedTestInfo(t, "BeforeLast", source, expected, res)
t.FailNow()
}
}
@@ -149,7 +150,7 @@ func TestAfter(t *testing.T) {
func after(t *testing.T, source, char, expected string) {
res := After(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "After", source, expected, res)
internal.LogFailedTestInfo(t, "After", source, expected, res)
t.FailNow()
}
}
@@ -163,7 +164,7 @@ func TestAfterLast(t *testing.T) {
func afterLast(t *testing.T, source, char, expected string) {
res := AfterLast(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "AfterLast", source, expected, res)
internal.LogFailedTestInfo(t, "AfterLast", source, expected, res)
t.FailNow()
}
}
@@ -178,7 +179,7 @@ func TestIsString(t *testing.T) {
func isString(t *testing.T, test interface{}, expected bool) {
res := IsString(test)
if res != expected {
utils.LogFailedTestInfo(t, "IsString", test, expected, res)
internal.LogFailedTestInfo(t, "IsString", test, expected, res)
t.FailNow()
}
}
@@ -194,7 +195,7 @@ func TestReverseStr(t *testing.T) {
func reverseStr(t *testing.T, test string, expected string) {
res := ReverseStr(test)
if res != expected {
utils.LogFailedTestInfo(t, "ReverseStr", test, expected, res)
internal.LogFailedTestInfo(t, "ReverseStr", test, expected, res)
t.FailNow()
}
}

View File

@@ -3,7 +3,7 @@ package validator
import (
"testing"
"github.com/duke-git/lancet/utils"
"github.com/duke-git/lancet/internal"
)
func TestIsNumberStr(t *testing.T) {
@@ -17,7 +17,7 @@ func TestIsNumberStr(t *testing.T) {
func isNumberStr(t *testing.T, source string, expected bool) {
res := IsNumberStr(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsNumberStr", source, expected, res)
internal.LogFailedTestInfo(t, "IsNumberStr", source, expected, res)
t.FailNow()
}
}
@@ -33,7 +33,7 @@ func TestIsFloatStr(t *testing.T) {
func isFloatStr(t *testing.T, source string, expected bool) {
res := IsFloatStr(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsFloatStr", source, expected, res)
internal.LogFailedTestInfo(t, "IsFloatStr", source, expected, res)
t.FailNow()
}
}
@@ -48,7 +48,7 @@ func TestIsIntStr(t *testing.T) {
func isIntStr(t *testing.T, source string, expected bool) {
res := IsIntStr(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsIntStr", source, expected, res)
internal.LogFailedTestInfo(t, "IsIntStr", source, expected, res)
t.FailNow()
}
}
@@ -63,7 +63,7 @@ func TestIsIp(t *testing.T) {
func isIp(t *testing.T, source string, expected bool) {
res := IsIp(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsIp", source, expected, res)
internal.LogFailedTestInfo(t, "IsIp", source, expected, res)
t.FailNow()
}
}
@@ -76,7 +76,7 @@ func TestIsIpV4(t *testing.T) {
func isIpV4(t *testing.T, source string, expected bool) {
res := IsIpV4(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsIpV4", source, expected, res)
internal.LogFailedTestInfo(t, "IsIpV4", source, expected, res)
t.FailNow()
}
}
@@ -89,7 +89,7 @@ func TestIsIpV6(t *testing.T) {
func isIpV6(t *testing.T, source string, expected bool) {
res := IsIpV6(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsIpV6", source, expected, res)
internal.LogFailedTestInfo(t, "IsIpV6", source, expected, res)
t.FailNow()
}
}
@@ -102,7 +102,7 @@ func TestIsDns(t *testing.T) {
func isDns(t *testing.T, source string, expected bool) {
res := IsDns(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsDns", source, expected, res)
internal.LogFailedTestInfo(t, "IsDns", source, expected, res)
t.FailNow()
}
}
@@ -115,7 +115,7 @@ func TestIsEmail(t *testing.T) {
func isEmail(t *testing.T, source string, expected bool) {
res := IsEmail(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsEmail", source, expected, res)
internal.LogFailedTestInfo(t, "IsEmail", source, expected, res)
t.FailNow()
}
}
@@ -129,7 +129,7 @@ func TestContainChinese(t *testing.T) {
func containChinese(t *testing.T, source string, expected bool) {
res := ContainChinese(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsContainChineseChar", source, expected, res)
internal.LogFailedTestInfo(t, "IsContainChineseChar", source, expected, res)
t.FailNow()
}
}
@@ -142,7 +142,7 @@ func TestIsChineseMobile(t *testing.T) {
func isChineseMobile(t *testing.T, source string, expected bool) {
res := IsChineseMobile(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsChineseMobile", source, expected, res)
internal.LogFailedTestInfo(t, "IsChineseMobile", source, expected, res)
t.FailNow()
}
}
@@ -156,7 +156,7 @@ func TestIsChinesePhone(t *testing.T) {
func isChinesePhone(t *testing.T, source string, expected bool) {
res := IsChinesePhone(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsChinesePhone", source, expected, res)
internal.LogFailedTestInfo(t, "IsChinesePhone", source, expected, res)
t.FailNow()
}
}
@@ -171,7 +171,7 @@ func TestIsChineseIdNum(t *testing.T) {
func isChineseIdNum(t *testing.T, source string, expected bool) {
res := IsChineseIdNum(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsChineseIdNum", source, expected, res)
internal.LogFailedTestInfo(t, "IsChineseIdNum", source, expected, res)
t.FailNow()
}
}
@@ -184,7 +184,7 @@ func TestIsCreditCard(t *testing.T) {
func isCreditCard(t *testing.T, source string, expected bool) {
res := IsCreditCard(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsCreditCard", source, expected, res)
internal.LogFailedTestInfo(t, "IsCreditCard", source, expected, res)
t.FailNow()
}
}
@@ -197,7 +197,7 @@ func TestIsBase64(t *testing.T) {
func isBase64(t *testing.T, source string, expected bool) {
res := IsBase64(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsBase64", source, expected, res)
internal.LogFailedTestInfo(t, "IsBase64", source, expected, res)
t.FailNow()
}
}
@@ -212,7 +212,7 @@ func TestIsEmptyString(t *testing.T) {
func isEmptyString(t *testing.T, source string, expected bool) {
res := IsEmptyString(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsEmptyString", source, expected, res)
internal.LogFailedTestInfo(t, "IsEmptyString", source, expected, res)
t.FailNow()
}
}
@@ -228,7 +228,7 @@ func TestIsAlpha(t *testing.T) {
func isAlpha(t *testing.T, source string, expected bool) {
res := IsAlpha(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsAlpha", source, expected, res)
internal.LogFailedTestInfo(t, "IsAlpha", source, expected, res)
t.FailNow()
}
}
@@ -243,7 +243,7 @@ func TestIsRegexMatch(t *testing.T) {
func isRegexMatch(t *testing.T, source, regex string, expected bool) {
res := IsRegexMatch(source, regex)
if res != expected {
utils.LogFailedTestInfo(t, "IsRegexMatch", source, expected, res)
internal.LogFailedTestInfo(t, "IsRegexMatch", source, expected, res)
t.FailNow()
}
}
@@ -261,7 +261,7 @@ func TestIsStrongPassword(t *testing.T) {
func isStrongPassword(t *testing.T, source string, length int, expected bool) {
res := IsStrongPassword(source, length)
if res != expected {
utils.LogFailedTestInfo(t, "IsStrongPassword", source, expected, res)
internal.LogFailedTestInfo(t, "IsStrongPassword", source, expected, res)
t.FailNow()
}
}
@@ -277,7 +277,7 @@ func TestIsWeakPassword(t *testing.T) {
func isWeakPassword(t *testing.T, source string, expected bool) {
res := IsWeakPassword(source)
if res != expected {
utils.LogFailedTestInfo(t, "IsWeakPassword", source, expected, res)
internal.LogFailedTestInfo(t, "IsWeakPassword", source, expected, res)
t.FailNow()
}
}