mirror of https://github.com/docker/docs.git
StackSender.Send never returns a nil value
Fix StackSender.Send to always honor the `W` and `R` modes, by: 1) returning a valid Sender and Receiver when the respective flags are set, and 2) returning a value which doesn't need to be Closed, when they are not. This also moves `NopSender` and `NopReceiver` out of `utils`, to prevent a circular dependency. Signed-off-by: Solomon Hykes <solomon@docker.com>
This commit is contained in:
parent
36b9bf7958
commit
396253a4ee
|
|
@ -161,8 +161,13 @@ func (r *PipeReceiver) Receive(mode int) (*beam.Message, beam.Receiver, beam.Sen
|
|||
return nil, nil, nil, err
|
||||
}
|
||||
var (
|
||||
in beam.Receiver
|
||||
out beam.Sender
|
||||
// Always return NopReceiver/NopSender instead of nil values,
|
||||
// because:
|
||||
// - if they were requested in the mode, they can safely be used
|
||||
// - if they were not requested, they can safely be ignored (ie no leak if they
|
||||
// aren't closed)
|
||||
in beam.Receiver = beam.NopReceiver{}
|
||||
out beam.Sender = beam.NopSender{}
|
||||
)
|
||||
if pin != nil {
|
||||
in = pin
|
||||
|
|
|
|||
|
|
@ -9,6 +9,20 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestReceiveW(t *testing.T) {
|
||||
r, w := Pipe()
|
||||
go func() {
|
||||
w.Send(&beam.Message{Name: "hello"}, 0)
|
||||
}()
|
||||
_, _, ww, err := r.Receive(beam.W)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, _, err := ww.Send(&beam.Message{Name: "this better not crash"}, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleSend(t *testing.T) {
|
||||
r, w := Pipe()
|
||||
defer r.Close()
|
||||
|
|
@ -37,8 +51,8 @@ func TestSimpleSend(t *testing.T) {
|
|||
|
||||
// assertMode verifies that the values of r and w match
|
||||
// mode.
|
||||
// If mode has the R bit set, r must be non-nil. Otherwise it must be nil.
|
||||
// If mode has the W bit set, w must be non-nil. Otherwise it must be nil.
|
||||
// If mode has the R bit set, r must be non-nil.
|
||||
// If mode has the W bit set, w must be non-nil.
|
||||
//
|
||||
// If any of these conditions are not met, t.Fatal is called and the active
|
||||
// test fails.
|
||||
|
|
@ -49,10 +63,6 @@ func assertMode(t *testing.T, r beam.Receiver, w beam.Sender, mode int) {
|
|||
t.Fatalf("should be non-nil: %#v", r)
|
||||
}
|
||||
// Otherwise it must be nil.
|
||||
} else {
|
||||
if r != nil {
|
||||
t.Fatalf("should be nil: %#v", r)
|
||||
}
|
||||
}
|
||||
// If mode has the W bit set, w must be non-nil
|
||||
if mode&beam.W != 0 {
|
||||
|
|
@ -60,10 +70,6 @@ func assertMode(t *testing.T, r beam.Receiver, w beam.Sender, mode int) {
|
|||
t.Fatalf("should be non-nil: %#v", w)
|
||||
}
|
||||
// Otherwise it must be nil.
|
||||
} else {
|
||||
if w != nil {
|
||||
t.Fatalf("should be nil: %#v", w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package beam
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type NopSender struct{}
|
||||
|
||||
func (s NopSender) Send(msg *Message, mode int) (Receiver, Sender, error) {
|
||||
return NopReceiver{}, NopSender{}, nil
|
||||
}
|
||||
|
||||
func (s NopSender) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type NopReceiver struct{}
|
||||
|
||||
func (r NopReceiver) Receive(mode int) (*Message, Receiver, Sender, error) {
|
||||
return nil, nil, nil, io.EOF
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ type Buffer []*beam.Message
|
|||
|
||||
func (buf *Buffer) Send(msg *beam.Message, mode int) (beam.Receiver, beam.Sender, error) {
|
||||
(*buf) = append(*buf, msg)
|
||||
return NopReceiver{}, NopSender{}, nil
|
||||
return beam.NopReceiver{}, beam.NopSender{}, nil
|
||||
}
|
||||
|
||||
func (buf *Buffer) Close() error {
|
||||
|
|
|
|||
22
utils/nop.go
22
utils/nop.go
|
|
@ -1,22 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"github.com/docker/beam"
|
||||
"io"
|
||||
)
|
||||
|
||||
type NopSender struct{}
|
||||
|
||||
func (s NopSender) Send(msg *beam.Message, mode int) (beam.Receiver, beam.Sender, error) {
|
||||
return NopReceiver{}, NopSender{}, nil
|
||||
}
|
||||
|
||||
func (s NopSender) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type NopReceiver struct{}
|
||||
|
||||
func (r NopReceiver) Receive(mode int) (*beam.Message, beam.Receiver, beam.Sender, error) {
|
||||
return nil, nil, nil, io.EOF
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ func (s *StackSender) Send(msg *beam.Message, mode int) (r beam.Receiver, w beam
|
|||
return r, w, err
|
||||
}
|
||||
// Silently drop messages if no valid backend is available.
|
||||
return NopSender{}.Send(msg, mode)
|
||||
return beam.NopSender{}.Send(msg, mode)
|
||||
}
|
||||
|
||||
func (s *StackSender) Add(dst beam.Sender) *StackSender {
|
||||
|
|
|
|||
Loading…
Reference in New Issue