github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/gridfs_test.go (about) 1 // mgo - MongoDB driver for Go 2 // 3 // Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net> 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // 1. Redistributions of source code must retain the above copyright notice, this 11 // list of conditions and the following disclaimer. 12 // 2. Redistributions in binary form must reproduce the above copyright notice, 13 // this list of conditions and the following disclaimer in the documentation 14 // and/or other materials provided with the distribution. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 package mgo_test 28 29 import ( 30 "io" 31 "os" 32 "time" 33 34 . "gopkg.in/check.v1" 35 "gopkg.in/mgo.v2" 36 "gopkg.in/mgo.v2/bson" 37 ) 38 39 func (s *S) TestGridFSCreate(c *C) { 40 session, err := mgo.Dial("localhost:40011") 41 c.Assert(err, IsNil) 42 defer session.Close() 43 44 db := session.DB("mydb") 45 46 before := bson.Now() 47 48 gfs := db.GridFS("fs") 49 file, err := gfs.Create("") 50 c.Assert(err, IsNil) 51 52 n, err := file.Write([]byte("some data")) 53 c.Assert(err, IsNil) 54 c.Assert(n, Equals, 9) 55 56 err = file.Close() 57 c.Assert(err, IsNil) 58 59 after := bson.Now() 60 61 // Check the file information. 62 result := M{} 63 err = db.C("fs.files").Find(nil).One(result) 64 c.Assert(err, IsNil) 65 66 fileId, ok := result["_id"].(bson.ObjectId) 67 c.Assert(ok, Equals, true) 68 c.Assert(fileId.Valid(), Equals, true) 69 result["_id"] = "<id>" 70 71 ud, ok := result["uploadDate"].(time.Time) 72 c.Assert(ok, Equals, true) 73 c.Assert(ud.After(before) && ud.Before(after), Equals, true) 74 result["uploadDate"] = "<timestamp>" 75 76 expected := M{ 77 "_id": "<id>", 78 "length": 9, 79 "chunkSize": 255 * 1024, 80 "uploadDate": "<timestamp>", 81 "md5": "1e50210a0202497fb79bc38b6ade6c34", 82 } 83 c.Assert(result, DeepEquals, expected) 84 85 // Check the chunk. 86 result = M{} 87 err = db.C("fs.chunks").Find(nil).One(result) 88 c.Assert(err, IsNil) 89 90 chunkId, ok := result["_id"].(bson.ObjectId) 91 c.Assert(ok, Equals, true) 92 c.Assert(chunkId.Valid(), Equals, true) 93 result["_id"] = "<id>" 94 95 expected = M{ 96 "_id": "<id>", 97 "files_id": fileId, 98 "n": 0, 99 "data": []byte("some data"), 100 } 101 c.Assert(result, DeepEquals, expected) 102 103 // Check that an index was created. 104 indexes, err := db.C("fs.chunks").Indexes() 105 c.Assert(err, IsNil) 106 c.Assert(len(indexes), Equals, 2) 107 c.Assert(indexes[1].Key, DeepEquals, []string{"files_id", "n"}) 108 } 109 110 func (s *S) TestGridFSFileDetails(c *C) { 111 session, err := mgo.Dial("localhost:40011") 112 c.Assert(err, IsNil) 113 defer session.Close() 114 115 db := session.DB("mydb") 116 117 gfs := db.GridFS("fs") 118 119 file, err := gfs.Create("myfile1.txt") 120 c.Assert(err, IsNil) 121 122 n, err := file.Write([]byte("some")) 123 c.Assert(err, IsNil) 124 c.Assert(n, Equals, 4) 125 126 c.Assert(file.Size(), Equals, int64(4)) 127 128 n, err = file.Write([]byte(" data")) 129 c.Assert(err, IsNil) 130 c.Assert(n, Equals, 5) 131 132 c.Assert(file.Size(), Equals, int64(9)) 133 134 id, _ := file.Id().(bson.ObjectId) 135 c.Assert(id.Valid(), Equals, true) 136 c.Assert(file.Name(), Equals, "myfile1.txt") 137 c.Assert(file.ContentType(), Equals, "") 138 139 var info interface{} 140 err = file.GetMeta(&info) 141 c.Assert(err, IsNil) 142 c.Assert(info, IsNil) 143 144 file.SetId("myid") 145 file.SetName("myfile2.txt") 146 file.SetContentType("text/plain") 147 file.SetMeta(M{"any": "thing"}) 148 149 c.Assert(file.Id(), Equals, "myid") 150 c.Assert(file.Name(), Equals, "myfile2.txt") 151 c.Assert(file.ContentType(), Equals, "text/plain") 152 153 err = file.GetMeta(&info) 154 c.Assert(err, IsNil) 155 c.Assert(info, DeepEquals, bson.M{"any": "thing"}) 156 157 err = file.Close() 158 c.Assert(err, IsNil) 159 160 c.Assert(file.MD5(), Equals, "1e50210a0202497fb79bc38b6ade6c34") 161 162 ud := file.UploadDate() 163 now := time.Now() 164 c.Assert(ud.Before(now), Equals, true) 165 c.Assert(ud.After(now.Add(-3*time.Second)), Equals, true) 166 167 result := M{} 168 err = db.C("fs.files").Find(nil).One(result) 169 c.Assert(err, IsNil) 170 171 result["uploadDate"] = "<timestamp>" 172 173 expected := M{ 174 "_id": "myid", 175 "length": 9, 176 "chunkSize": 255 * 1024, 177 "uploadDate": "<timestamp>", 178 "md5": "1e50210a0202497fb79bc38b6ade6c34", 179 "filename": "myfile2.txt", 180 "contentType": "text/plain", 181 "metadata": M{"any": "thing"}, 182 } 183 c.Assert(result, DeepEquals, expected) 184 } 185 186 func (s *S) TestGridFSSetUploadDate(c *C) { 187 session, err := mgo.Dial("localhost:40011") 188 c.Assert(err, IsNil) 189 defer session.Close() 190 191 db := session.DB("mydb") 192 193 gfs := db.GridFS("fs") 194 file, err := gfs.Create("") 195 c.Assert(err, IsNil) 196 197 t := time.Date(2014, 1, 1, 1, 1, 1, 0, time.Local) 198 file.SetUploadDate(t) 199 200 err = file.Close() 201 c.Assert(err, IsNil) 202 203 // Check the file information. 204 result := M{} 205 err = db.C("fs.files").Find(nil).One(result) 206 c.Assert(err, IsNil) 207 208 ud := result["uploadDate"].(time.Time) 209 if !ud.Equal(t) { 210 c.Fatalf("want upload date %s, got %s", t, ud) 211 } 212 } 213 214 func (s *S) TestGridFSCreateWithChunking(c *C) { 215 session, err := mgo.Dial("localhost:40011") 216 c.Assert(err, IsNil) 217 defer session.Close() 218 219 db := session.DB("mydb") 220 221 gfs := db.GridFS("fs") 222 223 file, err := gfs.Create("") 224 c.Assert(err, IsNil) 225 226 file.SetChunkSize(5) 227 228 // Smaller than the chunk size. 229 n, err := file.Write([]byte("abc")) 230 c.Assert(err, IsNil) 231 c.Assert(n, Equals, 3) 232 233 // Boundary in the middle. 234 n, err = file.Write([]byte("defg")) 235 c.Assert(err, IsNil) 236 c.Assert(n, Equals, 4) 237 238 // Boundary at the end. 239 n, err = file.Write([]byte("hij")) 240 c.Assert(err, IsNil) 241 c.Assert(n, Equals, 3) 242 243 // Larger than the chunk size, with 3 chunks. 244 n, err = file.Write([]byte("klmnopqrstuv")) 245 c.Assert(err, IsNil) 246 c.Assert(n, Equals, 12) 247 248 err = file.Close() 249 c.Assert(err, IsNil) 250 251 // Check the file information. 252 result := M{} 253 err = db.C("fs.files").Find(nil).One(result) 254 c.Assert(err, IsNil) 255 256 fileId, _ := result["_id"].(bson.ObjectId) 257 c.Assert(fileId.Valid(), Equals, true) 258 result["_id"] = "<id>" 259 result["uploadDate"] = "<timestamp>" 260 261 expected := M{ 262 "_id": "<id>", 263 "length": 22, 264 "chunkSize": 5, 265 "uploadDate": "<timestamp>", 266 "md5": "44a66044834cbe55040089cabfc102d5", 267 } 268 c.Assert(result, DeepEquals, expected) 269 270 // Check the chunks. 271 iter := db.C("fs.chunks").Find(nil).Sort("n").Iter() 272 dataChunks := []string{"abcde", "fghij", "klmno", "pqrst", "uv"} 273 for i := 0; ; i++ { 274 result = M{} 275 if !iter.Next(result) { 276 if i != 5 { 277 c.Fatalf("Expected 5 chunks, got %d", i) 278 } 279 break 280 } 281 c.Assert(iter.Close(), IsNil) 282 283 result["_id"] = "<id>" 284 285 expected = M{ 286 "_id": "<id>", 287 "files_id": fileId, 288 "n": i, 289 "data": []byte(dataChunks[i]), 290 } 291 c.Assert(result, DeepEquals, expected) 292 } 293 } 294 295 func (s *S) TestGridFSAbort(c *C) { 296 session, err := mgo.Dial("localhost:40011") 297 c.Assert(err, IsNil) 298 defer session.Close() 299 300 db := session.DB("mydb") 301 302 gfs := db.GridFS("fs") 303 file, err := gfs.Create("") 304 c.Assert(err, IsNil) 305 306 file.SetChunkSize(5) 307 308 n, err := file.Write([]byte("some data")) 309 c.Assert(err, IsNil) 310 c.Assert(n, Equals, 9) 311 312 var count int 313 for i := 0; i < 10; i++ { 314 count, err = db.C("fs.chunks").Count() 315 if count > 0 || err != nil { 316 break 317 } 318 } 319 c.Assert(err, IsNil) 320 c.Assert(count, Equals, 1) 321 322 file.Abort() 323 324 err = file.Close() 325 c.Assert(err, ErrorMatches, "write aborted") 326 327 count, err = db.C("fs.chunks").Count() 328 c.Assert(err, IsNil) 329 c.Assert(count, Equals, 0) 330 } 331 332 func (s *S) TestGridFSCloseConflict(c *C) { 333 session, err := mgo.Dial("localhost:40011") 334 c.Assert(err, IsNil) 335 defer session.Close() 336 337 db := session.DB("mydb") 338 339 db.C("fs.files").EnsureIndex(mgo.Index{Key: []string{"filename"}, Unique: true}) 340 341 // For a closing-time conflict 342 err = db.C("fs.files").Insert(M{"filename": "foo.txt"}) 343 c.Assert(err, IsNil) 344 345 gfs := db.GridFS("fs") 346 file, err := gfs.Create("foo.txt") 347 c.Assert(err, IsNil) 348 349 _, err = file.Write([]byte("some data")) 350 c.Assert(err, IsNil) 351 352 err = file.Close() 353 c.Assert(mgo.IsDup(err), Equals, true) 354 355 count, err := db.C("fs.chunks").Count() 356 c.Assert(err, IsNil) 357 c.Assert(count, Equals, 0) 358 } 359 360 func (s *S) TestGridFSOpenNotFound(c *C) { 361 session, err := mgo.Dial("localhost:40011") 362 c.Assert(err, IsNil) 363 defer session.Close() 364 365 db := session.DB("mydb") 366 367 gfs := db.GridFS("fs") 368 file, err := gfs.OpenId("non-existent") 369 c.Assert(err == mgo.ErrNotFound, Equals, true) 370 c.Assert(file, IsNil) 371 372 file, err = gfs.Open("non-existent") 373 c.Assert(err == mgo.ErrNotFound, Equals, true) 374 c.Assert(file, IsNil) 375 } 376 377 func (s *S) TestGridFSReadAll(c *C) { 378 session, err := mgo.Dial("localhost:40011") 379 c.Assert(err, IsNil) 380 defer session.Close() 381 382 db := session.DB("mydb") 383 384 gfs := db.GridFS("fs") 385 file, err := gfs.Create("") 386 c.Assert(err, IsNil) 387 id := file.Id() 388 389 file.SetChunkSize(5) 390 391 n, err := file.Write([]byte("abcdefghijklmnopqrstuv")) 392 c.Assert(err, IsNil) 393 c.Assert(n, Equals, 22) 394 395 err = file.Close() 396 c.Assert(err, IsNil) 397 398 file, err = gfs.OpenId(id) 399 c.Assert(err, IsNil) 400 401 b := make([]byte, 30) 402 n, err = file.Read(b) 403 c.Assert(n, Equals, 22) 404 c.Assert(err, IsNil) 405 406 n, err = file.Read(b) 407 c.Assert(n, Equals, 0) 408 c.Assert(err == io.EOF, Equals, true) 409 410 err = file.Close() 411 c.Assert(err, IsNil) 412 } 413 414 func (s *S) TestGridFSReadChunking(c *C) { 415 session, err := mgo.Dial("localhost:40011") 416 c.Assert(err, IsNil) 417 defer session.Close() 418 419 db := session.DB("mydb") 420 421 gfs := db.GridFS("fs") 422 423 file, err := gfs.Create("") 424 c.Assert(err, IsNil) 425 426 id := file.Id() 427 428 file.SetChunkSize(5) 429 430 n, err := file.Write([]byte("abcdefghijklmnopqrstuv")) 431 c.Assert(err, IsNil) 432 c.Assert(n, Equals, 22) 433 434 err = file.Close() 435 c.Assert(err, IsNil) 436 437 file, err = gfs.OpenId(id) 438 c.Assert(err, IsNil) 439 440 b := make([]byte, 30) 441 442 // Smaller than the chunk size. 443 n, err = file.Read(b[:3]) 444 c.Assert(err, IsNil) 445 c.Assert(n, Equals, 3) 446 c.Assert(b[:3], DeepEquals, []byte("abc")) 447 448 // Boundary in the middle. 449 n, err = file.Read(b[:4]) 450 c.Assert(err, IsNil) 451 c.Assert(n, Equals, 4) 452 c.Assert(b[:4], DeepEquals, []byte("defg")) 453 454 // Boundary at the end. 455 n, err = file.Read(b[:3]) 456 c.Assert(err, IsNil) 457 c.Assert(n, Equals, 3) 458 c.Assert(b[:3], DeepEquals, []byte("hij")) 459 460 // Larger than the chunk size, with 3 chunks. 461 n, err = file.Read(b) 462 c.Assert(err, IsNil) 463 c.Assert(n, Equals, 12) 464 c.Assert(b[:12], DeepEquals, []byte("klmnopqrstuv")) 465 466 n, err = file.Read(b) 467 c.Assert(n, Equals, 0) 468 c.Assert(err == io.EOF, Equals, true) 469 470 err = file.Close() 471 c.Assert(err, IsNil) 472 } 473 474 func (s *S) TestGridFSOpen(c *C) { 475 session, err := mgo.Dial("localhost:40011") 476 c.Assert(err, IsNil) 477 defer session.Close() 478 479 db := session.DB("mydb") 480 481 gfs := db.GridFS("fs") 482 483 file, err := gfs.Create("myfile.txt") 484 c.Assert(err, IsNil) 485 file.Write([]byte{'1'}) 486 file.Close() 487 488 file, err = gfs.Create("myfile.txt") 489 c.Assert(err, IsNil) 490 file.Write([]byte{'2'}) 491 file.Close() 492 493 file, err = gfs.Open("myfile.txt") 494 c.Assert(err, IsNil) 495 defer file.Close() 496 497 var b [1]byte 498 499 _, err = file.Read(b[:]) 500 c.Assert(err, IsNil) 501 c.Assert(string(b[:]), Equals, "2") 502 } 503 504 func (s *S) TestGridFSSeek(c *C) { 505 session, err := mgo.Dial("localhost:40011") 506 c.Assert(err, IsNil) 507 defer session.Close() 508 509 db := session.DB("mydb") 510 511 gfs := db.GridFS("fs") 512 file, err := gfs.Create("") 513 c.Assert(err, IsNil) 514 id := file.Id() 515 516 file.SetChunkSize(5) 517 518 n, err := file.Write([]byte("abcdefghijklmnopqrstuv")) 519 c.Assert(err, IsNil) 520 c.Assert(n, Equals, 22) 521 522 err = file.Close() 523 c.Assert(err, IsNil) 524 525 b := make([]byte, 5) 526 527 file, err = gfs.OpenId(id) 528 c.Assert(err, IsNil) 529 530 o, err := file.Seek(3, os.SEEK_SET) 531 c.Assert(err, IsNil) 532 c.Assert(o, Equals, int64(3)) 533 _, err = file.Read(b) 534 c.Assert(err, IsNil) 535 c.Assert(b, DeepEquals, []byte("defgh")) 536 537 o, err = file.Seek(5, os.SEEK_CUR) 538 c.Assert(err, IsNil) 539 c.Assert(o, Equals, int64(13)) 540 _, err = file.Read(b) 541 c.Assert(err, IsNil) 542 c.Assert(b, DeepEquals, []byte("nopqr")) 543 544 o, err = file.Seek(0, os.SEEK_END) 545 c.Assert(err, IsNil) 546 c.Assert(o, Equals, int64(22)) 547 n, err = file.Read(b) 548 c.Assert(err, Equals, io.EOF) 549 c.Assert(n, Equals, 0) 550 551 o, err = file.Seek(-10, os.SEEK_END) 552 c.Assert(err, IsNil) 553 c.Assert(o, Equals, int64(12)) 554 _, err = file.Read(b) 555 c.Assert(err, IsNil) 556 c.Assert(b, DeepEquals, []byte("mnopq")) 557 558 o, err = file.Seek(8, os.SEEK_SET) 559 c.Assert(err, IsNil) 560 c.Assert(o, Equals, int64(8)) 561 _, err = file.Read(b) 562 c.Assert(err, IsNil) 563 c.Assert(b, DeepEquals, []byte("ijklm")) 564 565 // Trivial seek forward within same chunk. Already 566 // got the data, shouldn't touch the database. 567 sent := mgo.GetStats().SentOps 568 o, err = file.Seek(1, os.SEEK_CUR) 569 c.Assert(err, IsNil) 570 c.Assert(o, Equals, int64(14)) 571 c.Assert(mgo.GetStats().SentOps, Equals, sent) 572 _, err = file.Read(b) 573 c.Assert(err, IsNil) 574 c.Assert(b, DeepEquals, []byte("opqrs")) 575 576 // Try seeking past end of file. 577 file.Seek(3, os.SEEK_SET) 578 o, err = file.Seek(23, os.SEEK_SET) 579 c.Assert(err, ErrorMatches, "seek past end of file") 580 c.Assert(o, Equals, int64(3)) 581 } 582 583 func (s *S) TestGridFSRemoveId(c *C) { 584 session, err := mgo.Dial("localhost:40011") 585 c.Assert(err, IsNil) 586 defer session.Close() 587 588 db := session.DB("mydb") 589 590 gfs := db.GridFS("fs") 591 592 file, err := gfs.Create("myfile.txt") 593 c.Assert(err, IsNil) 594 file.Write([]byte{'1'}) 595 file.Close() 596 597 file, err = gfs.Create("myfile.txt") 598 c.Assert(err, IsNil) 599 file.Write([]byte{'2'}) 600 id := file.Id() 601 file.Close() 602 603 err = gfs.RemoveId(id) 604 c.Assert(err, IsNil) 605 606 file, err = gfs.Open("myfile.txt") 607 c.Assert(err, IsNil) 608 defer file.Close() 609 610 var b [1]byte 611 612 _, err = file.Read(b[:]) 613 c.Assert(err, IsNil) 614 c.Assert(string(b[:]), Equals, "1") 615 616 n, err := db.C("fs.chunks").Find(M{"files_id": id}).Count() 617 c.Assert(err, IsNil) 618 c.Assert(n, Equals, 0) 619 } 620 621 func (s *S) TestGridFSRemove(c *C) { 622 session, err := mgo.Dial("localhost:40011") 623 c.Assert(err, IsNil) 624 defer session.Close() 625 626 db := session.DB("mydb") 627 628 gfs := db.GridFS("fs") 629 630 file, err := gfs.Create("myfile.txt") 631 c.Assert(err, IsNil) 632 file.Write([]byte{'1'}) 633 file.Close() 634 635 file, err = gfs.Create("myfile.txt") 636 c.Assert(err, IsNil) 637 file.Write([]byte{'2'}) 638 file.Close() 639 640 err = gfs.Remove("myfile.txt") 641 c.Assert(err, IsNil) 642 643 _, err = gfs.Open("myfile.txt") 644 c.Assert(err == mgo.ErrNotFound, Equals, true) 645 646 n, err := db.C("fs.chunks").Find(nil).Count() 647 c.Assert(err, IsNil) 648 c.Assert(n, Equals, 0) 649 } 650 651 func (s *S) TestGridFSOpenNext(c *C) { 652 session, err := mgo.Dial("localhost:40011") 653 c.Assert(err, IsNil) 654 defer session.Close() 655 656 db := session.DB("mydb") 657 658 gfs := db.GridFS("fs") 659 660 file, err := gfs.Create("myfile1.txt") 661 c.Assert(err, IsNil) 662 file.Write([]byte{'1'}) 663 file.Close() 664 665 file, err = gfs.Create("myfile2.txt") 666 c.Assert(err, IsNil) 667 file.Write([]byte{'2'}) 668 file.Close() 669 670 var f *mgo.GridFile 671 var b [1]byte 672 673 iter := gfs.Find(nil).Sort("-filename").Iter() 674 675 ok := gfs.OpenNext(iter, &f) 676 c.Assert(ok, Equals, true) 677 c.Check(f.Name(), Equals, "myfile2.txt") 678 679 _, err = f.Read(b[:]) 680 c.Assert(err, IsNil) 681 c.Assert(string(b[:]), Equals, "2") 682 683 ok = gfs.OpenNext(iter, &f) 684 c.Assert(ok, Equals, true) 685 c.Check(f.Name(), Equals, "myfile1.txt") 686 687 _, err = f.Read(b[:]) 688 c.Assert(err, IsNil) 689 c.Assert(string(b[:]), Equals, "1") 690 691 ok = gfs.OpenNext(iter, &f) 692 c.Assert(ok, Equals, false) 693 c.Assert(iter.Close(), IsNil) 694 c.Assert(f, IsNil) 695 696 // Do it again with a more restrictive query to make sure 697 // it's actually taken into account. 698 iter = gfs.Find(bson.M{"filename": "myfile1.txt"}).Iter() 699 700 ok = gfs.OpenNext(iter, &f) 701 c.Assert(ok, Equals, true) 702 c.Check(f.Name(), Equals, "myfile1.txt") 703 704 ok = gfs.OpenNext(iter, &f) 705 c.Assert(ok, Equals, false) 706 c.Assert(iter.Close(), IsNil) 707 c.Assert(f, IsNil) 708 }