// Encoder creates a new styxproto.Encoder that traces messages // before writing them to w. func Encoder(w io.Writer, fn Func) *styxproto.Encoder { rd, wr := io.Pipe() encoder := styxproto.NewEncoder(wr) decoder := styxproto.NewDecoderSize(rd, 8*kilobyte) go func() { for decoder.Next() { fn(decoder.Msg()) styxproto.Write(w, decoder.Msg()) } }() return encoder }
// Decoder creates a new styxproto.Decoder that traces messages // received on r. func Decoder(r io.Reader, fn Func) *styxproto.Decoder { rd, wr := io.Pipe() decoderInput := styxproto.NewDecoderSize(r, 8*kilobyte) decoderTrace := styxproto.NewDecoderSize(rd, 8*kilobyte) go func() { for decoderInput.Next() { fn(decoderInput.Msg()) styxproto.Write(wr, decoderInput.Msg()) } wr.Close() }() return decoderTrace }
func copyMsg(msg styxproto.Msg) styxproto.Msg { var err error rd, wr := io.Pipe() d := styxproto.NewDecoder(rd) go func() { _, err = styxproto.Write(wr, msg) wr.CloseWithError(err) }() for d.Next() { return d.Msg() } panic(fmt.Errorf("failed to copy %T message: %s", msg, d.Err())) }
func chanServer(t *testing.T, handler Handler) (in, out chan styxproto.Msg) { var ln netutil.PipeListener // last for one session srv := Server{ Handler: handler, ErrorLog: testLogger{t}, } go srv.Serve(&ln) conn, err := ln.Dial() if err != nil { panic(err) } // NOTE(droyo) by buffering the channel we allow the server to take // in multiple requests without being blocked on sending their responses. // This is a compromise between keeping the messages in order and having // an infinite buffer depth (such as with goroutine per channel). Good enough // for testing. out = make(chan styxproto.Msg, 1000) in = make(chan styxproto.Msg) go func() { for req := range in { if _, err := styxproto.Write(conn, req); err != nil { t.Error(err) break } } conn.Close() }() go func() { d := styxproto.NewDecoder(conn) for d.Next() { out <- copyMsg(d.Msg()) } close(out) }() return in, out }