server2_test.go (6934B)
1 package lib9p 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "io" 8 "os" 9 "reflect" 10 "sync" 11 "testing" 12 ) 13 14 // TestRunListener tests if the listener goroutine receives 9P messages 15 // and send them through the server's listenChan channel. 16 // It also checks whether the listener goroutine returns by canceling 17 // ctx, by checking if the server's listenChan is closed. 18 func TestRunListener(t *testing.T) { 19 tFile, err := os.Open("testdata/test_Tmsg.dat") 20 if err != nil { 21 t.Fatalf("open file: %v", err) 22 } 23 defer tFile.Close() 24 tFile2, err := os.Open("testdata/test_Tmsg.dat") 25 if err != nil { 26 t.Fatalf("open file: %v", err) 27 } 28 defer tFile2.Close() 29 c := &Conn{ 30 s: &Server{chatty9P: false}, 31 r: tFile, 32 } 33 oldReqPoolAdd := reqPoolAdd 34 defer func() { reqPoolAdd = oldReqPoolAdd }() 35 reqPoolAdd = func(*reqPool, uint16) (*request, error) { return &request{}, nil } 36 ctx, cancel := context.WithCancel(context.Background()) 37 defer cancel() 38 c.runListener(ctx, newReqPool()) 39 for { 40 want, err := RecvMsg(tFile2) 41 if err == io.EOF { 42 break 43 } else if err != nil { 44 t.Fatalf("recvmsg: %v", err) 45 } 46 r := <-c.listenChan 47 if r.listenErr != nil { 48 t.Fatalf("listenErr: %v", r.listenErr) 49 } 50 got := r.ifcall 51 if !reflect.DeepEqual(want, got) { 52 t.Errorf("listener modified message:\n\twant: %v\n\tgot: %v", 53 want, got) 54 } 55 } 56 } 57 58 // TestRunSpeaker tests if the speaker goroutine receives 9P messages 59 // and send them through the server's speakChan channel. 60 func TestRunResponder(t *testing.T) { 61 rFile, err := os.Open("testdata/test_Rmsg.dat") 62 if err != nil { 63 t.Fatalf("open file: %v", err) 64 } 65 defer rFile.Close() 66 r, w := io.Pipe() 67 c := &Conn{s: &Server{chatty9P: false}, w: w} 68 rp := newReqPool() 69 ctx, cancel := context.WithCancel(context.Background()) 70 defer cancel() 71 c.runResponder(ctx, rp) 72 for { 73 want, err := readMsg(rFile) 74 if err == io.EOF { 75 break 76 } else if err != nil { 77 t.Fatalf("readmsg: %v", err) 78 } 79 msg, err := unmarshal(want) 80 if err != nil { 81 t.Fatalf("unmarshal %v", err) 82 } 83 c.respChan <- &request{ 84 tag: msg.GetTag(), 85 ofcall: msg, 86 } 87 got := make([]byte, len(want)) 88 _, err = io.ReadFull(r, got) 89 if err != nil { 90 t.Fatalf("readfull: %v", err) 91 } 92 if !bytes.Equal(want, got) { 93 t.Errorf("responder modified message:\n\twant: %v\n\tgot: %v", 94 want, got) 95 } 96 } 97 } 98 99 func TestGetReq(t *testing.T) { 100 tFile, err := os.Open("testdata/test_Tmsg.dat") 101 if err != nil { 102 t.Fatalf("open file: %v", err) 103 } 104 defer tFile.Close() 105 tFile2, err := os.Open("testdata/test_Tmsg.dat") 106 if err != nil { 107 t.Fatalf("open file: %v", err) 108 } 109 defer tFile2.Close() 110 rp := newReqPool() 111 for { 112 got := getReq(tFile, rp, false) 113 if got.listenErr == io.EOF { 114 break 115 } else if got.listenErr != nil { 116 t.Fatalf("getReq: %v", got.listenErr) 117 } 118 wantMsg, err := RecvMsg(tFile2) 119 if err != nil { 120 t.Fatalf("recvmsg: %v", err) 121 } 122 if got.tag != wantMsg.GetTag() { 123 t.Errorf("r.tag: want: %v, got: %v", wantMsg.GetTag(), got.tag) 124 } 125 if !reflect.DeepEqual(got.ifcall, wantMsg) { 126 t.Errorf("r.ifcall:\n\twant: %v,\n\tgot: %v", wantMsg, got.ifcall) 127 } 128 got2, ok := rp.lookup(wantMsg.GetTag()) 129 if !ok { 130 t.Errorf("request not registered to the pool") 131 } 132 if got != got2 { 133 t.Errorf("wrong message in pool:\n\twant: %p,\n\tgot: %p", got, got2) 134 } 135 rp.delete(wantMsg.GetTag()) 136 } 137 } 138 139 func TestSVersion(t *testing.T) { 140 tests := []struct { 141 input *request 142 want *request 143 }{ 144 {&request{ifcall: &TVersion{Msize: 1024, Version: "9P2000"}}, 145 &request{ofcall: &RVersion{Msize: 1024, Version: "9P2000"}}}, 146 {&request{ifcall: &TVersion{Msize: 564, Version: "9P2000"}}, 147 &request{ofcall: &RVersion{Msize: 564, Version: "9P2000"}}}, 148 {&request{ifcall: &TVersion{Msize: 8 * 1024, Version: "9P2000"}}, 149 &request{ofcall: &RVersion{Msize: 1024, Version: "9P2000"}}}, 150 {&request{ifcall: &TVersion{Msize: 1024, Version: "unko"}}, 151 &request{ofcall: &RVersion{Msize: 1024, Version: "unknown"}}}, 152 } 153 tc := make(chan *request) 154 rc := make(chan *request) 155 c := &Conn{msize: 1024, mSizeLock: new(sync.Mutex), respChan: rc} 156 ctx, cancel := context.WithCancel(context.Background()) 157 defer cancel() 158 go sVersion(ctx, c, tc) 159 for _, test := range tests { 160 oldMsize := c.msize 161 tc <- test.input 162 ifcall := test.input.ifcall.(*TVersion) 163 wantmsg := test.want.ofcall.(*RVersion) 164 gotmsg := (<-rc).ofcall.(*RVersion) 165 if !reflect.DeepEqual(wantmsg, gotmsg) { 166 t.Errorf("want: %v,\n\tgot: %v", wantmsg, gotmsg) 167 } 168 if ifcall.Msize < oldMsize && c.msize != ifcall.Msize { 169 t.Errorf("msize not changed") 170 } 171 if ifcall.Msize >= oldMsize && c.msize != oldMsize { 172 t.Errorf("msize changed unexpectedly") 173 } 174 c.msize = oldMsize 175 } 176 } 177 178 func TestSAuth(t *testing.T) { 179 tests := []struct { 180 input *request 181 want *request 182 authFunc func(context.Context, *request) 183 }{ 184 {&request{ifcall: &TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}}, 185 &request{ofcall: &RError{Ename: errors.New("authentication not required")}}, nil}, 186 {&request{ifcall: &TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}}, 187 &request{ofcall: &RError{Ename: errors.New("NOFID can't be used for afid")}}, 188 func(ctx context.Context, r *request) {}}, 189 {&request{ifcall: &TAuth{Afid: 0, Uname: "kenji", Aname: ""}}, 190 &request{ofcall: &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}}}, 191 func(ctx context.Context, r *request) { 192 r.ofcall = &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}} 193 }}, 194 } 195 for _, test := range tests { 196 func() { 197 tc := make(chan *request) 198 rc := make(chan *request) 199 defer close(tc) 200 defer close(rc) 201 s := &Server{Auth: test.authFunc} 202 c := &Conn{s: s, respChan: rc, fPool: newFidPool()} 203 ctx, cancel := context.WithCancel(context.Background()) 204 defer cancel() 205 go sAuth(ctx, c, tc) 206 tc <- test.input 207 ofcall := (<-rc).ofcall 208 switch wantmsg := test.want.ofcall.(type) { 209 case *RAuth: 210 gotmsg, ok := ofcall.(*RAuth) 211 if !ok { 212 t.Errorf("unexpected message: %v", ofcall) 213 return 214 } 215 if !reflect.DeepEqual(wantmsg, gotmsg) { 216 t.Errorf("want: %v,\n\tgot: %v", wantmsg, gotmsg) 217 return 218 } 219 case *RError: 220 _, ok := ofcall.(*RError) 221 if !ok { 222 t.Errorf("unexpected message: %v", ofcall) 223 return 224 } 225 default: 226 t.Fatalf("unexpected message: %v", wantmsg) 227 } 228 }() 229 } 230 } 231 232 func TestSFlush(t *testing.T) { 233 rp := newReqPool() 234 tests := []struct { 235 input *request 236 }{ 237 {&request{ifcall: &TFlush{}, 238 oldreq: &request{pool: rp, done: make(chan struct{})}}}, 239 } 240 tc := make(chan *request) 241 rc := make(chan *request) 242 c := &Conn{msize: 1024, mSizeLock: new(sync.Mutex), respChan: rc} 243 ctx, cancel := context.WithCancel(context.Background()) 244 defer cancel() 245 go sFlush(ctx, c, tc) 246 for _, test := range tests { 247 tc <- test.input 248 if gotmsg, ok := (<-rc).ofcall.(*RFlush); !ok { 249 t.Errorf("unexpected message: %v", gotmsg) 250 } 251 if _, ok := <-test.input.oldreq.done; ok { 252 t.Errorf("done channel not closed") 253 } 254 } 255 }