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 | 		return nil, nil, nil, err | ||||||
| 	} | 	} | ||||||
| 	var ( | 	var ( | ||||||
| 		in  beam.Receiver | 		// Always return NopReceiver/NopSender instead of nil values,
 | ||||||
| 		out beam.Sender | 		// 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 { | 	if pin != nil { | ||||||
| 		in = pin | 		in = pin | ||||||
|  |  | ||||||
|  | @ -9,6 +9,20 @@ import ( | ||||||
| 	"testing" | 	"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) { | func TestSimpleSend(t *testing.T) { | ||||||
| 	r, w := Pipe() | 	r, w := Pipe() | ||||||
| 	defer r.Close() | 	defer r.Close() | ||||||
|  | @ -37,8 +51,8 @@ func TestSimpleSend(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| // assertMode verifies that the values of r and w match
 | // assertMode verifies that the values of r and w match
 | ||||||
| // mode.
 | // mode.
 | ||||||
| // If mode has the R bit set, r 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. Otherwise it must be 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
 | // If any of these conditions are not met, t.Fatal is called and the active
 | ||||||
| // test fails.
 | // 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) | 			t.Fatalf("should be non-nil: %#v", r) | ||||||
| 		} | 		} | ||||||
| 		// Otherwise it must be nil.
 | 		// 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 has the W bit set, w must be non-nil
 | ||||||
| 	if mode&beam.W != 0 { | 	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) | 			t.Fatalf("should be non-nil: %#v", w) | ||||||
| 		} | 		} | ||||||
| 		// Otherwise it must be nil.
 | 		// 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) { | func (buf *Buffer) Send(msg *beam.Message, mode int) (beam.Receiver, beam.Sender, error) { | ||||||
| 	(*buf) = append(*buf, msg) | 	(*buf) = append(*buf, msg) | ||||||
| 	return NopReceiver{}, NopSender{}, nil | 	return beam.NopReceiver{}, beam.NopSender{}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (buf *Buffer) Close() error { | 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 | 		return r, w, err | ||||||
| 	} | 	} | ||||||
| 	// Silently drop messages if no valid backend is available.
 | 	// 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 { | func (s *StackSender) Add(dst beam.Sender) *StackSender { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue