lib9p

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

commit b6b1b1994a1a761b65df60ab3b8ea9d2297d358c
parent b892d5497da09471cd1c2c53a238472ef63d77f2
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri,  5 Jan 2024 09:38:16 +0900

merge client_test.go and client2_test.go

Diffstat:
Dclient/client2_test.go | 838-------------------------------------------------------------------------------
Mclient/client_test.go | 836++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 833 insertions(+), 841 deletions(-)

diff --git a/client/client2_test.go b/client/client2_test.go @@ -1,838 +0,0 @@ -package client - -import ( - "bytes" - "context" - "errors" - "reflect" - "sync" - "testing" - - "git.mtkn.jp/lib9p" -) - -func newClientForTest(msize uint32, uname string) (*Client, <-chan lib9p.Msg, chan<- lib9p.Msg) { - ctx, cancel := context.WithCancel(context.Background()) - c := &Client{ - msize: msize, - mSizeLock: new(sync.Mutex), - uname: uname, - fPool: allocClientFidPool(), - errc: make(chan error), - cancel: cancel, - wg: new(sync.WaitGroup), - } - tmsgc, rmsgc := make(chan lib9p.Msg), make(chan lib9p.Msg) - c.txc = c.runMultiplexer(ctx, tmsgc, rmsgc) - return c, tmsgc, rmsgc -} - -func TestVersion(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TVersion - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}, - &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}}, - {"1", - &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "unko"}, - &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "unknown"}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotmsize uint32 - gotversion string - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotmsize, gotversion, goterr = - c.Version(ctx, ifcall.Tag, ifcall.Msize, ifcall.Version) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RVersion: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Msize != gotmsize || ofcall.Version != gotversion { - t.Errorf("%s: (mSize, verion) want: %d, %s, got: %d, %s", - test.name, ofcall.Msize, ofcall.Version, - gotmsize, gotversion) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestAuth(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TAuth - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TAuth{Tag: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, - &lib9p.RError{Tag: 0, Ename: errors.New("authentication not required.")}}, - {"1", - &lib9p.TAuth{Tag: 0, Afid: 0, Uname: "glenda", Aname: ""}, - &lib9p.RAuth{Tag: 0, Aqid: lib9p.Qid{0, 1, 2}}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotaqid lib9p.Qid - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotaqid, goterr = - c.Auth(ctx, ifcall.Tag, ifcall.Afid, ifcall.Uname, ifcall.Aname) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RAuth: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Aqid != gotaqid { - t.Errorf("%s: (qid) want: %v, got: %v", - test.name, ofcall.Aqid, gotaqid) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestAttach(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TAttach - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, - &lib9p.RAttach{Qid: lib9p.Qid{1, 2, 3}}}, - {"1", - &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, - &lib9p.RError{Ename: errors.New("authentication required")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotqid lib9p.Qid - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotqid, goterr = - c.Attach(ctx, ifcall.Tag, ifcall.Fid, ifcall.Afid, ifcall.Uname, ifcall.Aname) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RAttach: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Qid != gotqid { - t.Errorf("%s: (qid) want: %v, got: %v", - test.name, ofcall.Qid, gotqid) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestFlush(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TFlush - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TFlush{Oldtag: 1}, - &lib9p.RFlush{}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - goterr = - c.Flush(ctx, ifcall.Tag, ifcall.Oldtag) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RFlush: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestWalk(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TWalk - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TWalk{Fid: 0, Newfid: 1, Wnames: []string{"a", "b", "c"}}, - &lib9p.RWalk{Qids: []lib9p.Qid{lib9p.Qid{1, 2, 3}, lib9p.Qid{2, 3, 4}, lib9p.Qid{3, 4, 5}}}}, - {"1", - &lib9p.TWalk{Fid: 0, Newfid: 2, Wnames: []string{"a", "b", "c"}}, - &lib9p.RError{Ename: errors.New("not found")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotqids []lib9p.Qid - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotqids, goterr = - c.Walk(ctx, ifcall.Tag, ifcall.Fid, ifcall.Newfid, ifcall.Wnames) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RWalk: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if !reflect.DeepEqual(ofcall.Qids, gotqids) { - t.Errorf("%s: (qids) want: %v, got: %v", - test.name, ofcall.Qids, gotqids) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestOpen(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TOpen - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TOpen{Fid: 0, Mode: lib9p.OREAD}, - &lib9p.ROpen{Qid: lib9p.Qid{1, 2, 3}, Iounit: 1000}}, - {"1", - &lib9p.TOpen{Fid: 0, Mode: lib9p.OWRITE}, - &lib9p.RError{Ename: errors.New("permission denied")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotqid lib9p.Qid - gotiounit uint32 - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotqid, gotiounit, goterr = - c.Open(ctx, ifcall.Tag, ifcall.Fid, ifcall.Mode) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.ROpen: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { - t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", - test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestCreate(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TCreate - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0666, Mode: lib9p.OREAD}, - &lib9p.RCreate{Qid: lib9p.Qid{1, 2, 3}, Iounit: 1000}}, - {"1", - &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0777, Mode: lib9p.OWRITE}, - &lib9p.RError{Ename: errors.New("permission denied")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotqid lib9p.Qid - gotiounit uint32 - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotqid, gotiounit, goterr = - c.Create(ctx, ifcall.Tag, ifcall.Fid, ifcall.Name, ifcall.Perm, ifcall.Mode) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RCreate: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { - t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", - test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestRead(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TRead - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, - &lib9p.RRead{Count: 4, Data: []byte("unko")}}, - {"1", - &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, - &lib9p.RError{Ename: errors.New("not open")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotdata []byte - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotdata, goterr = - c.Read(ctx, ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RRead: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if !bytes.Equal(ofcall.Data, gotdata) { - t.Errorf("%s: (data) want: %v, got: %v", - test.name, ofcall.Data, gotdata) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestWrite(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TWrite - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("unko")}, - &lib9p.RWrite{Count: 4}}, - {"1", - &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("unko")}, - &lib9p.RError{Ename: errors.New("not open")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotcount uint32 - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotcount, goterr = - c.Write(ctx, ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count, ifcall.Data) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RWrite: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if ofcall.Count != gotcount { - t.Errorf("%s: (count) want: %v, got: %v", - test.name, ofcall.Count, gotcount) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestClunk(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TClunk - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TClunk{Fid: 0}, - &lib9p.RClunk{}}, - {"1", - &lib9p.TClunk{Fid: 0}, - &lib9p.RError{Ename: errors.New("unknown fid")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - goterr = - c.Clunk(ctx, ifcall.Tag, ifcall.Fid) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RClunk: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestRemove(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TRemove - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TRemove{Fid: 0}, - &lib9p.RRemove{}}, - {"1", - &lib9p.TRemove{Fid: 0}, - &lib9p.RError{Ename: errors.New("unknown fid")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - goterr = - c.Remove(ctx, ifcall.Tag, ifcall.Fid) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RRemove: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestStat(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TStat - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TStat{Fid: 0}, - &lib9p.RStat{Stat: &lib9p.Stat{Name: "file"}}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - gotstat *lib9p.Stat - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - gotstat, goterr = - c.Stat(ctx, ifcall.Tag, ifcall.Fid) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RStat: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - if !reflect.DeepEqual(ofcall.Stat, gotstat) { - t.Errorf("%s: (stat) want: %v, got: %v", - test.name, ofcall.Stat, gotstat) - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} - -func TestWstat(t *testing.T) { - tests := []struct { - name string - tmsg *lib9p.TWstat - rmsg lib9p.Msg - }{ - {"0", - &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Gid: "ken"}}, - &lib9p.RWstat{}}, - {"1", - &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Uid: "ken"}}, - &lib9p.RError{Ename: errors.New("permission denied.")}}, - } - for _, test := range tests { - func() { - c, tmsgc, rmsgc := newClientForTest(1024, "glenda") - defer c.Stop() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var ( - goterr error - done = make(chan struct{}) - ) - go func() { - ifcall := test.tmsg - goterr = - c.Wstat(ctx, ifcall.Tag, ifcall.Fid, ifcall.Stat) - close(done) - }() - gottmsg := <-tmsgc - if !reflect.DeepEqual(test.tmsg, gottmsg) { - t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", - test.name, test.tmsg, gottmsg) - return - } - rmsgc <- test.rmsg - select { - case err := <-c.errc: - t.Errorf("client error: %v", err) - return - case <-done: - } - switch ofcall := test.rmsg.(type) { - case *lib9p.RWstat: - if goterr != nil { - t.Errorf("%s: unexpected error: %v", test.name, goterr) - return - } - case *lib9p.RError: - if goterr == nil { - t.Errorf("%s: error expected: %v", test.name, ofcall) - } - default: - t.Errorf("%s: unexpected message: %v", test.name, ofcall) - } - }() - } -} diff --git a/client/client_test.go b/client/client_test.go @@ -1,25 +1,29 @@ package client import ( + "bytes" "context" + "errors" "io" + "reflect" + "sync" "testing" "git.mtkn.jp/lib9p" ) -func setupClient(fs lib9p.FS) (*Client, context.CancelFunc) { +func setupClientAndServer(fs lib9p.FS) (*Client, context.CancelFunc) { cr, sw := io.Pipe() sr, cw := io.Pipe() s := lib9p.NewServer(fs) ctx, cancel := context.WithCancel(context.Background()) go s.Serve(ctx, sr, sw) - c := NewClient(8*1024, "kenji", cr, cw) + c := NewClient(8*1024, "glenda", cr, cw) return c, cancel } func TestDupTag(t *testing.T) { - c, cancel := setupClient(testfs) + c, cancel := setupClientAndServer(testfs) defer cancel() testfs.slow = true defer func() { testfs.slow = false }() @@ -54,3 +58,829 @@ func TestDupTag(t *testing.T) { t.Error("dup tag not reported") } } + +func newClientForTest(msize uint32, uname string) (*Client, <-chan lib9p.Msg, chan<- lib9p.Msg) { + ctx, cancel := context.WithCancel(context.Background()) + c := &Client{ + msize: msize, + mSizeLock: new(sync.Mutex), + uname: uname, + fPool: allocClientFidPool(), + errc: make(chan error), + cancel: cancel, + wg: new(sync.WaitGroup), + } + tmsgc, rmsgc := make(chan lib9p.Msg), make(chan lib9p.Msg) + c.txc = c.runMultiplexer(ctx, tmsgc, rmsgc) + return c, tmsgc, rmsgc +} + +func TestVersion(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TVersion + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}, + &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}}, + {"1", + &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "unko"}, + &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "unknown"}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotmsize uint32 + gotversion string + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotmsize, gotversion, goterr = + c.Version(ctx, ifcall.Tag, ifcall.Msize, ifcall.Version) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RVersion: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Msize != gotmsize || ofcall.Version != gotversion { + t.Errorf("%s: (mSize, verion) want: %d, %s, got: %d, %s", + test.name, ofcall.Msize, ofcall.Version, + gotmsize, gotversion) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestAuth(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TAuth + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TAuth{Tag: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, + &lib9p.RError{Tag: 0, Ename: errors.New("authentication not required.")}}, + {"1", + &lib9p.TAuth{Tag: 0, Afid: 0, Uname: "glenda", Aname: ""}, + &lib9p.RAuth{Tag: 0, Aqid: lib9p.Qid{0, 1, 2}}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotaqid lib9p.Qid + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotaqid, goterr = + c.Auth(ctx, ifcall.Tag, ifcall.Afid, ifcall.Uname, ifcall.Aname) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RAuth: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Aqid != gotaqid { + t.Errorf("%s: (qid) want: %v, got: %v", + test.name, ofcall.Aqid, gotaqid) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestAttach(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TAttach + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, + &lib9p.RAttach{Qid: lib9p.Qid{1, 2, 3}}}, + {"1", + &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, + &lib9p.RError{Ename: errors.New("authentication required")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotqid lib9p.Qid + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotqid, goterr = + c.Attach(ctx, ifcall.Tag, ifcall.Fid, ifcall.Afid, ifcall.Uname, ifcall.Aname) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RAttach: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Qid != gotqid { + t.Errorf("%s: (qid) want: %v, got: %v", + test.name, ofcall.Qid, gotqid) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestFlush(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TFlush + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TFlush{Oldtag: 1}, + &lib9p.RFlush{}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + goterr = + c.Flush(ctx, ifcall.Tag, ifcall.Oldtag) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RFlush: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestWalk(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TWalk + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TWalk{Fid: 0, Newfid: 1, Wnames: []string{"a", "b", "c"}}, + &lib9p.RWalk{Qids: []lib9p.Qid{lib9p.Qid{1, 2, 3}, lib9p.Qid{2, 3, 4}, lib9p.Qid{3, 4, 5}}}}, + {"1", + &lib9p.TWalk{Fid: 0, Newfid: 2, Wnames: []string{"a", "b", "c"}}, + &lib9p.RError{Ename: errors.New("not found")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotqids []lib9p.Qid + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotqids, goterr = + c.Walk(ctx, ifcall.Tag, ifcall.Fid, ifcall.Newfid, ifcall.Wnames) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RWalk: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if !reflect.DeepEqual(ofcall.Qids, gotqids) { + t.Errorf("%s: (qids) want: %v, got: %v", + test.name, ofcall.Qids, gotqids) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestOpen(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TOpen + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TOpen{Fid: 0, Mode: lib9p.OREAD}, + &lib9p.ROpen{Qid: lib9p.Qid{1, 2, 3}, Iounit: 1000}}, + {"1", + &lib9p.TOpen{Fid: 0, Mode: lib9p.OWRITE}, + &lib9p.RError{Ename: errors.New("permission denied")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotqid lib9p.Qid + gotiounit uint32 + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotqid, gotiounit, goterr = + c.Open(ctx, ifcall.Tag, ifcall.Fid, ifcall.Mode) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.ROpen: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { + t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", + test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestCreate(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TCreate + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0666, Mode: lib9p.OREAD}, + &lib9p.RCreate{Qid: lib9p.Qid{1, 2, 3}, Iounit: 1000}}, + {"1", + &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0777, Mode: lib9p.OWRITE}, + &lib9p.RError{Ename: errors.New("permission denied")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotqid lib9p.Qid + gotiounit uint32 + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotqid, gotiounit, goterr = + c.Create(ctx, ifcall.Tag, ifcall.Fid, ifcall.Name, ifcall.Perm, ifcall.Mode) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RCreate: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { + t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", + test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestRead(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TRead + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, + &lib9p.RRead{Count: 4, Data: []byte("unko")}}, + {"1", + &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, + &lib9p.RError{Ename: errors.New("not open")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotdata []byte + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotdata, goterr = + c.Read(ctx, ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RRead: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if !bytes.Equal(ofcall.Data, gotdata) { + t.Errorf("%s: (data) want: %v, got: %v", + test.name, ofcall.Data, gotdata) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestWrite(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TWrite + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("unko")}, + &lib9p.RWrite{Count: 4}}, + {"1", + &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("unko")}, + &lib9p.RError{Ename: errors.New("not open")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotcount uint32 + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotcount, goterr = + c.Write(ctx, ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count, ifcall.Data) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RWrite: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if ofcall.Count != gotcount { + t.Errorf("%s: (count) want: %v, got: %v", + test.name, ofcall.Count, gotcount) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestClunk(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TClunk + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TClunk{Fid: 0}, + &lib9p.RClunk{}}, + {"1", + &lib9p.TClunk{Fid: 0}, + &lib9p.RError{Ename: errors.New("unknown fid")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + goterr = + c.Clunk(ctx, ifcall.Tag, ifcall.Fid) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RClunk: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestRemove(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TRemove + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TRemove{Fid: 0}, + &lib9p.RRemove{}}, + {"1", + &lib9p.TRemove{Fid: 0}, + &lib9p.RError{Ename: errors.New("unknown fid")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + goterr = + c.Remove(ctx, ifcall.Tag, ifcall.Fid) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RRemove: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestStat(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TStat + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TStat{Fid: 0}, + &lib9p.RStat{Stat: &lib9p.Stat{Name: "file"}}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gotstat *lib9p.Stat + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + gotstat, goterr = + c.Stat(ctx, ifcall.Tag, ifcall.Fid) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RStat: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + if !reflect.DeepEqual(ofcall.Stat, gotstat) { + t.Errorf("%s: (stat) want: %v, got: %v", + test.name, ofcall.Stat, gotstat) + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +} + +func TestWstat(t *testing.T) { + tests := []struct { + name string + tmsg *lib9p.TWstat + rmsg lib9p.Msg + }{ + {"0", + &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Gid: "ken"}}, + &lib9p.RWstat{}}, + {"1", + &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Uid: "ken"}}, + &lib9p.RError{Ename: errors.New("permission denied.")}}, + } + for _, test := range tests { + func() { + c, tmsgc, rmsgc := newClientForTest(1024, "glenda") + defer c.Stop() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + goterr error + done = make(chan struct{}) + ) + go func() { + ifcall := test.tmsg + goterr = + c.Wstat(ctx, ifcall.Tag, ifcall.Fid, ifcall.Stat) + close(done) + }() + gottmsg := <-tmsgc + if !reflect.DeepEqual(test.tmsg, gottmsg) { + t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", + test.name, test.tmsg, gottmsg) + return + } + rmsgc <- test.rmsg + select { + case err := <-c.errc: + t.Errorf("client error: %v", err) + return + case <-done: + } + switch ofcall := test.rmsg.(type) { + case *lib9p.RWstat: + if goterr != nil { + t.Errorf("%s: unexpected error: %v", test.name, goterr) + return + } + case *lib9p.RError: + if goterr == nil { + t.Errorf("%s: error expected: %v", test.name, ofcall) + } + default: + t.Errorf("%s: unexpected message: %v", test.name, ofcall) + } + }() + } +}