|
- /*
- *
- * Copyright 2018 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
- // Package testutils contains testing helpers.
- package testutils
-
- import (
- "errors"
- "net"
- "time"
- )
-
- var errClosed = errors.New("closed")
-
- type pipeAddr struct{}
-
- func (p pipeAddr) Network() string { return "pipe" }
- func (p pipeAddr) String() string { return "pipe" }
-
- // PipeListener is a listener with an unbuffered pipe. Each write will complete only once the other side reads. It
- // should only be created using NewPipeListener.
- type PipeListener struct {
- c chan chan<- net.Conn
- done chan struct{}
- }
-
- // NewPipeListener creates a new pipe listener.
- func NewPipeListener() *PipeListener {
- return &PipeListener{
- c: make(chan chan<- net.Conn),
- done: make(chan struct{}),
- }
- }
-
- // Accept accepts a connection.
- func (p *PipeListener) Accept() (net.Conn, error) {
- var connChan chan<- net.Conn
- select {
- case <-p.done:
- return nil, errClosed
- case connChan = <-p.c:
- select {
- case <-p.done:
- close(connChan)
- return nil, errClosed
- default:
- }
- }
- c1, c2 := net.Pipe()
- connChan <- c1
- close(connChan)
- return c2, nil
- }
-
- // Close closes the listener.
- func (p *PipeListener) Close() error {
- close(p.done)
- return nil
- }
-
- // Addr returns a pipe addr.
- func (p *PipeListener) Addr() net.Addr {
- return pipeAddr{}
- }
-
- // Dialer dials a connection.
- func (p *PipeListener) Dialer() func(string, time.Duration) (net.Conn, error) {
- return func(string, time.Duration) (net.Conn, error) {
- connChan := make(chan net.Conn)
- select {
- case p.c <- connChan:
- case <-p.done:
- return nil, errClosed
- }
- conn, ok := <-connChan
- if !ok {
- return nil, errClosed
- }
- return conn, nil
- }
- }
|