- first edition.
This commit is contained in:
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
.DS_Store
|
||||||
|
*.test
|
||||||
346
platform/jdapi/jdapi.go
Normal file
346
platform/jdapi/jdapi.go
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
package jdapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"github.com/satori/go.uuid"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JDAPI struct {
|
||||||
|
token string
|
||||||
|
appKey string
|
||||||
|
appSecret string
|
||||||
|
logger *zap.Logger
|
||||||
|
sugarLogger *zap.SugaredLogger
|
||||||
|
client http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
sleepSecondWhenLimited = 6 * time.Second
|
||||||
|
maxRetryCountWhenNetworkException = 3
|
||||||
|
maxRetryCountWhenReachLimited = 10
|
||||||
|
jdAPIURL = "https://openo2o.jd.com/djapi/%s"
|
||||||
|
AllPage = 0
|
||||||
|
DefaultPageSize = 50
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrJdParam = errors.New("can not marshal jd param")
|
||||||
|
ErrSystemErrMaxRetry = errors.New("JD System error reach max retry count!")
|
||||||
|
ErrLimitReachMaxRetry = errors.New("JD Reach max retry count!")
|
||||||
|
ErrHttpCode = errors.New("JD HTTP Code is not 200")
|
||||||
|
ErrFormatWrong = errors.New("JD Result format is strange!")
|
||||||
|
ErrJDCode = errors.New("JD code is not 0")
|
||||||
|
ErrInnerCodeIsNotOk = errors.New("JD result inner code is not ok")
|
||||||
|
|
||||||
|
exceedLimitCodes = map[string]int{
|
||||||
|
"10032": 1,
|
||||||
|
}
|
||||||
|
canRetryCodes = map[string]int{
|
||||||
|
"-10000": 1,
|
||||||
|
"-1": 1,
|
||||||
|
"10000": 1,
|
||||||
|
"100022": 1,
|
||||||
|
"100023": 1,
|
||||||
|
"100024": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
jdResultInnerCodeKeys = []string{"code", "retCode", "errorCode"}
|
||||||
|
|
||||||
|
jdResultInnerCodeOK = map[string]int{
|
||||||
|
"None": 1,
|
||||||
|
"0": 1,
|
||||||
|
"1": 1,
|
||||||
|
"190005": 1, // 部分失败
|
||||||
|
}
|
||||||
|
|
||||||
|
jdResultNoPageInnerDataKeys = []string{"result", "data"}
|
||||||
|
jdResultPageInner2DataKeys = []string{"result", "resultList"}
|
||||||
|
jdResultPageTotalCountKeys = []string{"totalCount", "count"}
|
||||||
|
)
|
||||||
|
|
||||||
|
type PageResultParser func(map[string]interface{}, int) ([]interface{}, int)
|
||||||
|
|
||||||
|
func getUUID() string {
|
||||||
|
return strings.ToUpper(strings.Replace(uuid.Must(uuid.NewV1()).String(), "-", "", -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getJDOperator() string {
|
||||||
|
return time.Now().Format("2006-01-02_15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCurTimeStr() string {
|
||||||
|
// return "2018-06-04 22:35:25"
|
||||||
|
return time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignParams(jdParams map[string]string) string {
|
||||||
|
var keys []string
|
||||||
|
for k := range jdParams {
|
||||||
|
if k != "app_secret" {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
allStr := ""
|
||||||
|
for _, k := range keys {
|
||||||
|
allStr += k + jdParams[k]
|
||||||
|
}
|
||||||
|
allStr = jdParams["app_secret"] + allStr + jdParams["app_secret"]
|
||||||
|
|
||||||
|
return fmt.Sprintf("%X", md5.Sum([]byte(allStr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func genGetURL(baseURL, apiStr string, params map[string]string) string {
|
||||||
|
fullURL := ""
|
||||||
|
|
||||||
|
if params != nil {
|
||||||
|
for k, v := range params {
|
||||||
|
if fullURL == "" {
|
||||||
|
fullURL = "?"
|
||||||
|
} else {
|
||||||
|
fullURL += "&"
|
||||||
|
}
|
||||||
|
fullURL += k + "=" + url.QueryEscape(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(baseURL, apiStr) + fullURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJDAPI(token, appKey, appSecret string, logger *zap.Logger) *JDAPI {
|
||||||
|
return &JDAPI{token, appKey, appSecret, logger, logger.Sugar(), http.Client{Timeout: time.Second * 10}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JDAPI) accessJDQuery(apiStr string, jdParams map[string]string) (result map[string]interface{}, err error) {
|
||||||
|
params := make(map[string]string)
|
||||||
|
params["v"] = "1.0"
|
||||||
|
params["format"] = "json"
|
||||||
|
params["app_key"] = j.appKey
|
||||||
|
params["app_secret"] = j.appSecret
|
||||||
|
params["token"] = j.token
|
||||||
|
|
||||||
|
if jdParams == nil {
|
||||||
|
jdParams = make(map[string]string, 0)
|
||||||
|
}
|
||||||
|
jdParamStr, err := json.Marshal(jdParams)
|
||||||
|
if err == nil {
|
||||||
|
params["jd_param_json"] = string(jdParamStr)
|
||||||
|
} else {
|
||||||
|
return nil, ErrJdParam
|
||||||
|
}
|
||||||
|
|
||||||
|
params["timestamp"] = getCurTimeStr()
|
||||||
|
sign := SignParams(params)
|
||||||
|
params["sign"] = sign
|
||||||
|
|
||||||
|
exceedLimitRetryCount := 0
|
||||||
|
systemErrorRetryCount := 0
|
||||||
|
for {
|
||||||
|
fullURL := genGetURL(jdAPIURL, apiStr, params)
|
||||||
|
j.sugarLogger.Debugf("fullURL:%v", fullURL)
|
||||||
|
response, err := j.client.Get(fullURL)
|
||||||
|
if err != nil {
|
||||||
|
j.sugarLogger.Debugf("client.Get return err:%v", err)
|
||||||
|
err, ok := err.(net.Error)
|
||||||
|
systemErrorRetryCount++
|
||||||
|
if ok && err.Timeout() && systemErrorRetryCount <= maxRetryCountWhenNetworkException {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
j.sugarLogger.Debugf("http code is:%d", response.StatusCode)
|
||||||
|
systemErrorRetryCount++
|
||||||
|
if systemErrorRetryCount <= maxRetryCountWhenNetworkException {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, ErrHttpCode
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonResult map[string]interface{}
|
||||||
|
bodyData, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
j.sugarLogger.Debugf("ioutil.ReadAll return:%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = utils.UnmarshalUseNumber(bodyData, &jsonResult)
|
||||||
|
if err != nil {
|
||||||
|
j.sugarLogger.Debugf("json.Unmarshal return:%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
code := jsonResult["code"].(string)
|
||||||
|
if code == "0" {
|
||||||
|
return jsonResult, nil
|
||||||
|
}
|
||||||
|
j.sugarLogger.Debugf("jd code is:%s", code)
|
||||||
|
if _, ok := exceedLimitCodes[code]; ok {
|
||||||
|
exceedLimitRetryCount++
|
||||||
|
if exceedLimitRetryCount <= maxRetryCountWhenReachLimited {
|
||||||
|
time.Sleep(sleepSecondWhenLimited)
|
||||||
|
} else {
|
||||||
|
return jsonResult, ErrLimitReachMaxRetry
|
||||||
|
}
|
||||||
|
} else if _, ok := canRetryCodes[code]; ok {
|
||||||
|
systemErrorRetryCount++
|
||||||
|
if systemErrorRetryCount > maxRetryCountWhenNetworkException {
|
||||||
|
return jsonResult, ErrSystemErrMaxRetry
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return jsonResult, ErrJDCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JDAPI) accessJDQueryNoPage(apiStr string, jdParams map[string]string, keyToRemove, keyToKeep []string) (interface{}, error) {
|
||||||
|
jsonResult, err := j.accessJDQuery(apiStr, jdParams)
|
||||||
|
if err != nil {
|
||||||
|
return jsonResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var data map[string]interface{}
|
||||||
|
err = utils.UnmarshalUseNumber([]byte(jsonResult["data"].(string)), &data)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return jsonResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
innerCode := ""
|
||||||
|
for _, innerCodeKey := range jdResultInnerCodeKeys {
|
||||||
|
if innerCode2, ok := data[innerCodeKey]; ok {
|
||||||
|
innerCode = innerCode2.(string)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := jdResultInnerCodeOK[innerCode]; ok {
|
||||||
|
for _, innerDataKey := range jdResultNoPageInnerDataKeys {
|
||||||
|
if innerData, ok := data[innerDataKey]; ok {
|
||||||
|
return innerData, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("Can not find inner data")
|
||||||
|
} else {
|
||||||
|
return utils.DictKeysMan(jsonResult, keyToRemove, keyToKeep), ErrInnerCodeIsNotOk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JDAPI) accessJDQueryHavePage(apiStr string, jdParams map[string]string, keyToRemove, keyToKeep []string, pageNo, pageSize int, pageResultParser PageResultParser) (interface{}, error) {
|
||||||
|
normalJDQueryHavePageResultParser := func(data map[string]interface{}, totalCount int) ([]interface{}, int) {
|
||||||
|
var result map[string]interface{}
|
||||||
|
var retVal []interface{}
|
||||||
|
|
||||||
|
tempResult := data["result"]
|
||||||
|
if resultStr, ok := tempResult.(string); ok {
|
||||||
|
if err := utils.UnmarshalUseNumber([]byte(resultStr), &tempResult); err != nil {
|
||||||
|
panic("Wrong format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = tempResult.(map[string]interface{})
|
||||||
|
|
||||||
|
if totalCount == 0 {
|
||||||
|
for _, totalCountKey := range jdResultPageTotalCountKeys {
|
||||||
|
if totalCount2, ok := result[totalCountKey]; ok {
|
||||||
|
totalCountInt64, _ := totalCount2.(json.Number).Int64()
|
||||||
|
totalCount = int(totalCountInt64)
|
||||||
|
if totalCount == 0 {
|
||||||
|
return make([]interface{}, 0), 0
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalCount == 0 {
|
||||||
|
panic("can not find totalCount key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, inner2ResultKey := range jdResultPageInner2DataKeys {
|
||||||
|
if inner2Result, ok := result[inner2ResultKey]; ok {
|
||||||
|
|
||||||
|
if inner2ResultStr, ok := inner2Result.(string); ok {
|
||||||
|
err := utils.UnmarshalUseNumber([]byte(inner2ResultStr), &retVal)
|
||||||
|
if err != nil {
|
||||||
|
panic("can not unmarshal inner2result")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retVal = inner2Result.([]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, totalCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("wrong format")
|
||||||
|
}
|
||||||
|
|
||||||
|
if pageResultParser == nil {
|
||||||
|
pageResultParser = normalJDQueryHavePageResultParser
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCount := 0
|
||||||
|
curPage := pageNo
|
||||||
|
if curPage == AllPage {
|
||||||
|
curPage = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal := make([]interface{}, 0)
|
||||||
|
localJdParams := make(map[string]string)
|
||||||
|
if jdParams != nil && len(jdParams) > 0 {
|
||||||
|
for k, v := range jdParams {
|
||||||
|
localJdParams[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
localJdParams["pageNo"] = strconv.FormatInt(int64(curPage), 10)
|
||||||
|
localJdParams["pageSize"] = strconv.FormatInt(int64(pageSize), 10)
|
||||||
|
jsonResult, err := j.accessJDQuery(apiStr, localJdParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var data map[string]interface{}
|
||||||
|
err = utils.UnmarshalUseNumber([]byte(jsonResult["data"].(string)), &data)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
innerCode := data["code"].(string)
|
||||||
|
if innerCode != "0" && innerCode != "200" {
|
||||||
|
return nil, ErrInnerCodeIsNotOk
|
||||||
|
}
|
||||||
|
|
||||||
|
inResult, totalCount2 := pageResultParser(data, totalCount)
|
||||||
|
totalCount = totalCount2
|
||||||
|
|
||||||
|
inResult = utils.DictKeysMan(inResult, keyToRemove, keyToKeep).([]interface{})
|
||||||
|
retVal = append(retVal, inResult...)
|
||||||
|
|
||||||
|
if curPage == pageNo || curPage*pageSize >= totalCount {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
curPage++
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
79
platform/jdapi/jdapi_test.go
Normal file
79
platform/jdapi/jdapi_test.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package jdapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
jdapi *JDAPI
|
||||||
|
sugarLogger *zap.SugaredLogger
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logger, _ := zap.NewDevelopment()
|
||||||
|
sugarLogger = logger.Sugar()
|
||||||
|
jdapi = NewJDAPI("91633f2a-c5f5-4982-a925-a220d19095c3", "1dba76d40cac446ca500c0391a0b6c9d", "a88d031a1e7b462cb1579f12e97fe7f4", logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTest(t *testing.T) {
|
||||||
|
sugarLogger.Debug(getCurTimeStr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessJDQuery(t *testing.T) {
|
||||||
|
result, err := jdapi.accessJDQuery("address/allcities", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when accessing accessJDQuery: %v", err)
|
||||||
|
} else {
|
||||||
|
code := result["code"].(string)
|
||||||
|
if code != "0" {
|
||||||
|
t.Fatalf("code is not 0, %v", code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessJDQueryNoPage(t *testing.T) {
|
||||||
|
result, err := jdapi.accessJDQueryNoPage("address/allcities", nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("accessJDQueryNoPage return error:%v", err)
|
||||||
|
}
|
||||||
|
cityInfo := result.([]interface{})
|
||||||
|
if len(cityInfo) == 0 {
|
||||||
|
t.Fatal("city info is empty")
|
||||||
|
}
|
||||||
|
oneCity := cityInfo[0].(map[string]interface{})
|
||||||
|
if _, ok := oneCity["areaName"]; !ok {
|
||||||
|
t.Fatal("no areaName key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessJDQueryHavePage(t *testing.T) {
|
||||||
|
result, err := jdapi.accessJDQueryHavePage("pms/querySkuInfos", nil, nil, nil, 1, 50, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("accessJDQueryHavePage return error:%v", err)
|
||||||
|
}
|
||||||
|
skuInfo := result.([]interface{})
|
||||||
|
if len(skuInfo) == 0 {
|
||||||
|
t.Fatal("city info is empty")
|
||||||
|
}
|
||||||
|
oneSku := skuInfo[0].(map[string]interface{})
|
||||||
|
if _, ok := oneSku["skuName"]; !ok {
|
||||||
|
t.Fatal("no skuName key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenGetURL(t *testing.T) {
|
||||||
|
params := make(map[string]string)
|
||||||
|
params["key"] = "v"
|
||||||
|
params["key2"] = "v2"
|
||||||
|
|
||||||
|
fullURL := genGetURL(jdAPIURL, "address/allcities", params)
|
||||||
|
|
||||||
|
response, err := http.Get(fullURL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get return error:%v", err)
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
}
|
||||||
78
utils/utils.go
Normal file
78
utils/utils.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DictKeysMan(data interface{}, keysToRemove []string, keysToKeep []string) interface{} {
|
||||||
|
if data == nil || (keysToKeep == nil && keysToRemove == nil) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
var keysToRemoveMap map[string]int
|
||||||
|
var keysToKeepMap map[string]int
|
||||||
|
if keysToKeep != nil {
|
||||||
|
keysToKeepMap = make(map[string]int)
|
||||||
|
for _, v := range keysToKeep {
|
||||||
|
keysToKeepMap[v] = 1
|
||||||
|
}
|
||||||
|
} else if keysToRemove != nil {
|
||||||
|
keysToRemoveMap = make(map[string]int)
|
||||||
|
for _, v := range keysToRemove {
|
||||||
|
keysToRemoveMap[v] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataIsSlice := true
|
||||||
|
valueOfData := reflect.ValueOf(data)
|
||||||
|
if valueOfData.Kind() != reflect.Slice {
|
||||||
|
dataIsSlice = false
|
||||||
|
valueOfData = reflect.ValueOf([]interface{}{data})
|
||||||
|
} else if valueOfData.Len() == 0 {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal := make([]interface{}, valueOfData.Len())
|
||||||
|
|
||||||
|
for index := 0; index < valueOfData.Len(); index++ {
|
||||||
|
realV := valueOfData.Index(index)
|
||||||
|
if realV.Kind() == reflect.Interface || realV.Kind() == reflect.Ptr {
|
||||||
|
realV = realV.Elem()
|
||||||
|
}
|
||||||
|
if keysToRemoveMap != nil || keysToKeepMap != nil {
|
||||||
|
mapV := make(map[string]interface{})
|
||||||
|
for _, key := range realV.MapKeys() {
|
||||||
|
fieldName := key.String()
|
||||||
|
wantThisField := true
|
||||||
|
if keysToKeepMap != nil {
|
||||||
|
if _, ok := keysToKeepMap[fieldName]; !ok {
|
||||||
|
wantThisField = false
|
||||||
|
}
|
||||||
|
} else if keysToRemoveMap != nil {
|
||||||
|
if _, ok := keysToRemoveMap[fieldName]; ok {
|
||||||
|
wantThisField = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if wantThisField {
|
||||||
|
mapV[fieldName] = realV.MapIndex(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retVal[index] = mapV
|
||||||
|
} else {
|
||||||
|
retVal[index] = realV.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dataIsSlice {
|
||||||
|
return retVal[0]
|
||||||
|
}
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalUseNumber(data []byte, result interface{}) error {
|
||||||
|
d := json.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.UseNumber()
|
||||||
|
return d.Decode(result)
|
||||||
|
}
|
||||||
35
utils/utils_test.go
Normal file
35
utils/utils_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type II interface {
|
||||||
|
foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
type TT struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t TT) foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
func TestDictKeysMan(t *testing.T) {
|
||||||
|
testData := map[string]string{"k1": "v1", "k2": "v2"}
|
||||||
|
result1 := DictKeysMan(testData, []string{"k1"}, nil).(map[string]interface{})
|
||||||
|
if _, ok := result1["k1"]; ok {
|
||||||
|
t.Error("Params keysToRemove can not remove key!")
|
||||||
|
}
|
||||||
|
if _, ok := result1["k2"]; !ok {
|
||||||
|
t.Error("Params keysToRemove removed wrong key!")
|
||||||
|
}
|
||||||
|
|
||||||
|
result2 := DictKeysMan([]interface{}{testData}, nil, []string{"k1"}).([]interface{})
|
||||||
|
result20 := result2[0].(map[string]interface{})
|
||||||
|
if _, ok := result20["k1"]; !ok {
|
||||||
|
t.Error("Params keysToKeep can not keep key!")
|
||||||
|
}
|
||||||
|
if _, ok := result20["k2"]; ok {
|
||||||
|
t.Error("Params keysToKeep keep wrong key!")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user