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

Compare commits

..

4 Commits

Author SHA1 Message Date
dudaodong
051f20caef release: v1.1.4, merge pr7 and pr8 2021-12-30 20:25:20 +08:00
donutloop
613785b07c function: catch earlier programming error (#8)
Place at first line of the function body a function type safe guard
check.
2021-12-30 20:22:00 +08:00
donutloop
0b0eb695e8 datetime: optimized func calls (#7)
Replace time parsing calls with less expensive operations
2021-12-30 10:29:10 +08:00
dudaodong
745082fff1 fix: update api url for http timeout issue in the task of github actions 2021-12-29 11:39:48 +08:00
7 changed files with 108 additions and 66 deletions

View File

@@ -6,7 +6,7 @@
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-1.1.4-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)

View File

@@ -6,7 +6,7 @@
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-1.1.4-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)

View File

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

View File

@@ -135,7 +135,10 @@ func TestFormatStrToTime(t *testing.T) {
"2021/01"}
for i := 0; i < len(cases); i++ {
res := FormatStrToTime(datetimeStr[i], cases[i])
res, err := FormatStrToTime(datetimeStr[i], cases[i])
if err != nil {
t.Fatal(err)
}
expected, _ := time.Parse(formats[i], datetimeStr[i])
if res != expected {
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)

View File

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

View File

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

View File

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