commit a0f5dfd7306057b0a5ab322b2c0d5ac10340771e
parent 45f58e3b361c861a6810c0b693a795f20160bcec
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 23 Dec 2023 22:13:42 +0900
add duptag error test
Diffstat:
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