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
131
132
133
134
135
136
137
|
package xmrpayclnt
import (
"net/url"
"testing"
"testing/synctest"
"time"
"github.com/stretchr/testify/require"
"gitlab.com/moneropay/moneropay/v2/pkg/model"
)
func newTestCallback(t *testing.T) Callback {
id := newCallbackId()
base, err := url.Parse("http://localhost")
require.NoError(t, err)
url := callbackUrl(base, id)
done := make(chan callbackId)
go func() {
// signal to callback that it can close
id := <-done
done <- id
close(done)
}()
return newCallback(id, url, done)
}
func TestCallbackRx(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
cb := newTestCallback(t)
defer cb.Close()
info := model.CallbackResponse{
Description: "lorem ipsum",
CreatedAt: time.Now(),
}
cb.in <- info
synctest.Wait()
require.Equal(t, info, <-cb.C)
})
}
// Callback blocks until it receives another callback POST request.
func TestCallbackBlockUntilRx(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
cb := newTestCallback(t)
defer cb.Close()
info := model.CallbackResponse{
Description: "lorem ipsum",
CreatedAt: time.Now(),
}
for i := 0; i < 5; i++ {
requireBlockingf(t, cb.C, "callback not blocking")
cb.in <- info
synctest.Wait()
require.Equal(t, info, <-cb.C)
}
})
}
// C and Complete channels closed when transaction completes.
func TestCallbackComplete(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
cb := newTestCallback(t)
defer cb.Close()
info := model.CallbackResponse{
Description: "lorem ipsum",
CreatedAt: time.Now(),
}
cb.in <- info
require.Equal(t, info, <-cb.C)
requireOpenf(t, cb.Complete, "complete channel closed before transaction is complete")
info.Complete = true
cb.in <- info
requireClosedf(t, cb.C, "channel not closed once transaction is finished")
requireClosedf(t, cb.Complete, "complete channel not closed once transaction finished")
})
}
// Channels closed when callback closed
func TestCallbackClose(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
cb := newTestCallback(t)
requireOpen(t, cb.C)
requireOpen(t, cb.Complete)
cb.Close()
requireClosed(t, cb.C)
requireClosed(t, cb.Complete)
})
}
func requireBlockingf[T any](t *testing.T, c <-chan T, msg string, args ...any) {
t.Helper()
synctest.Wait()
select {
case <-c:
t.Fatalf(msg, args...)
default:
}
}
func requireOpen[T any](t *testing.T, c <-chan T) {
t.Helper()
requireOpenf(t, c, "channel not open")
}
func requireOpenf[T any](t *testing.T, c <-chan T, msg string, args ...any) {
t.Helper()
synctest.Wait()
select {
case _, ok := <-c:
if !ok {
t.Fatalf(msg, args...)
}
default:
}
}
func requireClosed[T any](t *testing.T, c <-chan T) {
t.Helper()
requireClosedf(t, c, "channel not closed")
}
func requireClosedf[T any](t *testing.T, c <-chan T, msg string, args ...any) {
t.Helper()
synctest.Wait()
select {
case _, ok := <-c:
if ok {
t.Fatalf(msg, args...)
}
default:
t.Fatalf(msg, args...)
}
}
|