forked from Azure/go-amqp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
helpers_test.go
132 lines (124 loc) · 3.89 KB
/
helpers_test.go
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
package amqp
import (
"context"
"fmt"
"sync/atomic"
"testing"
"time"
"github.com/pdaures/go-amqp/internal/encoding"
"github.com/pdaures/go-amqp/internal/frames"
"github.com/pdaures/go-amqp/internal/mocks"
"github.com/stretchr/testify/require"
)
func sendInitialFlowFrame(t *testing.T, netConn *mocks.NetConn, handle uint32, credit uint32) {
nextIncoming := uint32(0)
count := uint32(0)
available := uint32(0)
b, err := mocks.EncodeFrame(mocks.FrameAMQP, 0, &frames.PerformFlow{
NextIncomingID: &nextIncoming,
IncomingWindow: 1000,
OutgoingWindow: 1000,
NextOutgoingID: nextIncoming + 1,
Handle: &handle,
DeliveryCount: &count,
LinkCredit: &credit,
Available: &available,
})
require.NoError(t, err)
netConn.SendFrame(b)
}
// standard frame handler for connecting/disconnecting etc.
// returns nil, nil for unhandled frames.
func senderFrameHandler(ssm encoding.SenderSettleMode) func(frames.FrameBody) ([]byte, error) {
return func(req frames.FrameBody) ([]byte, error) {
switch tt := req.(type) {
case *mocks.AMQPProto:
return []byte{'A', 'M', 'Q', 'P', 0, 1, 0, 0}, nil
case *frames.PerformOpen:
return mocks.PerformOpen("container")
case *frames.PerformClose:
return mocks.PerformClose(nil)
case *frames.PerformBegin:
return mocks.PerformBegin(0)
case *frames.PerformEnd:
return mocks.PerformEnd(0, nil)
case *frames.PerformAttach:
return mocks.SenderAttach(0, tt.Name, 0, ssm)
case *frames.PerformDetach:
return mocks.PerformDetach(0, 0, nil)
default:
return nil, nil
}
}
}
// similar to senderFrameHandler but returns an error on unhandled frames
func senderFrameHandlerNoUnhandled(ssm encoding.SenderSettleMode) func(frames.FrameBody) ([]byte, error) {
return func(req frames.FrameBody) ([]byte, error) {
b, err := senderFrameHandler(ssm)(req)
if b == nil && err == nil {
return nil, fmt.Errorf("unhandled frame %T", req)
}
return b, err
}
}
// standard frame handler for connecting/disconnecting etc.
// returns nil, nil for unhandled frames.
func receiverFrameHandler(rsm encoding.ReceiverSettleMode) func(frames.FrameBody) ([]byte, error) {
return func(req frames.FrameBody) ([]byte, error) {
switch tt := req.(type) {
case *mocks.AMQPProto:
return []byte{'A', 'M', 'Q', 'P', 0, 1, 0, 0}, nil
case *frames.PerformOpen:
return mocks.PerformOpen("container")
case *frames.PerformClose:
return mocks.PerformClose(nil)
case *frames.PerformBegin:
return mocks.PerformBegin(0)
case *frames.PerformEnd:
return mocks.PerformEnd(0, nil)
case *frames.PerformAttach:
return mocks.ReceiverAttach(0, tt.Name, 0, rsm, tt.Source.Filter)
case *frames.PerformDetach:
return mocks.PerformDetach(0, 0, nil)
default:
return nil, nil
}
}
}
// similar to receiverFrameHandler but returns an error on unhandled frames
// NOTE: consumes flow frames
func receiverFrameHandlerNoUnhandled(rsm encoding.ReceiverSettleMode) func(frames.FrameBody) ([]byte, error) {
return func(req frames.FrameBody) ([]byte, error) {
b, err := receiverFrameHandler(rsm)(req)
if b != nil || err != nil {
return b, err
}
switch req.(type) {
case *frames.PerformFlow, *mocks.KeepAlive:
return nil, nil
default:
return nil, fmt.Errorf("unhandled frame %T", req)
}
}
}
// helper to wait for a link to pause/resume
// returns an error if it times out waiting
func waitForLink(l *link, paused bool) error {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
for {
credit := atomic.LoadUint32(&l.linkCredit)
// waiting for the link to pause means its credit has been consumed
if (paused && credit == 0) || (!paused && credit > 0) {
return nil
} else if err := ctx.Err(); err != nil {
return err
}
select {
case <-l.Detached:
return fmt.Errorf("link detached: detachErr %v, error %v", l.detachError, l.err)
case <-time.After(50 * time.Millisecond):
// try again
}
}
}