lib9p

Go 9P library.
Log | Files | Refs | LICENSE

commit a0f5dfd7306057b0a5ab322b2c0d5ac10340771e
parent 45f58e3b361c861a6810c0b693a795f20160bcec
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 23 Dec 2023 22:13:42 +0900

add duptag error test

Diffstat:
Mclient/client.go | 11+++++++----
Mclient/client_test.go | 39+++++++++++++++++++++++++++++++++++++++
Mclient/req.go | 7+++++++
3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/client/client.go b/client/client.go @@ -193,7 +193,7 @@ func (c *Client) runMultiplexer(ctx context.Context, tmsgc chan<- lib9p.Msg, rms continue } if _, ok := rPool[req.tag]; ok { - c.errc <- fmt.Errorf("mux: duplicate tag: %d", req.tag) + req.errc <- fmt.Errorf("mux: duplicate tag: %d", req.tag) continue } rPool[req.tag] = req // TODO: wait for req.ctxDone channel. @@ -215,13 +215,12 @@ func (c *Client) runMultiplexer(ctx context.Context, tmsgc chan<- lib9p.Msg, rms delete(rPool, msg.GetTag()) if tflush, ok := req.tmsg.(*lib9p.TFlush); ok { if _, ok := msg.(*lib9p.RFlush); !ok { - c.errc <- fmt.Errorf("mux: response to Tflush is not Rflush") + req.errc <- fmt.Errorf("mux: response to Tflush is not Rflush") } delete(rPool, tflush.Oldtag) } req.rmsg = msg go func() { - defer close(req.rxc) select { case <-req.ctxDone: case req.rxc <- req: @@ -265,15 +264,19 @@ func (c *Client) runMultiplexer(ctx context.Context, tmsgc chan<- lib9p.Msg, rms func (c *Client) transact(ctx context.Context, tmsg lib9p.Msg) (lib9p.Msg, error) { ctx1, cancel1 := context.WithCancel(ctx) req := newClientReq(ctx1, tmsg) + defer req.Close() select { case <-ctx.Done(): return nil, ctx.Err() case c.txc <- req: } select { - case req = <-req.rxc: // TODO: this assignment is not required. + case req = <-req.rxc: // This assignment is not required. cancel1() return req.rmsg, req.err + case err := <-req.errc: // Client side error. + cancel1() + return nil, err case <-ctx.Done(): return nil, ctx.Err() } diff --git a/client/client_test.go b/client/client_test.go @@ -64,3 +64,41 @@ func TestClient2(t *testing.T) { } t.Log(string(b[:n])) } + +func TestDupTag(t *testing.T) { + conn := testfs.SetupConn() + defer conn.Close() + testfs.Fsys.Slow = true + defer func() { testfs.Fsys.Slow = false }() + bg := context.Background() + _, _, err := conn.C.Version(bg, 0, 8 * 1024, "9P2000") + if err != nil { + t.Fatal(err) + } + _, err = conn.C.Attach(bg, 0, 0, lib9p.NOFID, "kenji", "") + if err != nil { + t.Fatal(err) + } + wname := []string{"a"} + wqid, err := conn.C.Walk(bg, 0, 0, 1, wname) + if err != nil { + t.Fatal(err) + } else if len(wqid) != len(wname) { + t.Fatal("file not found") + } + _, _, err = conn.C.Open(bg, 0, 1, lib9p.OREAD) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithCancel(bg) + defer cancel() + go func() { + _, err = conn.C.Read(ctx, 0, 1, 0, 1024) + t.Log("unko") + }() + <-testfs.Fsys.Waitc + _, err = conn.C.Stat(bg, 0, 1) + if err == nil { + t.Error("dup tag not reported") + } +} +\ No newline at end of file diff --git a/client/req.go b/client/req.go @@ -14,6 +14,7 @@ type clientReq struct { tmsg lib9p.Msg rmsg lib9p.Msg err error + errc chan error // To report any client side error to transact(). rxc chan *clientReq ctxDone <-chan struct{} } @@ -28,9 +29,15 @@ func newClientReq(ctx context.Context, msg lib9p.Msg) *clientReq { tmsg: msg, rxc: make(chan *clientReq), ctxDone: ctx.Done(), + errc: make(chan error), } } +func (r *clientReq) Close() { + close(r.rxc) + close(r.errc) +} + // tagPool is a pool of tags being used by a client. type tagPool struct { m map[uint16]bool