aboutsummaryrefslogtreecommitdiffstats
path: root/callback_test.go
blob: c9de48ad91d0b934ae31d3819de3e509f3d259dd (plain) (blame)
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...)
	}
}