From 7d0f3d56121feccfe84600a39c362ba8bfcaa042 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Tue, 30 Jun 2026 16:03:45 -0230 Subject: init --- callback_test.go | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 callback_test.go (limited to 'callback_test.go') 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...) + } +} -- cgit v1.2.3