-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_test.go
More file actions
130 lines (101 loc) · 3.26 KB
/
Copy pathclient_test.go
File metadata and controls
130 lines (101 loc) · 3.26 KB
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
129
130
package client
import (
"sync"
"sync/atomic"
"testing"
"github.com/stretchr/testify/assert"
)
func TestClientGetSwitcher(t *testing.T) {
t.Run("should return cached instance for the same key", func(t *testing.T) {
BuildContext(Context{
Domain: "My Domain",
})
switcher1 := GetSwitcher("switcher1")
switcher2 := GetSwitcher("switcher1")
switcher3 := GetSwitcher("")
assert.Same(t, switcher1, switcher2, "expected the same instance for the same key")
assert.NotSame(t, switcher1, switcher3, "expected different instances for different keys")
})
t.Run("should replace the cached switchers after rebuilding the default context", func(t *testing.T) {
BuildContext(Context{
Domain: "First Domain",
})
first := GetSwitcher("switcher1")
BuildContext(Context{
Domain: "Second Domain",
})
second := GetSwitcher("switcher1")
assert.NotSame(t, first, second, "expected a new cached switcher after rebuilding the default context")
})
t.Run("should return the cached instance after concurrent insert", func(t *testing.T) {
client := NewClient(Context{Domain: "My Domain"})
blockFirst := make(chan struct{})
firstMissReached := make(chan struct{})
var hookCalls atomic.Int32
getSwitcherAfterReadMissHook = func() {
if hookCalls.Add(1) == 1 {
close(firstMissReached)
<-blockFirst
}
}
defer func() {
getSwitcherAfterReadMissHook = nil
}()
var wg sync.WaitGroup
var first *Switcher
wg.Go(func() {
first = client.GetSwitcher("switcher1")
})
<-firstMissReached
second := client.GetSwitcher("switcher1")
close(blockFirst)
wg.Wait()
assert.Same(t, first, second, "expected the same instance after concurrent insert")
assert.Len(t, client.switchers, 1, "expected only one instance in the cache")
})
}
func TestDefaultClient(t *testing.T) {
t.Run("should initialize the singleton when unset", func(t *testing.T) {
savedClient := globalClient.Load()
savedHook := defaultClientBeforeCompareAndSwapHook
globalClient.Store(nil)
defaultClientBeforeCompareAndSwapHook = nil
defer func() {
globalClient.Store(savedClient)
defaultClientBeforeCompareAndSwapHook = savedHook
}()
client := defaultClient()
assert.NotNil(t, client)
assert.Same(t, client, globalClient.Load(), "expected the singleton to be initialized")
})
t.Run("should return the loaded client after concurrent initialization", func(t *testing.T) {
savedClient := globalClient.Load()
savedHook := defaultClientBeforeCompareAndSwapHook
globalClient.Store(nil)
defer func() {
globalClient.Store(savedClient)
defaultClientBeforeCompareAndSwapHook = savedHook
}()
blockFirst := make(chan struct{})
firstCreated := make(chan struct{})
var hookCalls atomic.Int32
defaultClientBeforeCompareAndSwapHook = func() {
if hookCalls.Add(1) == 1 {
close(firstCreated)
<-blockFirst
}
}
var got *Client
var wg sync.WaitGroup
wg.Go(func() {
got = defaultClient()
})
<-firstCreated
expected := NewClient(Context{Domain: "My Domain"})
globalClient.Store(expected)
close(blockFirst)
wg.Wait()
assert.Same(t, expected, got, "expected the loaded client after concurrent initialization")
assert.Same(t, expected, globalClient.Load(), "expected the global client to be the same as the loaded client")
})
}