client_test.go (21826B)
1 package client 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "io" 8 "math/rand" 9 "reflect" 10 "sync" 11 "testing" 12 13 "git.mtkn.jp/lib9p" 14 ) 15 16 // TestClientCancel checks if the client goroutines cancel outstanding transactions 17 // propperly when the Client is canceled. 18 func TestClientCancel(t *testing.T) { 19 ctx, cancel := context.WithCancel(context.Background()) 20 cr, _ := io.Pipe() 21 sr, cw := io.Pipe() 22 defer func() { cr.Close(); sr.Close() }() 23 c := NewClient(ctx, 1024, "", cr, cw) 24 wg := new(sync.WaitGroup) 25 wg.Add(10) 26 for i := 0; i < 10; i++ { 27 go func(i int) { 28 defer wg.Done() 29 c.Version(uint16(i), 1024, "9P2000") 30 }(i) 31 } 32 for i := 0; i < 5; i++ { 33 _, err := lib9p.RecvMsg(sr) 34 if err != nil { 35 t.Fatal(err) 36 } 37 } 38 cancel() 39 wg.Wait() 40 } 41 42 func TestDupTag(t *testing.T) { 43 ctx, cancel := context.WithCancel(context.Background()) 44 c, r, _ := newClientForTest(ctx, 1024, "glenda") 45 defer cancel() 46 go c.Version(0, 1024, "9P2000") 47 _, err := lib9p.RecvMsg(r) 48 if err != nil { 49 t.Fatal(err) 50 } 51 _, _, err = c.Version(0, 1024, "9P2000") 52 if !errors.Is(err, lib9p.ErrDupTag) { 53 t.Error("duplicate tag error not reported: err:", err) 54 } 55 } 56 57 func newClientForTest(ctx context.Context, msize uint32, uname string) (*Client, io.Reader, io.Writer) { 58 c := &Client{ 59 msize: msize, 60 mSizeLock: new(sync.Mutex), 61 uname: uname, 62 rPool: newReqPool(), 63 wg: new(sync.WaitGroup), 64 } 65 cr, sw := io.Pipe() 66 sr, cw := io.Pipe() 67 c.txc = c.runMultiplexer(ctx, cr, cw) 68 return c, sr, sw 69 } 70 71 func TestMux(t *testing.T) { 72 tests := []struct { 73 tmsg, rmsg lib9p.Msg 74 }{ 75 {&lib9p.TVersion{}, &lib9p.RVersion{}}, 76 {&lib9p.TCreate{}, &lib9p.RError{Ename: errors.New("e")}}, 77 } 78 79 ctx, cancel := context.WithCancel(context.Background()) 80 defer cancel() 81 c, r, w := newClientForTest(ctx, 1024, "glenda") 82 for i, test := range tests { 83 tag := uint16(rand.Uint32()) 84 test.tmsg.SetTag(tag) 85 test.rmsg.SetTag(tag) 86 rq := newReq(test.tmsg) 87 c.txc <- rq 88 gottmsg, err := lib9p.RecvMsg(r) 89 if err != nil { 90 t.Error(err) 91 continue 92 } 93 if !reflect.DeepEqual(test.tmsg, gottmsg) { 94 t.Errorf("%d: mux modified tmsg:\n\twant: %v\n\tgot: %v", 95 i, test.tmsg, gottmsg) 96 continue 97 } 98 rq0, ok := c.rPool.lookup(tag) 99 if !ok { 100 t.Errorf("%d: req not registered to the pool.", i) 101 continue 102 } 103 if rq != rq0 { 104 t.Errorf("%d: wrong req registered.", i) 105 continue 106 } 107 if err = lib9p.SendMsg(test.rmsg, w); err != nil { 108 t.Error(err) 109 continue 110 } 111 rq = <-rq.rxc 112 if !reflect.DeepEqual(test.rmsg, rq.rmsg) { 113 t.Errorf("%d: mux modified tmsg:\n\twant: %v\n\tgot: %v", 114 i, test.tmsg, gottmsg) 115 } 116 _, ok = c.rPool.lookup(tag) 117 if ok { 118 t.Errorf("req not deleted from the pool.") 119 continue 120 } 121 } 122 } 123 124 func TestVersion(t *testing.T) { 125 tests := []struct { 126 name string 127 tmsg *lib9p.TVersion 128 rmsg lib9p.Msg 129 }{ 130 {"0", 131 &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}, 132 &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "9P2000"}}, 133 {"1", 134 &lib9p.TVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "hoge"}, 135 &lib9p.RVersion{Tag: lib9p.NOTAG, Msize: 1024, Version: "unknown"}}, 136 } 137 for _, test := range tests { 138 func() { 139 ctx, cancel := context.WithCancel(context.Background()) 140 c, r, w := newClientForTest(ctx, 1024, "glenda") 141 defer cancel() 142 var ( 143 gotmsize uint32 144 gotversion string 145 goterr error 146 done = make(chan struct{}) 147 ) 148 go func() { 149 ifcall := test.tmsg 150 gotmsize, gotversion, goterr = 151 c.Version(ifcall.Tag, ifcall.Msize, ifcall.Version) 152 close(done) 153 }() 154 gottmsg, err := lib9p.RecvMsg(r) 155 if err != nil { 156 t.Error(err) 157 } 158 if !reflect.DeepEqual(test.tmsg, gottmsg) { 159 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 160 test.name, test.tmsg, gottmsg) 161 return 162 } 163 lib9p.SendMsg(test.rmsg, w) 164 <-done 165 switch ofcall := test.rmsg.(type) { 166 case *lib9p.RVersion: 167 if goterr != nil { 168 t.Errorf("%s: unexpected error: %v", test.name, goterr) 169 return 170 } 171 if ofcall.Msize != gotmsize || ofcall.Version != gotversion { 172 t.Errorf("%s: (mSize, verion) want: %d, %s, got: %d, %s", 173 test.name, ofcall.Msize, ofcall.Version, 174 gotmsize, gotversion) 175 } 176 case *lib9p.RError: 177 if goterr == nil { 178 t.Errorf("%s: error expected: %v", test.name, ofcall) 179 } 180 default: 181 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 182 } 183 }() 184 } 185 } 186 187 func TestAuth(t *testing.T) { 188 tests := []struct { 189 name string 190 tmsg *lib9p.TAuth 191 rmsg lib9p.Msg 192 }{ 193 {"0", 194 &lib9p.TAuth{Tag: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, 195 &lib9p.RError{Tag: 0, Ename: errors.New("authentication not required.")}}, 196 {"1", 197 &lib9p.TAuth{Tag: 0, Afid: 0, Uname: "glenda", Aname: ""}, 198 &lib9p.RAuth{Tag: 0, Aqid: lib9p.Qid{Path: 1}}}, 199 } 200 for _, test := range tests { 201 func() { 202 ctx, cancel := context.WithCancel(context.Background()) 203 c, r, w := newClientForTest(ctx, 1024, "glenda") 204 defer cancel() 205 var ( 206 gotaqid lib9p.Qid 207 goterr error 208 done = make(chan struct{}) 209 ) 210 go func() { 211 ifcall := test.tmsg 212 gotaqid, goterr = 213 c.Auth(ifcall.Tag, ifcall.Afid, ifcall.Uname, ifcall.Aname) 214 close(done) 215 }() 216 gottmsg, err := lib9p.RecvMsg(r) 217 if err != nil { 218 t.Error(err) 219 } 220 if !reflect.DeepEqual(test.tmsg, gottmsg) { 221 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 222 test.name, test.tmsg, gottmsg) 223 return 224 } 225 lib9p.SendMsg(test.rmsg, w) 226 <-done 227 switch ofcall := test.rmsg.(type) { 228 case *lib9p.RAuth: 229 if goterr != nil { 230 t.Errorf("%s: unexpected error: %v", test.name, goterr) 231 return 232 } 233 if ofcall.Aqid != gotaqid { 234 t.Errorf("%s: (qid) want: %v, got: %v", 235 test.name, ofcall.Aqid, gotaqid) 236 } 237 case *lib9p.RError: 238 if goterr == nil { 239 t.Errorf("%s: error expected: %v", test.name, ofcall) 240 } 241 default: 242 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 243 } 244 }() 245 } 246 } 247 248 func TestAttach(t *testing.T) { 249 tests := []struct { 250 name string 251 tmsg *lib9p.TAttach 252 rmsg lib9p.Msg 253 }{ 254 {"0", 255 &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, 256 &lib9p.RAttach{Qid: lib9p.Qid{Path: 2}}}, 257 {"1", 258 &lib9p.TAttach{Fid: 0, Afid: lib9p.NOFID, Uname: "glenda", Aname: ""}, 259 &lib9p.RError{Ename: errors.New("authentication required")}}, 260 } 261 for _, test := range tests { 262 func() { 263 ctx, cancel := context.WithCancel(context.Background()) 264 c, r, w := newClientForTest(ctx, 1024, "glenda") 265 defer cancel() 266 var ( 267 gotqid lib9p.Qid 268 goterr error 269 done = make(chan struct{}) 270 ) 271 go func() { 272 ifcall := test.tmsg 273 gotqid, goterr = 274 c.Attach(ifcall.Tag, ifcall.Fid, ifcall.Afid, ifcall.Uname, ifcall.Aname) 275 close(done) 276 }() 277 gottmsg, err := lib9p.RecvMsg(r) 278 if err != nil { 279 t.Error(err) 280 } 281 if !reflect.DeepEqual(test.tmsg, gottmsg) { 282 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 283 test.name, test.tmsg, gottmsg) 284 return 285 } 286 lib9p.SendMsg(test.rmsg, w) 287 <-done 288 switch ofcall := test.rmsg.(type) { 289 case *lib9p.RAttach: 290 if goterr != nil { 291 t.Errorf("%s: unexpected error: %v", test.name, goterr) 292 return 293 } 294 if ofcall.Qid != gotqid { 295 t.Errorf("%s: (qid) want: %v, got: %v", 296 test.name, ofcall.Qid, gotqid) 297 } 298 case *lib9p.RError: 299 if goterr == nil { 300 t.Errorf("%s: error expected: %v", test.name, ofcall) 301 } 302 default: 303 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 304 } 305 }() 306 } 307 } 308 309 func TestFlush(t *testing.T) { 310 tests := []struct { 311 name string 312 tmsg *lib9p.TFlush 313 rmsg lib9p.Msg 314 }{ 315 {"0", 316 &lib9p.TFlush{Oldtag: 1}, 317 &lib9p.RFlush{}}, 318 } 319 for _, test := range tests { 320 func() { 321 ctx, cancel := context.WithCancel(context.Background()) 322 c, r, w := newClientForTest(ctx, 1024, "glenda") 323 defer cancel() 324 var ( 325 goterr error 326 done = make(chan struct{}) 327 ) 328 go func() { 329 ifcall := test.tmsg 330 goterr = 331 c.Flush(ifcall.Tag, ifcall.Oldtag) 332 close(done) 333 }() 334 gottmsg, err := lib9p.RecvMsg(r) 335 if err != nil { 336 t.Error(err) 337 } 338 if !reflect.DeepEqual(test.tmsg, gottmsg) { 339 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 340 test.name, test.tmsg, gottmsg) 341 return 342 } 343 lib9p.SendMsg(test.rmsg, w) 344 <-done 345 switch ofcall := test.rmsg.(type) { 346 case *lib9p.RFlush: 347 if goterr != nil { 348 t.Errorf("%s: unexpected error: %v", test.name, goterr) 349 return 350 } 351 case *lib9p.RError: 352 if goterr == nil { 353 t.Errorf("%s: error expected: %v", test.name, ofcall) 354 } 355 default: 356 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 357 } 358 }() 359 } 360 } 361 362 func TestWalk(t *testing.T) { 363 tests := []struct { 364 name string 365 tmsg *lib9p.TWalk 366 rmsg lib9p.Msg 367 }{ 368 {"0", 369 &lib9p.TWalk{Fid: 0, Newfid: 1, Wnames: []string{"a", "b", "c"}}, 370 &lib9p.RWalk{Qids: []lib9p.Qid{lib9p.Qid{Path: 0}, lib9p.Qid{Path: 1}, lib9p.Qid{Path: 2}}}}, 371 {"1", 372 &lib9p.TWalk{Fid: 0, Newfid: 2, Wnames: []string{"a", "b", "c"}}, 373 &lib9p.RError{Ename: errors.New("not found")}}, 374 } 375 for _, test := range tests { 376 func() { 377 ctx, cancel := context.WithCancel(context.Background()) 378 c, r, w := newClientForTest(ctx, 1024, "glenda") 379 defer cancel() 380 var ( 381 gotqids []lib9p.Qid 382 goterr error 383 done = make(chan struct{}) 384 ) 385 go func() { 386 ifcall := test.tmsg 387 gotqids, goterr = 388 c.Walk(ifcall.Tag, ifcall.Fid, ifcall.Newfid, ifcall.Wnames) 389 close(done) 390 }() 391 gottmsg, err := lib9p.RecvMsg(r) 392 if err != nil { 393 t.Error(err) 394 } 395 if !reflect.DeepEqual(test.tmsg, gottmsg) { 396 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 397 test.name, test.tmsg, gottmsg) 398 return 399 } 400 lib9p.SendMsg(test.rmsg, w) 401 <-done 402 switch ofcall := test.rmsg.(type) { 403 case *lib9p.RWalk: 404 if goterr != nil { 405 t.Errorf("%s: unexpected error: %v", test.name, goterr) 406 return 407 } 408 if !reflect.DeepEqual(ofcall.Qids, gotqids) { 409 t.Errorf("%s: (qids) want: %v, got: %v", 410 test.name, ofcall.Qids, gotqids) 411 } 412 case *lib9p.RError: 413 if goterr == nil { 414 t.Errorf("%s: error expected: %v", test.name, ofcall) 415 } 416 default: 417 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 418 } 419 }() 420 } 421 } 422 423 func TestOpen(t *testing.T) { 424 tests := []struct { 425 name string 426 tmsg *lib9p.TOpen 427 rmsg lib9p.Msg 428 }{ 429 {"0", 430 &lib9p.TOpen{Fid: 0, Mode: lib9p.OREAD}, 431 &lib9p.ROpen{Qid: lib9p.Qid{Path: 1}, Iounit: 1000}}, 432 {"1", 433 &lib9p.TOpen{Fid: 0, Mode: lib9p.OWRITE}, 434 &lib9p.RError{Ename: errors.New("permission denied")}}, 435 } 436 for _, test := range tests { 437 func() { 438 ctx, cancel := context.WithCancel(context.Background()) 439 c, r, w := newClientForTest(ctx, 1024, "glenda") 440 defer cancel() 441 var ( 442 gotqid lib9p.Qid 443 gotiounit uint32 444 goterr error 445 done = make(chan struct{}) 446 ) 447 go func() { 448 ifcall := test.tmsg 449 gotqid, gotiounit, goterr = 450 c.Open(ifcall.Tag, ifcall.Fid, ifcall.Mode) 451 close(done) 452 }() 453 gottmsg, err := lib9p.RecvMsg(r) 454 if err != nil { 455 t.Error(err) 456 } 457 if !reflect.DeepEqual(test.tmsg, gottmsg) { 458 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 459 test.name, test.tmsg, gottmsg) 460 return 461 } 462 lib9p.SendMsg(test.rmsg, w) 463 <-done 464 switch ofcall := test.rmsg.(type) { 465 case *lib9p.ROpen: 466 if goterr != nil { 467 t.Errorf("%s: unexpected error: %v", test.name, goterr) 468 return 469 } 470 if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { 471 t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", 472 test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) 473 } 474 case *lib9p.RError: 475 if goterr == nil { 476 t.Errorf("%s: error expected: %v", test.name, ofcall) 477 } 478 default: 479 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 480 } 481 }() 482 } 483 } 484 485 func TestCreate(t *testing.T) { 486 tests := []struct { 487 name string 488 tmsg *lib9p.TCreate 489 rmsg lib9p.Msg 490 }{ 491 {"0", 492 &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0666, Mode: lib9p.OREAD}, 493 &lib9p.RCreate{Qid: lib9p.Qid{Path: 0}, Iounit: 1000}}, 494 {"1", 495 &lib9p.TCreate{Fid: 0, Name: "file", Perm: 0777, Mode: lib9p.OWRITE}, 496 &lib9p.RError{Ename: errors.New("permission denied")}}, 497 } 498 for _, test := range tests { 499 func() { 500 ctx, cancel := context.WithCancel(context.Background()) 501 c, r, w := newClientForTest(ctx, 1024, "glenda") 502 defer cancel() 503 var ( 504 gotqid lib9p.Qid 505 gotiounit uint32 506 goterr error 507 done = make(chan struct{}) 508 ) 509 go func() { 510 ifcall := test.tmsg 511 gotqid, gotiounit, goterr = 512 c.Create(ifcall.Tag, ifcall.Fid, ifcall.Name, ifcall.Perm, ifcall.Mode) 513 close(done) 514 }() 515 gottmsg, err := lib9p.RecvMsg(r) 516 if err != nil { 517 t.Error(err) 518 } 519 if !reflect.DeepEqual(test.tmsg, gottmsg) { 520 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 521 test.name, test.tmsg, gottmsg) 522 return 523 } 524 lib9p.SendMsg(test.rmsg, w) 525 <-done 526 switch ofcall := test.rmsg.(type) { 527 case *lib9p.RCreate: 528 if goterr != nil { 529 t.Errorf("%s: unexpected error: %v", test.name, goterr) 530 return 531 } 532 if ofcall.Qid != gotqid || ofcall.Iounit != gotiounit { 533 t.Errorf("%s: (qid, iounit) want: %v, %d, got: %v, %d", 534 test.name, ofcall.Qid, ofcall.Iounit, gotqid, gotiounit) 535 } 536 case *lib9p.RError: 537 if goterr == nil { 538 t.Errorf("%s: error expected: %v", test.name, ofcall) 539 } 540 default: 541 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 542 } 543 }() 544 } 545 } 546 547 func TestRead(t *testing.T) { 548 tests := []struct { 549 name string 550 tmsg *lib9p.TRead 551 rmsg lib9p.Msg 552 }{ 553 {"0", 554 &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, 555 &lib9p.RRead{Count: 4, Data: []byte("hoge")}}, 556 {"1", 557 &lib9p.TRead{Fid: 0, Offset: 0, Count: 1000}, 558 &lib9p.RError{Ename: errors.New("not open")}}, 559 } 560 for _, test := range tests { 561 func() { 562 ctx, cancel := context.WithCancel(context.Background()) 563 c, r, w := newClientForTest(ctx, 1024, "glenda") 564 defer cancel() 565 var ( 566 gotdata []byte 567 goterr error 568 done = make(chan struct{}) 569 ) 570 go func() { 571 ifcall := test.tmsg 572 gotdata, goterr = 573 c.Read(ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count) 574 close(done) 575 }() 576 gottmsg, err := lib9p.RecvMsg(r) 577 if err != nil { 578 t.Error(err) 579 } 580 if !reflect.DeepEqual(test.tmsg, gottmsg) { 581 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 582 test.name, test.tmsg, gottmsg) 583 return 584 } 585 lib9p.SendMsg(test.rmsg, w) 586 <-done 587 switch ofcall := test.rmsg.(type) { 588 case *lib9p.RRead: 589 if goterr != nil { 590 t.Errorf("%s: unexpected error: %v", test.name, goterr) 591 return 592 } 593 if !bytes.Equal(ofcall.Data, gotdata) { 594 t.Errorf("%s: (data) want: %v, got: %v", 595 test.name, ofcall.Data, gotdata) 596 } 597 case *lib9p.RError: 598 if goterr == nil { 599 t.Errorf("%s: error expected: %v", test.name, ofcall) 600 } 601 default: 602 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 603 } 604 }() 605 } 606 } 607 608 func TestWrite(t *testing.T) { 609 tests := []struct { 610 name string 611 tmsg *lib9p.TWrite 612 rmsg lib9p.Msg 613 }{ 614 {"0", 615 &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("hoge")}, 616 &lib9p.RWrite{Count: 4}}, 617 {"1", 618 &lib9p.TWrite{Fid: 0, Offset: 0, Count: 4, Data: []byte("hoge")}, 619 &lib9p.RError{Ename: errors.New("not open")}}, 620 } 621 for _, test := range tests { 622 func() { 623 ctx, cancel := context.WithCancel(context.Background()) 624 c, r, w := newClientForTest(ctx, 1024, "glenda") 625 defer cancel() 626 var ( 627 gotcount uint32 628 goterr error 629 done = make(chan struct{}) 630 ) 631 go func() { 632 ifcall := test.tmsg 633 gotcount, goterr = 634 c.Write(ifcall.Tag, ifcall.Fid, ifcall.Offset, ifcall.Count, ifcall.Data) 635 close(done) 636 }() 637 gottmsg, err := lib9p.RecvMsg(r) 638 if err != nil { 639 t.Error(err) 640 } 641 if !reflect.DeepEqual(test.tmsg, gottmsg) { 642 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 643 test.name, test.tmsg, gottmsg) 644 return 645 } 646 lib9p.SendMsg(test.rmsg, w) 647 <-done 648 switch ofcall := test.rmsg.(type) { 649 case *lib9p.RWrite: 650 if goterr != nil { 651 t.Errorf("%s: unexpected error: %v", test.name, goterr) 652 return 653 } 654 if ofcall.Count != gotcount { 655 t.Errorf("%s: (count) want: %v, got: %v", 656 test.name, ofcall.Count, gotcount) 657 } 658 case *lib9p.RError: 659 if goterr == nil { 660 t.Errorf("%s: error expected: %v", test.name, ofcall) 661 } 662 default: 663 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 664 } 665 }() 666 } 667 } 668 669 func TestClunk(t *testing.T) { 670 tests := []struct { 671 name string 672 tmsg *lib9p.TClunk 673 rmsg lib9p.Msg 674 }{ 675 {"0", 676 &lib9p.TClunk{Fid: 0}, 677 &lib9p.RClunk{}}, 678 {"1", 679 &lib9p.TClunk{Fid: 0}, 680 &lib9p.RError{Ename: errors.New("unknown fid")}}, 681 } 682 for _, test := range tests { 683 func() { 684 ctx, cancel := context.WithCancel(context.Background()) 685 c, r, w := newClientForTest(ctx, 1024, "glenda") 686 defer cancel() 687 var ( 688 goterr error 689 done = make(chan struct{}) 690 ) 691 go func() { 692 ifcall := test.tmsg 693 goterr = 694 c.Clunk(ifcall.Tag, ifcall.Fid) 695 close(done) 696 }() 697 gottmsg, err := lib9p.RecvMsg(r) 698 if err != nil { 699 t.Error(err) 700 } 701 if !reflect.DeepEqual(test.tmsg, gottmsg) { 702 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 703 test.name, test.tmsg, gottmsg) 704 return 705 } 706 lib9p.SendMsg(test.rmsg, w) 707 <-done 708 switch ofcall := test.rmsg.(type) { 709 case *lib9p.RClunk: 710 if goterr != nil { 711 t.Errorf("%s: unexpected error: %v", test.name, goterr) 712 return 713 } 714 case *lib9p.RError: 715 if goterr == nil { 716 t.Errorf("%s: error expected: %v", test.name, ofcall) 717 } 718 default: 719 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 720 } 721 }() 722 } 723 } 724 725 func TestRemove(t *testing.T) { 726 tests := []struct { 727 name string 728 tmsg *lib9p.TRemove 729 rmsg lib9p.Msg 730 }{ 731 {"0", 732 &lib9p.TRemove{Fid: 0}, 733 &lib9p.RRemove{}}, 734 {"1", 735 &lib9p.TRemove{Fid: 0}, 736 &lib9p.RError{Ename: errors.New("unknown fid")}}, 737 } 738 for _, test := range tests { 739 func() { 740 ctx, cancel := context.WithCancel(context.Background()) 741 c, r, w := newClientForTest(ctx, 1024, "glenda") 742 defer cancel() 743 var ( 744 goterr error 745 done = make(chan struct{}) 746 ) 747 go func() { 748 ifcall := test.tmsg 749 goterr = 750 c.Remove(ifcall.Tag, ifcall.Fid) 751 close(done) 752 }() 753 gottmsg, err := lib9p.RecvMsg(r) 754 if err != nil { 755 t.Error(err) 756 } 757 if !reflect.DeepEqual(test.tmsg, gottmsg) { 758 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 759 test.name, test.tmsg, gottmsg) 760 return 761 } 762 lib9p.SendMsg(test.rmsg, w) 763 <-done 764 switch ofcall := test.rmsg.(type) { 765 case *lib9p.RRemove: 766 if goterr != nil { 767 t.Errorf("%s: unexpected error: %v", test.name, goterr) 768 return 769 } 770 case *lib9p.RError: 771 if goterr == nil { 772 t.Errorf("%s: error expected: %v", test.name, ofcall) 773 } 774 default: 775 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 776 } 777 }() 778 } 779 } 780 781 func TestStat(t *testing.T) { 782 tests := []struct { 783 name string 784 tmsg *lib9p.TStat 785 rmsg lib9p.Msg 786 }{ 787 {"0", 788 &lib9p.TStat{Fid: 0}, 789 &lib9p.RStat{Stat: &lib9p.Stat{Name: "file"}}}, 790 } 791 for _, test := range tests { 792 func() { 793 ctx, cancel := context.WithCancel(context.Background()) 794 c, r, w := newClientForTest(ctx, 1024, "glenda") 795 defer cancel() 796 var ( 797 gotstat *lib9p.Stat 798 goterr error 799 done = make(chan struct{}) 800 ) 801 go func() { 802 ifcall := test.tmsg 803 gotstat, goterr = 804 c.Stat(ifcall.Tag, ifcall.Fid) 805 close(done) 806 }() 807 gottmsg, err := lib9p.RecvMsg(r) 808 if err != nil { 809 t.Error(err) 810 } 811 if !reflect.DeepEqual(test.tmsg, gottmsg) { 812 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 813 test.name, test.tmsg, gottmsg) 814 return 815 } 816 lib9p.SendMsg(test.rmsg, w) 817 <-done 818 switch ofcall := test.rmsg.(type) { 819 case *lib9p.RStat: 820 if goterr != nil { 821 t.Errorf("%s: unexpected error: %v", test.name, goterr) 822 return 823 } 824 if !reflect.DeepEqual(ofcall.Stat, gotstat) { 825 t.Errorf("%s: (stat) want: %v, got: %v", 826 test.name, ofcall.Stat, gotstat) 827 } 828 case *lib9p.RError: 829 if goterr == nil { 830 t.Errorf("%s: error expected: %v", test.name, ofcall) 831 } 832 default: 833 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 834 } 835 }() 836 } 837 } 838 839 func TestWstat(t *testing.T) { 840 tests := []struct { 841 name string 842 tmsg *lib9p.TWstat 843 rmsg lib9p.Msg 844 }{ 845 {"0", 846 &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Gid: "ken"}}, 847 &lib9p.RWstat{}}, 848 {"1", 849 &lib9p.TWstat{Fid: 0, Stat: &lib9p.Stat{Name: "file", Uid: "ken"}}, 850 &lib9p.RError{Ename: errors.New("permission denied.")}}, 851 } 852 for _, test := range tests { 853 func() { 854 ctx, cancel := context.WithCancel(context.Background()) 855 c, r, w := newClientForTest(ctx, 1024, "glenda") 856 defer cancel() 857 var ( 858 goterr error 859 done = make(chan struct{}) 860 ) 861 go func() { 862 ifcall := test.tmsg 863 goterr = 864 c.Wstat(ifcall.Tag, ifcall.Fid, ifcall.Stat) 865 close(done) 866 }() 867 gottmsg, err := lib9p.RecvMsg(r) 868 if err != nil { 869 t.Error(err) 870 } 871 if !reflect.DeepEqual(test.tmsg, gottmsg) { 872 t.Errorf("%s: tmsg modified:\n\twant: %v\n\tgot: %v", 873 test.name, test.tmsg, gottmsg) 874 return 875 } 876 lib9p.SendMsg(test.rmsg, w) 877 <-done 878 switch ofcall := test.rmsg.(type) { 879 case *lib9p.RWstat: 880 if goterr != nil { 881 t.Errorf("%s: unexpected error: %v", test.name, goterr) 882 return 883 } 884 case *lib9p.RError: 885 if goterr == nil { 886 t.Errorf("%s: error expected: %v", test.name, ofcall) 887 } 888 default: 889 t.Errorf("%s: unexpected message: %v", test.name, ofcall) 890 } 891 }() 892 } 893 }