aboutsummaryrefslogtreecommitdiffstats
path: root/callback_test.go
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2026-06-30 16:03:45 -0230
committerSam Anthony <sam@samanthony.xyz>2026-06-30 16:03:45 -0230
commit7d0f3d56121feccfe84600a39c362ba8bfcaa042 (patch)
tree0e412db49a133af1020ae13d6a0f3930fa04ee06 /callback_test.go
downloadxmrpayclnt-7d0f3d56121feccfe84600a39c362ba8bfcaa042.zip
init
Diffstat (limited to 'callback_test.go')
-rw-r--r--callback_test.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/callback_test.go b/callback_test.go
new file mode 100644
index 0000000..c9de48a
--- /dev/null
+++ b/callback_test.go
@@ -0,0 +1,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...)
+ }
+}