func (f *Flow) Test(conn Conn) error {
	for _, action := range f.actions {
		err := f.test(conn, action)
		if err != nil {
			return err
		}
	}
	return nil
}
Test starts the flow on the given Conn and reports to the specified test.
package mock
import (
	"errors"
	"fmt"
	"io"
	"strings"
	"time"
)
type Conn interface {
	Send(pkt interface{}) error
	Receive() (interface{}, error)
	Close() error
}
type Pipe struct {
	pipe  chan interface{}
	close chan struct{}
}
func NewPipe() *Pipe {
	return &Pipe{
		pipe:  make(chan interface{}),
		close: make(chan struct{}),
	}
}
func (conn *Pipe) Send(pkt interface{}) error {
	select {
	case conn.pipe <- pkt:
		return nil
	case <-conn.close:
		return errors.New("closed")
	}
}
func (conn *Pipe) Receive() (interface{}, error) {
	select {
	case pkt := <-conn.pipe:
		return pkt, nil
	case <-conn.close:
		return nil, io.EOF
	}
}
func (conn *Pipe) Close() error {
	close(conn.close)
	return nil
}
const (
	actionSend byte = iota
	actionReceive
	actionSkip
	actionRun
	actionClose
	actionEnd
)
type action struct {
	kind     byte
	packets  []interface{}
	fn       func()
	ch       chan struct{}
	duration time.Duration
}
type Flow struct {
	debug   bool
	actions []action
}
func NewFlow() *Flow {
	return &Flow{
		actions: make([]action, 0),
	}
}
func (f *Flow) Debug() *Flow {
	f.debug = true
	return f
}
func (f *Flow) Send(pkts ...interface{}) *Flow {
	f.add(action{
		kind:    actionSend,
		packets: pkts,
	})
	return f
}
func (f *Flow) Receive(pkts ...interface{}) *Flow {
	f.add(action{
		kind:    actionReceive,
		packets: pkts,
	})
	return f
}
func (f *Flow) Skip(pkts ...interface{}) *Flow {
	f.add(action{
		kind:    actionSkip,
		packets: pkts,
	})
	return f
}
func (f *Flow) Run(fn func()) *Flow {
	f.add(action{
		kind: actionRun,
		fn:   fn,
	})
	return f
}
func (f *Flow) Close() *Flow {
	f.add(action{
		kind: actionClose,
	})
	return f
}
func (f *Flow) End() *Flow {
	f.add(action{
		kind: actionEnd,
	})
	return f
}