lib9p

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

commit 319ffd2f3612b0d89d4cc75add8c35b0b85063fc
parent 58665125f9ee01e8cd45387d5841035ab970a12b
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri,  5 Jan 2024 09:32:35 +0900

add client tests

Diffstat:
Mclient/client.go | 4++--
Mclient/client2_test.go | 681+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mclient/file_test.go | 4++--
3 files changed, 685 insertions(+), 4 deletions(-)

diff --git a/client/client.go b/client/client.go @@ -484,13 +484,13 @@ func (c *Client) Stat(ctx context.Context, tag uint16, fid uint32) (*lib9p.Stat, } } func (c *Client) Wstat(ctx context.Context, tag uint16, fid uint32, stat *lib9p.Stat) error { - tmsg := &lib9p.TWStat{Tag: tag, Fid: fid, Stat: stat} + tmsg := &lib9p.TWstat{Tag: tag, Fid: fid, Stat: stat} rmsg, err := c.transact(ctx, tmsg) if err != nil { return fmt.Errorf("transact: %v", err) } switch rmsg := rmsg.(type) { - case *lib9p.RWStat: + case *lib9p.RWstat: return nil case *lib9p.RError: return rmsg.Ename diff --git a/client/client2_test.go b/client/client2_test.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "context" "errors" "reflect" @@ -155,3 +156,683 @@ func TestAuth(t *testing.T) { }() } } + +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/file_test.go b/client/file_test.go @@ -25,9 +25,9 @@ func mount(fs lib9p.FS) (cfs *FS, cancel context.CancelFunc, err error) { return cfs, cancel, nil } -// TestStat tests whether Stat returns the same lib9p.Stat as testfs.Fsys defines. +// TestFileStat tests whether Stat returns the same lib9p.Stat as testfs.Fsys defines. // TODO: work in progress. -func TestStat(t *testing.T) { +func TestFileStat(t *testing.T) { } // TestReadDir tests whether ReadDir returns the same dir entries as testfs.Fsys