mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-08 14:42:27 +08:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd8a18677 | ||
|
|
3de906d7c9 | ||
|
|
56fc12c660 | ||
|
|
7a9b0847f9 | ||
|
|
9266d99249 | ||
|
|
f15131f032 | ||
|
|
b4a49fccfd | ||
|
|
94b1a1d383 | ||
|
|
7db46696f6 | ||
|
|
d4f49af2ad | ||
|
|
ed4acc1c67 | ||
|
|
042a00296f | ||
|
|
b42aac53b3 | ||
|
|
c625a88067 | ||
|
|
e15ae9eb98 | ||
|
|
bb4ac01209 | ||
|
|
147c1625b5 | ||
|
|
2aed55f704 | ||
|
|
051f20caef | ||
|
|
613785b07c | ||
|
|
0b0eb695e8 | ||
|
|
745082fff1 | ||
|
|
24b8da360e | ||
|
|
b106c428ae | ||
|
|
8b1171d0cb | ||
|
|
ab012f2545 | ||
|
|
a952cb208a | ||
|
|
f239a8ca8e | ||
|
|
5c6626b37e | ||
|
|
16b5101600 | ||
|
|
ec983b7aa6 | ||
|
|
56fc2aabd6 | ||
|
|
0ddd52225b | ||
|
|
3919160e38 | ||
|
|
40ec5bc0f6 | ||
|
|
99faeccb05 | ||
|
|
ad777bc877 | ||
|
|
589ce7404f | ||
|
|
6ab4fca433 | ||
|
|
b33a9cbfe3 | ||
|
|
9ad9d1805b | ||
|
|
0a1386f5a7 | ||
|
|
b5541ea177 | ||
|
|
578b1bba65 | ||
|
|
3045d56503 | ||
|
|
f1dbd943aa | ||
|
|
e87f3b70f0 | ||
|
|
26b59dd56b | ||
|
|
143aba7112 | ||
|
|
60f3a72c88 | ||
|
|
d1b74cfcfb | ||
|
|
72a89be8c1 | ||
|
|
0cf59323ff | ||
|
|
afec27fb4e | ||
|
|
3021985df9 | ||
|
|
188d52cd9d | ||
|
|
8c8f991390 | ||
|
|
b7bb7c6ae0 | ||
|
|
2e04a41f34 | ||
|
|
acb7873832 | ||
|
|
8b3cc3266d | ||
|
|
62c570d29b | ||
|
|
4e5d3c2603 | ||
|
|
561b590e13 | ||
|
|
f2ed3c6270 | ||
|
|
fee6cb17f3 | ||
|
|
7d39d1319b | ||
|
|
59d7281967 | ||
|
|
bdf052819d | ||
|
|
0148af4839 | ||
|
|
99b74e6fc6 | ||
|
|
499c1df9bd | ||
|
|
6af13a01de | ||
|
|
0c4b512084 | ||
|
|
4848647918 | ||
|
|
45fc84d1f2 |
22
.github/workflows/codecov.yml
vendored
Normal file
22
.github/workflows/codecov.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Test and coverage
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
- uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: "1.16"
|
||||||
|
- name: Run coverage
|
||||||
|
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
.idea/*
|
.idea/*
|
||||||
.vscode/*
|
.vscode/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
cryptor/*.txt
|
||||||
|
fileutil/*.txt
|
||||||
|
cryptor/*.pem
|
||||||
80
README.md
80
README.md
@@ -5,6 +5,12 @@
|
|||||||
</p>
|
</p>
|
||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||
|

|
||||||
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -15,7 +21,7 @@ English | [简体中文](./README_zh-CN.md)
|
|||||||
### Feature
|
### Feature
|
||||||
|
|
||||||
- 👏 Comprehensive, efficient and reusable.
|
- 👏 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.
|
- 💅 Only depend on the go standard library.
|
||||||
- 🌍 Unit test for exery exported function.
|
- 🌍 Unit test for exery exported function.
|
||||||
|
|
||||||
@@ -53,7 +59,7 @@ func main() {
|
|||||||
|
|
||||||
### API Documentation
|
### API Documentation
|
||||||
|
|
||||||
#### 1. convertor contains some functions for data convertion.
|
#### 1. convertor contains some functions for data convertion
|
||||||
|
|
||||||
- Support conversion between commonly used data types.
|
- Support conversion between commonly used data types.
|
||||||
- Usage: import "github.com/duke-git/lancet/cryptor"
|
- Usage: import "github.com/duke-git/lancet/cryptor"
|
||||||
@@ -91,7 +97,7 @@ func ToString(value interface{}) string //convert value to string
|
|||||||
func StructToMap(value interface{}) (map[string]interface{}, error) //convert struct to map, only convert exported field, tag `json` should be set
|
func StructToMap(value interface{}) (map[string]interface{}, error) //convert struct to map, only convert exported field, tag `json` should be set
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. cryptor is for data encryption and decryption.
|
#### 2. cryptor is for data encryption and decryption
|
||||||
|
|
||||||
- Support md5, hmac, aes, des, ras.
|
- Support md5, hmac, aes, des, ras.
|
||||||
- Usage: import "github.com/duke-git/lancet/cryptor"
|
- Usage: import "github.com/duke-git/lancet/cryptor"
|
||||||
@@ -139,6 +145,8 @@ func HmacMd5(data, key string) string //get hmac md5 value
|
|||||||
func HmacSha1(data, key string) string //get hmac sha1 value
|
func HmacSha1(data, key string) string //get hmac sha1 value
|
||||||
func HmacSha256(data, key string) string //get hmac sha256 value
|
func HmacSha256(data, key string) string //get hmac sha256 value
|
||||||
func HmacSha512(data, key string) string //get hmac sha512 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 Sha1(data string) string //get sha1 value
|
||||||
func Sha256(data string) string //getsha256 value
|
func Sha256(data string) string //getsha256 value
|
||||||
func Sha512(data string) string //get sha512 value
|
func Sha512(data string) string //get sha512 value
|
||||||
@@ -201,15 +209,18 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- 函数列表:
|
- Function list:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
func ClearFile(path string) error //write empty string to path file
|
||||||
func CreateFile(path string) bool // create a file in path
|
func CreateFile(path string) bool // create a file in path
|
||||||
func CopyFile(srcFilePath string, dstFilePath string) error //copy src file to dst file
|
func CopyFile(srcFilePath string, dstFilePath string) error //copy src file to dst file
|
||||||
func IsExist(path string) bool //checks if a file or directory exists
|
func IsExist(path string) bool //checks if a file or directory exists
|
||||||
func IsDir(path string) bool //checks if the path is directy or not
|
func IsDir(path string) bool //checks if the path is directy or not
|
||||||
func ListFileNames(path string) ([]string, error) //return all file names in the path
|
func ListFileNames(path string) ([]string, error) //return all file names in the path
|
||||||
func RemoveFile(path string) error //remove the path file
|
func RemoveFile(path string) error //remove the path file
|
||||||
|
func ReadFileToString(path string) (string, error) //return string of file content
|
||||||
|
func ReadFileByLine(path string)([]string, error) //read file content by line
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. formatter is for data format
|
#### 5. formatter is for data format
|
||||||
@@ -237,7 +248,43 @@ func main() {
|
|||||||
func Comma(v interface{}, symbol string) string //add comma to number by every 3 numbers from right. ahead by symbol char
|
func Comma(v interface{}, symbol string) string //add comma to number by every 3 numbers from right. ahead by symbol char
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 6. netutil is for net process
|
#### 6. function can control the function execution and support functional programming
|
||||||
|
|
||||||
|
- Control function execution and support functional programming.
|
||||||
|
- Usage: import "github.com/duke-git/lancet/function"
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
function.Delay(2*time.Second, print, "hello world")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Function list:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called n or more times
|
||||||
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called less than n times
|
||||||
|
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //make a curryed function
|
||||||
|
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
|
||||||
|
|
||||||
- Ip and http request method.
|
- Ip and http request method.
|
||||||
- Usage: import "github.com/duke-git/lancet/netutil".
|
- Usage: import "github.com/duke-git/lancet/netutil".
|
||||||
@@ -282,9 +329,10 @@ func HttpPut(url string, params ...interface{}) (*http.Response, error) //http p
|
|||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete request
|
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete request
|
||||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch request
|
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch request
|
||||||
func ConvertMapToQueryString(param map[string]interface{}) string //convert map to url query string
|
func ConvertMapToQueryString(param map[string]interface{}) string //convert map to url query string
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error //decode http response to specified interface
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 7. random is for rand string and int generation.
|
#### 8. random is for rand string and int generation
|
||||||
|
|
||||||
- Generate random string and int.
|
- Generate random string and int.
|
||||||
- Usage: import "github.com/duke-git/lancet/random".
|
- Usage: import "github.com/duke-git/lancet/random".
|
||||||
@@ -313,7 +361,7 @@ func RandInt(min, max int) int //generate random int
|
|||||||
func RandString(length int) string //generate random string
|
func RandString(length int) string //generate random string
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 8. slice is for process slice
|
#### 9. slice is for process slice
|
||||||
|
|
||||||
- Contain function for process slice.
|
- Contain function for process slice.
|
||||||
- Usage: import "github.com/duke-git/lancet/slice"
|
- Usage: import "github.com/duke-git/lancet/slice"
|
||||||
@@ -336,7 +384,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- Function list:
|
- Function list:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Contain(slice interface{}, value interface{}) bool //check if the value is in the slice or not
|
func Contain(slice interface{}, value interface{}) bool //check if the value is in the slice or not
|
||||||
@@ -344,20 +392,30 @@ func Chunk(slice []interface{}, size int) [][]interface{} //creates an slice of
|
|||||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //convert originalSlice to newSliceType
|
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 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 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 Filter(slice, function interface{}) interface{} //filter slice, 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 IntSlice(slice interface{}) ([]int, error) //convert value to int slice
|
||||||
func InterfaceSlice(slice interface{}) []interface{} //convert value to interface{} 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.
|
||||||
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index.
|
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index.
|
||||||
func Map(slice, function interface{}) interface{} //map lisce, function signature should be func(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 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 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 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
|
func StringSlice(slice interface{}) []string //convert value to string slice
|
||||||
func Unique(slice interface{}) interface{} //remove duplicate elements in slice
|
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 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
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 9. strutil is for processing string
|
#### 10. strutil is for processing string
|
||||||
|
|
||||||
- Contain functions to precess string
|
- Contain functions to precess string
|
||||||
- Usage: import "github.com/duke-git/lancet/strutil"
|
- Usage: import "github.com/duke-git/lancet/strutil"
|
||||||
@@ -379,7 +437,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- Function list:
|
- Function list:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func After(s, char string) string //create substring in source string after position when char first appear
|
func After(s, char string) string //create substring in source string after position when char first appear
|
||||||
@@ -397,7 +455,7 @@ func ReverseStr(s string) string //return string whose char order is reversed to
|
|||||||
func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_bar"
|
func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_bar"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 10. validator is for data validation
|
#### 11. validator is for data validation
|
||||||
|
|
||||||
- Contain function for data validation.
|
- Contain function for data validation.
|
||||||
- Usage: import "github.com/duke-git/lancet/validator".
|
- Usage: import "github.com/duke-git/lancet/validator".
|
||||||
|
|||||||
@@ -5,6 +5,12 @@
|
|||||||
</p>
|
</p>
|
||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||
|

|
||||||
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -15,9 +21,9 @@
|
|||||||
### 特性
|
### 特性
|
||||||
|
|
||||||
- 👏 全面、高效、可复用
|
- 👏 全面、高效、可复用
|
||||||
- 💪 100+常用go工具函数,支持string、slice、datetime、net、crypt...
|
- 💪 140+常用go工具函数,支持string、slice、datetime、net、crypt...
|
||||||
- 💅 只依赖go标准库
|
- 💅 只依赖go标准库
|
||||||
- 🌍 所有导出函数单测试覆盖率100%
|
- 🌍 所有导出函数单元测试覆盖率100%
|
||||||
|
|
||||||
### 安装
|
### 安装
|
||||||
|
|
||||||
@@ -57,7 +63,7 @@ func main() {
|
|||||||
#### 1. convertor数据转换包
|
#### 1. convertor数据转换包
|
||||||
|
|
||||||
- 转换函数支持常用数据类型之间的转换
|
- 转换函数支持常用数据类型之间的转换
|
||||||
- 导入包:import "github.com/duke-git/lancet/cryptor"
|
- 导入包:import "github.com/duke-git/lancet/convertor"
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -94,7 +100,7 @@ func StructToMap(value interface{}) (map[string]interface{}, error) //struct串
|
|||||||
|
|
||||||
#### 2. cryptor加解密包
|
#### 2. cryptor加解密包
|
||||||
|
|
||||||
- 加密函数是支持md5, hmac, aes, des, ras
|
- 加密函数支持md5, hmac, aes, des, ras
|
||||||
- 导入包:import "github.com/duke-git/lancet/cryptor"
|
- 导入包:import "github.com/duke-git/lancet/cryptor"
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -140,6 +146,8 @@ func HmacMd5(data, key string) string //获取hmac md5值
|
|||||||
func HmacSha1(data, key string) string //获取hmac sha1值
|
func HmacSha1(data, key string) string //获取hmac sha1值
|
||||||
func HmacSha256(data, key string) string //获取hmac sha256值
|
func HmacSha256(data, key string) string //获取hmac sha256值
|
||||||
func HmacSha512(data, key string) string //获取hmac sha512值
|
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 Sha1(data string) string //获取sha1值
|
||||||
func Sha256(data string) string //获取sha256值
|
func Sha256(data string) string //获取sha256值
|
||||||
func Sha512(data string) string //获取sha512值
|
func Sha512(data string) string //获取sha512值
|
||||||
@@ -205,12 +213,15 @@ func main() {
|
|||||||
- 函数列表:
|
- 函数列表:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
func ClearFile(path string) error //清空文件内容
|
||||||
func IsExist(path string) bool //判断文件/目录是否存在
|
func IsExist(path string) bool //判断文件/目录是否存在
|
||||||
func CreateFile(path string) bool //创建文件
|
func CreateFile(path string) bool //创建文件
|
||||||
func IsDir(path string) bool //判断是否为目录
|
func IsDir(path string) bool //判断是否为目录
|
||||||
func RemoveFile(path string) error //删除文件
|
func RemoveFile(path string) error //删除文件
|
||||||
func CopyFile(srcFilePath string, dstFilePath string) error //复制文件
|
func CopyFile(srcFilePath string, dstFilePath string) error //复制文件
|
||||||
func ListFileNames(path string) ([]string, error) //列出目录下所有文件名称
|
func ListFileNames(path string) ([]string, error) //列出目录下所有文件名称
|
||||||
|
func ReadFileToString(path string) (string, error) //读取文件内容为字符串
|
||||||
|
func ReadFileByLine(path string)([]string, error) //按行读取文件内容
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. formatter格式化处理包
|
#### 5. formatter格式化处理包
|
||||||
@@ -238,7 +249,43 @@ func main() {
|
|||||||
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
|
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 6. netutil网络处理包
|
#### 6. function包可以控制函数执行,支持部分函数式编程
|
||||||
|
|
||||||
|
- 控制函数执行,支持部分函数式编程
|
||||||
|
- 导入包:import "github.com/duke-git/lancet/function"
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
function.Delay(2*time.Second, print, "hello world")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Function list:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数, 只有在运行了n次之后才有效果
|
||||||
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数,调用不超过n次。 当n已经达到时,最后一个函数调用的结果将被记住并返回
|
||||||
|
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网络处理包
|
||||||
|
|
||||||
- 处理ip, http请求相关函数
|
- 处理ip, http请求相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/netutil"
|
- 导入包:import "github.com/duke-git/lancet/netutil"
|
||||||
@@ -283,9 +330,10 @@ func HttpPut(url string, params ...interface{}) (*http.Response, error) //http p
|
|||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete请求
|
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete请求
|
||||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch请求
|
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch请求
|
||||||
func ConvertMapToQueryString(param map[string]interface{}) string //将map转换成url query string
|
func ConvertMapToQueryString(param map[string]interface{}) string //将map转换成url query string
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error //将http响应解码成特定interface
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 7. random随机数处理包
|
#### 8. random随机数处理包
|
||||||
|
|
||||||
- 生成和处理随机数
|
- 生成和处理随机数
|
||||||
- 导入包:import "github.com/duke-git/lancet/random"
|
- 导入包:import "github.com/duke-git/lancet/random"
|
||||||
@@ -314,7 +362,7 @@ func RandInt(min, max int) int //生成随机int
|
|||||||
func RandString(length int) string //生成随机string
|
func RandString(length int) string //生成随机string
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 8. slice切片操作包
|
#### 9. slice切片操作包
|
||||||
|
|
||||||
- 切片操作相关函数
|
- 切片操作相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/slice"
|
- 导入包:import "github.com/duke-git/lancet/slice"
|
||||||
@@ -345,20 +393,30 @@ func Chunk(slice []interface{}, size int) [][]interface{} //均分slice
|
|||||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
|
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
|
||||||
func Difference(slice1, slice2 interface{}) interface{} //返回
|
func Difference(slice1, slice2 interface{}) interface{} //返回
|
||||||
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //删除切片中start到end位置的值
|
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{}, bool)//查找slice中第一个符合条件的元素,函数签名:func(index int, value interface{}) bool
|
||||||
func Filter(slice, function interface{}) interface{} //过滤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 IntSlice(slice interface{}) ([]int, error) //转成int切片
|
||||||
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
|
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
|
||||||
|
func Intersection(slices ...interface{}) interface{} //slice交集,去重
|
||||||
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置插入value
|
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置插入value
|
||||||
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{}
|
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{}
|
||||||
func ReverseSlice(slice interface{}) //反转切片
|
func ReverseSlice(slice interface{}) //反转切片
|
||||||
func Reduce(slice, function, zero interface{}) interface{} //切片reduce操作, 函数签名:func(index int, value1, value2 interface{}) 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 SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
|
||||||
func StringSlice(slice interface{}) []string //转为string切片
|
func StringSlice(slice interface{}) []string //转为string切片
|
||||||
func Unique(slice interface{}) interface{} //去重切片
|
func Unique(slice interface{}) interface{} //去重切片
|
||||||
|
func Union(slices ...interface{}) interface{} //slice并集, 去重
|
||||||
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置更新value
|
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
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 9. strutil字符串处理包
|
#### 10. strutil字符串处理包
|
||||||
|
|
||||||
- 字符串操作相关函数
|
- 字符串操作相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/strutil"
|
- 导入包:import "github.com/duke-git/lancet/strutil"
|
||||||
@@ -398,7 +456,7 @@ func ReverseStr(s string) string //字符串逆袭
|
|||||||
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
|
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 10. validator验证器包
|
#### 11. validator验证器包
|
||||||
|
|
||||||
- 数据校验相关函数
|
- 数据校验相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/validator"
|
- 导入包:import "github.com/duke-git/lancet/validator"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func ToBool(s string) (bool, error) {
|
|||||||
return strconv.ParseBool(s)
|
return strconv.ParseBool(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToBool convert interface to bytes
|
// ToBytes convert interface to bytes
|
||||||
func ToBytes(data interface{}) ([]byte, error) {
|
func ToBytes(data interface{}) ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := gob.NewEncoder(&buf)
|
enc := gob.NewEncoder(&buf)
|
||||||
@@ -45,44 +45,34 @@ func ToChar(s string) []string {
|
|||||||
|
|
||||||
// ToString convert value to string
|
// ToString convert value to string
|
||||||
func ToString(value interface{}) string {
|
func ToString(value interface{}) string {
|
||||||
var res string
|
res := ""
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
switch v := value.(type) {
|
|
||||||
case float64:
|
v := reflect.ValueOf(value)
|
||||||
res = strconv.FormatFloat(v, 'f', -1, 64)
|
|
||||||
case float32:
|
switch value.(type) {
|
||||||
res = strconv.FormatFloat(float64(v), 'f', -1, 64)
|
case float32, float64:
|
||||||
case int:
|
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||||
res = strconv.Itoa(v)
|
return res
|
||||||
case uint:
|
case int, int8, int16, int32, int64:
|
||||||
res = strconv.Itoa(int(v))
|
res = strconv.FormatInt(v.Int(), 10)
|
||||||
case int8:
|
return res
|
||||||
res = strconv.Itoa(int(v))
|
case uint, uint8, uint16, uint32, uint64:
|
||||||
case uint8:
|
res = strconv.FormatUint(v.Uint(), 10)
|
||||||
res = strconv.Itoa(int(v))
|
return res
|
||||||
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)
|
|
||||||
case string:
|
case string:
|
||||||
res = value.(string)
|
res = v.String()
|
||||||
|
return res
|
||||||
case []byte:
|
case []byte:
|
||||||
res = string(value.([]byte))
|
res = string(v.Bytes())
|
||||||
|
return res
|
||||||
default:
|
default:
|
||||||
newValue, _ := json.Marshal(value)
|
newValue, _ := json.Marshal(value)
|
||||||
res = string(newValue)
|
res = string(newValue)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJson convert value to a valid json string
|
// ToJson convert value to a valid json string
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package convertor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToChar(t *testing.T) {
|
func TestToChar(t *testing.T) {
|
||||||
@@ -17,7 +18,7 @@ func TestToChar(t *testing.T) {
|
|||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := ToChar(cases[i])
|
res := ToChar(cases[i])
|
||||||
if !reflect.DeepEqual(res, expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +31,7 @@ func TestToBool(t *testing.T) {
|
|||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res, _ := ToBool(cases[i])
|
res, _ := ToBool(cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,74 +52,85 @@ func TestToBytes(t *testing.T) {
|
|||||||
res, _ := ToBytes(cases[i])
|
res, _ := ToBytes(cases[i])
|
||||||
fmt.Println(res)
|
fmt.Println(res)
|
||||||
if !reflect.DeepEqual(res, expected[i]) {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToInt(t *testing.T) {
|
func TestToInt(t *testing.T) {
|
||||||
cases := []interface{}{"123", "-123", 123, "abc", false, "111111111111111111111111111111111111111"}
|
cases := []interface{}{"123", "-123", 123,
|
||||||
expected := []int64{123, -123, 123, 0, 0, 0}
|
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||||
|
float32(12.3), float64(12.3),
|
||||||
|
"abc", false, "111111111111111111111111111111111111111"}
|
||||||
|
|
||||||
|
expected := []int64{123, -123, 123, 123, 123, 123, 123, 123, 12, 12, 0, 0, 0}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res, _ := ToInt(cases[i])
|
res, _ := ToInt(cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToFloat(t *testing.T) {
|
func TestToFloat(t *testing.T) {
|
||||||
cases := []interface{}{"", "-1", "-.11", "1.23e3", ".123e10", "abc"}
|
cases := []interface{}{
|
||||||
expected := []float64{0, -1, -0.11, 1230, 0.123e10, 0}
|
"", "-1", "-.11", "1.23e3", ".123e10", "abc",
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
expected := []float64{0, -1, -0.11, 1230, 0.123e10, 0,
|
||||||
|
0, 1, -1, 123, 123, 123, 123, 123, 123, 123, 12.3, 12.300000190734863}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res, _ := ToFloat(cases[i])
|
res, _ := ToFloat(cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToString(t *testing.T) {
|
func TestToString(t *testing.T) {
|
||||||
// basic type
|
|
||||||
toString(t, "a1", "a1")
|
|
||||||
toString(t, 111, "111")
|
|
||||||
toString(t, 111.01, "111.01")
|
|
||||||
toString(t, true, "true")
|
|
||||||
//toString(t, 1.5+10i, "(1.5+10i)")
|
|
||||||
|
|
||||||
// slice
|
|
||||||
aSlice := []int{1, 2, 3}
|
|
||||||
toString(t, aSlice, "[1,2,3]")
|
|
||||||
|
|
||||||
// map
|
// map
|
||||||
aMap := make(map[string]int)
|
aMap := make(map[string]int)
|
||||||
aMap["a"] = 1
|
aMap["a"] = 1
|
||||||
aMap["b"] = 2
|
aMap["b"] = 2
|
||||||
aMap["c"] = 3
|
aMap["c"] = 3
|
||||||
|
|
||||||
toString(t, aMap, "{\"a\":1,\"b\":2,\"c\":3}")
|
|
||||||
|
|
||||||
// struct
|
// struct
|
||||||
type TestStruct struct {
|
type TestStruct struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
aStruct := TestStruct{Name: "TestStruct"}
|
aStruct := TestStruct{Name: "TestStruct"}
|
||||||
toString(t, aStruct, "{\"Name\":\"TestStruct\"}")
|
|
||||||
}
|
|
||||||
|
|
||||||
func toString(t *testing.T, test interface{}, expected string) {
|
cases := []interface{}{
|
||||||
res := ToString(test)
|
"", nil,
|
||||||
if res != expected {
|
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||||
utils.LogFailedTestInfo(t, "ToString", test, expected, res)
|
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||||
t.FailNow()
|
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",
|
||||||
|
"[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] {
|
||||||
|
internal.LogFailedTestInfo(t, "ToString", cases[i], expected[i], res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToJson(t *testing.T) {
|
func TestToJson(t *testing.T) {
|
||||||
// map
|
// map
|
||||||
aMap := make(map[string]int)
|
aMap := make(map[string]int)
|
||||||
@@ -129,7 +141,7 @@ func TestToJson(t *testing.T) {
|
|||||||
mapJson := "{\"a\":1,\"b\":2,\"c\":3}"
|
mapJson := "{\"a\":1,\"b\":2,\"c\":3}"
|
||||||
r1, _ := ToJson(aMap)
|
r1, _ := ToJson(aMap)
|
||||||
if r1 != mapJson {
|
if r1 != mapJson {
|
||||||
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
internal.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +153,7 @@ func TestToJson(t *testing.T) {
|
|||||||
structJson := "{\"Name\":\"TestStruct\"}"
|
structJson := "{\"Name\":\"TestStruct\"}"
|
||||||
r2, _ := ToJson(aStruct)
|
r2, _ := ToJson(aStruct)
|
||||||
if r2 != structJson {
|
if r2 != structJson {
|
||||||
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
internal.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +175,7 @@ func TestStructToMap(t *testing.T) {
|
|||||||
//exp1["100"] = 100
|
//exp1["100"] = 100
|
||||||
|
|
||||||
if !reflect.DeepEqual(pm1, m1) {
|
if !reflect.DeepEqual(pm1, m1) {
|
||||||
utils.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
|
internal.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +190,7 @@ func TestStructToMap(t *testing.T) {
|
|||||||
m2["100"] = 100
|
m2["100"] = 100
|
||||||
|
|
||||||
if reflect.DeepEqual(pm2, m2) {
|
if reflect.DeepEqual(pm2, m2) {
|
||||||
utils.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
|
internal.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +202,7 @@ func TestColorHexToRGB(t *testing.T) {
|
|||||||
expected := "0,51,102"
|
expected := "0,51,102"
|
||||||
|
|
||||||
if colorRGB != expected {
|
if colorRGB != expected {
|
||||||
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
|
internal.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +216,7 @@ func TestColorRGBToHex(t *testing.T) {
|
|||||||
expected := "#003366"
|
expected := "#003366"
|
||||||
|
|
||||||
if colorHex != expected {
|
if colorHex != expected {
|
||||||
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
|
internal.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func AesCbcEncrypt(data, key []byte) []byte {
|
|||||||
return encrypted
|
return encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
// AesEcbDecrypt decrypt data with key use AES CBC algorithm
|
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
|
||||||
// len(key) should be 16, 24 or 32
|
// len(key) should be 16, 24 or 32
|
||||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||||
block, _ := aes.NewCipher(key)
|
block, _ := aes.NewCipher(key)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cryptor
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAesEcbEncrypt(t *testing.T) {
|
func TestAesEcbEncrypt(t *testing.T) {
|
||||||
@@ -14,7 +14,7 @@ func TestAesEcbEncrypt(t *testing.T) {
|
|||||||
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(aesEcbDecrypt) != data {
|
if string(aesEcbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "AesEcbEncrypt/AesEcbDecrypt", data, data, string(aesEcbDecrypt))
|
internal.LogFailedTestInfo(t, "AesEcbEncrypt/AesEcbDecrypt", data, data, string(aesEcbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ func TestAesCbcEncrypt(t *testing.T) {
|
|||||||
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(aesCbcDecrypt) != data {
|
if string(aesCbcDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "AesCbcEncrypt/AesCbcDecrypt", data, data, string(aesCbcDecrypt))
|
internal.LogFailedTestInfo(t, "AesCbcEncrypt/AesCbcDecrypt", data, data, string(aesCbcDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ func TestAesCtrCrypt(t *testing.T) {
|
|||||||
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
||||||
|
|
||||||
if string(aesCtrDeCrypt) != data {
|
if string(aesCtrDeCrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "AesCtrCrypt", data, data, string(aesCtrDeCrypt))
|
internal.LogFailedTestInfo(t, "AesCtrCrypt", data, data, string(aesCtrDeCrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func TestAesCfbEncrypt(t *testing.T) {
|
|||||||
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(aesCfbDecrypt) != data {
|
if string(aesCfbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "AesCfbEncrypt/AesCfbDecrypt", data, data, string(aesCfbDecrypt))
|
internal.LogFailedTestInfo(t, "AesCfbEncrypt/AesCfbDecrypt", data, data, string(aesCfbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ func TestAesOfbEncrypt(t *testing.T) {
|
|||||||
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
|
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(aesOfbDecrypt) != data {
|
if string(aesOfbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "AesOfbEncrypt/AesOfbDecrypt", data, data, string(aesOfbDecrypt))
|
internal.LogFailedTestInfo(t, "AesOfbEncrypt/AesOfbDecrypt", data, data, string(aesOfbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ func Base64StdEncode(s string) string {
|
|||||||
return base64.StdEncoding.EncodeToString([]byte(s))
|
return base64.StdEncoding.EncodeToString([]byte(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base64StdEncode decode a base64 encoded string
|
// Base64StdDecode decode a base64 encoded string
|
||||||
func Base64StdDecode(s string) string {
|
func Base64StdDecode(s string) string {
|
||||||
b, _ := base64.StdEncoding.DecodeString(s)
|
b, _ := base64.StdEncoding.DecodeString(s)
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Md5Str return the md5 value of string
|
// Md5String return the md5 value of string
|
||||||
func Md5String(s string) string {
|
func Md5String(s string) string {
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
h.Write([]byte(s))
|
h.Write([]byte(s))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBase64StdEncode(t *testing.T) {
|
func TestBase64StdEncode(t *testing.T) {
|
||||||
@@ -13,7 +13,7 @@ func TestBase64StdEncode(t *testing.T) {
|
|||||||
bs := Base64StdEncode(s)
|
bs := Base64StdEncode(s)
|
||||||
|
|
||||||
if bs != "aGVsbG8gd29ybGQ=" {
|
if bs != "aGVsbG8gd29ybGQ=" {
|
||||||
utils.LogFailedTestInfo(t, "Base64StdEncode", s, "aGVsbG8gd29ybGQ=", bs)
|
internal.LogFailedTestInfo(t, "Base64StdEncode", s, "aGVsbG8gd29ybGQ=", bs)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ func TestBase64StdDecode(t *testing.T) {
|
|||||||
s := Base64StdDecode(bs)
|
s := Base64StdDecode(bs)
|
||||||
|
|
||||||
if s != "hello world" {
|
if s != "hello world" {
|
||||||
utils.LogFailedTestInfo(t, "Base64StdDecode", bs, "hello world=", s)
|
internal.LogFailedTestInfo(t, "Base64StdDecode", bs, "hello world=", s)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ func TestMd5String(t *testing.T) {
|
|||||||
expected := "5d41402abc4b2a76b9719d911017c592"
|
expected := "5d41402abc4b2a76b9719d911017c592"
|
||||||
|
|
||||||
if smd5 != expected {
|
if smd5 != expected {
|
||||||
utils.LogFailedTestInfo(t, "Md5String", s, expected, smd5)
|
internal.LogFailedTestInfo(t, "Md5String", s, expected, smd5)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ func TestHmacMd5(t *testing.T) {
|
|||||||
expected := "5f4c9faaff0a1ad3007d9ddc06abe36d"
|
expected := "5f4c9faaff0a1ad3007d9ddc06abe36d"
|
||||||
|
|
||||||
if hmacMd5 != expected {
|
if hmacMd5 != expected {
|
||||||
utils.LogFailedTestInfo(t, "HmacMd5", s, expected, hmacMd5)
|
internal.LogFailedTestInfo(t, "HmacMd5", s, expected, hmacMd5)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ func TestHmacSha1(t *testing.T) {
|
|||||||
expected := "3826f812255d8683f051ee97346d1359234d5dbd"
|
expected := "3826f812255d8683f051ee97346d1359234d5dbd"
|
||||||
|
|
||||||
if hmacSha1 != expected {
|
if hmacSha1 != expected {
|
||||||
utils.LogFailedTestInfo(t, "HmacSha1", s, expected, hmacSha1)
|
internal.LogFailedTestInfo(t, "HmacSha1", s, expected, hmacSha1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func TestHmacSha256(t *testing.T) {
|
|||||||
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
|
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
|
||||||
|
|
||||||
if hmacSha256 != expected {
|
if hmacSha256 != expected {
|
||||||
utils.LogFailedTestInfo(t, "HmacSha256", s, expected, hmacSha256)
|
internal.LogFailedTestInfo(t, "HmacSha256", s, expected, hmacSha256)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ func TestHmacSha512(t *testing.T) {
|
|||||||
expected := "5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175"
|
expected := "5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175"
|
||||||
|
|
||||||
if hmacSha512 != expected {
|
if hmacSha512 != expected {
|
||||||
utils.LogFailedTestInfo(t, "HmacSha512", s, expected, hmacSha512)
|
internal.LogFailedTestInfo(t, "HmacSha512", s, expected, hmacSha512)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func TestSha1(t *testing.T) {
|
|||||||
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
||||||
|
|
||||||
if sha1 != expected {
|
if sha1 != expected {
|
||||||
utils.LogFailedTestInfo(t, "Sha1", s, expected, sha1)
|
internal.LogFailedTestInfo(t, "Sha1", s, expected, sha1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ func TestSha256(t *testing.T) {
|
|||||||
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
||||||
|
|
||||||
if sha256 != expected {
|
if sha256 != expected {
|
||||||
utils.LogFailedTestInfo(t, "Sha256", s, expected, sha256)
|
internal.LogFailedTestInfo(t, "Sha256", s, expected, sha256)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func TestSha512(t *testing.T) {
|
|||||||
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
||||||
|
|
||||||
if sha512 != expected {
|
if sha512 != expected {
|
||||||
utils.LogFailedTestInfo(t, "Sha512", s, expected, sha512)
|
internal.LogFailedTestInfo(t, "Sha512", s, expected, sha512)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cryptor
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDesEcbEncrypt(t *testing.T) {
|
func TestDesEcbEncrypt(t *testing.T) {
|
||||||
@@ -14,7 +14,7 @@ func TestDesEcbEncrypt(t *testing.T) {
|
|||||||
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
|
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(desEcbDecrypt) != data {
|
if string(desEcbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "DesEcbEncrypt/DesEcbDecrypt", data, data, string(desEcbDecrypt))
|
internal.LogFailedTestInfo(t, "DesEcbEncrypt/DesEcbDecrypt", data, data, string(desEcbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ func TestDesCbcEncrypt(t *testing.T) {
|
|||||||
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
|
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(desCbcDecrypt) != data {
|
if string(desCbcDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "DesCbcEncrypt/DesCbcDecrypt", data, data, string(desCbcDecrypt))
|
internal.LogFailedTestInfo(t, "DesCbcEncrypt/DesCbcDecrypt", data, data, string(desCbcDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ func TestDesCtrCrypt(t *testing.T) {
|
|||||||
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
||||||
|
|
||||||
if string(desCtrDeCrypt) != data {
|
if string(desCtrDeCrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "DesCtrCrypt", data, data, string(desCtrDeCrypt))
|
internal.LogFailedTestInfo(t, "DesCtrCrypt", data, data, string(desCtrDeCrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func TestDesCfbEncrypt(t *testing.T) {
|
|||||||
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
|
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(desCfbDecrypt) != data {
|
if string(desCfbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "DesCfbEncrypt/DesCfbDecrypt", data, data, string(desCfbDecrypt))
|
internal.LogFailedTestInfo(t, "DesCfbEncrypt/DesCfbDecrypt", data, data, string(desCfbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ func TestDesOfbEncrypt(t *testing.T) {
|
|||||||
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
|
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
|
||||||
|
|
||||||
if string(desOfbDecrypt) != data {
|
if string(desOfbDecrypt) != data {
|
||||||
utils.LogFailedTestInfo(t, "DesOfbEncrypt/DesOfbDecrypt", data, data, string(desOfbDecrypt))
|
internal.LogFailedTestInfo(t, "DesOfbEncrypt/DesOfbDecrypt", data, data, string(desOfbDecrypt))
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cryptor
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRsaEncrypt(t *testing.T) {
|
func TestRsaEncrypt(t *testing.T) {
|
||||||
@@ -13,7 +13,7 @@ func TestRsaEncrypt(t *testing.T) {
|
|||||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||||
|
|
||||||
if string(data) != string(decrypted) {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// Use of this source code is governed by MIT license.
|
// Use of this source code is governed by MIT license.
|
||||||
|
|
||||||
// Package datetime implements some functions to format date and time.
|
// Package datetime implements some functions to format date and time.
|
||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
// 1. `format` param in FormatTimeToStr function should be as flow:
|
// 1. `format` param in FormatTimeToStr function should be as flow:
|
||||||
//"yyyy-mm-dd hh:mm:ss"
|
//"yyyy-mm-dd hh:mm:ss"
|
||||||
@@ -23,11 +22,10 @@
|
|||||||
//"mm"
|
//"mm"
|
||||||
//"hh:mm:ss"
|
//"hh:mm:ss"
|
||||||
//"mm:ss"
|
//"mm:ss"
|
||||||
|
|
||||||
package datetime
|
package datetime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,24 +56,17 @@ func init() {
|
|||||||
|
|
||||||
// AddMinute add or sub minute to the time
|
// AddMinute add or sub minute to the time
|
||||||
func AddMinute(t time.Time, minute int64) time.Time {
|
func AddMinute(t time.Time, minute int64) time.Time {
|
||||||
s := strconv.FormatInt(minute, 10)
|
return t.Add(time.Minute * time.Duration(minute))
|
||||||
m, _ := time.ParseDuration(s + "m")
|
|
||||||
return t.Add(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHour add or sub hour to the time
|
// AddHour add or sub hour to the time
|
||||||
func AddHour(t time.Time, hour int64) time.Time {
|
func AddHour(t time.Time, hour int64) time.Time {
|
||||||
s := strconv.FormatInt(hour, 10)
|
return t.Add(time.Hour * time.Duration(hour))
|
||||||
h, _ := time.ParseDuration(s + "h")
|
|
||||||
return t.Add(h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDay add or sub day to the time
|
// AddDay add or sub day to the time
|
||||||
func AddDay(t time.Time, day int64) time.Time {
|
func AddDay(t time.Time, day int64) time.Time {
|
||||||
dayHours := day * 24
|
return t.Add(24 * time.Hour * time.Duration(day))
|
||||||
d := strconv.FormatInt(dayHours, 10)
|
|
||||||
h, _ := time.ParseDuration(d + "h")
|
|
||||||
return t.Add(h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNowDate return format yyyy-mm-dd of current date
|
// GetNowDate return format yyyy-mm-dd of current date
|
||||||
@@ -111,7 +102,11 @@ func FormatTimeToStr(t time.Time, format string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FormatStrToTime convert string to time
|
// FormatStrToTime convert string to time
|
||||||
func FormatStrToTime(str, format string) time.Time {
|
func FormatStrToTime(str, format string) (time.Time, error) {
|
||||||
t, _ := time.Parse(timeFormat[format], str)
|
v, ok := timeFormat[format]
|
||||||
return t
|
if !ok {
|
||||||
|
return time.Time{}, fmt.Errorf("format %s not found", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Parse(v, str)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package datetime
|
package datetime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -12,14 +12,14 @@ func TestAddDay(t *testing.T) {
|
|||||||
after2Days := AddDay(now, 2)
|
after2Days := AddDay(now, 2)
|
||||||
diff1 := after2Days.Sub(now)
|
diff1 := after2Days.Sub(now)
|
||||||
if diff1.Hours() != 48 {
|
if diff1.Hours() != 48 {
|
||||||
utils.LogFailedTestInfo(t, "AddDay", now, 48, diff1.Hours())
|
internal.LogFailedTestInfo(t, "AddDay", now, 48, diff1.Hours())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
before2Days := AddDay(now, -2)
|
before2Days := AddDay(now, -2)
|
||||||
diff2 := before2Days.Sub(now)
|
diff2 := before2Days.Sub(now)
|
||||||
if diff2.Hours() != -48 {
|
if diff2.Hours() != -48 {
|
||||||
utils.LogFailedTestInfo(t, "AddDay", now, -48, diff2.Hours())
|
internal.LogFailedTestInfo(t, "AddDay", now, -48, diff2.Hours())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,14 +30,14 @@ func TestAddHour(t *testing.T) {
|
|||||||
after2Hours := AddHour(now, 2)
|
after2Hours := AddHour(now, 2)
|
||||||
diff1 := after2Hours.Sub(now)
|
diff1 := after2Hours.Sub(now)
|
||||||
if diff1.Hours() != 2 {
|
if diff1.Hours() != 2 {
|
||||||
utils.LogFailedTestInfo(t, "AddHour", now, 2, diff1.Hours())
|
internal.LogFailedTestInfo(t, "AddHour", now, 2, diff1.Hours())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
before2Hours := AddHour(now, -2)
|
before2Hours := AddHour(now, -2)
|
||||||
diff2 := before2Hours.Sub(now)
|
diff2 := before2Hours.Sub(now)
|
||||||
if diff2.Hours() != -2 {
|
if diff2.Hours() != -2 {
|
||||||
utils.LogFailedTestInfo(t, "AddHour", now, -2, diff2.Hours())
|
internal.LogFailedTestInfo(t, "AddHour", now, -2, diff2.Hours())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,14 +48,14 @@ func TestAddMinute(t *testing.T) {
|
|||||||
after2Minutes := AddMinute(now, 2)
|
after2Minutes := AddMinute(now, 2)
|
||||||
diff1 := after2Minutes.Sub(now)
|
diff1 := after2Minutes.Sub(now)
|
||||||
if diff1.Minutes() != 2 {
|
if diff1.Minutes() != 2 {
|
||||||
utils.LogFailedTestInfo(t, "AddMinute", now, 2, diff1.Minutes())
|
internal.LogFailedTestInfo(t, "AddMinute", now, 2, diff1.Minutes())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
before2Minutes := AddMinute(now, -2)
|
before2Minutes := AddMinute(now, -2)
|
||||||
diff2 := before2Minutes.Sub(now)
|
diff2 := before2Minutes.Sub(now)
|
||||||
if diff2.Minutes() != -2 {
|
if diff2.Minutes() != -2 {
|
||||||
utils.LogFailedTestInfo(t, "AddMinute", now, -2, diff2.Minutes())
|
internal.LogFailedTestInfo(t, "AddMinute", now, -2, diff2.Minutes())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ func TestGetNowDate(t *testing.T) {
|
|||||||
date := GetNowDate()
|
date := GetNowDate()
|
||||||
expected := time.Now().Format("2006-01-02")
|
expected := time.Now().Format("2006-01-02")
|
||||||
if date != expected {
|
if date != expected {
|
||||||
utils.LogFailedTestInfo(t, "GetNowDate", "", expected, date)
|
internal.LogFailedTestInfo(t, "GetNowDate", "", expected, date)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ func TestGetNotTime(t *testing.T) {
|
|||||||
ts := GetNowTime()
|
ts := GetNowTime()
|
||||||
expected := time.Now().Format("15:04:05")
|
expected := time.Now().Format("15:04:05")
|
||||||
if ts != expected {
|
if ts != expected {
|
||||||
utils.LogFailedTestInfo(t, "GetNowTime", "", expected, ts)
|
internal.LogFailedTestInfo(t, "GetNowTime", "", expected, ts)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func TestGetNowDateTime(t *testing.T) {
|
|||||||
ts := GetNowDateTime()
|
ts := GetNowDateTime()
|
||||||
expected := time.Now().Format("2006-01-02 15:04:05")
|
expected := time.Now().Format("2006-01-02 15:04:05")
|
||||||
if ts != expected {
|
if ts != expected {
|
||||||
utils.LogFailedTestInfo(t, "GetNowDateTime", "", expected, ts)
|
internal.LogFailedTestInfo(t, "GetNowDateTime", "", expected, ts)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ func TestFormatTimeToStr(t *testing.T) {
|
|||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := FormatTimeToStr(datetime, cases[i])
|
res := FormatTimeToStr(datetime, cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,10 +135,13 @@ func TestFormatStrToTime(t *testing.T) {
|
|||||||
"2021/01"}
|
"2021/01"}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
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])
|
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
|
internal.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,23 @@
|
|||||||
// Use of this source code is governed by MIT license.
|
// Use of this source code is governed by MIT license.
|
||||||
|
|
||||||
// Package fileutil implements some basic functions for file operations
|
// Package fileutil implements some basic functions for file operations
|
||||||
|
|
||||||
package fileutil
|
package fileutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsFileExists checks if a file or directory exists
|
// IsExist checks if a file or directory exists
|
||||||
func IsExist(path string) bool {
|
func IsExist(path string) bool {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if errors.Is(err, os.ErrExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -35,7 +35,7 @@ func CreateFile(path string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFileExists checks if the path is directy or not
|
// IsDir checks if the path is directory or not
|
||||||
func IsDir(path string) bool {
|
func IsDir(path string) bool {
|
||||||
file, err := os.Stat(path)
|
file, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -70,13 +70,59 @@ func CopyFile(srcFilePath string, dstFilePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ClearFile write empty string to path file
|
||||||
|
func ClearFile(path string) error {
|
||||||
|
f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = f.WriteString("")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//ReadFileToString return string of file content
|
||||||
|
func ReadFileToString(path string) (string, error) {
|
||||||
|
bytes, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(bytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFileByLine read file line by line
|
||||||
|
func ReadFileByLine(path string) ([]string, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
res := make([]string, 0)
|
||||||
|
buf := bufio.NewReader(f)
|
||||||
|
|
||||||
|
for {
|
||||||
|
line, _, err := buf.ReadLine()
|
||||||
|
l := string(line)
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res = append(res, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListFileNames return all file names in the path
|
// ListFileNames return all file names in the path
|
||||||
func ListFileNames(path string) ([]string, error) {
|
func ListFileNames(path string) ([]string, error) {
|
||||||
if !IsExist(path) {
|
if !IsExist(path) {
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
package fileutil
|
package fileutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsExist(t *testing.T) {
|
func TestIsExist(t *testing.T) {
|
||||||
cases := []string{"./", "./a.txt"}
|
cases := []string{"./", "./file.go", "./a.txt"}
|
||||||
expected := []bool{true, false}
|
expected := []bool{true, true, false}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := IsExist(cases[i])
|
res := IsExist(cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,15 +26,15 @@ func TestCreateFile(t *testing.T) {
|
|||||||
if CreateFile(f) {
|
if CreateFile(f) {
|
||||||
file, err := os.Open(f)
|
file, err := os.Open(f)
|
||||||
if err != nil {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
if file.Name() != f {
|
if file.Name() != f {
|
||||||
utils.LogFailedTestInfo(t, "CreateFile", f, f, file.Name())
|
internal.LogFailedTestInfo(t, "CreateFile", f, f, file.Name())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
utils.LogFailedTestInfo(t, "CreateFile", f, f, "create file error")
|
internal.LogFailedTestInfo(t, "CreateFile", f, f, "create file error")
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +46,7 @@ func TestIsDir(t *testing.T) {
|
|||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := IsDir(cases[i])
|
res := IsDir(cases[i])
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,11 +57,11 @@ func TestRemoveFile(t *testing.T) {
|
|||||||
if CreateFile(f) {
|
if CreateFile(f) {
|
||||||
err := RemoveFile(f)
|
err := RemoveFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.LogFailedTestInfo(t, "RemoveFile", f, f, err.Error())
|
internal.LogFailedTestInfo(t, "RemoveFile", f, f, err.Error())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
utils.LogFailedTestInfo(t, "RemoveFile", f, f, "create file error")
|
internal.LogFailedTestInfo(t, "RemoveFile", f, f, "create file error")
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,25 +76,63 @@ func TestCopyFile(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
file, err := os.Open(dstFile)
|
file, err := os.Open(dstFile)
|
||||||
if err != nil {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
if file.Name() != dstFile {
|
if file.Name() != dstFile {
|
||||||
utils.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, file.Name())
|
internal.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, file.Name())
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListFileNames(t *testing.T) {
|
func TestListFileNames(t *testing.T) {
|
||||||
filesInCurrentPath, err := ListFileNames("./")
|
filesInCurrentPath, err := ListFileNames("../datetime/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
expected := []string{"file.go", "file_test.go"}
|
expected := []string{"datetime.go", "datetime_test.go"}
|
||||||
if !reflect.DeepEqual(filesInCurrentPath, expected) {
|
if !reflect.DeepEqual(filesInCurrentPath, expected) {
|
||||||
utils.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
|
internal.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFileToString(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello world")
|
||||||
|
|
||||||
|
res, _ := ReadFileToString(path)
|
||||||
|
if res != "hello world" {
|
||||||
|
internal.LogFailedTestInfo(t, "ReadFileToString", path, "hello world", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClearFile(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello world")
|
||||||
|
|
||||||
|
CreateFile(path)
|
||||||
|
|
||||||
|
res, _ := ReadFileToString(path)
|
||||||
|
if res != "" {
|
||||||
|
internal.LogFailedTestInfo(t, "CreateFile", path, "", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFileByLine(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello\nworld")
|
||||||
|
|
||||||
|
expected := []string{"hello", "world"}
|
||||||
|
res, _ := ReadFileByLine(path)
|
||||||
|
if !reflect.DeepEqual(res, expected) {
|
||||||
|
internal.LogFailedTestInfo(t, "ReadFileByLine", path, expected, res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,4 @@ func Comma(v interface{}, symbol string) string {
|
|||||||
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
||||||
}
|
}
|
||||||
return symbol + commaString(s)
|
return symbol + commaString(s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestComma(t *testing.T) {
|
func TestComma(t *testing.T) {
|
||||||
comma(t, "", "","")
|
comma(t, "", "", "")
|
||||||
comma(t, "aa", "","")
|
comma(t, "aa", "", "")
|
||||||
comma(t, "123", "","123")
|
comma(t, "aa.a", "", "")
|
||||||
comma(t, "12345", "","12,345")
|
comma(t, []int{1}, "", "")
|
||||||
comma(t, 12345, "","12,345")
|
comma(t, "123", "", "123")
|
||||||
comma(t, 12345, "$","$12,345")
|
comma(t, "12345", "", "12,345")
|
||||||
comma(t, 12345, "¥","¥12,345")
|
comma(t, 12345, "", "12,345")
|
||||||
comma(t, 12345.6789, "","12,345.6789")
|
comma(t, 12345, "$", "$12,345")
|
||||||
|
comma(t, 12345, "¥", "¥12,345")
|
||||||
|
comma(t, 12345.6789, "", "12,345.6789")
|
||||||
}
|
}
|
||||||
|
|
||||||
func comma(t *testing.T, test interface{}, symbol string, expected interface{}) {
|
func comma(t *testing.T, test interface{}, symbol string, expected interface{}) {
|
||||||
res:= Comma(test, symbol)
|
res := Comma(test, symbol)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "Comma", test, expected, res)
|
internal.LogFailedTestInfo(t, "Comma", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,22 +18,23 @@ func numString(value interface{}) string {
|
|||||||
switch reflect.TypeOf(value).Kind() {
|
switch reflect.TypeOf(value).Kind() {
|
||||||
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
|
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
|
||||||
return fmt.Sprintf("%v", value)
|
return fmt.Sprintf("%v", value)
|
||||||
case reflect.String: {
|
case reflect.String:
|
||||||
sv := fmt.Sprintf("%v", value)
|
{
|
||||||
if strings.Contains(sv, ".") {
|
sv := fmt.Sprintf("%v", value)
|
||||||
_, err := strconv.ParseFloat(sv, 64)
|
if strings.Contains(sv, ".") {
|
||||||
if err == nil {
|
_, err := strconv.ParseFloat(sv, 64)
|
||||||
return sv
|
if err == nil {
|
||||||
}
|
return sv
|
||||||
}else {
|
}
|
||||||
_, err := strconv.ParseInt(sv, 10, 64)
|
} else {
|
||||||
if err == nil {
|
_, err := strconv.ParseInt(sv, 10, 64)
|
||||||
return sv
|
if err == nil {
|
||||||
|
return sv
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
90
function/function.go
Normal file
90
function/function.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
|
// Package function implements some functions for control the function execution and some is for functional programming.
|
||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 unsafeInvokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = unsafeInvokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
if n <= 0 {
|
||||||
|
fn = nil
|
||||||
|
}
|
||||||
|
n--
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fn is for curry function which is func(...interface{}) interface{}
|
||||||
|
type Fn func(...interface{}) interface{}
|
||||||
|
|
||||||
|
// Curry make a curry function
|
||||||
|
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} {
|
||||||
|
return func(values ...interface{}) interface{} {
|
||||||
|
v := append([]interface{}{i}, values...)
|
||||||
|
return f(v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose compose the functions from right to left
|
||||||
|
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} {
|
||||||
|
return func(s ...interface{}) interface{} {
|
||||||
|
f := fnList[0]
|
||||||
|
restFn := fnList[1:]
|
||||||
|
|
||||||
|
if len(fnList) == 1 {
|
||||||
|
return f(s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f(Compose(restFn...)(s...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay make the function execution after delayed time
|
||||||
|
func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
|
||||||
|
time.Sleep(delay)
|
||||||
|
invokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
unsafeInvokeFunc(fn, args...)
|
||||||
|
select {
|
||||||
|
case <-time.After(d):
|
||||||
|
case <-quit:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return quit
|
||||||
|
}
|
||||||
114
function/function_test.go
Normal file
114
function/function_test.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAfter(t *testing.T) {
|
||||||
|
arr := []string{"a", "b"}
|
||||||
|
f := After(len(arr), func(i int) int {
|
||||||
|
fmt.Println("print done")
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
type cb func(args ...interface{}) []reflect.Value
|
||||||
|
print := func(i int, s string, fn cb) {
|
||||||
|
fmt.Printf("print: arr[%d] is %s \n", i, s)
|
||||||
|
v := fn(i)
|
||||||
|
if v != nil {
|
||||||
|
vv := v[0].Int()
|
||||||
|
if vv != 1 {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("print: arr is", arr)
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
print(i, arr[i], f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBefore(t *testing.T) {
|
||||||
|
arr := []string{"a", "b", "c", "d", "e"}
|
||||||
|
f := Before(3, func(i int) int {
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
|
||||||
|
var res []int64
|
||||||
|
type cb func(args ...interface{}) []reflect.Value
|
||||||
|
appendStr := func(i int, s string, fn cb) {
|
||||||
|
fmt.Printf("appendStr: arr[%d] is %s \n", i, s)
|
||||||
|
v := fn(i)
|
||||||
|
res = append(res, v[0].Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
appendStr(i, arr[i], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := []int64{0, 1, 2, 2, 2}
|
||||||
|
if !reflect.DeepEqual(expect, res) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCurry(t *testing.T) {
|
||||||
|
add := func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
var addCurry Fn = func(values ...interface{}) interface{} {
|
||||||
|
return add(values[0].(int), values[1].(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
add1 := addCurry.Curry(1)
|
||||||
|
v := add1(2)
|
||||||
|
if v != 3 {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompose(t *testing.T) {
|
||||||
|
toUpper := func(a ...interface{}) interface{} {
|
||||||
|
return strings.ToUpper(a[0].(string))
|
||||||
|
}
|
||||||
|
toLower := func(a ...interface{}) interface{} {
|
||||||
|
return strings.ToLower(a[0].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := toUpper(toLower("aBCde"))
|
||||||
|
cf := Compose(toUpper, toLower)
|
||||||
|
res := cf("aBCde")
|
||||||
|
|
||||||
|
if res != expect {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelay(t *testing.T) {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
Delay(2*time.Second, print, "test delay")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchedule(t *testing.T) {
|
||||||
|
var res []string
|
||||||
|
appendStr := func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
res = append(res, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop := Schedule(1*time.Second, appendStr, "*")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
close(stop)
|
||||||
|
|
||||||
|
expect := []string{"*", "*", "*", "*", "*"}
|
||||||
|
if !reflect.DeepEqual(expect, res) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
fmt.Println("done")
|
||||||
|
}
|
||||||
39
function/function_util.go
Normal file
39
function/function_util.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||||
|
fv := functionValue(fn)
|
||||||
|
params := make([]reflect.Value, len(args))
|
||||||
|
for i, item := range args {
|
||||||
|
params[i] = reflect.ValueOf(item)
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
||||||
|
}
|
||||||
|
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
37
function/watcher.go
Normal 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
32
function/watcher_test.go
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
// Package utils implements is for internal use.
|
// Package internal is for internal use.
|
||||||
package utils
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LogFailedTestInfo log test failed info for internal use
|
||||||
func LogFailedTestInfo(t *testing.T, testCase, input, expected, result interface{}) {
|
func LogFailedTestInfo(t *testing.T, testCase, input, expected, result interface{}) {
|
||||||
errInfo := fmt.Sprintf("Test case %v: input is %+v, expected %v, but result is %v", testCase, input, expected, result)
|
errInfo := fmt.Sprintf("Test case %v: input is %+v, expected %v, but result is %v", testCase, input, expected, result)
|
||||||
t.Error(errInfo)
|
t.Error(errInfo)
|
||||||
@@ -47,6 +47,7 @@ func GetPublicIpInfo() (*PublicIpInfo, error) {
|
|||||||
return &ip, nil
|
return &ip, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PublicIpInfo public ip info: country, region, isp, city, lat, lon, ip
|
||||||
type PublicIpInfo struct {
|
type PublicIpInfo struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package netutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetInternalIp(t *testing.T) {
|
func TestGetInternalIp(t *testing.T) {
|
||||||
internalIp := GetInternalIp()
|
internalIp := GetInternalIp()
|
||||||
ip := net.ParseIP(internalIp)
|
ip := net.ParseIP(internalIp)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
utils.LogFailedTestInfo(t, "GetInternalIp", "GetInternalIp", "", ip)
|
internal.LogFailedTestInfo(t, "GetInternalIp", "GetInternalIp", "", ip)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ func TestIsPublicIP(t *testing.T) {
|
|||||||
res := IsPublicIP(ips[i])
|
res := IsPublicIP(ips[i])
|
||||||
|
|
||||||
if res != expected[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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -20,27 +22,36 @@ import (
|
|||||||
|
|
||||||
//HttpGet send get http request
|
//HttpGet send get http request
|
||||||
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
|
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
|
//HttpPost send post http request
|
||||||
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
|
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
|
//HttpPut send put http request
|
||||||
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
|
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
|
//HttpDelete send delete http request
|
||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
|
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
|
// HttpPatch send patch http request
|
||||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) {
|
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
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error {
|
||||||
|
if resp == nil {
|
||||||
|
return errors.New("InvalidResp")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return json.NewDecoder(resp.Body).Decode(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertMapToQueryString convert map to sorted url query string
|
// ConvertMapToQueryString convert map to sorted url query string
|
||||||
|
|||||||
@@ -4,17 +4,19 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHttpGet(t *testing.T) {
|
func TestHttpGet(t *testing.T) {
|
||||||
url := "https://gutendex.com/books?"
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
queryParams := make(map[string]interface{})
|
header := map[string]string{
|
||||||
queryParams["ids"] = "1"
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := HttpGet(url, nil, queryParams)
|
resp, err := HttpGet(url, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@@ -22,23 +24,20 @@ func TestHttpGet(t *testing.T) {
|
|||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpPost(t *testing.T) {
|
func TestHttpPost(t *testing.T) {
|
||||||
url := "http://public-api-v1.aspirantzhang.com/users"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
type User struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
}
|
|
||||||
user := User{
|
|
||||||
"test",
|
|
||||||
"test@test.com",
|
|
||||||
}
|
|
||||||
bodyParams, _ := json.Marshal(user)
|
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"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)
|
resp, err := HttpPost(url, header, nil, bodyParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -49,19 +48,18 @@ func TestHttpPost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpPut(t *testing.T) {
|
func TestHttpPut(t *testing.T) {
|
||||||
url := "http://public-api-v1.aspirantzhang.com/users/10420"
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
type User struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
}
|
|
||||||
user := User{
|
|
||||||
"test",
|
|
||||||
"test@test.com",
|
|
||||||
}
|
|
||||||
bodyParams, _ := json.Marshal(user)
|
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"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)
|
resp, err := HttpPut(url, header, nil, bodyParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -71,8 +69,30 @@ func TestHttpPut(t *testing.T) {
|
|||||||
fmt.Println("response: ", resp.StatusCode, string(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) {
|
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)
|
resp, err := HttpDelete(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -92,7 +112,35 @@ func TestConvertMapToQueryString(t *testing.T) {
|
|||||||
expected := "a=1&b=2&c=3"
|
expected := "a=1&b=2&c=3"
|
||||||
r := ConvertMapToQueryString(m)
|
r := ConvertMapToQueryString(m)
|
||||||
if r != expected {
|
if r != expected {
|
||||||
utils.LogFailedTestInfo(t, "ConvertMapToQueryString", m, expected, r)
|
internal.LogFailedTestInfo(t, "ConvertMapToQueryString", m, expected, r)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseResponse(t *testing.T) {
|
||||||
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
|
header := map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := HttpGet(url, header)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
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("response: ", toDoResp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"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 {
|
if len(reqUrl) == 0 {
|
||||||
return nil, errors.New("url should be specified")
|
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{}
|
client := &http.Client{}
|
||||||
|
err := setUrl(req, reqUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
switch len(params) {
|
switch len(params) {
|
||||||
case 0:
|
|
||||||
err := setUrl(req, reqUrl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case 1:
|
case 1:
|
||||||
err := setUrl(req, reqUrl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setHeader(req, params[0])
|
err = setHeader(req, params[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
err := setHeader(req, params[0])
|
err := setHeaderAndQueryParam(req, reqUrl, params[0], params[1])
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setQueryParam(req, reqUrl, params[1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
err := setHeader(req, params[0])
|
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setQueryParam(req, reqUrl, params[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setBodyByte(req, params[2])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
err := setHeader(req, params[0])
|
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setQueryParam(req, reqUrl, params[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = setBodyByte(req, params[2])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -78,13 +54,40 @@ func request(method, reqUrl string, params ...interface{}) (*http.Response, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, e := client.Do(req)
|
resp, e := client.Do(req)
|
||||||
return resp, e
|
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 {
|
func setHeader(req *http.Request, header interface{}) error {
|
||||||
if header != nil {
|
if header != nil {
|
||||||
switch v := header.(type) {
|
switch v := header.(type) {
|
||||||
@@ -109,6 +112,7 @@ func setHeader(req *http.Request, header interface{}) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUrl(req *http.Request, reqUrl string) error {
|
func setUrl(req *http.Request, reqUrl string) error {
|
||||||
u, err := url.Parse(reqUrl)
|
u, err := url.Parse(reqUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -117,6 +121,7 @@ func setUrl(req *http.Request, reqUrl string) error {
|
|||||||
req.URL = u
|
req.URL = u
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
|
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
|
||||||
var values url.Values
|
var values url.Values
|
||||||
if queryParam != nil {
|
if queryParam != nil {
|
||||||
@@ -124,7 +129,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
|
|||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
values = url.Values{}
|
values = url.Values{}
|
||||||
for k := range v {
|
for k := range v {
|
||||||
values.Set(k, fmt.Sprintf("%s", v[k]))
|
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||||
}
|
}
|
||||||
case url.Values:
|
case url.Values:
|
||||||
values = v
|
values = v
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* @Descripttion:
|
||||||
|
* @version: v1.0.0
|
||||||
|
* @Author: dudaodong@kingsoft.com
|
||||||
|
* @Date: 2021-11-29 11:43:28
|
||||||
|
* @LastEditors: dudaodong@kingsoft.com
|
||||||
|
* @LastEditTime: 2021-12-01 18:05:29
|
||||||
|
*/
|
||||||
package random
|
package random
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRandString(t *testing.T) {
|
func TestRandString(t *testing.T) {
|
||||||
@@ -15,32 +24,48 @@ func TestRandString(t *testing.T) {
|
|||||||
reg := regexp.MustCompile(pattern)
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
if len(randStr) != 6 || !reg.MatchString(randStr) {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandInt(t *testing.T) {
|
func TestRandInt(t *testing.T) {
|
||||||
randInt := RandInt(1, 10)
|
res1 := RandInt(1, 10)
|
||||||
|
if res1 < 1 || res1 >= 10 {
|
||||||
|
internal.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", res1)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
if randInt < 1 || randInt >= 10 {
|
res2 := RandInt(1, 1)
|
||||||
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", randInt)
|
if res2 != 1 {
|
||||||
|
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 {
|
||||||
|
internal.LogFailedTestInfo(t, "RandInt", "RandInt(10, 1)", "RandInt(10, 1) should between [1, 10) ", res3)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandBytes(t *testing.T) {
|
func TestRandBytes(t *testing.T) {
|
||||||
randBytes := RandBytes(4)
|
randBytes := RandBytes(4)
|
||||||
|
|
||||||
if len(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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(randBytes)
|
v := reflect.ValueOf(randBytes)
|
||||||
et := v.Type().Elem()
|
et := v.Type().Elem()
|
||||||
if v.Kind() != reflect.Slice || et.Kind() != reflect.Uint8 {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randErr := RandBytes(0)
|
||||||
|
if randErr != nil {
|
||||||
|
internal.LogFailedTestInfo(t, "RandBytes", "RandBytes(0)", "RandBytes(0) should return nil", randErr)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
348
slice/slice.go
348
slice/slice.go
@@ -7,16 +7,20 @@ package slice
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Contain check if the value is in the slice or not
|
// Contain check if the value is in the iterable type or not
|
||||||
func Contain(slice interface{}, value interface{}) bool {
|
func Contain(iterableType interface{}, value interface{}) bool {
|
||||||
v := reflect.ValueOf(slice)
|
|
||||||
switch reflect.TypeOf(slice).Kind() {
|
v := reflect.ValueOf(iterableType)
|
||||||
|
|
||||||
|
switch kind := reflect.TypeOf(iterableType).Kind(); kind {
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
if v.Index(i).Interface() == value {
|
if v.Index(i).Interface() == value {
|
||||||
@@ -29,9 +33,15 @@ func Contain(slice interface{}, value interface{}) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
s := fmt.Sprintf("%v", slice)
|
s := iterableType.(string)
|
||||||
ss := fmt.Sprintf("%v", value)
|
ss, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
panic("kind mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
return strings.Contains(s, ss)
|
return strings.Contains(s, ss)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("kind %s is not support", iterableType))
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -89,6 +99,50 @@ func Difference(slice1, slice2 interface{}) interface{} {
|
|||||||
return res.Interface()
|
return res.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every return true if all of the values in the slice pass the predicate function.
|
||||||
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
|
func Every(slice, function 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
currentLength++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentLength == sv.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some return true if any of the values in the list pass the predicate function.
|
||||||
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
|
func Some(slice, function 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
has := false
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
||||||
|
if flag.Bool() {
|
||||||
|
has = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
// Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for.
|
// Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for.
|
||||||
// The function signature should be func(index int, value interface{}) bool .
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
func Filter(slice, function interface{}) interface{} {
|
func Filter(slice, function interface{}) interface{} {
|
||||||
@@ -97,7 +151,7 @@ func Filter(slice, function interface{}) interface{} {
|
|||||||
|
|
||||||
elemType := sv.Type().Elem()
|
elemType := sv.Type().Elem()
|
||||||
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
|
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
|
||||||
panic("Filter function must be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexes []int
|
var indexes []int
|
||||||
@@ -115,6 +169,84 @@ func Filter(slice, function interface{}) interface{} {
|
|||||||
return res.Interface()
|
return res.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 GroupBy(slice, function interface{}) (interface{}, interface{}) {
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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`.
|
// Map creates an slice of values by running each element of `slice` thru `function`.
|
||||||
// The function signature should be func(index int, value interface{}) interface{}.
|
// The function signature should be func(index int, value interface{}) interface{}.
|
||||||
func Map(slice, function interface{}) interface{} {
|
func Map(slice, function interface{}) interface{} {
|
||||||
@@ -123,7 +255,7 @@ func Map(slice, function interface{}) interface{} {
|
|||||||
|
|
||||||
elemType := sv.Type().Elem()
|
elemType := sv.Type().Elem()
|
||||||
if checkSliceCallbackFuncSignature(fn, elemType, nil) {
|
if checkSliceCallbackFuncSignature(fn, elemType, nil) {
|
||||||
panic("Map function must be of type func(int, " + elemType.String() + ")" + elemType.String())
|
panic("function param should be of type func(int, " + elemType.String() + ")" + elemType.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
res := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
|
res := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
|
||||||
@@ -137,20 +269,19 @@ func Map(slice, function interface{}) interface{} {
|
|||||||
// The function signature should be func(index int, value1, value2 interface{}) interface{} .
|
// The function signature should be func(index int, value1, value2 interface{}) interface{} .
|
||||||
func Reduce(slice, function, zero interface{}) interface{} {
|
func Reduce(slice, function, zero interface{}) interface{} {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
|
elementType := sv.Type().Elem()
|
||||||
|
|
||||||
len := sv.Len()
|
len := sv.Len()
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
return zero
|
return zero
|
||||||
} else if len == 1 {
|
} else if len == 1 {
|
||||||
return sv.Index(0)
|
return sv.Index(0).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
elementType := sv.Type().Elem()
|
|
||||||
fn := functionValue(function)
|
fn := functionValue(function)
|
||||||
|
|
||||||
if checkSliceCallbackFuncSignature(fn, elementType, elementType, elementType) {
|
if checkSliceCallbackFuncSignature(fn, elementType, elementType, elementType) {
|
||||||
t := elementType.String()
|
t := elementType.String()
|
||||||
panic("Reduce function must be of type func(int, " + t + ", " + t + ")" + t)
|
panic("function param should be of type func(int, " + t + ", " + t + ")" + t)
|
||||||
}
|
}
|
||||||
|
|
||||||
var params [3]reflect.Value
|
var params [3]reflect.Value
|
||||||
@@ -187,32 +318,34 @@ func InterfaceSlice(slice interface{}) []interface{} {
|
|||||||
|
|
||||||
// StringSlice convert param to slice of string.
|
// StringSlice convert param to slice of string.
|
||||||
func StringSlice(slice interface{}) []string {
|
func StringSlice(slice interface{}) []string {
|
||||||
var res []string
|
|
||||||
|
|
||||||
v := sliceValue(slice)
|
v := sliceValue(slice)
|
||||||
|
|
||||||
|
out := make([]string, v.Len())
|
||||||
for i := 0; i < v.Len(); i++ {
|
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.
|
// IntSlice convert param to slice of int.
|
||||||
func IntSlice(slice interface{}) ([]int, error) {
|
func IntSlice(slice interface{}) []int {
|
||||||
var res []int
|
|
||||||
|
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
|
|
||||||
|
out := make([]int, sv.Len())
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
v := sv.Index(i).Interface()
|
v, ok := sv.Index(i).Interface().(int)
|
||||||
switch v := v.(type) {
|
if !ok {
|
||||||
case int:
|
panic("invalid element type")
|
||||||
res = append(res, v)
|
|
||||||
default:
|
|
||||||
return nil, errors.New("InvalidSliceElementType")
|
|
||||||
}
|
}
|
||||||
|
out[i] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertSlice convert original slice to new data type element of slice.
|
// ConvertSlice convert original slice to new data type element of slice.
|
||||||
@@ -257,6 +390,37 @@ func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error
|
|||||||
return v.Interface(), nil
|
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.
|
// InsertByIndex insert the element into slice at index.
|
||||||
// Insert value: s = append(s[:i], append([]T{x}, s[i:]...)...)
|
// Insert value: s = append(s[:i], append([]T{x}, s[i:]...)...)
|
||||||
// Insert slice: a = append(a[:i], append(b, a[i:]...)...)
|
// Insert slice: a = append(a[:i], append(b, a[i:]...)...)
|
||||||
@@ -298,6 +462,7 @@ func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}
|
|||||||
if index < 0 || index >= v.Len() {
|
if index < 0 || index >= v.Len() {
|
||||||
return slice, errors.New("InvalidSliceIndex")
|
return slice, errors.New("InvalidSliceIndex")
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
|
if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
|
||||||
return slice, errors.New("InvalidValueType")
|
return slice, errors.New("InvalidValueType")
|
||||||
}
|
}
|
||||||
@@ -314,22 +479,27 @@ func Unique(slice interface{}) interface{} {
|
|||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
|
|
||||||
var res []interface{}
|
var temp []interface{}
|
||||||
|
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
v := sv.Index(i).Interface()
|
v := sv.Index(i).Interface()
|
||||||
flag := true
|
skip := true
|
||||||
for j := range res {
|
for j := range temp {
|
||||||
if v == res[j] {
|
if v == temp[j] {
|
||||||
flag = false
|
skip = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if flag {
|
if skip {
|
||||||
res = append(res, v)
|
temp = append(temp, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
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()
|
||||||
|
|
||||||
// if use map filter, the result slice element order is random, not same as origin slice
|
// if use map filter, the result slice element order is random, not same as origin slice
|
||||||
//mp := make(map[interface{}]bool)
|
//mp := make(map[interface{}]bool)
|
||||||
@@ -346,21 +516,94 @@ func Unique(slice interface{}) interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
|
||||||
|
func Union(slices ...interface{}) interface{} {
|
||||||
|
if len(slices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// append all slices, then unique it
|
||||||
|
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()
|
||||||
|
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(allSlices[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unique(res.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection creates a slice of unique values that included by all slices.
|
||||||
|
func Intersection(slices ...interface{}) interface{} {
|
||||||
|
if len(slices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
reduceFunc := func(index int, slice1, slice2 interface{}) interface{} {
|
||||||
|
set := make([]interface{}, 0)
|
||||||
|
hash := make(map[interface{}]bool)
|
||||||
|
|
||||||
|
sv1 := reflect.ValueOf(slice1)
|
||||||
|
for i := 0; i < sv1.Len(); i++ {
|
||||||
|
v := sv1.Index(i).Interface()
|
||||||
|
hash[v] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
sv2 := reflect.ValueOf(slice2)
|
||||||
|
for i := 0; i < sv2.Len(); i++ {
|
||||||
|
el := sv2.Index(i).Interface()
|
||||||
|
if _, found := hash[el]; found {
|
||||||
|
set = append(set, el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res := reflect.MakeSlice(sv1.Type(), len(set), len(set))
|
||||||
|
for i := 0; i < len(set); i++ {
|
||||||
|
res.Index(i).Set(reflect.ValueOf(set[i]))
|
||||||
|
}
|
||||||
|
return res.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
res := Reduce(slices, reduceFunc, nil)
|
||||||
|
return Unique(res)
|
||||||
|
}
|
||||||
|
|
||||||
// ReverseSlice return slice of element order is reversed to the given slice
|
// ReverseSlice return slice of element order is reversed to the given slice
|
||||||
func ReverseSlice(slice interface{}) {
|
func ReverseSlice(slice interface{}) {
|
||||||
v := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
swp := reflect.Swapper(v.Interface())
|
swp := reflect.Swapper(sv.Interface())
|
||||||
for i, j := 0, v.Len()-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, sv.Len()-1; i < j; i, j = i+1, j-1 {
|
||||||
swp(i, j)
|
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
|
// SortByField return sorted slice by field
|
||||||
// Slice element should be struct, field type should be int, uint, string, or bool
|
// 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
|
// default sortType is ascending (asc), if descending order, set sortType to desc
|
||||||
func SortByField(slice interface{}, field string, sortType ...string) error {
|
func SortByField(slice interface{}, field string, sortType ...string) error {
|
||||||
v := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
t := v.Type().Elem()
|
t := sv.Type().Elem()
|
||||||
|
|
||||||
if t.Kind() == reflect.Ptr {
|
if t.Kind() == reflect.Ptr {
|
||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
@@ -393,8 +636,8 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(slice, func(i, j int) bool {
|
sort.Slice(slice, func(i, j int) bool {
|
||||||
a := v.Index(i)
|
a := sv.Index(i)
|
||||||
b := v.Index(j)
|
b := sv.Index(j)
|
||||||
if t.Kind() == reflect.Ptr {
|
if t.Kind() == reflect.Ptr {
|
||||||
a = a.Elem()
|
a = a.Elem()
|
||||||
b = b.Elem()
|
b = b.Elem()
|
||||||
@@ -409,3 +652,26 @@ func SortByField(slice interface{}, field string, sortType ...string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Without creates a slice excluding all given values
|
||||||
|
func Without(slice interface{}, values ...interface{}) interface{} {
|
||||||
|
sv := sliceValue(slice)
|
||||||
|
if sv.Len() == 0 {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexes []int
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
v := sv.Index(i).Interface()
|
||||||
|
if !Contain(values, v) {
|
||||||
|
indexes = append(indexes, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := reflect.MakeSlice(sv.Type(), len(indexes), len(indexes))
|
||||||
|
for i := range indexes {
|
||||||
|
res.Index(i).Set(sv.Index(indexes[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.Interface()
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestContain(t *testing.T) {
|
func TestContain(t *testing.T) {
|
||||||
@@ -14,12 +14,21 @@ func TestContain(t *testing.T) {
|
|||||||
|
|
||||||
var t2 []string
|
var t2 []string
|
||||||
contain(t, t2, "1", false)
|
contain(t, t2, "1", false)
|
||||||
|
|
||||||
|
m := make(map[string]int)
|
||||||
|
m["a"] = 1
|
||||||
|
contain(t, m, "a", true)
|
||||||
|
contain(t, m, "b", false)
|
||||||
|
|
||||||
|
s := "hello"
|
||||||
|
contain(t, s, "h", true)
|
||||||
|
contain(t, s, "s", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
|
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
|
||||||
res := Contain(test, value)
|
res := Contain(test, value)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "Contain", test, expected, res)
|
internal.LogFailedTestInfo(t, "Contain", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +78,7 @@ func TestChunk(t *testing.T) {
|
|||||||
func chunk(t *testing.T, test []interface{}, num int, expected [][]interface{}) {
|
func chunk(t *testing.T, test []interface{}, num int, expected [][]interface{}) {
|
||||||
res := Chunk(test, num)
|
res := Chunk(test, num)
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "Chunk", test, expected, res)
|
internal.LogFailedTestInfo(t, "Chunk", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,15 +96,39 @@ func TestConvertSlice(t *testing.T) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEvery(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 5}
|
||||||
|
isEven := func(i, num int) bool {
|
||||||
|
return num%2 == 0
|
||||||
|
}
|
||||||
|
res := Every(nums, isEven)
|
||||||
|
if res != false {
|
||||||
|
internal.LogFailedTestInfo(t, "Every", nums, false, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSome(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 5}
|
||||||
|
isEven := func(i, num int) bool {
|
||||||
|
return num%2 == 0
|
||||||
|
}
|
||||||
|
res := Some(nums, isEven)
|
||||||
|
if res != true {
|
||||||
|
internal.LogFailedTestInfo(t, "Some", nums, true, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
func TestFilter(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4, 5}
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
even := func(i, num int) bool {
|
even := func(i, num int) bool {
|
||||||
return num%2 == 0
|
return num%2 == 0
|
||||||
}
|
}
|
||||||
e1 := []int{2, 4}
|
e1 := []int{2, 4}
|
||||||
r1 := Filter(s1, even)
|
r1 := Filter(nums, even)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Filter", s1, e1, r1)
|
internal.LogFailedTestInfo(t, "Filter", nums, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,12 +155,74 @@ func TestFilter(t *testing.T) {
|
|||||||
|
|
||||||
r2 := Filter(students, filterFunc)
|
r2 := Filter(students, filterFunc)
|
||||||
if !reflect.DeepEqual(r2, e2) {
|
if !reflect.DeepEqual(r2, e2) {
|
||||||
utils.LogFailedTestInfo(t, "Filter", students, e2, r2)
|
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
|
||||||
t.FailNow()
|
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, ok := Find(nums, even)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("found nothing")
|
||||||
|
}
|
||||||
|
|
||||||
|
if res != 2 {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4}
|
s1 := []int{1, 2, 3, 4}
|
||||||
multiplyTwo := func(i, num int) int {
|
multiplyTwo := func(i, num int) int {
|
||||||
@@ -136,7 +231,7 @@ func TestMap(t *testing.T) {
|
|||||||
e1 := []int{2, 4, 6, 8}
|
e1 := []int{2, 4, 6, 8}
|
||||||
r1 := Map(s1, multiplyTwo)
|
r1 := Map(s1, multiplyTwo)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Map", s1, e1, r1)
|
internal.LogFailedTestInfo(t, "Map", s1, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,34 +256,27 @@ func TestMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
r2 := Map(students, mapFunc)
|
r2 := Map(students, mapFunc)
|
||||||
if !reflect.DeepEqual(r2, e2) {
|
if !reflect.DeepEqual(r2, e2) {
|
||||||
utils.LogFailedTestInfo(t, "Filter", students, e2, r2)
|
internal.LogFailedTestInfo(t, "Filter", students, e2, r2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4}
|
cases := [][]int{
|
||||||
f1 := func(i, v1, v2 int) int {
|
{},
|
||||||
|
{1},
|
||||||
|
{1, 2, 3, 4}}
|
||||||
|
expected := []int{0, 1, 10}
|
||||||
|
f := func(i, v1, v2 int) int {
|
||||||
return v1 + v2
|
return v1 + v2
|
||||||
}
|
}
|
||||||
e1 := 10
|
for i := 0; i < len(cases); i++ {
|
||||||
r1 := Reduce(s1, f1, 0)
|
res := Reduce(cases[i], f, 0)
|
||||||
if e1 != r1 {
|
if res != expected[i] {
|
||||||
utils.LogFailedTestInfo(t, "Reduce", s1, e1, r1)
|
internal.LogFailedTestInfo(t, "Reduce", cases[i], expected[i], res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed Reduce function should be func(i int, v1, v2 int) int
|
|
||||||
//s1 := []int{1, 2, 3, 4}
|
|
||||||
//f1 := func(i string, v1, v2 int) int { //i should be int
|
|
||||||
// return v1+v2
|
|
||||||
//}
|
|
||||||
//e1 := 10
|
|
||||||
//r1 := Reduce(s1, f1, 0)
|
|
||||||
//if e1 != r1 {
|
|
||||||
// utils.LogFailedTestInfo(t, "Reduce", s1, e1, r1)
|
|
||||||
// t.FailNow()
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntSlice(t *testing.T) {
|
func TestIntSlice(t *testing.T) {
|
||||||
@@ -199,12 +287,10 @@ func TestIntSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func intSlice(t *testing.T, test interface{}, expected []int) {
|
func intSlice(t *testing.T, test interface{}, expected []int) {
|
||||||
res, err := IntSlice(test)
|
res := IntSlice(test)
|
||||||
if err != nil {
|
|
||||||
t.Error("IntSlice Error: " + err.Error())
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "IntSlice", test, expected, res)
|
internal.LogFailedTestInfo(t, "IntSlice", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,7 +305,7 @@ func TestStringSlice(t *testing.T) {
|
|||||||
func stringSlice(t *testing.T, test interface{}, expected []string) {
|
func stringSlice(t *testing.T, test interface{}, expected []string) {
|
||||||
res := StringSlice(test)
|
res := StringSlice(test)
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "StringSlice", test, expected, res)
|
internal.LogFailedTestInfo(t, "StringSlice", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +319,7 @@ func TestInterfaceSlice(t *testing.T) {
|
|||||||
func interfaceSlice(t *testing.T, test interface{}, expected []interface{}) {
|
func interfaceSlice(t *testing.T, test interface{}, expected []interface{}) {
|
||||||
res := InterfaceSlice(test)
|
res := InterfaceSlice(test)
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "InterfaceSlice", test, expected, res)
|
internal.LogFailedTestInfo(t, "InterfaceSlice", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,7 +371,30 @@ func deleteByIndex(t *testing.T, origin, test interface{}, start, end int, expec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(res, expected) {
|
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()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +431,7 @@ func insertByIndex(t *testing.T, test interface{}, index int, value, expected in
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "InsertByIndex", test, expected, res)
|
internal.LogFailedTestInfo(t, "InsertByIndex", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,11 +449,6 @@ func TestUpdateByIndex(t *testing.T) {
|
|||||||
r3 := []string{"a", "b", "1"}
|
r3 := []string{"a", "b", "1"}
|
||||||
updateByIndex(t, t1, 2, "1", r3)
|
updateByIndex(t, t1, 2, "1", r3)
|
||||||
|
|
||||||
//failed
|
|
||||||
//t1 = []string{"a","b","c"}
|
|
||||||
//r4 := []string{"a", "b", "1"}
|
|
||||||
//updateByIndex(t, t1, 3, "1", r4)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
|
func updateByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
|
||||||
@@ -354,7 +458,7 @@ func updateByIndex(t *testing.T, test interface{}, index int, value, expected in
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(res, expected) {
|
if !reflect.DeepEqual(res, expected) {
|
||||||
utils.LogFailedTestInfo(t, "UpdateByIndex", test, expected, res)
|
internal.LogFailedTestInfo(t, "UpdateByIndex", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,27 +466,74 @@ func updateByIndex(t *testing.T, test interface{}, index int, value, expected in
|
|||||||
func TestUnique(t *testing.T) {
|
func TestUnique(t *testing.T) {
|
||||||
t1 := []int{1, 2, 2, 3}
|
t1 := []int{1, 2, 2, 3}
|
||||||
e1 := []int{1, 2, 3}
|
e1 := []int{1, 2, 3}
|
||||||
r1, _ := IntSlice(Unique(t1))
|
r1 := Unique(t1)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Unique", t1, e1, r1)
|
internal.LogFailedTestInfo(t, "Unique", t1, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := []string{"a", "a", "b", "c"}
|
t2 := []string{"a", "a", "b", "c"}
|
||||||
e2 := []string{"a", "b", "c"}
|
e2 := []string{"a", "b", "c"}
|
||||||
r2 := StringSlice(Unique(t2))
|
r2 := Unique(t2)
|
||||||
if !reflect.DeepEqual(r2, e2) {
|
if !reflect.DeepEqual(r2, e2) {
|
||||||
utils.LogFailedTestInfo(t, "Unique", t2, e2, r2)
|
internal.LogFailedTestInfo(t, "Unique", t2, e2, r2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnion(t *testing.T) {
|
||||||
|
s1 := []int{1, 3, 4, 6}
|
||||||
|
s2 := []int{1, 2, 5, 6}
|
||||||
|
s3 := []int{0, 4, 5, 7}
|
||||||
|
|
||||||
|
expected1 := []int{1, 3, 4, 6, 2, 5, 0, 7}
|
||||||
|
res1 := Union(s1, s2, s3)
|
||||||
|
if !reflect.DeepEqual(res1, expected1) {
|
||||||
|
internal.LogFailedTestInfo(t, "Union", s1, expected1, res1)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
expected2 := []int{1, 3, 4, 6}
|
||||||
|
res2 := Union(s1)
|
||||||
|
if !reflect.DeepEqual(res2, expected2) {
|
||||||
|
internal.LogFailedTestInfo(t, "Union", s1, expected2, res2)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersection(t *testing.T) {
|
||||||
|
s1 := []int{1, 2, 2, 3}
|
||||||
|
s2 := []int{1, 2, 3, 4}
|
||||||
|
s3 := []int{0, 2, 3, 5, 6}
|
||||||
|
s4 := []int{0, 5, 6}
|
||||||
|
|
||||||
|
expected := [][]int{
|
||||||
|
{2, 3},
|
||||||
|
{1, 2, 3},
|
||||||
|
{1, 2, 3},
|
||||||
|
{},
|
||||||
|
}
|
||||||
|
res := []interface{}{
|
||||||
|
Intersection(s1, s2, s3),
|
||||||
|
Intersection(s1, s2),
|
||||||
|
Intersection(s1),
|
||||||
|
Intersection(s1, s4),
|
||||||
|
}
|
||||||
|
for i := 0; i < len(res); i++ {
|
||||||
|
if !reflect.DeepEqual(res[i], expected[i]) {
|
||||||
|
internal.LogFailedTestInfo(t, "Intersection", "Intersection", expected[i], res[i])
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestReverseSlice(t *testing.T) {
|
func TestReverseSlice(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4, 5}
|
s1 := []int{1, 2, 3, 4, 5}
|
||||||
e1 := []int{5, 4, 3, 2, 1}
|
e1 := []int{5, 4, 3, 2, 1}
|
||||||
ReverseSlice(s1)
|
ReverseSlice(s1)
|
||||||
if !reflect.DeepEqual(s1, e1) {
|
if !reflect.DeepEqual(s1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "ReverseSlice", s1, e1, s1)
|
internal.LogFailedTestInfo(t, "ReverseSlice", s1, e1, s1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +541,7 @@ func TestReverseSlice(t *testing.T) {
|
|||||||
e2 := []string{"e", "d", "c", "b", "a"}
|
e2 := []string{"e", "d", "c", "b", "a"}
|
||||||
ReverseSlice(s2)
|
ReverseSlice(s2)
|
||||||
if !reflect.DeepEqual(s2, e2) {
|
if !reflect.DeepEqual(s2, e2) {
|
||||||
utils.LogFailedTestInfo(t, "ReverseSlice", s2, e2, s2)
|
internal.LogFailedTestInfo(t, "ReverseSlice", s2, e2, s2)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,7 +552,7 @@ func TestDifference(t *testing.T) {
|
|||||||
e1 := []int{1, 2, 3}
|
e1 := []int{1, 2, 3}
|
||||||
r1 := Difference(s1, s2)
|
r1 := Difference(s1, s2)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Difference", s1, e1, r1)
|
internal.LogFailedTestInfo(t, "Difference", s1, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,8 +582,30 @@ func TestSortByField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(students, sortByAge) {
|
if !reflect.DeepEqual(students, sortByAge) {
|
||||||
utils.LogFailedTestInfo(t, "SortByField", students, sortByAge, students)
|
internal.LogFailedTestInfo(t, "SortByField", students, sortByAge, students)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithout(t *testing.T) {
|
||||||
|
s := []int{1, 2, 3, 4, 5}
|
||||||
|
expected := []int{3, 4, 5}
|
||||||
|
res := Without(s, 1, 2)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(res, expected) {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,3 +52,14 @@ func checkSliceCallbackFuncSignature(fn reflect.Value, types ...reflect.Type) bo
|
|||||||
}
|
}
|
||||||
return true
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ package strutil
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CamelCase covert string to camelCase string.
|
// CamelCase covert string to camelCase string.
|
||||||
@@ -40,18 +42,16 @@ func Capitalize(s string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ""
|
out := make([]rune, len(s))
|
||||||
for i, v := range []rune(s) {
|
for i, v := range s {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if v >= 97 && v <= 122 {
|
out[i] = unicode.ToUpper(v)
|
||||||
v -= 32
|
|
||||||
}
|
|
||||||
res += string(v)
|
|
||||||
} else {
|
} else {
|
||||||
res += strings.ToLower(string(v))
|
out[i] = unicode.ToLower(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
|
return string(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LowerFirst converts the first character of string to lower case.
|
// LowerFirst converts the first character of string to lower case.
|
||||||
@@ -60,20 +60,10 @@ func LowerFirst(s string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ""
|
r, size := utf8.DecodeRuneInString(s)
|
||||||
for i, v := range []rune(s) {
|
r = unicode.ToLower(r)
|
||||||
if i == 0 {
|
|
||||||
if v >= 65 && v <= 96 {
|
return string(r) + s[size:]
|
||||||
v += 32
|
|
||||||
res += string(v)
|
|
||||||
} else {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res += string(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PadEnd pads string on the right side if it's shorter than size.
|
// PadEnd pads string on the right side if it's shorter than size.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package strutil
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCamelCase(t *testing.T) {
|
func TestCamelCase(t *testing.T) {
|
||||||
@@ -16,7 +16,7 @@ func TestCamelCase(t *testing.T) {
|
|||||||
func camelCase(t *testing.T, test string, expected string) {
|
func camelCase(t *testing.T, test string, expected string) {
|
||||||
res := CamelCase(test)
|
res := CamelCase(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "CamelCase", test, expected, res)
|
internal.LogFailedTestInfo(t, "CamelCase", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ func TestCapitalize(t *testing.T) {
|
|||||||
func capitalize(t *testing.T, test string, expected string) {
|
func capitalize(t *testing.T, test string, expected string) {
|
||||||
res := Capitalize(test)
|
res := Capitalize(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "Capitalize", test, expected, res)
|
internal.LogFailedTestInfo(t, "Capitalize", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func TestKebabCase(t *testing.T) {
|
|||||||
func kebabCase(t *testing.T, test string, expected string) {
|
func kebabCase(t *testing.T, test string, expected string) {
|
||||||
res := KebabCase(test)
|
res := KebabCase(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "KebabCase", test, expected, res)
|
internal.LogFailedTestInfo(t, "KebabCase", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func TestSnakeCase(t *testing.T) {
|
|||||||
func snakeCase(t *testing.T, test string, expected string) {
|
func snakeCase(t *testing.T, test string, expected string) {
|
||||||
res := SnakeCase(test)
|
res := SnakeCase(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "SnakeCase", test, expected, res)
|
internal.LogFailedTestInfo(t, "SnakeCase", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,12 +70,13 @@ func TestLowerFirst(t *testing.T) {
|
|||||||
lowerFirst(t, "foo", "foo")
|
lowerFirst(t, "foo", "foo")
|
||||||
lowerFirst(t, "BAR", "bAR")
|
lowerFirst(t, "BAR", "bAR")
|
||||||
lowerFirst(t, "FOo", "fOo")
|
lowerFirst(t, "FOo", "fOo")
|
||||||
|
lowerFirst(t, "FOo大", "fOo大")
|
||||||
}
|
}
|
||||||
|
|
||||||
func lowerFirst(t *testing.T, test string, expected string) {
|
func lowerFirst(t *testing.T, test string, expected string) {
|
||||||
res := LowerFirst(test)
|
res := LowerFirst(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "LowerFirst", test, expected, res)
|
internal.LogFailedTestInfo(t, "LowerFirst", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +92,7 @@ func TestPadEnd(t *testing.T) {
|
|||||||
func padEnd(t *testing.T, source string, size int, fillString string, expected string) {
|
func padEnd(t *testing.T, source string, size int, fillString string, expected string) {
|
||||||
res := PadEnd(source, size, fillString)
|
res := PadEnd(source, size, fillString)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
|
internal.LogFailedTestInfo(t, "PadEnd", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +108,7 @@ func TestPadStart(t *testing.T) {
|
|||||||
func padStart(t *testing.T, source string, size int, fillString string, expected string) {
|
func padStart(t *testing.T, source string, size int, fillString string, expected string) {
|
||||||
res := PadStart(source, size, fillString)
|
res := PadStart(source, size, fillString)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
|
internal.LogFailedTestInfo(t, "PadEnd", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,7 +122,7 @@ func TestBefore(t *testing.T) {
|
|||||||
func before(t *testing.T, source, char, expected string) {
|
func before(t *testing.T, source, char, expected string) {
|
||||||
res := Before(source, char)
|
res := Before(source, char)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "Before", source, expected, res)
|
internal.LogFailedTestInfo(t, "Before", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +136,7 @@ func TestBeforeLast(t *testing.T) {
|
|||||||
func beforeLast(t *testing.T, source, char, expected string) {
|
func beforeLast(t *testing.T, source, char, expected string) {
|
||||||
res := BeforeLast(source, char)
|
res := BeforeLast(source, char)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "BeforeLast", source, expected, res)
|
internal.LogFailedTestInfo(t, "BeforeLast", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,7 @@ func TestAfter(t *testing.T) {
|
|||||||
func after(t *testing.T, source, char, expected string) {
|
func after(t *testing.T, source, char, expected string) {
|
||||||
res := After(source, char)
|
res := After(source, char)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "After", source, expected, res)
|
internal.LogFailedTestInfo(t, "After", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +164,7 @@ func TestAfterLast(t *testing.T) {
|
|||||||
func afterLast(t *testing.T, source, char, expected string) {
|
func afterLast(t *testing.T, source, char, expected string) {
|
||||||
res := AfterLast(source, char)
|
res := AfterLast(source, char)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "AfterLast", source, expected, res)
|
internal.LogFailedTestInfo(t, "AfterLast", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ func TestIsString(t *testing.T) {
|
|||||||
func isString(t *testing.T, test interface{}, expected bool) {
|
func isString(t *testing.T, test interface{}, expected bool) {
|
||||||
res := IsString(test)
|
res := IsString(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsString", test, expected, res)
|
internal.LogFailedTestInfo(t, "IsString", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +195,7 @@ func TestReverseStr(t *testing.T) {
|
|||||||
func reverseStr(t *testing.T, test string, expected string) {
|
func reverseStr(t *testing.T, test string, expected string) {
|
||||||
res := ReverseStr(test)
|
res := ReverseStr(test)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "ReverseStr", test, expected, res)
|
internal.LogFailedTestInfo(t, "ReverseStr", test, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var isAlphaRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`)
|
||||||
|
|
||||||
// IsAlpha checks if the string contains only letters (a-zA-Z)
|
// IsAlpha checks if the string contains only letters (a-zA-Z)
|
||||||
func IsAlpha(s string) bool {
|
func IsAlpha(s string) bool {
|
||||||
pattern := `^[a-zA-Z]+$`
|
return isAlphaRegexMatcher.MatchString(s)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNumberStr check if the string can convert to a number.
|
// IsNumberStr check if the string can convert to a number.
|
||||||
@@ -26,26 +26,20 @@ func IsNumberStr(s string) bool {
|
|||||||
// IsFloatStr check if the string can convert to a float.
|
// IsFloatStr check if the string can convert to a float.
|
||||||
func IsFloatStr(s string) bool {
|
func IsFloatStr(s string) bool {
|
||||||
_, e := strconv.ParseFloat(s, 64)
|
_, e := strconv.ParseFloat(s, 64)
|
||||||
|
return e == nil
|
||||||
if e != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isIntStrRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
||||||
|
|
||||||
// IsIntStr check if the string can convert to a integer.
|
// IsIntStr check if the string can convert to a integer.
|
||||||
func IsIntStr(s string) bool {
|
func IsIntStr(s string) bool {
|
||||||
match, _ := regexp.MatchString(`^[\+-]?\d+$`, s)
|
return isIntStrRegexMatcher.MatchString(s)
|
||||||
return match
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIp check if the string is a ip address.
|
// IsIp check if the string is a ip address.
|
||||||
func IsIp(ipstr string) bool {
|
func IsIp(ipstr string) bool {
|
||||||
ip := net.ParseIP(ipstr)
|
ip := net.ParseIP(ipstr)
|
||||||
if ip == nil {
|
return ip != nil
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIpV4 check if the string is a ipv4 address.
|
// IsIpV4 check if the string is a ipv4 address.
|
||||||
@@ -78,61 +72,61 @@ func IsIpV6(ipstr string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isDnsRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
|
||||||
|
|
||||||
// IsDns check if the string is dns.
|
// IsDns check if the string is dns.
|
||||||
func IsDns(dns string) bool {
|
func IsDns(dns string) bool {
|
||||||
pattern := `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`
|
return isDnsRegexMatcher.MatchString(dns)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(dns)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isEmailRegexMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
|
||||||
|
|
||||||
// IsEmail check if the string is a email address.
|
// IsEmail check if the string is a email address.
|
||||||
func IsEmail(email string) bool {
|
func IsEmail(email string) bool {
|
||||||
pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`
|
return isEmailRegexMatcher.MatchString(email)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(email)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isChineseMobileRegexMatcher *regexp.Regexp = regexp.MustCompile("^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$")
|
||||||
|
|
||||||
// IsChineseMobile check if the string is chinese mobile number.
|
// IsChineseMobile check if the string is chinese mobile number.
|
||||||
func IsChineseMobile(mobileNum string) bool {
|
func IsChineseMobile(mobileNum string) bool {
|
||||||
pattern := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"
|
return isChineseMobileRegexMatcher.MatchString(mobileNum)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(mobileNum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isChineseIdNumRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
|
||||||
|
|
||||||
// IsChineseIdNum check if the string is chinese id number.
|
// IsChineseIdNum check if the string is chinese id number.
|
||||||
func IsChineseIdNum(id string) bool {
|
func IsChineseIdNum(id string) bool {
|
||||||
pattern := `^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`
|
return isChineseIdNumRegexMatcher.MatchString(id)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var containChineseRegexMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
|
||||||
|
|
||||||
// ContainChinese check if the string contain mandarin chinese.
|
// ContainChinese check if the string contain mandarin chinese.
|
||||||
func ContainChinese(s string) bool {
|
func ContainChinese(s string) bool {
|
||||||
pattern := "[\u4e00-\u9fa5]"
|
return containChineseRegexMatcher.MatchString(s)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isChinesePhoneRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}`)
|
||||||
|
|
||||||
// IsChinesePhone check if the string is chinese phone number.
|
// IsChinesePhone check if the string is chinese phone number.
|
||||||
// Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx
|
// Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx
|
||||||
func IsChinesePhone(phone string) bool {
|
func IsChinesePhone(phone string) bool {
|
||||||
pattern := `\d{3}-\d{8}|\d{4}-\d{7}`
|
return isChinesePhoneRegexMatcher.MatchString(phone)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(phone)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isCreditCardRegexMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
|
||||||
|
|
||||||
// IsCreditCard check if the string is credit card.
|
// IsCreditCard check if the string is credit card.
|
||||||
func IsCreditCard(creditCart string) bool {
|
func IsCreditCard(creditCart string) bool {
|
||||||
pattern := `^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`
|
return isCreditCardRegexMatcher.MatchString(creditCart)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(creditCart)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isBase64RegexMatcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
|
||||||
|
|
||||||
// IsBase64 check if the string is base64 string.
|
// IsBase64 check if the string is base64 string.
|
||||||
func IsBase64(base64 string) bool {
|
func IsBase64(base64 string) bool {
|
||||||
pattern := `^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`
|
return isBase64RegexMatcher.MatchString(base64)
|
||||||
reg := regexp.MustCompile(pattern)
|
|
||||||
return reg.MatchString(base64)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmptyString check if the string is empty.
|
// IsEmptyString check if the string is empty.
|
||||||
@@ -191,4 +185,3 @@ func IsWeakPassword(password string) bool {
|
|||||||
|
|
||||||
return (num || letter) && !special
|
return (num || letter) && !special
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package validator
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/utils"
|
"github.com/duke-git/lancet/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsNumberStr(t *testing.T) {
|
func TestIsNumberStr(t *testing.T) {
|
||||||
@@ -17,7 +17,7 @@ func TestIsNumberStr(t *testing.T) {
|
|||||||
func isNumberStr(t *testing.T, source string, expected bool) {
|
func isNumberStr(t *testing.T, source string, expected bool) {
|
||||||
res := IsNumberStr(source)
|
res := IsNumberStr(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsNumberStr", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsNumberStr", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ func TestIsFloatStr(t *testing.T) {
|
|||||||
func isFloatStr(t *testing.T, source string, expected bool) {
|
func isFloatStr(t *testing.T, source string, expected bool) {
|
||||||
res := IsFloatStr(source)
|
res := IsFloatStr(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsFloatStr", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsFloatStr", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ func TestIsIntStr(t *testing.T) {
|
|||||||
func isIntStr(t *testing.T, source string, expected bool) {
|
func isIntStr(t *testing.T, source string, expected bool) {
|
||||||
res := IsIntStr(source)
|
res := IsIntStr(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsIntStr", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsIntStr", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ func TestIsIp(t *testing.T) {
|
|||||||
func isIp(t *testing.T, source string, expected bool) {
|
func isIp(t *testing.T, source string, expected bool) {
|
||||||
res := IsIp(source)
|
res := IsIp(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsIp", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsIp", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ func TestIsIpV4(t *testing.T) {
|
|||||||
func isIpV4(t *testing.T, source string, expected bool) {
|
func isIpV4(t *testing.T, source string, expected bool) {
|
||||||
res := IsIpV4(source)
|
res := IsIpV4(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsIpV4", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsIpV4", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func TestIsIpV6(t *testing.T) {
|
|||||||
func isIpV6(t *testing.T, source string, expected bool) {
|
func isIpV6(t *testing.T, source string, expected bool) {
|
||||||
res := IsIpV6(source)
|
res := IsIpV6(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsIpV6", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsIpV6", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ func TestIsDns(t *testing.T) {
|
|||||||
func isDns(t *testing.T, source string, expected bool) {
|
func isDns(t *testing.T, source string, expected bool) {
|
||||||
res := IsDns(source)
|
res := IsDns(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsDns", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsDns", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ func TestIsEmail(t *testing.T) {
|
|||||||
func isEmail(t *testing.T, source string, expected bool) {
|
func isEmail(t *testing.T, source string, expected bool) {
|
||||||
res := IsEmail(source)
|
res := IsEmail(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsEmail", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsEmail", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ func TestContainChinese(t *testing.T) {
|
|||||||
func containChinese(t *testing.T, source string, expected bool) {
|
func containChinese(t *testing.T, source string, expected bool) {
|
||||||
res := ContainChinese(source)
|
res := ContainChinese(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsContainChineseChar", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsContainChineseChar", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ func TestIsChineseMobile(t *testing.T) {
|
|||||||
func isChineseMobile(t *testing.T, source string, expected bool) {
|
func isChineseMobile(t *testing.T, source string, expected bool) {
|
||||||
res := IsChineseMobile(source)
|
res := IsChineseMobile(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsChineseMobile", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsChineseMobile", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ func TestIsChinesePhone(t *testing.T) {
|
|||||||
func isChinesePhone(t *testing.T, source string, expected bool) {
|
func isChinesePhone(t *testing.T, source string, expected bool) {
|
||||||
res := IsChinesePhone(source)
|
res := IsChinesePhone(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsChinesePhone", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsChinesePhone", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ func TestIsChineseIdNum(t *testing.T) {
|
|||||||
func isChineseIdNum(t *testing.T, source string, expected bool) {
|
func isChineseIdNum(t *testing.T, source string, expected bool) {
|
||||||
res := IsChineseIdNum(source)
|
res := IsChineseIdNum(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsChineseIdNum", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsChineseIdNum", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,20 +184,20 @@ func TestIsCreditCard(t *testing.T) {
|
|||||||
func isCreditCard(t *testing.T, source string, expected bool) {
|
func isCreditCard(t *testing.T, source string, expected bool) {
|
||||||
res := IsCreditCard(source)
|
res := IsCreditCard(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsCreditCard", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsCreditCard", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsBase64(t *testing.T) {
|
func TestIsBase64(t *testing.T) {
|
||||||
isBase64(t, "aGVsbG8", true)
|
isBase64(t, "aGVsbG8=", true)
|
||||||
isBase64(t, "123456", false)
|
isBase64(t, "123456", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBase64(t *testing.T, source string, expected bool) {
|
func isBase64(t *testing.T, source string, expected bool) {
|
||||||
res := IsBase64(source)
|
res := IsBase64(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsBase64", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsBase64", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ func TestIsEmptyString(t *testing.T) {
|
|||||||
func isEmptyString(t *testing.T, source string, expected bool) {
|
func isEmptyString(t *testing.T, source string, expected bool) {
|
||||||
res := IsEmptyString(source)
|
res := IsEmptyString(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsEmptyString", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsEmptyString", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ func TestIsAlpha(t *testing.T) {
|
|||||||
func isAlpha(t *testing.T, source string, expected bool) {
|
func isAlpha(t *testing.T, source string, expected bool) {
|
||||||
res := IsAlpha(source)
|
res := IsAlpha(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsAlpha", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsAlpha", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ func TestIsRegexMatch(t *testing.T) {
|
|||||||
func isRegexMatch(t *testing.T, source, regex string, expected bool) {
|
func isRegexMatch(t *testing.T, source, regex string, expected bool) {
|
||||||
res := IsRegexMatch(source, regex)
|
res := IsRegexMatch(source, regex)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsRegexMatch", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsRegexMatch", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,7 +261,7 @@ func TestIsStrongPassword(t *testing.T) {
|
|||||||
func isStrongPassword(t *testing.T, source string, length int, expected bool) {
|
func isStrongPassword(t *testing.T, source string, length int, expected bool) {
|
||||||
res := IsStrongPassword(source, length)
|
res := IsStrongPassword(source, length)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsStrongPassword", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsStrongPassword", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +277,7 @@ func TestIsWeakPassword(t *testing.T) {
|
|||||||
func isWeakPassword(t *testing.T, source string, expected bool) {
|
func isWeakPassword(t *testing.T, source string, expected bool) {
|
||||||
res := IsWeakPassword(source)
|
res := IsWeakPassword(source)
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "IsWeakPassword", source, expected, res)
|
internal.LogFailedTestInfo(t, "IsWeakPassword", source, expected, res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user