forked from statsig-io/go-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
128 lines (111 loc) · 2.71 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package statsig
import (
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"encoding/json"
"errors"
"strconv"
"testing"
"time"
)
func defaultString(v, d string) string {
if v == "" {
return d
}
return v
}
func getHash(key string) []byte {
hasher := sha256.New()
bytes := []byte(key)
hasher.Write(bytes)
return hasher.Sum(nil)
}
func getDJB2Hash(key string) string {
hash := uint64(0)
bytes := []byte(key)
for _, b := range bytes {
hash = ((hash << 5) - hash) + uint64(b)
hash = hash & ((1 << 32) - 1)
}
return strconv.FormatUint(hash, 10)
}
func getHashUint64Encoding(key string) uint64 {
hash := getHash(key)
return binary.BigEndian.Uint64(hash)
}
func getHashBase64StringEncoding(configName string) string {
hash := getHash(configName)
return base64.StdEncoding.EncodeToString(hash)
}
func safeGetFirst(slice []string) string {
if len(slice) > 0 {
return slice[0]
}
return ""
}
func safeParseJSONint64(val interface{}) int64 {
if num, ok := val.(json.Number); ok {
i64, _ := strconv.ParseInt(string(num), 10, 64)
return i64
} else {
return 0
}
}
func compareMetadata(t *testing.T, metadata map[string]string, expected map[string]string, time int64) {
v, _ := json.Marshal(metadata)
var rawMetadata map[string]string
_ = json.Unmarshal(v, &rawMetadata)
for key, value1 := range expected {
if value2, exists := metadata[key]; exists {
if value1 != value2 {
t.Errorf("Values for key '%s' do not match. Expected: %+v. Received: %+v", key, value1, value2)
}
} else {
t.Errorf("Key '%s' does not exist in metadata", key)
}
}
for _, key := range []string{"configSyncTime", "initTime"} {
value, exists := metadata[key]
if !exists {
t.Errorf("'%s' does not exist in metadata", key)
}
if strconv.FormatInt(time, 10) != value {
t.Errorf("'%s' does not have the expected time %d. Actual %s", key, time, value)
}
}
now := getUnixMilli()
serverTime, _ := strconv.ParseInt(metadata["serverTime"], 10, 64)
if now-1000 <= serverTime && serverTime <= now+1000 {
return
}
t.Errorf("serverTime is outside of the valid range. Expected %d (±2000), Actual %d", now, serverTime)
}
func toError(err interface{}) error {
errAsError, ok := err.(error)
if ok {
return errAsError
} else {
errAsString, ok := err.(string)
if ok {
return errors.New(errAsString)
} else {
return errors.New("")
}
}
}
func getUnixMilli() int64 {
// time.Now().UnixMilli() wasn't added until go 1.17
unixNano := time.Now().UnixNano()
return unixNano / int64(time.Millisecond)
}
func hashName(hashAlgorithm string, name string) string {
switch hashAlgorithm {
case "sha256":
return getHashBase64StringEncoding(name)
case "djb2":
return getDJB2Hash(name)
default:
return name
}
}