github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/session_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  	"flag"
    31  	"fmt"
    32  	"math"
    33  	"os"
    34  	"runtime"
    35  	"sort"
    36  	"strconv"
    37  	"strings"
    38  	"time"
    39  
    40  	. "gopkg.in/check.v1"
    41  	"gopkg.in/mgo.v2"
    42  	"gopkg.in/mgo.v2/bson"
    43  )
    44  
    45  func (s *S) TestRunString(c *C) {
    46  	session, err := mgo.Dial("localhost:40001")
    47  	c.Assert(err, IsNil)
    48  	defer session.Close()
    49  
    50  	result := struct{ Ok int }{}
    51  	err = session.Run("ping", &result)
    52  	c.Assert(err, IsNil)
    53  	c.Assert(result.Ok, Equals, 1)
    54  }
    55  
    56  func (s *S) TestRunValue(c *C) {
    57  	session, err := mgo.Dial("localhost:40001")
    58  	c.Assert(err, IsNil)
    59  	defer session.Close()
    60  
    61  	result := struct{ Ok int }{}
    62  	err = session.Run(M{"ping": 1}, &result)
    63  	c.Assert(err, IsNil)
    64  	c.Assert(result.Ok, Equals, 1)
    65  }
    66  
    67  func (s *S) TestPing(c *C) {
    68  	session, err := mgo.Dial("localhost:40001")
    69  	c.Assert(err, IsNil)
    70  	defer session.Close()
    71  
    72  	// Just ensure the nonce has been received.
    73  	result := struct{}{}
    74  	err = session.Run("ping", &result)
    75  
    76  	mgo.ResetStats()
    77  
    78  	err = session.Ping()
    79  	c.Assert(err, IsNil)
    80  
    81  	// Pretty boring.
    82  	stats := mgo.GetStats()
    83  	c.Assert(stats.SentOps, Equals, 1)
    84  	c.Assert(stats.ReceivedOps, Equals, 1)
    85  }
    86  
    87  func (s *S) TestDialIPAddress(c *C) {
    88  	session, err := mgo.Dial("127.0.0.1:40001")
    89  	c.Assert(err, IsNil)
    90  	defer session.Close()
    91  
    92  	if os.Getenv("NOIPV6") != "1" {
    93  		session, err = mgo.Dial("[::1%]:40001")
    94  		c.Assert(err, IsNil)
    95  		defer session.Close()
    96  	}
    97  }
    98  
    99  func (s *S) TestURLSingle(c *C) {
   100  	session, err := mgo.Dial("mongodb://localhost:40001/")
   101  	c.Assert(err, IsNil)
   102  	defer session.Close()
   103  
   104  	result := struct{ Ok int }{}
   105  	err = session.Run("ping", &result)
   106  	c.Assert(err, IsNil)
   107  	c.Assert(result.Ok, Equals, 1)
   108  }
   109  
   110  func (s *S) TestURLMany(c *C) {
   111  	session, err := mgo.Dial("mongodb://localhost:40011,localhost:40012/")
   112  	c.Assert(err, IsNil)
   113  	defer session.Close()
   114  
   115  	result := struct{ Ok int }{}
   116  	err = session.Run("ping", &result)
   117  	c.Assert(err, IsNil)
   118  	c.Assert(result.Ok, Equals, 1)
   119  }
   120  
   121  func (s *S) TestURLParsing(c *C) {
   122  	urls := []string{
   123  		"localhost:40001?foo=1&bar=2",
   124  		"localhost:40001?foo=1;bar=2",
   125  	}
   126  	for _, url := range urls {
   127  		session, err := mgo.Dial(url)
   128  		if session != nil {
   129  			session.Close()
   130  		}
   131  		c.Assert(err, ErrorMatches, "unsupported connection URL option: (foo=1|bar=2)")
   132  	}
   133  }
   134  
   135  func (s *S) TestInsertFindOne(c *C) {
   136  	session, err := mgo.Dial("localhost:40001")
   137  	c.Assert(err, IsNil)
   138  	defer session.Close()
   139  
   140  	coll := session.DB("mydb").C("mycoll")
   141  	err = coll.Insert(M{"a": 1, "b": 2})
   142  	c.Assert(err, IsNil)
   143  	err = coll.Insert(M{"a": 1, "b": 3})
   144  	c.Assert(err, IsNil)
   145  
   146  	result := struct{ A, B int }{}
   147  
   148  	err = coll.Find(M{"a": 1}).Sort("b").One(&result)
   149  	c.Assert(err, IsNil)
   150  	c.Assert(result.A, Equals, 1)
   151  	c.Assert(result.B, Equals, 2)
   152  
   153  	err = coll.Find(M{"a": 1}).Sort("-b").One(&result)
   154  	c.Assert(err, IsNil)
   155  	c.Assert(result.A, Equals, 1)
   156  	c.Assert(result.B, Equals, 3)
   157  }
   158  
   159  func (s *S) TestInsertFindOneNil(c *C) {
   160  	session, err := mgo.Dial("localhost:40002")
   161  	c.Assert(err, IsNil)
   162  	defer session.Close()
   163  
   164  	coll := session.DB("mydb").C("mycoll")
   165  	err = coll.Find(nil).One(nil)
   166  	c.Assert(err, ErrorMatches, "unauthorized.*|not authorized.*")
   167  }
   168  
   169  func (s *S) TestInsertFindOneMap(c *C) {
   170  	session, err := mgo.Dial("localhost:40001")
   171  	c.Assert(err, IsNil)
   172  	defer session.Close()
   173  
   174  	coll := session.DB("mydb").C("mycoll")
   175  	err = coll.Insert(M{"a": 1, "b": 2})
   176  	c.Assert(err, IsNil)
   177  	result := make(M)
   178  	err = coll.Find(M{"a": 1}).One(result)
   179  	c.Assert(err, IsNil)
   180  	c.Assert(result["a"], Equals, 1)
   181  	c.Assert(result["b"], Equals, 2)
   182  }
   183  
   184  func (s *S) TestInsertFindAll(c *C) {
   185  	session, err := mgo.Dial("localhost:40001")
   186  	c.Assert(err, IsNil)
   187  	defer session.Close()
   188  
   189  	coll := session.DB("mydb").C("mycoll")
   190  	err = coll.Insert(M{"a": 1, "b": 2})
   191  	c.Assert(err, IsNil)
   192  	err = coll.Insert(M{"a": 3, "b": 4})
   193  	c.Assert(err, IsNil)
   194  
   195  	type R struct{ A, B int }
   196  	var result []R
   197  
   198  	assertResult := func() {
   199  		c.Assert(len(result), Equals, 2)
   200  		c.Assert(result[0].A, Equals, 1)
   201  		c.Assert(result[0].B, Equals, 2)
   202  		c.Assert(result[1].A, Equals, 3)
   203  		c.Assert(result[1].B, Equals, 4)
   204  	}
   205  
   206  	// nil slice
   207  	err = coll.Find(nil).Sort("a").All(&result)
   208  	c.Assert(err, IsNil)
   209  	assertResult()
   210  
   211  	// Previously allocated slice
   212  	allocd := make([]R, 5)
   213  	result = allocd
   214  	err = coll.Find(nil).Sort("a").All(&result)
   215  	c.Assert(err, IsNil)
   216  	assertResult()
   217  
   218  	// Ensure result is backed by the originally allocated array
   219  	c.Assert(&result[0], Equals, &allocd[0])
   220  
   221  	// Non-pointer slice error
   222  	f := func() { coll.Find(nil).All(result) }
   223  	c.Assert(f, Panics, "result argument must be a slice address")
   224  
   225  	// Non-slice error
   226  	f = func() { coll.Find(nil).All(new(int)) }
   227  	c.Assert(f, Panics, "result argument must be a slice address")
   228  }
   229  
   230  func (s *S) TestFindRef(c *C) {
   231  	session, err := mgo.Dial("localhost:40001")
   232  	c.Assert(err, IsNil)
   233  	defer session.Close()
   234  
   235  	db1 := session.DB("db1")
   236  	db1col1 := db1.C("col1")
   237  
   238  	db2 := session.DB("db2")
   239  	db2col1 := db2.C("col1")
   240  
   241  	err = db1col1.Insert(M{"_id": 1, "n": 1})
   242  	c.Assert(err, IsNil)
   243  	err = db1col1.Insert(M{"_id": 2, "n": 2})
   244  	c.Assert(err, IsNil)
   245  	err = db2col1.Insert(M{"_id": 2, "n": 3})
   246  	c.Assert(err, IsNil)
   247  
   248  	result := struct{ N int }{}
   249  
   250  	ref1 := &mgo.DBRef{Collection: "col1", Id: 1}
   251  	ref2 := &mgo.DBRef{Collection: "col1", Id: 2, Database: "db2"}
   252  
   253  	err = db1.FindRef(ref1).One(&result)
   254  	c.Assert(err, IsNil)
   255  	c.Assert(result.N, Equals, 1)
   256  
   257  	err = db1.FindRef(ref2).One(&result)
   258  	c.Assert(err, IsNil)
   259  	c.Assert(result.N, Equals, 3)
   260  
   261  	err = db2.FindRef(ref1).One(&result)
   262  	c.Assert(err, Equals, mgo.ErrNotFound)
   263  
   264  	err = db2.FindRef(ref2).One(&result)
   265  	c.Assert(err, IsNil)
   266  	c.Assert(result.N, Equals, 3)
   267  
   268  	err = session.FindRef(ref2).One(&result)
   269  	c.Assert(err, IsNil)
   270  	c.Assert(result.N, Equals, 3)
   271  
   272  	f := func() { session.FindRef(ref1).One(&result) }
   273  	c.Assert(f, PanicMatches, "Can't resolve database for &mgo.DBRef{Collection:\"col1\", Id:1, Database:\"\"}")
   274  }
   275  
   276  func (s *S) TestDatabaseAndCollectionNames(c *C) {
   277  	session, err := mgo.Dial("localhost:40001")
   278  	c.Assert(err, IsNil)
   279  	defer session.Close()
   280  
   281  	db1 := session.DB("db1")
   282  	db1col1 := db1.C("col1")
   283  	db1col2 := db1.C("col2")
   284  
   285  	db2 := session.DB("db2")
   286  	db2col1 := db2.C("col3")
   287  
   288  	err = db1col1.Insert(M{"_id": 1})
   289  	c.Assert(err, IsNil)
   290  	err = db1col2.Insert(M{"_id": 1})
   291  	c.Assert(err, IsNil)
   292  	err = db2col1.Insert(M{"_id": 1})
   293  	c.Assert(err, IsNil)
   294  
   295  	names, err := session.DatabaseNames()
   296  	c.Assert(err, IsNil)
   297  	c.Assert(filterDBs(names), DeepEquals, []string{"db1", "db2"})
   298  
   299  	// Try to exercise cursor logic. 2.8.0-rc3 still ignores this.
   300  	session.SetBatch(2)
   301  
   302  	names, err = db1.CollectionNames()
   303  	c.Assert(err, IsNil)
   304  	c.Assert(names, DeepEquals, []string{"col1", "col2", "system.indexes"})
   305  
   306  	names, err = db2.CollectionNames()
   307  	c.Assert(err, IsNil)
   308  	c.Assert(names, DeepEquals, []string{"col3", "system.indexes"})
   309  }
   310  
   311  func (s *S) TestSelect(c *C) {
   312  	session, err := mgo.Dial("localhost:40001")
   313  	c.Assert(err, IsNil)
   314  	defer session.Close()
   315  
   316  	coll := session.DB("mydb").C("mycoll")
   317  	coll.Insert(M{"a": 1, "b": 2})
   318  
   319  	result := struct{ A, B int }{}
   320  
   321  	err = coll.Find(M{"a": 1}).Select(M{"b": 1}).One(&result)
   322  	c.Assert(err, IsNil)
   323  	c.Assert(result.A, Equals, 0)
   324  	c.Assert(result.B, Equals, 2)
   325  }
   326  
   327  func (s *S) TestInlineMap(c *C) {
   328  	session, err := mgo.Dial("localhost:40001")
   329  	c.Assert(err, IsNil)
   330  	defer session.Close()
   331  
   332  	coll := session.DB("mydb").C("mycoll")
   333  
   334  	var v, result1 struct {
   335  		A int
   336  		M map[string]int ",inline"
   337  	}
   338  
   339  	v.A = 1
   340  	v.M = map[string]int{"b": 2}
   341  	err = coll.Insert(v)
   342  	c.Assert(err, IsNil)
   343  
   344  	noId := M{"_id": 0}
   345  
   346  	err = coll.Find(nil).Select(noId).One(&result1)
   347  	c.Assert(err, IsNil)
   348  	c.Assert(result1.A, Equals, 1)
   349  	c.Assert(result1.M, DeepEquals, map[string]int{"b": 2})
   350  
   351  	var result2 M
   352  	err = coll.Find(nil).Select(noId).One(&result2)
   353  	c.Assert(err, IsNil)
   354  	c.Assert(result2, DeepEquals, M{"a": 1, "b": 2})
   355  
   356  }
   357  
   358  func (s *S) TestUpdate(c *C) {
   359  	session, err := mgo.Dial("localhost:40001")
   360  	c.Assert(err, IsNil)
   361  	defer session.Close()
   362  
   363  	coll := session.DB("mydb").C("mycoll")
   364  
   365  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   366  	for _, n := range ns {
   367  		err := coll.Insert(M{"k": n, "n": n})
   368  		c.Assert(err, IsNil)
   369  	}
   370  
   371  	// No changes is a no-op and shouldn't return an error.
   372  	err = coll.Update(M{"k": 42}, M{"$set": M{"n": 42}})
   373  	c.Assert(err, IsNil)
   374  
   375  	err = coll.Update(M{"k": 42}, M{"$inc": M{"n": 1}})
   376  	c.Assert(err, IsNil)
   377  
   378  	result := make(M)
   379  	err = coll.Find(M{"k": 42}).One(result)
   380  	c.Assert(err, IsNil)
   381  	c.Assert(result["n"], Equals, 43)
   382  
   383  	err = coll.Update(M{"k": 47}, M{"k": 47, "n": 47})
   384  	c.Assert(err, Equals, mgo.ErrNotFound)
   385  
   386  	err = coll.Find(M{"k": 47}).One(result)
   387  	c.Assert(err, Equals, mgo.ErrNotFound)
   388  }
   389  
   390  func (s *S) TestUpdateId(c *C) {
   391  	session, err := mgo.Dial("localhost:40001")
   392  	c.Assert(err, IsNil)
   393  	defer session.Close()
   394  
   395  	coll := session.DB("mydb").C("mycoll")
   396  
   397  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   398  	for _, n := range ns {
   399  		err := coll.Insert(M{"_id": n, "n": n})
   400  		c.Assert(err, IsNil)
   401  	}
   402  
   403  	err = coll.UpdateId(42, M{"$inc": M{"n": 1}})
   404  	c.Assert(err, IsNil)
   405  
   406  	result := make(M)
   407  	err = coll.FindId(42).One(result)
   408  	c.Assert(err, IsNil)
   409  	c.Assert(result["n"], Equals, 43)
   410  
   411  	err = coll.UpdateId(47, M{"k": 47, "n": 47})
   412  	c.Assert(err, Equals, mgo.ErrNotFound)
   413  
   414  	err = coll.FindId(47).One(result)
   415  	c.Assert(err, Equals, mgo.ErrNotFound)
   416  }
   417  
   418  func (s *S) TestUpdateNil(c *C) {
   419  	session, err := mgo.Dial("localhost:40001")
   420  	c.Assert(err, IsNil)
   421  	defer session.Close()
   422  
   423  	coll := session.DB("mydb").C("mycoll")
   424  
   425  	err = coll.Insert(M{"k": 42, "n": 42})
   426  	c.Assert(err, IsNil)
   427  	err = coll.Update(nil, M{"$inc": M{"n": 1}})
   428  	c.Assert(err, IsNil)
   429  
   430  	result := make(M)
   431  	err = coll.Find(M{"k": 42}).One(result)
   432  	c.Assert(err, IsNil)
   433  	c.Assert(result["n"], Equals, 43)
   434  
   435  	err = coll.Insert(M{"k": 45, "n": 45})
   436  	c.Assert(err, IsNil)
   437  	_, err = coll.UpdateAll(nil, M{"$inc": M{"n": 1}})
   438  	c.Assert(err, IsNil)
   439  
   440  	err = coll.Find(M{"k": 42}).One(result)
   441  	c.Assert(err, IsNil)
   442  	c.Assert(result["n"], Equals, 44)
   443  	err = coll.Find(M{"k": 45}).One(result)
   444  	c.Assert(err, IsNil)
   445  	c.Assert(result["n"], Equals, 46)
   446  }
   447  
   448  func (s *S) TestUpsert(c *C) {
   449  	session, err := mgo.Dial("localhost:40001")
   450  	c.Assert(err, IsNil)
   451  	defer session.Close()
   452  
   453  	coll := session.DB("mydb").C("mycoll")
   454  
   455  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   456  	for _, n := range ns {
   457  		err := coll.Insert(bson.D{{"k", n}, {"n", n}})
   458  		c.Assert(err, IsNil)
   459  	}
   460  
   461  	info, err := coll.Upsert(M{"k": 42}, bson.D{{"k", 42}, {"n", 24}})
   462  	c.Assert(err, IsNil)
   463  	c.Assert(info.Updated, Equals, 1)
   464  	c.Assert(info.Matched, Equals, 1)
   465  	c.Assert(info.UpsertedId, IsNil)
   466  
   467  	result := M{}
   468  	err = coll.Find(M{"k": 42}).One(result)
   469  	c.Assert(err, IsNil)
   470  	c.Assert(result["n"], Equals, 24)
   471  
   472  	// Match but do not change.
   473  	info, err = coll.Upsert(M{"k": 42}, bson.D{{"k", 42}, {"n", 24}})
   474  	c.Assert(err, IsNil)
   475  	c.Assert(info.Updated, Equals, 1) // On 2.6+ this feels like a server mistake.
   476  	c.Assert(info.Matched, Equals, 1)
   477  	c.Assert(info.UpsertedId, IsNil)
   478  
   479  	// Insert with internally created id.
   480  	info, err = coll.Upsert(M{"k": 47}, M{"k": 47, "n": 47})
   481  	c.Assert(err, IsNil)
   482  	c.Assert(info.Updated, Equals, 0)
   483  	c.Assert(info.Matched, Equals, 0)
   484  	c.Assert(info.UpsertedId, NotNil)
   485  
   486  	err = coll.Find(M{"k": 47}).One(result)
   487  	c.Assert(err, IsNil)
   488  	c.Assert(result["n"], Equals, 47)
   489  
   490  	result = M{}
   491  	err = coll.Find(M{"_id": info.UpsertedId}).One(result)
   492  	c.Assert(err, IsNil)
   493  	c.Assert(result["n"], Equals, 47)
   494  
   495  	// Insert with provided id.
   496  	info, err = coll.Upsert(M{"k": 48}, M{"k": 48, "n": 48, "_id": 48})
   497  	c.Assert(err, IsNil)
   498  	c.Assert(info.Updated, Equals, 0)
   499  	c.Assert(info.Matched, Equals, 0)
   500  	if s.versionAtLeast(2, 6) {
   501  		c.Assert(info.UpsertedId, Equals, 48)
   502  	} else {
   503  		c.Assert(info.UpsertedId, IsNil) // Unfortunate, but that's what Mongo gave us.
   504  	}
   505  
   506  	err = coll.Find(M{"k": 48}).One(result)
   507  	c.Assert(err, IsNil)
   508  	c.Assert(result["n"], Equals, 48)
   509  }
   510  
   511  func (s *S) TestUpsertId(c *C) {
   512  	session, err := mgo.Dial("localhost:40001")
   513  	c.Assert(err, IsNil)
   514  	defer session.Close()
   515  
   516  	coll := session.DB("mydb").C("mycoll")
   517  
   518  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   519  	for _, n := range ns {
   520  		err := coll.Insert(M{"_id": n, "n": n})
   521  		c.Assert(err, IsNil)
   522  	}
   523  
   524  	info, err := coll.UpsertId(42, M{"n": 24})
   525  	c.Assert(err, IsNil)
   526  	c.Assert(info.Updated, Equals, 1)
   527  	c.Assert(info.UpsertedId, IsNil)
   528  
   529  	result := M{}
   530  	err = coll.FindId(42).One(result)
   531  	c.Assert(err, IsNil)
   532  	c.Assert(result["n"], Equals, 24)
   533  
   534  	info, err = coll.UpsertId(47, M{"_id": 47, "n": 47})
   535  	c.Assert(err, IsNil)
   536  	c.Assert(info.Updated, Equals, 0)
   537  	if s.versionAtLeast(2, 6) {
   538  		c.Assert(info.UpsertedId, Equals, 47)
   539  	} else {
   540  		c.Assert(info.UpsertedId, IsNil)
   541  	}
   542  
   543  	err = coll.FindId(47).One(result)
   544  	c.Assert(err, IsNil)
   545  	c.Assert(result["n"], Equals, 47)
   546  }
   547  
   548  func (s *S) TestUpdateAll(c *C) {
   549  	session, err := mgo.Dial("localhost:40001")
   550  	c.Assert(err, IsNil)
   551  	defer session.Close()
   552  
   553  	coll := session.DB("mydb").C("mycoll")
   554  
   555  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   556  	for _, n := range ns {
   557  		err := coll.Insert(M{"k": n, "n": n})
   558  		c.Assert(err, IsNil)
   559  	}
   560  
   561  	info, err := coll.UpdateAll(M{"k": M{"$gt": 42}}, M{"$unset": M{"missing": 1}})
   562  	c.Assert(err, IsNil)
   563  	if s.versionAtLeast(2, 6) {
   564  		c.Assert(info.Updated, Equals, 0)
   565  		c.Assert(info.Matched, Equals, 4)
   566  	} else {
   567  		c.Assert(info.Updated, Equals, 4)
   568  		c.Assert(info.Matched, Equals, 4)
   569  	}
   570  
   571  	info, err = coll.UpdateAll(M{"k": M{"$gt": 42}}, M{"$inc": M{"n": 1}})
   572  	c.Assert(err, IsNil)
   573  	c.Assert(info.Updated, Equals, 4)
   574  	c.Assert(info.Matched, Equals, 4)
   575  
   576  	result := make(M)
   577  	err = coll.Find(M{"k": 42}).One(result)
   578  	c.Assert(err, IsNil)
   579  	c.Assert(result["n"], Equals, 42)
   580  
   581  	err = coll.Find(M{"k": 43}).One(result)
   582  	c.Assert(err, IsNil)
   583  	c.Assert(result["n"], Equals, 44)
   584  
   585  	err = coll.Find(M{"k": 44}).One(result)
   586  	c.Assert(err, IsNil)
   587  	c.Assert(result["n"], Equals, 45)
   588  
   589  	if !s.versionAtLeast(2, 6) {
   590  		// 2.6 made this invalid.
   591  		info, err = coll.UpdateAll(M{"k": 47}, M{"k": 47, "n": 47})
   592  		c.Assert(err, Equals, nil)
   593  		c.Assert(info.Updated, Equals, 0)
   594  	}
   595  }
   596  
   597  func (s *S) TestRemove(c *C) {
   598  	session, err := mgo.Dial("localhost:40001")
   599  	c.Assert(err, IsNil)
   600  	defer session.Close()
   601  
   602  	coll := session.DB("mydb").C("mycoll")
   603  
   604  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   605  	for _, n := range ns {
   606  		err := coll.Insert(M{"n": n})
   607  		c.Assert(err, IsNil)
   608  	}
   609  
   610  	err = coll.Remove(M{"n": M{"$gt": 42}})
   611  	c.Assert(err, IsNil)
   612  
   613  	result := &struct{ N int }{}
   614  	err = coll.Find(M{"n": 42}).One(result)
   615  	c.Assert(err, IsNil)
   616  	c.Assert(result.N, Equals, 42)
   617  
   618  	err = coll.Find(M{"n": 43}).One(result)
   619  	c.Assert(err, Equals, mgo.ErrNotFound)
   620  
   621  	err = coll.Find(M{"n": 44}).One(result)
   622  	c.Assert(err, IsNil)
   623  	c.Assert(result.N, Equals, 44)
   624  }
   625  
   626  func (s *S) TestRemoveId(c *C) {
   627  	session, err := mgo.Dial("localhost:40001")
   628  	c.Assert(err, IsNil)
   629  	defer session.Close()
   630  
   631  	coll := session.DB("mydb").C("mycoll")
   632  
   633  	err = coll.Insert(M{"_id": 40}, M{"_id": 41}, M{"_id": 42})
   634  	c.Assert(err, IsNil)
   635  
   636  	err = coll.RemoveId(41)
   637  	c.Assert(err, IsNil)
   638  
   639  	c.Assert(coll.FindId(40).One(nil), IsNil)
   640  	c.Assert(coll.FindId(41).One(nil), Equals, mgo.ErrNotFound)
   641  	c.Assert(coll.FindId(42).One(nil), IsNil)
   642  }
   643  
   644  func (s *S) TestRemoveUnsafe(c *C) {
   645  	session, err := mgo.Dial("localhost:40001")
   646  	c.Assert(err, IsNil)
   647  	defer session.Close()
   648  
   649  	session.SetSafe(nil)
   650  
   651  	coll := session.DB("mydb").C("mycoll")
   652  
   653  	err = coll.Insert(M{"_id": 40}, M{"_id": 41}, M{"_id": 42})
   654  	c.Assert(err, IsNil)
   655  
   656  	err = coll.RemoveId(41)
   657  	c.Assert(err, IsNil)
   658  
   659  	c.Assert(coll.FindId(40).One(nil), IsNil)
   660  	c.Assert(coll.FindId(41).One(nil), Equals, mgo.ErrNotFound)
   661  	c.Assert(coll.FindId(42).One(nil), IsNil)
   662  }
   663  
   664  func (s *S) TestRemoveAll(c *C) {
   665  	session, err := mgo.Dial("localhost:40001")
   666  	c.Assert(err, IsNil)
   667  	defer session.Close()
   668  
   669  	coll := session.DB("mydb").C("mycoll")
   670  
   671  	ns := []int{40, 41, 42, 43, 44, 45, 46}
   672  	for _, n := range ns {
   673  		err := coll.Insert(M{"n": n})
   674  		c.Assert(err, IsNil)
   675  	}
   676  
   677  	info, err := coll.RemoveAll(M{"n": M{"$gt": 42}})
   678  	c.Assert(err, IsNil)
   679  	c.Assert(info.Updated, Equals, 0)
   680  	c.Assert(info.Removed, Equals, 4)
   681  	c.Assert(info.Matched, Equals, 4)
   682  	c.Assert(info.UpsertedId, IsNil)
   683  
   684  	result := &struct{ N int }{}
   685  	err = coll.Find(M{"n": 42}).One(result)
   686  	c.Assert(err, IsNil)
   687  	c.Assert(result.N, Equals, 42)
   688  
   689  	err = coll.Find(M{"n": 43}).One(result)
   690  	c.Assert(err, Equals, mgo.ErrNotFound)
   691  
   692  	err = coll.Find(M{"n": 44}).One(result)
   693  	c.Assert(err, Equals, mgo.ErrNotFound)
   694  
   695  	info, err = coll.RemoveAll(nil)
   696  	c.Assert(err, IsNil)
   697  	c.Assert(info.Updated, Equals, 0)
   698  	c.Assert(info.Removed, Equals, 3)
   699  	c.Assert(info.Matched, Equals, 3)
   700  	c.Assert(info.UpsertedId, IsNil)
   701  
   702  	n, err := coll.Find(nil).Count()
   703  	c.Assert(err, IsNil)
   704  	c.Assert(n, Equals, 0)
   705  }
   706  
   707  func (s *S) TestDropDatabase(c *C) {
   708  	session, err := mgo.Dial("localhost:40001")
   709  	c.Assert(err, IsNil)
   710  	defer session.Close()
   711  
   712  	db1 := session.DB("db1")
   713  	db1.C("col").Insert(M{"_id": 1})
   714  
   715  	db2 := session.DB("db2")
   716  	db2.C("col").Insert(M{"_id": 1})
   717  
   718  	err = db1.DropDatabase()
   719  	c.Assert(err, IsNil)
   720  
   721  	names, err := session.DatabaseNames()
   722  	c.Assert(err, IsNil)
   723  	c.Assert(filterDBs(names), DeepEquals, []string{"db2"})
   724  
   725  	err = db2.DropDatabase()
   726  	c.Assert(err, IsNil)
   727  
   728  	names, err = session.DatabaseNames()
   729  	c.Assert(err, IsNil)
   730  	c.Assert(filterDBs(names), DeepEquals, []string{})
   731  }
   732  
   733  func filterDBs(dbs []string) []string {
   734  	var i int
   735  	for _, name := range dbs {
   736  		switch name {
   737  		case "admin", "local":
   738  		default:
   739  			dbs[i] = name
   740  			i++
   741  		}
   742  	}
   743  	if len(dbs) == 0 {
   744  		return []string{}
   745  	}
   746  	return dbs[:i]
   747  }
   748  
   749  func (s *S) TestDropCollection(c *C) {
   750  	session, err := mgo.Dial("localhost:40001")
   751  	c.Assert(err, IsNil)
   752  	defer session.Close()
   753  
   754  	db := session.DB("db1")
   755  	db.C("col1").Insert(M{"_id": 1})
   756  	db.C("col2").Insert(M{"_id": 1})
   757  
   758  	err = db.C("col1").DropCollection()
   759  	c.Assert(err, IsNil)
   760  
   761  	names, err := db.CollectionNames()
   762  	c.Assert(err, IsNil)
   763  	c.Assert(names, DeepEquals, []string{"col2", "system.indexes"})
   764  
   765  	err = db.C("col2").DropCollection()
   766  	c.Assert(err, IsNil)
   767  
   768  	names, err = db.CollectionNames()
   769  	c.Assert(err, IsNil)
   770  	c.Assert(names, DeepEquals, []string{"system.indexes"})
   771  }
   772  
   773  func (s *S) TestCreateCollectionCapped(c *C) {
   774  	session, err := mgo.Dial("localhost:40001")
   775  	c.Assert(err, IsNil)
   776  	defer session.Close()
   777  
   778  	coll := session.DB("mydb").C("mycoll")
   779  
   780  	info := &mgo.CollectionInfo{
   781  		Capped:   true,
   782  		MaxBytes: 1024,
   783  		MaxDocs:  3,
   784  	}
   785  	err = coll.Create(info)
   786  	c.Assert(err, IsNil)
   787  
   788  	ns := []int{1, 2, 3, 4, 5}
   789  	for _, n := range ns {
   790  		err := coll.Insert(M{"n": n})
   791  		c.Assert(err, IsNil)
   792  	}
   793  
   794  	n, err := coll.Find(nil).Count()
   795  	c.Assert(err, IsNil)
   796  	c.Assert(n, Equals, 3)
   797  }
   798  
   799  func (s *S) TestCreateCollectionNoIndex(c *C) {
   800  	session, err := mgo.Dial("localhost:40001")
   801  	c.Assert(err, IsNil)
   802  	defer session.Close()
   803  
   804  	coll := session.DB("mydb").C("mycoll")
   805  
   806  	info := &mgo.CollectionInfo{
   807  		DisableIdIndex: true,
   808  	}
   809  	err = coll.Create(info)
   810  	c.Assert(err, IsNil)
   811  
   812  	err = coll.Insert(M{"n": 1})
   813  	c.Assert(err, IsNil)
   814  
   815  	indexes, err := coll.Indexes()
   816  	c.Assert(indexes, HasLen, 0)
   817  }
   818  
   819  func (s *S) TestCreateCollectionForceIndex(c *C) {
   820  	session, err := mgo.Dial("localhost:40001")
   821  	c.Assert(err, IsNil)
   822  	defer session.Close()
   823  
   824  	coll := session.DB("mydb").C("mycoll")
   825  
   826  	info := &mgo.CollectionInfo{
   827  		ForceIdIndex: true,
   828  		Capped:       true,
   829  		MaxBytes:     1024,
   830  	}
   831  	err = coll.Create(info)
   832  	c.Assert(err, IsNil)
   833  
   834  	err = coll.Insert(M{"n": 1})
   835  	c.Assert(err, IsNil)
   836  
   837  	indexes, err := coll.Indexes()
   838  	c.Assert(indexes, HasLen, 1)
   839  }
   840  
   841  func (s *S) TestCreateCollectionValidator(c *C) {
   842  	if !s.versionAtLeast(3, 2) {
   843  		c.Skip("validation depends on MongoDB 3.2+")
   844  	}
   845  	session, err := mgo.Dial("localhost:40001")
   846  	c.Assert(err, IsNil)
   847  	defer session.Close()
   848  
   849  	db := session.DB("mydb")
   850  	coll := db.C("mycoll")
   851  
   852  	// Test Validator.
   853  	info := &mgo.CollectionInfo{
   854  		Validator: M{"b": M{"$exists": true}},
   855  	}
   856  	err = coll.Create(info)
   857  	c.Assert(err, IsNil)
   858  	err = coll.Insert(M{"a": 1})
   859  	c.Assert(err, ErrorMatches, "Document failed validation")
   860  	err = coll.DropCollection()
   861  	c.Assert(err, IsNil)
   862  
   863  	// Test ValidatorAction.
   864  	info = &mgo.CollectionInfo{
   865  		Validator:        M{"b": M{"$exists": true}},
   866  		ValidationAction: "warn",
   867  	}
   868  	err = coll.Create(info)
   869  	c.Assert(err, IsNil)
   870  	err = coll.Insert(M{"a": 1})
   871  	c.Assert(err, IsNil)
   872  	err = coll.DropCollection()
   873  	c.Assert(err, IsNil)
   874  
   875  	// Test ValidationLevel.
   876  	info = &mgo.CollectionInfo{
   877  		Validator:       M{"a": M{"$exists": true}},
   878  		ValidationLevel: "moderate",
   879  	}
   880  	err = coll.Create(info)
   881  	err = coll.Insert(M{"a": 1})
   882  	c.Assert(err, IsNil)
   883  	err = db.Run(bson.D{{"collMod", "mycoll"}, {"validator", M{"b": M{"$exists": true}}}}, nil)
   884  	c.Assert(err, IsNil)
   885  	err = coll.Insert(M{"a": 2})
   886  	c.Assert(err, ErrorMatches, "Document failed validation")
   887  	err = coll.Update(M{"a": 1}, M{"c": 1})
   888  	c.Assert(err, IsNil)
   889  	err = coll.DropCollection()
   890  	c.Assert(err, IsNil)
   891  }
   892  
   893  func (s *S) TestCreateCollectionStorageEngine(c *C) {
   894  	if !s.versionAtLeast(3, 0) {
   895  		c.Skip("storageEngine option depends on MongoDB 3.0+")
   896  	}
   897  	session, err := mgo.Dial("localhost:40001")
   898  	c.Assert(err, IsNil)
   899  	defer session.Close()
   900  
   901  	db := session.DB("mydb")
   902  	coll := db.C("mycoll")
   903  
   904  	info := &mgo.CollectionInfo{
   905  		StorageEngine: M{"test": M{}},
   906  	}
   907  	err = coll.Create(info)
   908  	c.Assert(err, ErrorMatches, "test is not a registered storage engine for this server")
   909  }
   910  
   911  func (s *S) TestIsDupValues(c *C) {
   912  	c.Assert(mgo.IsDup(nil), Equals, false)
   913  	c.Assert(mgo.IsDup(&mgo.LastError{Code: 1}), Equals, false)
   914  	c.Assert(mgo.IsDup(&mgo.QueryError{Code: 1}), Equals, false)
   915  	c.Assert(mgo.IsDup(&mgo.LastError{Code: 11000}), Equals, true)
   916  	c.Assert(mgo.IsDup(&mgo.QueryError{Code: 11000}), Equals, true)
   917  	c.Assert(mgo.IsDup(&mgo.LastError{Code: 11001}), Equals, true)
   918  	c.Assert(mgo.IsDup(&mgo.QueryError{Code: 11001}), Equals, true)
   919  	c.Assert(mgo.IsDup(&mgo.LastError{Code: 12582}), Equals, true)
   920  	c.Assert(mgo.IsDup(&mgo.QueryError{Code: 12582}), Equals, true)
   921  	lerr := &mgo.LastError{Code: 16460, Err: "error inserting 1 documents to shard ... caused by :: E11000 duplicate key error index: ..."}
   922  	c.Assert(mgo.IsDup(lerr), Equals, true)
   923  }
   924  
   925  func (s *S) TestIsDupPrimary(c *C) {
   926  	session, err := mgo.Dial("localhost:40001")
   927  	c.Assert(err, IsNil)
   928  	defer session.Close()
   929  
   930  	coll := session.DB("mydb").C("mycoll")
   931  
   932  	err = coll.Insert(M{"_id": 1})
   933  	c.Assert(err, IsNil)
   934  	err = coll.Insert(M{"_id": 1})
   935  	c.Assert(err, ErrorMatches, ".*duplicate key error.*")
   936  	c.Assert(mgo.IsDup(err), Equals, true)
   937  }
   938  
   939  func (s *S) TestIsDupUnique(c *C) {
   940  	session, err := mgo.Dial("localhost:40001")
   941  	c.Assert(err, IsNil)
   942  	defer session.Close()
   943  
   944  	index := mgo.Index{
   945  		Key:    []string{"a", "b"},
   946  		Unique: true,
   947  	}
   948  
   949  	coll := session.DB("mydb").C("mycoll")
   950  
   951  	err = coll.EnsureIndex(index)
   952  	c.Assert(err, IsNil)
   953  
   954  	err = coll.Insert(M{"a": 1, "b": 1})
   955  	c.Assert(err, IsNil)
   956  	err = coll.Insert(M{"a": 1, "b": 1})
   957  	c.Assert(err, ErrorMatches, ".*duplicate key error.*")
   958  	c.Assert(mgo.IsDup(err), Equals, true)
   959  }
   960  
   961  func (s *S) TestIsDupCapped(c *C) {
   962  	session, err := mgo.Dial("localhost:40001")
   963  	c.Assert(err, IsNil)
   964  	defer session.Close()
   965  
   966  	coll := session.DB("mydb").C("mycoll")
   967  
   968  	info := &mgo.CollectionInfo{
   969  		ForceIdIndex: true,
   970  		Capped:       true,
   971  		MaxBytes:     1024,
   972  	}
   973  	err = coll.Create(info)
   974  	c.Assert(err, IsNil)
   975  
   976  	err = coll.Insert(M{"_id": 1})
   977  	c.Assert(err, IsNil)
   978  	err = coll.Insert(M{"_id": 1})
   979  	// The error was different for capped collections before 2.6.
   980  	c.Assert(err, ErrorMatches, ".*duplicate key.*")
   981  	// The issue is reduced by using IsDup.
   982  	c.Assert(mgo.IsDup(err), Equals, true)
   983  }
   984  
   985  func (s *S) TestIsDupFindAndModify(c *C) {
   986  	session, err := mgo.Dial("localhost:40001")
   987  	c.Assert(err, IsNil)
   988  	defer session.Close()
   989  
   990  	coll := session.DB("mydb").C("mycoll")
   991  
   992  	err = coll.EnsureIndex(mgo.Index{Key: []string{"n"}, Unique: true})
   993  	c.Assert(err, IsNil)
   994  
   995  	err = coll.Insert(M{"n": 1})
   996  	c.Assert(err, IsNil)
   997  	err = coll.Insert(M{"n": 2})
   998  	c.Assert(err, IsNil)
   999  	_, err = coll.Find(M{"n": 1}).Apply(mgo.Change{Update: M{"$inc": M{"n": 1}}}, bson.M{})
  1000  	c.Assert(err, ErrorMatches, ".*duplicate key error.*")
  1001  	c.Assert(mgo.IsDup(err), Equals, true)
  1002  }
  1003  
  1004  func (s *S) TestIsDupRetryUpsert(c *C) {
  1005  	session, err := mgo.Dial("localhost:40001")
  1006  	c.Assert(err, IsNil)
  1007  	defer session.Close()
  1008  
  1009  	coll := session.DB("mydb").C("mycoll")
  1010  
  1011  	err = coll.Insert(bson.M{"_id": 1, "x": 1})
  1012  	c.Assert(err, IsNil)
  1013  
  1014  	_, err = coll.Upsert(bson.M{"_id": 1, "x": 2}, bson.M{"$set": bson.M{"x": 3}})
  1015  	c.Assert(mgo.IsDup(err), Equals, true)
  1016  
  1017  	_, err = coll.Find(bson.M{"_id": 1, "x": 2}).Apply(mgo.Change{
  1018  		Update: bson.M{"$set": bson.M{"x": 3}},
  1019  		Upsert: true,
  1020  	}, nil)
  1021  	c.Assert(mgo.IsDup(err), Equals, true)
  1022  }
  1023  
  1024  func (s *S) TestFindAndModify(c *C) {
  1025  	session, err := mgo.Dial("localhost:40011")
  1026  	c.Assert(err, IsNil)
  1027  	defer session.Close()
  1028  
  1029  	coll := session.DB("mydb").C("mycoll")
  1030  
  1031  	err = coll.Insert(M{"n": 42})
  1032  
  1033  	session.SetMode(mgo.Monotonic, true)
  1034  
  1035  	result := M{}
  1036  	info, err := coll.Find(M{"n": 42}).Apply(mgo.Change{Update: M{"$inc": M{"n": 1}}}, result)
  1037  	c.Assert(err, IsNil)
  1038  	c.Assert(result["n"], Equals, 42)
  1039  	c.Assert(info.Updated, Equals, 1)
  1040  	c.Assert(info.Matched, Equals, 1)
  1041  	c.Assert(info.Removed, Equals, 0)
  1042  	c.Assert(info.UpsertedId, IsNil)
  1043  
  1044  	// A nil result parameter should be acceptable.
  1045  	info, err = coll.Find(M{"n": 43}).Apply(mgo.Change{Update: M{"$unset": M{"missing": 1}}}, nil)
  1046  	c.Assert(err, IsNil)
  1047  	c.Assert(info.Updated, Equals, 1) // On 2.6+ this feels like a server mistake.
  1048  	c.Assert(info.Matched, Equals, 1)
  1049  	c.Assert(info.Removed, Equals, 0)
  1050  	c.Assert(info.UpsertedId, IsNil)
  1051  
  1052  	result = M{}
  1053  	info, err = coll.Find(M{"n": 43}).Apply(mgo.Change{Update: M{"$inc": M{"n": 1}}, ReturnNew: true}, result)
  1054  	c.Assert(err, IsNil)
  1055  	c.Assert(result["n"], Equals, 44)
  1056  	c.Assert(info.Updated, Equals, 1)
  1057  	c.Assert(info.Removed, Equals, 0)
  1058  	c.Assert(info.UpsertedId, IsNil)
  1059  
  1060  	result = M{}
  1061  	info, err = coll.Find(M{"n": 50}).Apply(mgo.Change{Upsert: true, Update: M{"n": 51, "o": 52}}, result)
  1062  	c.Assert(err, IsNil)
  1063  	c.Assert(result["n"], IsNil)
  1064  	c.Assert(info.Updated, Equals, 0)
  1065  	c.Assert(info.Removed, Equals, 0)
  1066  	c.Assert(info.UpsertedId, NotNil)
  1067  
  1068  	result = M{}
  1069  	info, err = coll.Find(nil).Sort("-n").Apply(mgo.Change{Update: M{"$inc": M{"n": 1}}, ReturnNew: true}, result)
  1070  	c.Assert(err, IsNil)
  1071  	c.Assert(result["n"], Equals, 52)
  1072  	c.Assert(info.Updated, Equals, 1)
  1073  	c.Assert(info.Removed, Equals, 0)
  1074  	c.Assert(info.UpsertedId, IsNil)
  1075  
  1076  	result = M{}
  1077  	info, err = coll.Find(M{"n": 52}).Select(M{"o": 1}).Apply(mgo.Change{Remove: true}, result)
  1078  	c.Assert(err, IsNil)
  1079  	c.Assert(result["n"], IsNil)
  1080  	c.Assert(result["o"], Equals, 52)
  1081  	c.Assert(info.Updated, Equals, 0)
  1082  	c.Assert(info.Removed, Equals, 1)
  1083  	c.Assert(info.UpsertedId, IsNil)
  1084  
  1085  	result = M{}
  1086  	info, err = coll.Find(M{"n": 60}).Apply(mgo.Change{Remove: true}, result)
  1087  	c.Assert(err, Equals, mgo.ErrNotFound)
  1088  	c.Assert(len(result), Equals, 0)
  1089  	c.Assert(info, IsNil)
  1090  }
  1091  
  1092  func (s *S) TestFindAndModifyBug997828(c *C) {
  1093  	session, err := mgo.Dial("localhost:40001")
  1094  	c.Assert(err, IsNil)
  1095  	defer session.Close()
  1096  
  1097  	coll := session.DB("mydb").C("mycoll")
  1098  
  1099  	err = coll.Insert(M{"n": "not-a-number"})
  1100  
  1101  	result := make(M)
  1102  	_, err = coll.Find(M{"n": "not-a-number"}).Apply(mgo.Change{Update: M{"$inc": M{"n": 1}}}, result)
  1103  	c.Assert(err, ErrorMatches, `(exception: )?Cannot apply \$inc .*`)
  1104  	if s.versionAtLeast(2, 1) {
  1105  		qerr, _ := err.(*mgo.QueryError)
  1106  		c.Assert(qerr, NotNil, Commentf("err: %#v", err))
  1107  		if s.versionAtLeast(2, 6) {
  1108  			// Oh, the dance of error codes. :-(
  1109  			c.Assert(qerr.Code, Equals, 16837)
  1110  		} else {
  1111  			c.Assert(qerr.Code, Equals, 10140)
  1112  		}
  1113  	} else {
  1114  		lerr, _ := err.(*mgo.LastError)
  1115  		c.Assert(lerr, NotNil, Commentf("err: %#v", err))
  1116  		c.Assert(lerr.Code, Equals, 10140)
  1117  	}
  1118  }
  1119  
  1120  func (s *S) TestFindAndModifyErrmsgDoc(c *C) {
  1121  	session, err := mgo.Dial("localhost:40001")
  1122  	c.Assert(err, IsNil)
  1123  	defer session.Close()
  1124  
  1125  	coll := session.DB("mydb").C("mycoll")
  1126  
  1127  	err = coll.Insert(M{"errmsg": "an error"})
  1128  
  1129  	var result M
  1130  	_, err = coll.Find(M{}).Apply(mgo.Change{Update: M{"$set": M{"n": 1}}}, &result)
  1131  	c.Assert(err, IsNil)
  1132  }
  1133  
  1134  func (s *S) TestCountCollection(c *C) {
  1135  	session, err := mgo.Dial("localhost:40001")
  1136  	c.Assert(err, IsNil)
  1137  	defer session.Close()
  1138  
  1139  	coll := session.DB("mydb").C("mycoll")
  1140  
  1141  	ns := []int{40, 41, 42}
  1142  	for _, n := range ns {
  1143  		err := coll.Insert(M{"n": n})
  1144  		c.Assert(err, IsNil)
  1145  	}
  1146  
  1147  	n, err := coll.Count()
  1148  	c.Assert(err, IsNil)
  1149  	c.Assert(n, Equals, 3)
  1150  }
  1151  
  1152  func (s *S) TestCountQuery(c *C) {
  1153  	session, err := mgo.Dial("localhost:40001")
  1154  	c.Assert(err, IsNil)
  1155  	defer session.Close()
  1156  
  1157  	coll := session.DB("mydb").C("mycoll")
  1158  
  1159  	ns := []int{40, 41, 42}
  1160  	for _, n := range ns {
  1161  		err := coll.Insert(M{"n": n})
  1162  		c.Assert(err, IsNil)
  1163  	}
  1164  
  1165  	n, err := coll.Find(M{"n": M{"$gt": 40}}).Count()
  1166  	c.Assert(err, IsNil)
  1167  	c.Assert(n, Equals, 2)
  1168  }
  1169  
  1170  func (s *S) TestCountQuerySorted(c *C) {
  1171  	session, err := mgo.Dial("localhost:40001")
  1172  	c.Assert(err, IsNil)
  1173  	defer session.Close()
  1174  
  1175  	coll := session.DB("mydb").C("mycoll")
  1176  
  1177  	ns := []int{40, 41, 42}
  1178  	for _, n := range ns {
  1179  		err := coll.Insert(M{"n": n})
  1180  		c.Assert(err, IsNil)
  1181  	}
  1182  
  1183  	n, err := coll.Find(M{"n": M{"$gt": 40}}).Sort("n").Count()
  1184  	c.Assert(err, IsNil)
  1185  	c.Assert(n, Equals, 2)
  1186  }
  1187  
  1188  func (s *S) TestCountSkipLimit(c *C) {
  1189  	session, err := mgo.Dial("localhost:40001")
  1190  	c.Assert(err, IsNil)
  1191  	defer session.Close()
  1192  
  1193  	coll := session.DB("mydb").C("mycoll")
  1194  
  1195  	ns := []int{40, 41, 42, 43, 44}
  1196  	for _, n := range ns {
  1197  		err := coll.Insert(M{"n": n})
  1198  		c.Assert(err, IsNil)
  1199  	}
  1200  
  1201  	n, err := coll.Find(nil).Skip(1).Limit(3).Count()
  1202  	c.Assert(err, IsNil)
  1203  	c.Assert(n, Equals, 3)
  1204  
  1205  	n, err = coll.Find(nil).Skip(1).Limit(5).Count()
  1206  	c.Assert(err, IsNil)
  1207  	c.Assert(n, Equals, 4)
  1208  }
  1209  
  1210  func (s *S) TestQueryExplain(c *C) {
  1211  	session, err := mgo.Dial("localhost:40001")
  1212  	c.Assert(err, IsNil)
  1213  	defer session.Close()
  1214  
  1215  	coll := session.DB("mydb").C("mycoll")
  1216  
  1217  	ns := []int{40, 41, 42}
  1218  	for _, n := range ns {
  1219  		err := coll.Insert(M{"n": n})
  1220  		c.Assert(err, IsNil)
  1221  	}
  1222  
  1223  	m := M{}
  1224  	query := coll.Find(nil).Limit(2)
  1225  	err = query.Explain(m)
  1226  	c.Assert(err, IsNil)
  1227  	if m["queryPlanner"] != nil {
  1228  		c.Assert(m["executionStats"].(M)["totalDocsExamined"], Equals, 2)
  1229  	} else {
  1230  		c.Assert(m["cursor"], Equals, "BasicCursor")
  1231  		c.Assert(m["nscanned"], Equals, 2)
  1232  		c.Assert(m["n"], Equals, 2)
  1233  	}
  1234  
  1235  	n := 0
  1236  	var result M
  1237  	iter := query.Iter()
  1238  	for iter.Next(&result) {
  1239  		n++
  1240  	}
  1241  	c.Assert(iter.Close(), IsNil)
  1242  	c.Assert(n, Equals, 2)
  1243  }
  1244  
  1245  func (s *S) TestQuerySetMaxScan(c *C) {
  1246  	session, err := mgo.Dial("localhost:40001")
  1247  	c.Assert(err, IsNil)
  1248  	defer session.Close()
  1249  	coll := session.DB("mydb").C("mycoll")
  1250  
  1251  	ns := []int{40, 41, 42}
  1252  	for _, n := range ns {
  1253  		err := coll.Insert(M{"n": n})
  1254  		c.Assert(err, IsNil)
  1255  	}
  1256  
  1257  	query := coll.Find(nil).SetMaxScan(2)
  1258  	var result []M
  1259  	err = query.All(&result)
  1260  	c.Assert(err, IsNil)
  1261  	c.Assert(result, HasLen, 2)
  1262  }
  1263  
  1264  func (s *S) TestQuerySetMaxTime(c *C) {
  1265  	if !s.versionAtLeast(2, 6) {
  1266  		c.Skip("SetMaxTime only supported in 2.6+")
  1267  	}
  1268  
  1269  	session, err := mgo.Dial("localhost:40001")
  1270  	c.Assert(err, IsNil)
  1271  	defer session.Close()
  1272  	coll := session.DB("mydb").C("mycoll")
  1273  
  1274  	for i := 0; i < 1000; i++ {
  1275  		err := coll.Insert(M{"n": i})
  1276  		c.Assert(err, IsNil)
  1277  	}
  1278  
  1279  	query := coll.Find(nil)
  1280  	query.SetMaxTime(1 * time.Millisecond)
  1281  	query.Batch(2)
  1282  	var result []M
  1283  	err = query.All(&result)
  1284  	c.Assert(err, ErrorMatches, "operation exceeded time limit")
  1285  }
  1286  
  1287  func (s *S) TestQueryHint(c *C) {
  1288  	session, err := mgo.Dial("localhost:40001")
  1289  	c.Assert(err, IsNil)
  1290  	defer session.Close()
  1291  
  1292  	coll := session.DB("mydb").C("mycoll")
  1293  	coll.EnsureIndexKey("a")
  1294  
  1295  	m := M{}
  1296  	err = coll.Find(nil).Hint("a").Explain(m)
  1297  	c.Assert(err, IsNil)
  1298  
  1299  	if m["queryPlanner"] != nil {
  1300  		m = m["queryPlanner"].(M)
  1301  		m = m["winningPlan"].(M)
  1302  		m = m["inputStage"].(M)
  1303  		c.Assert(m["indexName"], Equals, "a_1")
  1304  	} else {
  1305  		c.Assert(m["indexBounds"], NotNil)
  1306  		c.Assert(m["indexBounds"].(M)["a"], NotNil)
  1307  	}
  1308  }
  1309  
  1310  func (s *S) TestQueryComment(c *C) {
  1311  	session, err := mgo.Dial("localhost:40001")
  1312  	c.Assert(err, IsNil)
  1313  	defer session.Close()
  1314  
  1315  	db := session.DB("mydb")
  1316  	coll := db.C("mycoll")
  1317  
  1318  	err = db.Run(bson.M{"profile": 2}, nil)
  1319  	c.Assert(err, IsNil)
  1320  
  1321  	ns := []int{40, 41, 42}
  1322  	for _, n := range ns {
  1323  		err := coll.Insert(M{"n": n})
  1324  		c.Assert(err, IsNil)
  1325  	}
  1326  
  1327  	query := coll.Find(bson.M{"n": 41})
  1328  	query.Comment("some comment")
  1329  	err = query.One(nil)
  1330  	c.Assert(err, IsNil)
  1331  
  1332  	query = coll.Find(bson.M{"n": 41})
  1333  	query.Comment("another comment")
  1334  	err = query.One(nil)
  1335  	c.Assert(err, IsNil)
  1336  
  1337  	commentField := "query.$comment"
  1338  	nField := "query.$query.n"
  1339  	if s.versionAtLeast(3, 2) {
  1340  		commentField = "query.comment"
  1341  		nField = "query.filter.n"
  1342  	}
  1343  	n, err := session.DB("mydb").C("system.profile").Find(bson.M{nField: 41, commentField: "some comment"}).Count()
  1344  	c.Assert(err, IsNil)
  1345  	c.Assert(n, Equals, 1)
  1346  }
  1347  
  1348  func (s *S) TestFindOneNotFound(c *C) {
  1349  	session, err := mgo.Dial("localhost:40001")
  1350  	c.Assert(err, IsNil)
  1351  	defer session.Close()
  1352  
  1353  	coll := session.DB("mydb").C("mycoll")
  1354  
  1355  	result := struct{ A, B int }{}
  1356  	err = coll.Find(M{"a": 1}).One(&result)
  1357  	c.Assert(err, Equals, mgo.ErrNotFound)
  1358  	c.Assert(err, ErrorMatches, "not found")
  1359  	c.Assert(err == mgo.ErrNotFound, Equals, true)
  1360  }
  1361  
  1362  func (s *S) TestFindIterNotFound(c *C) {
  1363  	session, err := mgo.Dial("localhost:40001")
  1364  	c.Assert(err, IsNil)
  1365  	defer session.Close()
  1366  
  1367  	coll := session.DB("mydb").C("mycoll")
  1368  
  1369  	result := struct{ A, B int }{}
  1370  	iter := coll.Find(M{"a": 1}).Iter()
  1371  	ok := iter.Next(&result)
  1372  	c.Assert(ok, Equals, false)
  1373  	c.Assert(iter.Err(), IsNil)
  1374  }
  1375  
  1376  func (s *S) TestFindNil(c *C) {
  1377  	session, err := mgo.Dial("localhost:40001")
  1378  	c.Assert(err, IsNil)
  1379  	defer session.Close()
  1380  
  1381  	coll := session.DB("mydb").C("mycoll")
  1382  	err = coll.Insert(M{"n": 1})
  1383  	c.Assert(err, IsNil)
  1384  
  1385  	result := struct{ N int }{}
  1386  
  1387  	err = coll.Find(nil).One(&result)
  1388  	c.Assert(err, IsNil)
  1389  	c.Assert(result.N, Equals, 1)
  1390  }
  1391  
  1392  func (s *S) TestFindId(c *C) {
  1393  	session, err := mgo.Dial("localhost:40001")
  1394  	c.Assert(err, IsNil)
  1395  	defer session.Close()
  1396  
  1397  	coll := session.DB("mydb").C("mycoll")
  1398  	err = coll.Insert(M{"_id": 41, "n": 41})
  1399  	c.Assert(err, IsNil)
  1400  	err = coll.Insert(M{"_id": 42, "n": 42})
  1401  	c.Assert(err, IsNil)
  1402  
  1403  	result := struct{ N int }{}
  1404  
  1405  	err = coll.FindId(42).One(&result)
  1406  	c.Assert(err, IsNil)
  1407  	c.Assert(result.N, Equals, 42)
  1408  }
  1409  
  1410  func (s *S) TestFindIterAll(c *C) {
  1411  	session, err := mgo.Dial("localhost:40001")
  1412  	c.Assert(err, IsNil)
  1413  	defer session.Close()
  1414  
  1415  	coll := session.DB("mydb").C("mycoll")
  1416  
  1417  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1418  	for _, n := range ns {
  1419  		coll.Insert(M{"n": n})
  1420  	}
  1421  
  1422  	session.Refresh() // Release socket.
  1423  
  1424  	mgo.ResetStats()
  1425  
  1426  	iter := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2).Iter()
  1427  	result := struct{ N int }{}
  1428  	for i := 2; i < 7; i++ {
  1429  		ok := iter.Next(&result)
  1430  		c.Assert(ok, Equals, true, Commentf("err=%v", err))
  1431  		c.Assert(result.N, Equals, ns[i])
  1432  		if i == 1 {
  1433  			stats := mgo.GetStats()
  1434  			c.Assert(stats.ReceivedDocs, Equals, 2)
  1435  		}
  1436  	}
  1437  
  1438  	ok := iter.Next(&result)
  1439  	c.Assert(ok, Equals, false)
  1440  	c.Assert(iter.Close(), IsNil)
  1441  
  1442  	session.Refresh() // Release socket.
  1443  
  1444  	stats := mgo.GetStats()
  1445  	c.Assert(stats.SentOps, Equals, 3)     // 1*QUERY_OP + 2*GET_MORE_OP
  1446  	c.Assert(stats.ReceivedOps, Equals, 3) // and their REPLY_OPs.
  1447  	if s.versionAtLeast(3, 2) {
  1448  		// In 3.2+ responses come in batches inside the op reply docs.
  1449  		c.Assert(stats.ReceivedDocs, Equals, 3)
  1450  	} else {
  1451  		c.Assert(stats.ReceivedDocs, Equals, 5)
  1452  	}
  1453  	c.Assert(stats.SocketsInUse, Equals, 0)
  1454  }
  1455  
  1456  func (s *S) TestFindIterTwiceWithSameQuery(c *C) {
  1457  	session, err := mgo.Dial("localhost:40001")
  1458  	c.Assert(err, IsNil)
  1459  	defer session.Close()
  1460  
  1461  	coll := session.DB("mydb").C("mycoll")
  1462  
  1463  	for i := 40; i != 47; i++ {
  1464  		err := coll.Insert(M{"n": i})
  1465  		c.Assert(err, IsNil)
  1466  	}
  1467  
  1468  	query := coll.Find(M{}).Sort("n")
  1469  
  1470  	iter1 := query.Skip(1).Iter()
  1471  	iter2 := query.Skip(2).Iter()
  1472  
  1473  	var result struct{ N int }
  1474  	ok := iter2.Next(&result)
  1475  	c.Assert(ok, Equals, true)
  1476  	c.Assert(result.N, Equals, 42)
  1477  	ok = iter1.Next(&result)
  1478  	c.Assert(ok, Equals, true)
  1479  	c.Assert(result.N, Equals, 41)
  1480  }
  1481  
  1482  func (s *S) TestFindIterWithoutResults(c *C) {
  1483  	session, err := mgo.Dial("localhost:40001")
  1484  	c.Assert(err, IsNil)
  1485  	defer session.Close()
  1486  
  1487  	coll := session.DB("mydb").C("mycoll")
  1488  	coll.Insert(M{"n": 42})
  1489  
  1490  	iter := coll.Find(M{"n": 0}).Iter()
  1491  
  1492  	result := struct{ N int }{}
  1493  	ok := iter.Next(&result)
  1494  	c.Assert(ok, Equals, false)
  1495  	c.Assert(iter.Close(), IsNil)
  1496  	c.Assert(result.N, Equals, 0)
  1497  }
  1498  
  1499  func (s *S) TestFindIterLimit(c *C) {
  1500  	session, err := mgo.Dial("localhost:40001")
  1501  	c.Assert(err, IsNil)
  1502  	defer session.Close()
  1503  
  1504  	coll := session.DB("mydb").C("mycoll")
  1505  
  1506  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1507  	for _, n := range ns {
  1508  		err := coll.Insert(M{"n": n})
  1509  		c.Assert(err, IsNil)
  1510  	}
  1511  
  1512  	session.Refresh() // Release socket.
  1513  
  1514  	mgo.ResetStats()
  1515  
  1516  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Limit(3)
  1517  	iter := query.Iter()
  1518  
  1519  	result := struct{ N int }{}
  1520  	for i := 2; i < 5; i++ {
  1521  		ok := iter.Next(&result)
  1522  		c.Assert(ok, Equals, true)
  1523  		c.Assert(result.N, Equals, ns[i])
  1524  	}
  1525  
  1526  	ok := iter.Next(&result)
  1527  	c.Assert(ok, Equals, false)
  1528  	c.Assert(iter.Close(), IsNil)
  1529  
  1530  	session.Refresh() // Release socket.
  1531  
  1532  	stats := mgo.GetStats()
  1533  	if s.versionAtLeast(3, 2) {
  1534  		// Limit works properly in 3.2+, and results are batched in single doc.
  1535  		c.Assert(stats.SentOps, Equals, 1)     // 1*QUERY_OP
  1536  		c.Assert(stats.ReceivedOps, Equals, 1) // and its REPLY_OP
  1537  		c.Assert(stats.ReceivedDocs, Equals, 1)
  1538  	} else {
  1539  		c.Assert(stats.SentOps, Equals, 2)     // 1*QUERY_OP + 1*KILL_CURSORS_OP
  1540  		c.Assert(stats.ReceivedOps, Equals, 1) // and its REPLY_OP
  1541  		c.Assert(stats.ReceivedDocs, Equals, 3)
  1542  	}
  1543  	c.Assert(stats.SocketsInUse, Equals, 0)
  1544  }
  1545  
  1546  var cursorTimeout = flag.Bool("cursor-timeout", false, "Enable cursor timeout test")
  1547  
  1548  func (s *S) TestFindIterCursorTimeout(c *C) {
  1549  	if !*cursorTimeout {
  1550  		c.Skip("-cursor-timeout")
  1551  	}
  1552  	session, err := mgo.Dial("localhost:40001")
  1553  	c.Assert(err, IsNil)
  1554  	defer session.Close()
  1555  
  1556  	type Doc struct {
  1557  		Id int "_id"
  1558  	}
  1559  
  1560  	coll := session.DB("test").C("test")
  1561  	coll.Remove(nil)
  1562  	for i := 0; i < 100; i++ {
  1563  		err = coll.Insert(Doc{i})
  1564  		c.Assert(err, IsNil)
  1565  	}
  1566  
  1567  	session.SetBatch(1)
  1568  	iter := coll.Find(nil).Iter()
  1569  	var doc Doc
  1570  	if !iter.Next(&doc) {
  1571  		c.Fatalf("iterator failed to return any documents")
  1572  	}
  1573  
  1574  	for i := 10; i > 0; i-- {
  1575  		c.Logf("Sleeping... %d minutes to go...", i)
  1576  		time.Sleep(1*time.Minute + 2*time.Second)
  1577  	}
  1578  
  1579  	// Drain any existing documents that were fetched.
  1580  	if !iter.Next(&doc) {
  1581  		c.Fatalf("iterator with timed out cursor failed to return previously cached document")
  1582  	}
  1583  	if iter.Next(&doc) {
  1584  		c.Fatalf("timed out cursor returned document")
  1585  	}
  1586  
  1587  	c.Assert(iter.Err(), Equals, mgo.ErrCursor)
  1588  }
  1589  
  1590  func (s *S) TestTooManyItemsLimitBug(c *C) {
  1591  	if *fast {
  1592  		c.Skip("-fast")
  1593  	}
  1594  
  1595  	session, err := mgo.Dial("localhost:40001")
  1596  	c.Assert(err, IsNil)
  1597  	defer session.Close()
  1598  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU()))
  1599  
  1600  	mgo.SetDebug(false)
  1601  	coll := session.DB("mydb").C("mycoll")
  1602  	words := strings.Split("foo bar baz", " ")
  1603  	for i := 0; i < 5; i++ {
  1604  		words = append(words, words...)
  1605  	}
  1606  	doc := bson.D{{"words", words}}
  1607  	inserts := 10000
  1608  	limit := 5000
  1609  	iters := 0
  1610  	c.Assert(inserts > limit, Equals, true)
  1611  	for i := 0; i < inserts; i++ {
  1612  		err := coll.Insert(&doc)
  1613  		c.Assert(err, IsNil)
  1614  	}
  1615  	iter := coll.Find(nil).Limit(limit).Iter()
  1616  	for iter.Next(&doc) {
  1617  		if iters%100 == 0 {
  1618  			c.Logf("Seen %d docments", iters)
  1619  		}
  1620  		iters++
  1621  	}
  1622  	c.Assert(iter.Close(), IsNil)
  1623  	c.Assert(iters, Equals, limit)
  1624  }
  1625  
  1626  func (s *S) TestBatchSizeZeroGetMore(c *C) {
  1627  	if *fast {
  1628  		c.Skip("-fast")
  1629  	}
  1630  
  1631  	session, err := mgo.Dial("localhost:40001")
  1632  	c.Assert(err, IsNil)
  1633  	defer session.Close()
  1634  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU()))
  1635  
  1636  	mgo.SetDebug(false)
  1637  	coll := session.DB("mydb").C("mycoll")
  1638  	words := strings.Split("foo bar baz", " ")
  1639  	for i := 0; i < 5; i++ {
  1640  		words = append(words, words...)
  1641  	}
  1642  	doc := bson.D{{"words", words}}
  1643  	inserts := 10000
  1644  	iters := 0
  1645  	for i := 0; i < inserts; i++ {
  1646  		err := coll.Insert(&doc)
  1647  		c.Assert(err, IsNil)
  1648  	}
  1649  	iter := coll.Find(nil).Iter()
  1650  	for iter.Next(&doc) {
  1651  		if iters%100 == 0 {
  1652  			c.Logf("Seen %d docments", iters)
  1653  		}
  1654  		iters++
  1655  	}
  1656  	c.Assert(iter.Close(), IsNil)
  1657  }
  1658  
  1659  func serverCursorsOpen(session *mgo.Session) int {
  1660  	var result struct {
  1661  		Cursors struct {
  1662  			TotalOpen int `bson:"totalOpen"`
  1663  			TimedOut  int `bson:"timedOut"`
  1664  		}
  1665  	}
  1666  	err := session.Run("serverStatus", &result)
  1667  	if err != nil {
  1668  		panic(err)
  1669  	}
  1670  	return result.Cursors.TotalOpen
  1671  }
  1672  
  1673  func (s *S) TestFindIterLimitWithMore(c *C) {
  1674  	session, err := mgo.Dial("localhost:40001")
  1675  	c.Assert(err, IsNil)
  1676  	defer session.Close()
  1677  
  1678  	coll := session.DB("mydb").C("mycoll")
  1679  
  1680  	// Insane amounts of logging otherwise due to the
  1681  	// amount of data being shuffled.
  1682  	mgo.SetDebug(false)
  1683  	defer mgo.SetDebug(true)
  1684  
  1685  	// Should amount to more than 4MB bson payload,
  1686  	// the default limit per result chunk.
  1687  	const total = 4096
  1688  	var d struct{ A [1024]byte }
  1689  	docs := make([]interface{}, total)
  1690  	for i := 0; i < total; i++ {
  1691  		docs[i] = &d
  1692  	}
  1693  	err = coll.Insert(docs...)
  1694  	c.Assert(err, IsNil)
  1695  
  1696  	n, err := coll.Count()
  1697  	c.Assert(err, IsNil)
  1698  	c.Assert(n, Equals, total)
  1699  
  1700  	// First, try restricting to a single chunk with a negative limit.
  1701  	nresults := 0
  1702  	iter := coll.Find(nil).Limit(-total).Iter()
  1703  	var discard struct{}
  1704  	for iter.Next(&discard) {
  1705  		nresults++
  1706  	}
  1707  	if nresults < total/2 || nresults >= total {
  1708  		c.Fatalf("Bad result size with negative limit: %d", nresults)
  1709  	}
  1710  
  1711  	cursorsOpen := serverCursorsOpen(session)
  1712  
  1713  	// Try again, with a positive limit. Should reach the end now,
  1714  	// using multiple chunks.
  1715  	nresults = 0
  1716  	iter = coll.Find(nil).Limit(total).Iter()
  1717  	for iter.Next(&discard) {
  1718  		nresults++
  1719  	}
  1720  	c.Assert(nresults, Equals, total)
  1721  
  1722  	// Ensure the cursor used is properly killed.
  1723  	c.Assert(serverCursorsOpen(session), Equals, cursorsOpen)
  1724  
  1725  	// Edge case, -MinInt == -MinInt.
  1726  	nresults = 0
  1727  	iter = coll.Find(nil).Limit(math.MinInt32).Iter()
  1728  	for iter.Next(&discard) {
  1729  		nresults++
  1730  	}
  1731  	if nresults < total/2 || nresults >= total {
  1732  		c.Fatalf("Bad result size with MinInt32 limit: %d", nresults)
  1733  	}
  1734  }
  1735  
  1736  func (s *S) TestFindIterLimitWithBatch(c *C) {
  1737  	session, err := mgo.Dial("localhost:40001")
  1738  	c.Assert(err, IsNil)
  1739  	defer session.Close()
  1740  
  1741  	coll := session.DB("mydb").C("mycoll")
  1742  
  1743  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1744  	for _, n := range ns {
  1745  		coll.Insert(M{"n": n})
  1746  	}
  1747  
  1748  	// Ping the database to ensure the nonce has been received already.
  1749  	c.Assert(session.Ping(), IsNil)
  1750  
  1751  	session.Refresh() // Release socket.
  1752  
  1753  	mgo.ResetStats()
  1754  
  1755  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Limit(3).Batch(2)
  1756  	iter := query.Iter()
  1757  	result := struct{ N int }{}
  1758  	for i := 2; i < 5; i++ {
  1759  		ok := iter.Next(&result)
  1760  		c.Assert(ok, Equals, true)
  1761  		c.Assert(result.N, Equals, ns[i])
  1762  		if i == 3 {
  1763  			stats := mgo.GetStats()
  1764  			if s.versionAtLeast(3, 2) {
  1765  				// In 3.2+ responses come in batches inside the op reply docs.
  1766  				c.Assert(stats.ReceivedDocs, Equals, 1)
  1767  			} else {
  1768  				c.Assert(stats.ReceivedDocs, Equals, 2)
  1769  			}
  1770  		}
  1771  	}
  1772  
  1773  	ok := iter.Next(&result)
  1774  	c.Assert(ok, Equals, false)
  1775  	c.Assert(iter.Close(), IsNil)
  1776  
  1777  	session.Refresh() // Release socket.
  1778  
  1779  	stats := mgo.GetStats()
  1780  	if s.versionAtLeast(3, 2) {
  1781  		// In 3.2+ limit works properly even with multiple batches..
  1782  		c.Assert(stats.SentOps, Equals, 2)     // 1*QUERY_OP + 1*GET_MORE_OP
  1783  		c.Assert(stats.ReceivedOps, Equals, 2) // and its REPLY_OPs
  1784  
  1785  		// In 3.2+ responses come in batches inside the op reply docs.
  1786  		c.Assert(stats.ReceivedDocs, Equals, 2)
  1787  	} else {
  1788  		c.Assert(stats.SentOps, Equals, 3)     // 1*QUERY_OP + 1*GET_MORE_OP + 1*KILL_CURSORS_OP
  1789  		c.Assert(stats.ReceivedOps, Equals, 2) // and its REPLY_OPs
  1790  		c.Assert(stats.ReceivedDocs, Equals, 3)
  1791  	}
  1792  	c.Assert(stats.SocketsInUse, Equals, 0)
  1793  }
  1794  
  1795  func (s *S) TestFindIterSortWithBatch(c *C) {
  1796  	session, err := mgo.Dial("localhost:40001")
  1797  	c.Assert(err, IsNil)
  1798  	defer session.Close()
  1799  
  1800  	coll := session.DB("mydb").C("mycoll")
  1801  
  1802  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1803  	for _, n := range ns {
  1804  		coll.Insert(M{"n": n})
  1805  	}
  1806  
  1807  	// Without this, the logic above breaks because Mongo refuses to
  1808  	// return a cursor with an in-memory sort.
  1809  	coll.EnsureIndexKey("n")
  1810  
  1811  	// Ping the database to ensure the nonce has been received already.
  1812  	c.Assert(session.Ping(), IsNil)
  1813  
  1814  	session.Refresh() // Release socket.
  1815  
  1816  	mgo.ResetStats()
  1817  
  1818  	query := coll.Find(M{"n": M{"$lte": 44}}).Sort("-n").Batch(2)
  1819  	iter := query.Iter()
  1820  	ns = []int{46, 45, 44, 43, 42, 41, 40}
  1821  	result := struct{ N int }{}
  1822  	for i := 2; i < len(ns); i++ {
  1823  		c.Logf("i=%d", i)
  1824  		ok := iter.Next(&result)
  1825  		c.Assert(ok, Equals, true)
  1826  		c.Assert(result.N, Equals, ns[i])
  1827  		if i == 3 {
  1828  			stats := mgo.GetStats()
  1829  			if s.versionAtLeast(3, 2) {
  1830  				// Find command in 3.2+ bundles batches in a single document.
  1831  				c.Assert(stats.ReceivedDocs, Equals, 1)
  1832  			} else {
  1833  				c.Assert(stats.ReceivedDocs, Equals, 2)
  1834  			}
  1835  		}
  1836  	}
  1837  
  1838  	ok := iter.Next(&result)
  1839  	c.Assert(ok, Equals, false)
  1840  	c.Assert(iter.Close(), IsNil)
  1841  
  1842  	session.Refresh() // Release socket.
  1843  
  1844  	stats := mgo.GetStats()
  1845  	c.Assert(stats.SentOps, Equals, 3)     // 1*QUERY_OP + 2*GET_MORE_OP
  1846  	c.Assert(stats.ReceivedOps, Equals, 3) // and its REPLY_OPs
  1847  	if s.versionAtLeast(3, 2) {
  1848  		// Find command in 3.2+ bundles batches in a single document.
  1849  		c.Assert(stats.ReceivedDocs, Equals, 3)
  1850  	} else {
  1851  		c.Assert(stats.ReceivedDocs, Equals, 5)
  1852  	}
  1853  	c.Assert(stats.SocketsInUse, Equals, 0)
  1854  }
  1855  
  1856  // Test tailable cursors in a situation where Next has to sleep to
  1857  // respect the timeout requested on Tail.
  1858  func (s *S) TestFindTailTimeoutWithSleep(c *C) {
  1859  	if *fast {
  1860  		c.Skip("-fast")
  1861  	}
  1862  
  1863  	session, err := mgo.Dial("localhost:40001")
  1864  	c.Assert(err, IsNil)
  1865  	defer session.Close()
  1866  
  1867  	cresult := struct{ ErrMsg string }{}
  1868  
  1869  	db := session.DB("mydb")
  1870  	err = db.Run(bson.D{{"create", "mycoll"}, {"capped", true}, {"size", 1024}}, &cresult)
  1871  	c.Assert(err, IsNil)
  1872  	c.Assert(cresult.ErrMsg, Equals, "")
  1873  	coll := db.C("mycoll")
  1874  
  1875  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1876  	for _, n := range ns {
  1877  		coll.Insert(M{"n": n})
  1878  	}
  1879  
  1880  	session.Refresh() // Release socket.
  1881  
  1882  	mgo.ResetStats()
  1883  
  1884  	timeout := 5 * time.Second
  1885  
  1886  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2)
  1887  	iter := query.Tail(timeout)
  1888  
  1889  	n := len(ns)
  1890  	result := struct{ N int }{}
  1891  	for i := 2; i != n; i++ {
  1892  		ok := iter.Next(&result)
  1893  		c.Assert(ok, Equals, true)
  1894  		c.Assert(iter.Err(), IsNil)
  1895  		c.Assert(iter.Timeout(), Equals, false)
  1896  		c.Assert(result.N, Equals, ns[i])
  1897  		if i == 3 { // The batch boundary.
  1898  			stats := mgo.GetStats()
  1899  			c.Assert(stats.ReceivedDocs, Equals, 2)
  1900  		}
  1901  	}
  1902  
  1903  	mgo.ResetStats()
  1904  
  1905  	// The following call to Next will block.
  1906  	done := make(chan bool)
  1907  	defer func() { <-done }()
  1908  	go func() {
  1909  		// The internal AwaitData timing of MongoDB is around 2 seconds,
  1910  		// so this should force mgo to sleep at least once by itself to
  1911  		// respect the requested timeout.
  1912  		c.Logf("[GOROUTINE] Starting and sleeping...")
  1913  		time.Sleep(timeout - 2*time.Second)
  1914  		c.Logf("[GOROUTINE] Woke up...")
  1915  		session := session.New()
  1916  		c.Logf("[GOROUTINE] Session created and will insert...")
  1917  		err := coll.Insert(M{"n": 47})
  1918  		c.Logf("[GOROUTINE] Insert attempted, err=%v...", err)
  1919  		session.Close()
  1920  		c.Logf("[GOROUTINE] Session closed.")
  1921  		c.Check(err, IsNil)
  1922  		done <- true
  1923  	}()
  1924  
  1925  	c.Log("Will wait for Next with N=47...")
  1926  	ok := iter.Next(&result)
  1927  	c.Log("Next unblocked...")
  1928  	c.Assert(ok, Equals, true)
  1929  
  1930  	c.Assert(iter.Err(), IsNil)
  1931  	c.Assert(iter.Timeout(), Equals, false)
  1932  	c.Assert(result.N, Equals, 47)
  1933  	c.Log("Got Next with N=47!")
  1934  
  1935  	c.Log("Will wait for a result which will never come...")
  1936  
  1937  	started := time.Now()
  1938  	ok = iter.Next(&result)
  1939  	c.Assert(ok, Equals, false)
  1940  	c.Assert(iter.Err(), IsNil)
  1941  	c.Assert(iter.Timeout(), Equals, true)
  1942  	c.Assert(started.Before(time.Now().Add(-timeout)), Equals, true)
  1943  
  1944  	c.Log("Will now reuse the timed out tail cursor...")
  1945  
  1946  	coll.Insert(M{"n": 48})
  1947  	ok = iter.Next(&result)
  1948  	c.Assert(ok, Equals, true)
  1949  	c.Assert(iter.Close(), IsNil)
  1950  	c.Assert(iter.Timeout(), Equals, false)
  1951  	c.Assert(result.N, Equals, 48)
  1952  }
  1953  
  1954  // Test tailable cursors in a situation where Next never gets to sleep once
  1955  // to respect the timeout requested on Tail.
  1956  func (s *S) TestFindTailTimeoutNoSleep(c *C) {
  1957  	session, err := mgo.Dial("localhost:40001")
  1958  	c.Assert(err, IsNil)
  1959  	defer session.Close()
  1960  
  1961  	cresult := struct{ ErrMsg string }{}
  1962  
  1963  	db := session.DB("mydb")
  1964  	err = db.Run(bson.D{{"create", "mycoll"}, {"capped", true}, {"size", 1024}}, &cresult)
  1965  	c.Assert(err, IsNil)
  1966  	c.Assert(cresult.ErrMsg, Equals, "")
  1967  	coll := db.C("mycoll")
  1968  
  1969  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  1970  	for _, n := range ns {
  1971  		coll.Insert(M{"n": n})
  1972  	}
  1973  
  1974  	session.Refresh() // Release socket.
  1975  
  1976  	mgo.ResetStats()
  1977  
  1978  	timeout := 1 * time.Second
  1979  
  1980  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2)
  1981  	iter := query.Tail(timeout)
  1982  
  1983  	n := len(ns)
  1984  	result := struct{ N int }{}
  1985  	for i := 2; i != n; i++ {
  1986  		ok := iter.Next(&result)
  1987  		c.Assert(ok, Equals, true)
  1988  		c.Assert(iter.Err(), IsNil)
  1989  		c.Assert(iter.Timeout(), Equals, false)
  1990  		c.Assert(result.N, Equals, ns[i])
  1991  		if i == 3 { // The batch boundary.
  1992  			stats := mgo.GetStats()
  1993  			c.Assert(stats.ReceivedDocs, Equals, 2)
  1994  		}
  1995  	}
  1996  
  1997  	// The following call to Next will block.
  1998  	go func() {
  1999  		// The internal AwaitData timing of MongoDB is around 2 seconds,
  2000  		// so this item should arrive within the AwaitData threshold.
  2001  		time.Sleep(500 * time.Millisecond)
  2002  		session := session.New()
  2003  		defer session.Close()
  2004  		coll := session.DB("mydb").C("mycoll")
  2005  		coll.Insert(M{"n": 47})
  2006  	}()
  2007  
  2008  	c.Log("Will wait for Next with N=47...")
  2009  	ok := iter.Next(&result)
  2010  	c.Assert(ok, Equals, true)
  2011  	c.Assert(iter.Err(), IsNil)
  2012  	c.Assert(iter.Timeout(), Equals, false)
  2013  	c.Assert(result.N, Equals, 47)
  2014  	c.Log("Got Next with N=47!")
  2015  
  2016  	c.Log("Will wait for a result which will never come...")
  2017  
  2018  	started := time.Now()
  2019  	ok = iter.Next(&result)
  2020  	c.Assert(ok, Equals, false)
  2021  	c.Assert(iter.Err(), IsNil)
  2022  	c.Assert(iter.Timeout(), Equals, true)
  2023  	c.Assert(started.Before(time.Now().Add(-timeout)), Equals, true)
  2024  
  2025  	c.Log("Will now reuse the timed out tail cursor...")
  2026  
  2027  	coll.Insert(M{"n": 48})
  2028  	ok = iter.Next(&result)
  2029  	c.Assert(ok, Equals, true)
  2030  	c.Assert(iter.Close(), IsNil)
  2031  	c.Assert(iter.Timeout(), Equals, false)
  2032  	c.Assert(result.N, Equals, 48)
  2033  }
  2034  
  2035  // Test tailable cursors in a situation where Next never gets to sleep once
  2036  // to respect the timeout requested on Tail.
  2037  func (s *S) TestFindTailNoTimeout(c *C) {
  2038  	if *fast {
  2039  		c.Skip("-fast")
  2040  	}
  2041  
  2042  	session, err := mgo.Dial("localhost:40001")
  2043  	c.Assert(err, IsNil)
  2044  	defer session.Close()
  2045  
  2046  	cresult := struct{ ErrMsg string }{}
  2047  
  2048  	db := session.DB("mydb")
  2049  	err = db.Run(bson.D{{"create", "mycoll"}, {"capped", true}, {"size", 1024}}, &cresult)
  2050  	c.Assert(err, IsNil)
  2051  	c.Assert(cresult.ErrMsg, Equals, "")
  2052  	coll := db.C("mycoll")
  2053  
  2054  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  2055  	for _, n := range ns {
  2056  		coll.Insert(M{"n": n})
  2057  	}
  2058  
  2059  	session.Refresh() // Release socket.
  2060  
  2061  	mgo.ResetStats()
  2062  
  2063  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2)
  2064  	iter := query.Tail(-1)
  2065  	c.Assert(err, IsNil)
  2066  
  2067  	n := len(ns)
  2068  	result := struct{ N int }{}
  2069  	for i := 2; i != n; i++ {
  2070  		ok := iter.Next(&result)
  2071  		c.Assert(ok, Equals, true)
  2072  		c.Assert(result.N, Equals, ns[i])
  2073  		if i == 3 { // The batch boundary.
  2074  			stats := mgo.GetStats()
  2075  			c.Assert(stats.ReceivedDocs, Equals, 2)
  2076  		}
  2077  	}
  2078  
  2079  	mgo.ResetStats()
  2080  
  2081  	// The following call to Next will block.
  2082  	go func() {
  2083  		time.Sleep(5e8)
  2084  		session := session.New()
  2085  		defer session.Close()
  2086  		coll := session.DB("mydb").C("mycoll")
  2087  		coll.Insert(M{"n": 47})
  2088  	}()
  2089  
  2090  	c.Log("Will wait for Next with N=47...")
  2091  	ok := iter.Next(&result)
  2092  	c.Assert(ok, Equals, true)
  2093  	c.Assert(iter.Err(), IsNil)
  2094  	c.Assert(iter.Timeout(), Equals, false)
  2095  	c.Assert(result.N, Equals, 47)
  2096  	c.Log("Got Next with N=47!")
  2097  
  2098  	c.Log("Will wait for a result which will never come...")
  2099  
  2100  	gotNext := make(chan bool)
  2101  	go func() {
  2102  		ok := iter.Next(&result)
  2103  		gotNext <- ok
  2104  	}()
  2105  
  2106  	select {
  2107  	case ok := <-gotNext:
  2108  		c.Fatalf("Next returned: %v", ok)
  2109  	case <-time.After(3e9):
  2110  		// Good. Should still be sleeping at that point.
  2111  	}
  2112  
  2113  	// Closing the session should cause Next to return.
  2114  	session.Close()
  2115  
  2116  	select {
  2117  	case ok := <-gotNext:
  2118  		c.Assert(ok, Equals, false)
  2119  		c.Assert(iter.Err(), ErrorMatches, "Closed explicitly")
  2120  		c.Assert(iter.Timeout(), Equals, false)
  2121  	case <-time.After(1e9):
  2122  		c.Fatal("Closing the session did not unblock Next")
  2123  	}
  2124  }
  2125  
  2126  func (s *S) TestIterNextResetsResult(c *C) {
  2127  	session, err := mgo.Dial("localhost:40001")
  2128  	c.Assert(err, IsNil)
  2129  	defer session.Close()
  2130  
  2131  	coll := session.DB("mydb").C("mycoll")
  2132  
  2133  	ns := []int{1, 2, 3}
  2134  	for _, n := range ns {
  2135  		coll.Insert(M{"n" + strconv.Itoa(n): n})
  2136  	}
  2137  
  2138  	query := coll.Find(nil).Sort("$natural")
  2139  
  2140  	i := 0
  2141  	var sresult *struct{ N1, N2, N3 int }
  2142  	iter := query.Iter()
  2143  	for iter.Next(&sresult) {
  2144  		switch i {
  2145  		case 0:
  2146  			c.Assert(sresult.N1, Equals, 1)
  2147  			c.Assert(sresult.N2+sresult.N3, Equals, 0)
  2148  		case 1:
  2149  			c.Assert(sresult.N2, Equals, 2)
  2150  			c.Assert(sresult.N1+sresult.N3, Equals, 0)
  2151  		case 2:
  2152  			c.Assert(sresult.N3, Equals, 3)
  2153  			c.Assert(sresult.N1+sresult.N2, Equals, 0)
  2154  		}
  2155  		i++
  2156  	}
  2157  	c.Assert(iter.Close(), IsNil)
  2158  
  2159  	i = 0
  2160  	var mresult M
  2161  	iter = query.Iter()
  2162  	for iter.Next(&mresult) {
  2163  		delete(mresult, "_id")
  2164  		switch i {
  2165  		case 0:
  2166  			c.Assert(mresult, DeepEquals, M{"n1": 1})
  2167  		case 1:
  2168  			c.Assert(mresult, DeepEquals, M{"n2": 2})
  2169  		case 2:
  2170  			c.Assert(mresult, DeepEquals, M{"n3": 3})
  2171  		}
  2172  		i++
  2173  	}
  2174  	c.Assert(iter.Close(), IsNil)
  2175  
  2176  	i = 0
  2177  	var iresult interface{}
  2178  	iter = query.Iter()
  2179  	for iter.Next(&iresult) {
  2180  		mresult, ok := iresult.(bson.M)
  2181  		c.Assert(ok, Equals, true, Commentf("%#v", iresult))
  2182  		delete(mresult, "_id")
  2183  		switch i {
  2184  		case 0:
  2185  			c.Assert(mresult, DeepEquals, bson.M{"n1": 1})
  2186  		case 1:
  2187  			c.Assert(mresult, DeepEquals, bson.M{"n2": 2})
  2188  		case 2:
  2189  			c.Assert(mresult, DeepEquals, bson.M{"n3": 3})
  2190  		}
  2191  		i++
  2192  	}
  2193  	c.Assert(iter.Close(), IsNil)
  2194  }
  2195  
  2196  func (s *S) TestFindForOnIter(c *C) {
  2197  	session, err := mgo.Dial("localhost:40001")
  2198  	c.Assert(err, IsNil)
  2199  	defer session.Close()
  2200  
  2201  	coll := session.DB("mydb").C("mycoll")
  2202  
  2203  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  2204  	for _, n := range ns {
  2205  		coll.Insert(M{"n": n})
  2206  	}
  2207  
  2208  	session.Refresh() // Release socket.
  2209  
  2210  	mgo.ResetStats()
  2211  
  2212  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2)
  2213  	iter := query.Iter()
  2214  
  2215  	i := 2
  2216  	var result *struct{ N int }
  2217  	err = iter.For(&result, func() error {
  2218  		c.Assert(i < 7, Equals, true)
  2219  		c.Assert(result.N, Equals, ns[i])
  2220  		if i == 1 {
  2221  			stats := mgo.GetStats()
  2222  			if s.versionAtLeast(3, 2) {
  2223  				// Find command in 3.2+ bundles batches in a single document.
  2224  				c.Assert(stats.ReceivedDocs, Equals, 1)
  2225  			} else {
  2226  				c.Assert(stats.ReceivedDocs, Equals, 2)
  2227  			}
  2228  		}
  2229  		i++
  2230  		return nil
  2231  	})
  2232  	c.Assert(err, IsNil)
  2233  
  2234  	session.Refresh() // Release socket.
  2235  
  2236  	stats := mgo.GetStats()
  2237  	c.Assert(stats.SentOps, Equals, 3)     // 1*QUERY_OP + 2*GET_MORE_OP
  2238  	c.Assert(stats.ReceivedOps, Equals, 3) // and their REPLY_OPs.
  2239  	if s.versionAtLeast(3, 2) {
  2240  		// Find command in 3.2+ bundles batches in a single document.
  2241  		c.Assert(stats.ReceivedDocs, Equals, 3)
  2242  	} else {
  2243  		c.Assert(stats.ReceivedDocs, Equals, 5)
  2244  	}
  2245  	c.Assert(stats.SocketsInUse, Equals, 0)
  2246  }
  2247  
  2248  func (s *S) TestFindFor(c *C) {
  2249  	session, err := mgo.Dial("localhost:40001")
  2250  	c.Assert(err, IsNil)
  2251  	defer session.Close()
  2252  
  2253  	coll := session.DB("mydb").C("mycoll")
  2254  
  2255  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  2256  	for _, n := range ns {
  2257  		coll.Insert(M{"n": n})
  2258  	}
  2259  
  2260  	session.Refresh() // Release socket.
  2261  
  2262  	mgo.ResetStats()
  2263  
  2264  	query := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2)
  2265  
  2266  	i := 2
  2267  	var result *struct{ N int }
  2268  	err = query.For(&result, func() error {
  2269  		c.Assert(i < 7, Equals, true)
  2270  		c.Assert(result.N, Equals, ns[i])
  2271  		if i == 1 {
  2272  			stats := mgo.GetStats()
  2273  			c.Assert(stats.ReceivedDocs, Equals, 2)
  2274  			if s.versionAtLeast(3, 2) {
  2275  				// Find command in 3.2+ bundles batches in a single document.
  2276  				c.Assert(stats.ReceivedDocs, Equals, 1)
  2277  			} else {
  2278  				c.Assert(stats.ReceivedDocs, Equals, 2)
  2279  			}
  2280  		}
  2281  		i++
  2282  		return nil
  2283  	})
  2284  	c.Assert(err, IsNil)
  2285  
  2286  	session.Refresh() // Release socket.
  2287  
  2288  	stats := mgo.GetStats()
  2289  	c.Assert(stats.SentOps, Equals, 3)     // 1*QUERY_OP + 2*GET_MORE_OP
  2290  	c.Assert(stats.ReceivedOps, Equals, 3) // and their REPLY_OPs.
  2291  	if s.versionAtLeast(3, 2) {
  2292  		// Find command in 3.2+ bundles batches in a single document.
  2293  		c.Assert(stats.ReceivedDocs, Equals, 3)
  2294  	} else {
  2295  		c.Assert(stats.ReceivedDocs, Equals, 5)
  2296  	}
  2297  	c.Assert(stats.SocketsInUse, Equals, 0)
  2298  }
  2299  
  2300  func (s *S) TestFindForStopOnError(c *C) {
  2301  	session, err := mgo.Dial("localhost:40001")
  2302  	c.Assert(err, IsNil)
  2303  	defer session.Close()
  2304  
  2305  	coll := session.DB("mydb").C("mycoll")
  2306  
  2307  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  2308  	for _, n := range ns {
  2309  		coll.Insert(M{"n": n})
  2310  	}
  2311  
  2312  	query := coll.Find(M{"n": M{"$gte": 42}})
  2313  	i := 2
  2314  	var result *struct{ N int }
  2315  	err = query.For(&result, func() error {
  2316  		c.Assert(i < 4, Equals, true)
  2317  		c.Assert(result.N, Equals, ns[i])
  2318  		if i == 3 {
  2319  			return fmt.Errorf("stop!")
  2320  		}
  2321  		i++
  2322  		return nil
  2323  	})
  2324  	c.Assert(err, ErrorMatches, "stop!")
  2325  }
  2326  
  2327  func (s *S) TestFindForResetsResult(c *C) {
  2328  	session, err := mgo.Dial("localhost:40001")
  2329  	c.Assert(err, IsNil)
  2330  	defer session.Close()
  2331  
  2332  	coll := session.DB("mydb").C("mycoll")
  2333  
  2334  	ns := []int{1, 2, 3}
  2335  	for _, n := range ns {
  2336  		coll.Insert(M{"n" + strconv.Itoa(n): n})
  2337  	}
  2338  
  2339  	query := coll.Find(nil).Sort("$natural")
  2340  
  2341  	i := 0
  2342  	var sresult *struct{ N1, N2, N3 int }
  2343  	err = query.For(&sresult, func() error {
  2344  		switch i {
  2345  		case 0:
  2346  			c.Assert(sresult.N1, Equals, 1)
  2347  			c.Assert(sresult.N2+sresult.N3, Equals, 0)
  2348  		case 1:
  2349  			c.Assert(sresult.N2, Equals, 2)
  2350  			c.Assert(sresult.N1+sresult.N3, Equals, 0)
  2351  		case 2:
  2352  			c.Assert(sresult.N3, Equals, 3)
  2353  			c.Assert(sresult.N1+sresult.N2, Equals, 0)
  2354  		}
  2355  		i++
  2356  		return nil
  2357  	})
  2358  	c.Assert(err, IsNil)
  2359  
  2360  	i = 0
  2361  	var mresult M
  2362  	err = query.For(&mresult, func() error {
  2363  		delete(mresult, "_id")
  2364  		switch i {
  2365  		case 0:
  2366  			c.Assert(mresult, DeepEquals, M{"n1": 1})
  2367  		case 1:
  2368  			c.Assert(mresult, DeepEquals, M{"n2": 2})
  2369  		case 2:
  2370  			c.Assert(mresult, DeepEquals, M{"n3": 3})
  2371  		}
  2372  		i++
  2373  		return nil
  2374  	})
  2375  	c.Assert(err, IsNil)
  2376  
  2377  	i = 0
  2378  	var iresult interface{}
  2379  	err = query.For(&iresult, func() error {
  2380  		mresult, ok := iresult.(bson.M)
  2381  		c.Assert(ok, Equals, true, Commentf("%#v", iresult))
  2382  		delete(mresult, "_id")
  2383  		switch i {
  2384  		case 0:
  2385  			c.Assert(mresult, DeepEquals, bson.M{"n1": 1})
  2386  		case 1:
  2387  			c.Assert(mresult, DeepEquals, bson.M{"n2": 2})
  2388  		case 2:
  2389  			c.Assert(mresult, DeepEquals, bson.M{"n3": 3})
  2390  		}
  2391  		i++
  2392  		return nil
  2393  	})
  2394  	c.Assert(err, IsNil)
  2395  }
  2396  
  2397  func (s *S) TestFindIterSnapshot(c *C) {
  2398  	if s.versionAtLeast(3, 2) {
  2399  		c.Skip("Broken in 3.2: https://jira.mongodb.org/browse/SERVER-21403")
  2400  	}
  2401  
  2402  	session, err := mgo.Dial("localhost:40001")
  2403  	c.Assert(err, IsNil)
  2404  	defer session.Close()
  2405  
  2406  	// Insane amounts of logging otherwise due to the
  2407  	// amount of data being shuffled.
  2408  	mgo.SetDebug(false)
  2409  	defer mgo.SetDebug(true)
  2410  
  2411  	coll := session.DB("mydb").C("mycoll")
  2412  
  2413  	var a [1024000]byte
  2414  
  2415  	for n := 0; n < 10; n++ {
  2416  		err := coll.Insert(M{"_id": n, "n": n, "a1": &a})
  2417  		c.Assert(err, IsNil)
  2418  	}
  2419  
  2420  	query := coll.Find(M{"n": M{"$gt": -1}}).Batch(2).Prefetch(0)
  2421  	query.Snapshot()
  2422  	iter := query.Iter()
  2423  
  2424  	seen := map[int]bool{}
  2425  	result := struct {
  2426  		Id int "_id"
  2427  	}{}
  2428  	for iter.Next(&result) {
  2429  		if len(seen) == 2 {
  2430  			// Grow all entries so that they have to move.
  2431  			// Backwards so that the order is inverted.
  2432  			for n := 10; n >= 0; n-- {
  2433  				_, err := coll.Upsert(M{"_id": n}, M{"$set": M{"a2": &a}})
  2434  				c.Assert(err, IsNil)
  2435  			}
  2436  		}
  2437  		if seen[result.Id] {
  2438  			c.Fatalf("seen duplicated key: %d", result.Id)
  2439  		}
  2440  		seen[result.Id] = true
  2441  	}
  2442  	c.Assert(iter.Close(), IsNil)
  2443  }
  2444  
  2445  func (s *S) TestSort(c *C) {
  2446  	session, err := mgo.Dial("localhost:40001")
  2447  	c.Assert(err, IsNil)
  2448  	defer session.Close()
  2449  
  2450  	coll := session.DB("mydb").C("mycoll")
  2451  
  2452  	coll.Insert(M{"a": 1, "b": 1})
  2453  	coll.Insert(M{"a": 2, "b": 2})
  2454  	coll.Insert(M{"a": 2, "b": 1})
  2455  	coll.Insert(M{"a": 0, "b": 1})
  2456  	coll.Insert(M{"a": 2, "b": 0})
  2457  	coll.Insert(M{"a": 0, "b": 2})
  2458  	coll.Insert(M{"a": 1, "b": 2})
  2459  	coll.Insert(M{"a": 0, "b": 0})
  2460  	coll.Insert(M{"a": 1, "b": 0})
  2461  
  2462  	query := coll.Find(M{})
  2463  	query.Sort("-a") // Should be ignored.
  2464  	query.Sort("-b", "a")
  2465  	iter := query.Iter()
  2466  
  2467  	l := make([]int, 18)
  2468  	r := struct{ A, B int }{}
  2469  	for i := 0; i != len(l); i += 2 {
  2470  		ok := iter.Next(&r)
  2471  		c.Assert(ok, Equals, true)
  2472  		c.Assert(err, IsNil)
  2473  		l[i] = r.A
  2474  		l[i+1] = r.B
  2475  	}
  2476  
  2477  	c.Assert(l, DeepEquals, []int{0, 2, 1, 2, 2, 2, 0, 1, 1, 1, 2, 1, 0, 0, 1, 0, 2, 0})
  2478  }
  2479  
  2480  func (s *S) TestSortWithBadArgs(c *C) {
  2481  	session, err := mgo.Dial("localhost:40001")
  2482  	c.Assert(err, IsNil)
  2483  	defer session.Close()
  2484  
  2485  	coll := session.DB("mydb").C("mycoll")
  2486  
  2487  	f1 := func() { coll.Find(nil).Sort("") }
  2488  	f2 := func() { coll.Find(nil).Sort("+") }
  2489  	f3 := func() { coll.Find(nil).Sort("foo", "-") }
  2490  
  2491  	for _, f := range []func(){f1, f2, f3} {
  2492  		c.Assert(f, PanicMatches, "Sort: empty field name")
  2493  	}
  2494  }
  2495  
  2496  func (s *S) TestSortScoreText(c *C) {
  2497  	session, err := mgo.Dial("localhost:40001")
  2498  	c.Assert(err, IsNil)
  2499  	defer session.Close()
  2500  
  2501  	if !s.versionAtLeast(2, 4) {
  2502  		c.Skip("Text search depends on 2.4+")
  2503  	}
  2504  
  2505  	coll := session.DB("mydb").C("mycoll")
  2506  
  2507  	err = coll.EnsureIndex(mgo.Index{
  2508  		Key: []string{"$text:a", "$text:b"},
  2509  	})
  2510  	msg := "text search not enabled"
  2511  	if err != nil && strings.Contains(err.Error(), msg) {
  2512  		c.Skip(msg)
  2513  	}
  2514  	c.Assert(err, IsNil)
  2515  
  2516  	err = coll.Insert(M{
  2517  		"a": "none",
  2518  		"b": "twice: foo foo",
  2519  	})
  2520  	c.Assert(err, IsNil)
  2521  	err = coll.Insert(M{
  2522  		"a": "just once: foo",
  2523  		"b": "none",
  2524  	})
  2525  	c.Assert(err, IsNil)
  2526  	err = coll.Insert(M{
  2527  		"a": "many: foo foo foo",
  2528  		"b": "none",
  2529  	})
  2530  	c.Assert(err, IsNil)
  2531  	err = coll.Insert(M{
  2532  		"a": "none",
  2533  		"b": "none",
  2534  		"c": "ignore: foo",
  2535  	})
  2536  	c.Assert(err, IsNil)
  2537  
  2538  	query := coll.Find(M{"$text": M{"$search": "foo"}})
  2539  	query.Select(M{"score": M{"$meta": "textScore"}})
  2540  	query.Sort("$textScore:score")
  2541  	iter := query.Iter()
  2542  
  2543  	var r struct{ A, B string }
  2544  	var results []string
  2545  	for iter.Next(&r) {
  2546  		results = append(results, r.A, r.B)
  2547  	}
  2548  
  2549  	c.Assert(results, DeepEquals, []string{
  2550  		"many: foo foo foo", "none",
  2551  		"none", "twice: foo foo",
  2552  		"just once: foo", "none",
  2553  	})
  2554  }
  2555  
  2556  func (s *S) TestPrefetching(c *C) {
  2557  	session, err := mgo.Dial("localhost:40001")
  2558  	c.Assert(err, IsNil)
  2559  	defer session.Close()
  2560  
  2561  	coll := session.DB("mydb").C("mycoll")
  2562  
  2563  	const total = 600
  2564  	const batch = 100
  2565  	mgo.SetDebug(false)
  2566  	docs := make([]interface{}, total)
  2567  	for i := 0; i != total; i++ {
  2568  		docs[i] = bson.D{{"n", i}}
  2569  	}
  2570  	err = coll.Insert(docs...)
  2571  	c.Assert(err, IsNil)
  2572  
  2573  	for testi := 0; testi < 5; testi++ {
  2574  		mgo.ResetStats()
  2575  
  2576  		var iter *mgo.Iter
  2577  		var beforeMore int
  2578  
  2579  		switch testi {
  2580  		case 0: // The default session value.
  2581  			session.SetBatch(batch)
  2582  			iter = coll.Find(M{}).Iter()
  2583  			beforeMore = 75
  2584  
  2585  		case 2: // Changing the session value.
  2586  			session.SetBatch(batch)
  2587  			session.SetPrefetch(0.27)
  2588  			iter = coll.Find(M{}).Iter()
  2589  			beforeMore = 73
  2590  
  2591  		case 1: // Changing via query methods.
  2592  			iter = coll.Find(M{}).Prefetch(0.27).Batch(batch).Iter()
  2593  			beforeMore = 73
  2594  
  2595  		case 3: // With prefetch on first document.
  2596  			iter = coll.Find(M{}).Prefetch(1.0).Batch(batch).Iter()
  2597  			beforeMore = 0
  2598  
  2599  		case 4: // Without prefetch.
  2600  			iter = coll.Find(M{}).Prefetch(0).Batch(batch).Iter()
  2601  			beforeMore = 100
  2602  		}
  2603  
  2604  		pings := 0
  2605  		for batchi := 0; batchi < len(docs)/batch-1; batchi++ {
  2606  			c.Logf("Iterating over %d documents on batch %d", beforeMore, batchi)
  2607  			var result struct{ N int }
  2608  			for i := 0; i < beforeMore; i++ {
  2609  				ok := iter.Next(&result)
  2610  				c.Assert(ok, Equals, true, Commentf("iter.Err: %v", iter.Err()))
  2611  			}
  2612  			beforeMore = 99
  2613  			c.Logf("Done iterating.")
  2614  
  2615  			session.Run("ping", nil) // Roundtrip to settle down.
  2616  			pings++
  2617  
  2618  			stats := mgo.GetStats()
  2619  			if s.versionAtLeast(3, 2) {
  2620  				// Find command in 3.2+ bundles batches in a single document.
  2621  				c.Assert(stats.ReceivedDocs, Equals, (batchi+1)+pings)
  2622  			} else {
  2623  				c.Assert(stats.ReceivedDocs, Equals, (batchi+1)*batch+pings)
  2624  			}
  2625  
  2626  			c.Logf("Iterating over one more document on batch %d", batchi)
  2627  			ok := iter.Next(&result)
  2628  			c.Assert(ok, Equals, true, Commentf("iter.Err: %v", iter.Err()))
  2629  			c.Logf("Done iterating.")
  2630  
  2631  			session.Run("ping", nil) // Roundtrip to settle down.
  2632  			pings++
  2633  
  2634  			stats = mgo.GetStats()
  2635  			if s.versionAtLeast(3, 2) {
  2636  				// Find command in 3.2+ bundles batches in a single document.
  2637  				c.Assert(stats.ReceivedDocs, Equals, (batchi+2)+pings)
  2638  			} else {
  2639  				c.Assert(stats.ReceivedDocs, Equals, (batchi+2)*batch+pings)
  2640  			}
  2641  		}
  2642  	}
  2643  }
  2644  
  2645  func (s *S) TestSafeSetting(c *C) {
  2646  	session, err := mgo.Dial("localhost:40001")
  2647  	c.Assert(err, IsNil)
  2648  	defer session.Close()
  2649  
  2650  	// Check the default
  2651  	safe := session.Safe()
  2652  	c.Assert(safe.W, Equals, 0)
  2653  	c.Assert(safe.WMode, Equals, "")
  2654  	c.Assert(safe.WTimeout, Equals, 0)
  2655  	c.Assert(safe.FSync, Equals, false)
  2656  	c.Assert(safe.J, Equals, false)
  2657  
  2658  	// Tweak it
  2659  	session.SetSafe(&mgo.Safe{W: 1, WTimeout: 2, FSync: true})
  2660  	safe = session.Safe()
  2661  	c.Assert(safe.W, Equals, 1)
  2662  	c.Assert(safe.WMode, Equals, "")
  2663  	c.Assert(safe.WTimeout, Equals, 2)
  2664  	c.Assert(safe.FSync, Equals, true)
  2665  	c.Assert(safe.J, Equals, false)
  2666  
  2667  	// Reset it again.
  2668  	session.SetSafe(&mgo.Safe{})
  2669  	safe = session.Safe()
  2670  	c.Assert(safe.W, Equals, 0)
  2671  	c.Assert(safe.WMode, Equals, "")
  2672  	c.Assert(safe.WTimeout, Equals, 0)
  2673  	c.Assert(safe.FSync, Equals, false)
  2674  	c.Assert(safe.J, Equals, false)
  2675  
  2676  	// Ensure safety to something more conservative.
  2677  	session.SetSafe(&mgo.Safe{W: 5, WTimeout: 6, J: true})
  2678  	safe = session.Safe()
  2679  	c.Assert(safe.W, Equals, 5)
  2680  	c.Assert(safe.WMode, Equals, "")
  2681  	c.Assert(safe.WTimeout, Equals, 6)
  2682  	c.Assert(safe.FSync, Equals, false)
  2683  	c.Assert(safe.J, Equals, true)
  2684  
  2685  	// Ensure safety to something less conservative won't change it.
  2686  	session.EnsureSafe(&mgo.Safe{W: 4, WTimeout: 7})
  2687  	safe = session.Safe()
  2688  	c.Assert(safe.W, Equals, 5)
  2689  	c.Assert(safe.WMode, Equals, "")
  2690  	c.Assert(safe.WTimeout, Equals, 6)
  2691  	c.Assert(safe.FSync, Equals, false)
  2692  	c.Assert(safe.J, Equals, true)
  2693  
  2694  	// But to something more conservative will.
  2695  	session.EnsureSafe(&mgo.Safe{W: 6, WTimeout: 4, FSync: true})
  2696  	safe = session.Safe()
  2697  	c.Assert(safe.W, Equals, 6)
  2698  	c.Assert(safe.WMode, Equals, "")
  2699  	c.Assert(safe.WTimeout, Equals, 4)
  2700  	c.Assert(safe.FSync, Equals, true)
  2701  	c.Assert(safe.J, Equals, false)
  2702  
  2703  	// Even more conservative.
  2704  	session.EnsureSafe(&mgo.Safe{WMode: "majority", WTimeout: 2})
  2705  	safe = session.Safe()
  2706  	c.Assert(safe.W, Equals, 0)
  2707  	c.Assert(safe.WMode, Equals, "majority")
  2708  	c.Assert(safe.WTimeout, Equals, 2)
  2709  	c.Assert(safe.FSync, Equals, true)
  2710  	c.Assert(safe.J, Equals, false)
  2711  
  2712  	// WMode always overrides, whatever it is, but J doesn't.
  2713  	session.EnsureSafe(&mgo.Safe{WMode: "something", J: true})
  2714  	safe = session.Safe()
  2715  	c.Assert(safe.W, Equals, 0)
  2716  	c.Assert(safe.WMode, Equals, "something")
  2717  	c.Assert(safe.WTimeout, Equals, 2)
  2718  	c.Assert(safe.FSync, Equals, true)
  2719  	c.Assert(safe.J, Equals, false)
  2720  
  2721  	// EnsureSafe with nil does nothing.
  2722  	session.EnsureSafe(nil)
  2723  	safe = session.Safe()
  2724  	c.Assert(safe.W, Equals, 0)
  2725  	c.Assert(safe.WMode, Equals, "something")
  2726  	c.Assert(safe.WTimeout, Equals, 2)
  2727  	c.Assert(safe.FSync, Equals, true)
  2728  	c.Assert(safe.J, Equals, false)
  2729  
  2730  	// Changing the safety of a cloned session doesn't touch the original.
  2731  	clone := session.Clone()
  2732  	defer clone.Close()
  2733  	clone.EnsureSafe(&mgo.Safe{WMode: "foo"})
  2734  	safe = session.Safe()
  2735  	c.Assert(safe.WMode, Equals, "something")
  2736  }
  2737  
  2738  func (s *S) TestSafeInsert(c *C) {
  2739  	session, err := mgo.Dial("localhost:40001")
  2740  	c.Assert(err, IsNil)
  2741  	defer session.Close()
  2742  
  2743  	coll := session.DB("mydb").C("mycoll")
  2744  
  2745  	// Insert an element with a predefined key.
  2746  	err = coll.Insert(M{"_id": 1})
  2747  	c.Assert(err, IsNil)
  2748  
  2749  	mgo.ResetStats()
  2750  
  2751  	// Session should be safe by default, so inserting it again must fail.
  2752  	err = coll.Insert(M{"_id": 1})
  2753  	c.Assert(err, ErrorMatches, ".*E11000 duplicate.*")
  2754  	c.Assert(err.(*mgo.LastError).Code, Equals, 11000)
  2755  
  2756  	// It must have sent two operations (INSERT_OP + getLastError QUERY_OP)
  2757  	stats := mgo.GetStats()
  2758  
  2759  	if s.versionAtLeast(2, 6) {
  2760  		c.Assert(stats.SentOps, Equals, 1)
  2761  	} else {
  2762  		c.Assert(stats.SentOps, Equals, 2)
  2763  	}
  2764  
  2765  	mgo.ResetStats()
  2766  
  2767  	// If we disable safety, though, it won't complain.
  2768  	session.SetSafe(nil)
  2769  	err = coll.Insert(M{"_id": 1})
  2770  	c.Assert(err, IsNil)
  2771  
  2772  	// Must have sent a single operation this time (just the INSERT_OP)
  2773  	stats = mgo.GetStats()
  2774  	c.Assert(stats.SentOps, Equals, 1)
  2775  }
  2776  
  2777  func (s *S) TestSafeParameters(c *C) {
  2778  	session, err := mgo.Dial("localhost:40011")
  2779  	c.Assert(err, IsNil)
  2780  	defer session.Close()
  2781  
  2782  	coll := session.DB("mydb").C("mycoll")
  2783  
  2784  	// Tweak the safety parameters to something unachievable.
  2785  	session.SetSafe(&mgo.Safe{W: 4, WTimeout: 100})
  2786  	err = coll.Insert(M{"_id": 1})
  2787  	c.Assert(err, ErrorMatches, "timeout|timed out waiting for slaves|Not enough data-bearing nodes|waiting for replication timed out") // :-(
  2788  	if !s.versionAtLeast(2, 6) {
  2789  		// 2.6 turned it into a query error.
  2790  		c.Assert(err.(*mgo.LastError).WTimeout, Equals, true)
  2791  	}
  2792  }
  2793  
  2794  func (s *S) TestQueryErrorOne(c *C) {
  2795  	session, err := mgo.Dial("localhost:40001")
  2796  	c.Assert(err, IsNil)
  2797  	defer session.Close()
  2798  
  2799  	coll := session.DB("mydb").C("mycoll")
  2800  
  2801  	err = coll.Find(M{"a": 1}).Select(M{"a": M{"b": 1}}).One(nil)
  2802  	c.Assert(err, ErrorMatches, ".*Unsupported projection option:.*")
  2803  	c.Assert(err.(*mgo.QueryError).Message, Matches, ".*Unsupported projection option:.*")
  2804  	// Oh, the dance of error codes. :-(
  2805  	if s.versionAtLeast(3, 2) {
  2806  		c.Assert(err.(*mgo.QueryError).Code, Equals, 2)
  2807  	} else if s.versionAtLeast(2, 6) {
  2808  		c.Assert(err.(*mgo.QueryError).Code, Equals, 17287)
  2809  	} else {
  2810  		c.Assert(err.(*mgo.QueryError).Code, Equals, 13097)
  2811  	}
  2812  }
  2813  
  2814  func (s *S) TestQueryErrorNext(c *C) {
  2815  	session, err := mgo.Dial("localhost:40001")
  2816  	c.Assert(err, IsNil)
  2817  	defer session.Close()
  2818  
  2819  	coll := session.DB("mydb").C("mycoll")
  2820  
  2821  	iter := coll.Find(M{"a": 1}).Select(M{"a": M{"b": 1}}).Iter()
  2822  
  2823  	var result struct{}
  2824  	ok := iter.Next(&result)
  2825  	c.Assert(ok, Equals, false)
  2826  
  2827  	err = iter.Close()
  2828  	c.Assert(err, ErrorMatches, ".*Unsupported projection option:.*")
  2829  	c.Assert(err.(*mgo.QueryError).Message, Matches, ".*Unsupported projection option:.*")
  2830  	// Oh, the dance of error codes. :-(
  2831  	if s.versionAtLeast(3, 2) {
  2832  		c.Assert(err.(*mgo.QueryError).Code, Equals, 2)
  2833  	} else if s.versionAtLeast(2, 6) {
  2834  		c.Assert(err.(*mgo.QueryError).Code, Equals, 17287)
  2835  	} else {
  2836  		c.Assert(err.(*mgo.QueryError).Code, Equals, 13097)
  2837  	}
  2838  	c.Assert(iter.Err(), Equals, err)
  2839  }
  2840  
  2841  var indexTests = []struct {
  2842  	index    mgo.Index
  2843  	expected M
  2844  }{{
  2845  	mgo.Index{
  2846  		Key:        []string{"a"},
  2847  		Background: true,
  2848  	},
  2849  	M{
  2850  		"name":       "a_1",
  2851  		"key":        M{"a": 1},
  2852  		"ns":         "mydb.mycoll",
  2853  		"background": true,
  2854  	},
  2855  }, {
  2856  	mgo.Index{
  2857  		Key:      []string{"a", "-b"},
  2858  		Unique:   true,
  2859  		DropDups: true,
  2860  	},
  2861  	M{
  2862  		"name":     "a_1_b_-1",
  2863  		"key":      M{"a": 1, "b": -1},
  2864  		"ns":       "mydb.mycoll",
  2865  		"unique":   true,
  2866  		"dropDups": true,
  2867  	},
  2868  }, {
  2869  	mgo.Index{
  2870  		Key:  []string{"@loc_old"}, // Obsolete
  2871  		Min:  -500,
  2872  		Max:  500,
  2873  		Bits: 32,
  2874  	},
  2875  	M{
  2876  		"name": "loc_old_2d",
  2877  		"key":  M{"loc_old": "2d"},
  2878  		"ns":   "mydb.mycoll",
  2879  		"min":  -500.0,
  2880  		"max":  500.0,
  2881  		"bits": 32,
  2882  	},
  2883  }, {
  2884  	mgo.Index{
  2885  		Key:  []string{"$2d:loc"},
  2886  		Min:  -500,
  2887  		Max:  500,
  2888  		Bits: 32,
  2889  	},
  2890  	M{
  2891  		"name": "loc_2d",
  2892  		"key":  M{"loc": "2d"},
  2893  		"ns":   "mydb.mycoll",
  2894  		"min":  -500.0,
  2895  		"max":  500.0,
  2896  		"bits": 32,
  2897  	},
  2898  }, {
  2899  	mgo.Index{
  2900  		Key:  []string{"$2d:loc"},
  2901  		Minf: -500.1,
  2902  		Maxf: 500.1,
  2903  		Min:  1, // Should be ignored
  2904  		Max:  2,
  2905  		Bits: 32,
  2906  	},
  2907  	M{
  2908  		"name": "loc_2d",
  2909  		"key":  M{"loc": "2d"},
  2910  		"ns":   "mydb.mycoll",
  2911  		"min":  -500.1,
  2912  		"max":  500.1,
  2913  		"bits": 32,
  2914  	},
  2915  }, {
  2916  	mgo.Index{
  2917  		Key:        []string{"$geoHaystack:loc", "type"},
  2918  		BucketSize: 1,
  2919  	},
  2920  	M{
  2921  		"name":       "loc_geoHaystack_type_1",
  2922  		"key":        M{"loc": "geoHaystack", "type": 1},
  2923  		"ns":         "mydb.mycoll",
  2924  		"bucketSize": 1.0,
  2925  	},
  2926  }, {
  2927  	mgo.Index{
  2928  		Key:     []string{"$text:a", "$text:b"},
  2929  		Weights: map[string]int{"b": 42},
  2930  	},
  2931  	M{
  2932  		"name":              "a_text_b_text",
  2933  		"key":               M{"_fts": "text", "_ftsx": 1},
  2934  		"ns":                "mydb.mycoll",
  2935  		"weights":           M{"a": 1, "b": 42},
  2936  		"default_language":  "english",
  2937  		"language_override": "language",
  2938  		"textIndexVersion":  2,
  2939  	},
  2940  }, {
  2941  	mgo.Index{
  2942  		Key:              []string{"$text:a"},
  2943  		DefaultLanguage:  "portuguese",
  2944  		LanguageOverride: "idioma",
  2945  	},
  2946  	M{
  2947  		"name":              "a_text",
  2948  		"key":               M{"_fts": "text", "_ftsx": 1},
  2949  		"ns":                "mydb.mycoll",
  2950  		"weights":           M{"a": 1},
  2951  		"default_language":  "portuguese",
  2952  		"language_override": "idioma",
  2953  		"textIndexVersion":  2,
  2954  	},
  2955  }, {
  2956  	mgo.Index{
  2957  		Key: []string{"$text:$**"},
  2958  	},
  2959  	M{
  2960  		"name":              "$**_text",
  2961  		"key":               M{"_fts": "text", "_ftsx": 1},
  2962  		"ns":                "mydb.mycoll",
  2963  		"weights":           M{"$**": 1},
  2964  		"default_language":  "english",
  2965  		"language_override": "language",
  2966  		"textIndexVersion":  2,
  2967  	},
  2968  }, {
  2969  	mgo.Index{
  2970  		Key:  []string{"cn"},
  2971  		Name: "CustomName",
  2972  	},
  2973  	M{
  2974  		"name": "CustomName",
  2975  		"key":  M{"cn": 1},
  2976  		"ns":   "mydb.mycoll",
  2977  	},
  2978  }}
  2979  
  2980  func (s *S) TestEnsureIndex(c *C) {
  2981  	session, err := mgo.Dial("localhost:40001")
  2982  	c.Assert(err, IsNil)
  2983  	defer session.Close()
  2984  
  2985  	coll := session.DB("mydb").C("mycoll")
  2986  	idxs := session.DB("mydb").C("system.indexes")
  2987  
  2988  	for _, test := range indexTests {
  2989  		if !s.versionAtLeast(2, 4) && test.expected["textIndexVersion"] != nil {
  2990  			continue
  2991  		}
  2992  
  2993  		err = coll.EnsureIndex(test.index)
  2994  		msg := "text search not enabled"
  2995  		if err != nil && strings.Contains(err.Error(), msg) {
  2996  			continue
  2997  		}
  2998  		c.Assert(err, IsNil)
  2999  
  3000  		expectedName := test.index.Name
  3001  		if expectedName == "" {
  3002  			expectedName, _ = test.expected["name"].(string)
  3003  		}
  3004  
  3005  		obtained := M{}
  3006  		err = idxs.Find(M{"name": expectedName}).One(obtained)
  3007  		c.Assert(err, IsNil)
  3008  
  3009  		delete(obtained, "v")
  3010  
  3011  		if s.versionAtLeast(2, 7) {
  3012  			// Was deprecated in 2.6, and not being reported by 2.7+.
  3013  			delete(test.expected, "dropDups")
  3014  			test.index.DropDups = false
  3015  		}
  3016  		if s.versionAtLeast(3, 2) && test.expected["textIndexVersion"] != nil {
  3017  			test.expected["textIndexVersion"] = 3
  3018  		}
  3019  
  3020  		c.Assert(obtained, DeepEquals, test.expected)
  3021  
  3022  		// The result of Indexes must match closely what was used to create the index.
  3023  		indexes, err := coll.Indexes()
  3024  		c.Assert(err, IsNil)
  3025  		c.Assert(indexes, HasLen, 2)
  3026  		gotIndex := indexes[0]
  3027  		if gotIndex.Name == "_id_" {
  3028  			gotIndex = indexes[1]
  3029  		}
  3030  		wantIndex := test.index
  3031  		if wantIndex.Name == "" {
  3032  			wantIndex.Name = gotIndex.Name
  3033  		}
  3034  		if strings.HasPrefix(wantIndex.Key[0], "@") {
  3035  			wantIndex.Key[0] = "$2d:" + wantIndex.Key[0][1:]
  3036  		}
  3037  		if wantIndex.Minf == 0 && wantIndex.Maxf == 0 {
  3038  			wantIndex.Minf = float64(wantIndex.Min)
  3039  			wantIndex.Maxf = float64(wantIndex.Max)
  3040  		} else {
  3041  			wantIndex.Min = gotIndex.Min
  3042  			wantIndex.Max = gotIndex.Max
  3043  		}
  3044  		if wantIndex.DefaultLanguage == "" {
  3045  			wantIndex.DefaultLanguage = gotIndex.DefaultLanguage
  3046  		}
  3047  		if wantIndex.LanguageOverride == "" {
  3048  			wantIndex.LanguageOverride = gotIndex.LanguageOverride
  3049  		}
  3050  		for name, _ := range gotIndex.Weights {
  3051  			if _, ok := wantIndex.Weights[name]; !ok {
  3052  				if wantIndex.Weights == nil {
  3053  					wantIndex.Weights = make(map[string]int)
  3054  				}
  3055  				wantIndex.Weights[name] = 1
  3056  			}
  3057  		}
  3058  		c.Assert(gotIndex, DeepEquals, wantIndex)
  3059  
  3060  		// Drop created index by key or by name if a custom name was used.
  3061  		if test.index.Name == "" {
  3062  			err = coll.DropIndex(test.index.Key...)
  3063  			c.Assert(err, IsNil)
  3064  		} else {
  3065  			err = coll.DropIndexName(test.index.Name)
  3066  			c.Assert(err, IsNil)
  3067  		}
  3068  	}
  3069  }
  3070  
  3071  func (s *S) TestEnsureIndexWithBadInfo(c *C) {
  3072  	session, err := mgo.Dial("localhost:40001")
  3073  	c.Assert(err, IsNil)
  3074  	defer session.Close()
  3075  
  3076  	coll := session.DB("mydb").C("mycoll")
  3077  
  3078  	err = coll.EnsureIndex(mgo.Index{})
  3079  	c.Assert(err, ErrorMatches, "invalid index key:.*")
  3080  
  3081  	err = coll.EnsureIndex(mgo.Index{Key: []string{""}})
  3082  	c.Assert(err, ErrorMatches, "invalid index key:.*")
  3083  }
  3084  
  3085  func (s *S) TestEnsureIndexWithUnsafeSession(c *C) {
  3086  	session, err := mgo.Dial("localhost:40001")
  3087  	c.Assert(err, IsNil)
  3088  	defer session.Close()
  3089  
  3090  	session.SetSafe(nil)
  3091  
  3092  	coll := session.DB("mydb").C("mycoll")
  3093  
  3094  	err = coll.Insert(M{"a": 1})
  3095  	c.Assert(err, IsNil)
  3096  
  3097  	err = coll.Insert(M{"a": 1})
  3098  	c.Assert(err, IsNil)
  3099  
  3100  	// Should fail since there are duplicated entries.
  3101  	index := mgo.Index{
  3102  		Key:    []string{"a"},
  3103  		Unique: true,
  3104  	}
  3105  
  3106  	err = coll.EnsureIndex(index)
  3107  	c.Assert(err, ErrorMatches, ".*duplicate key error.*")
  3108  }
  3109  
  3110  func (s *S) TestEnsureIndexKey(c *C) {
  3111  	session, err := mgo.Dial("localhost:40001")
  3112  	c.Assert(err, IsNil)
  3113  	defer session.Close()
  3114  
  3115  	coll := session.DB("mydb").C("mycoll")
  3116  
  3117  	err = coll.EnsureIndexKey("a")
  3118  	c.Assert(err, IsNil)
  3119  
  3120  	err = coll.EnsureIndexKey("a", "-b")
  3121  	c.Assert(err, IsNil)
  3122  
  3123  	sysidx := session.DB("mydb").C("system.indexes")
  3124  
  3125  	result1 := M{}
  3126  	err = sysidx.Find(M{"name": "a_1"}).One(result1)
  3127  	c.Assert(err, IsNil)
  3128  
  3129  	result2 := M{}
  3130  	err = sysidx.Find(M{"name": "a_1_b_-1"}).One(result2)
  3131  	c.Assert(err, IsNil)
  3132  
  3133  	delete(result1, "v")
  3134  	expected1 := M{
  3135  		"name": "a_1",
  3136  		"key":  M{"a": 1},
  3137  		"ns":   "mydb.mycoll",
  3138  	}
  3139  	c.Assert(result1, DeepEquals, expected1)
  3140  
  3141  	delete(result2, "v")
  3142  	expected2 := M{
  3143  		"name": "a_1_b_-1",
  3144  		"key":  M{"a": 1, "b": -1},
  3145  		"ns":   "mydb.mycoll",
  3146  	}
  3147  	c.Assert(result2, DeepEquals, expected2)
  3148  }
  3149  
  3150  func (s *S) TestEnsureIndexDropIndex(c *C) {
  3151  	session, err := mgo.Dial("localhost:40001")
  3152  	c.Assert(err, IsNil)
  3153  	defer session.Close()
  3154  
  3155  	coll := session.DB("mydb").C("mycoll")
  3156  
  3157  	err = coll.EnsureIndexKey("a")
  3158  	c.Assert(err, IsNil)
  3159  
  3160  	err = coll.EnsureIndexKey("-b")
  3161  	c.Assert(err, IsNil)
  3162  
  3163  	err = coll.DropIndex("-b")
  3164  	c.Assert(err, IsNil)
  3165  
  3166  	sysidx := session.DB("mydb").C("system.indexes")
  3167  
  3168  	err = sysidx.Find(M{"name": "a_1"}).One(nil)
  3169  	c.Assert(err, IsNil)
  3170  
  3171  	err = sysidx.Find(M{"name": "b_1"}).One(nil)
  3172  	c.Assert(err, Equals, mgo.ErrNotFound)
  3173  
  3174  	err = coll.DropIndex("a")
  3175  	c.Assert(err, IsNil)
  3176  
  3177  	err = sysidx.Find(M{"name": "a_1"}).One(nil)
  3178  	c.Assert(err, Equals, mgo.ErrNotFound)
  3179  
  3180  	err = coll.DropIndex("a")
  3181  	c.Assert(err, ErrorMatches, "index not found.*")
  3182  }
  3183  
  3184  func (s *S) TestEnsureIndexDropIndexName(c *C) {
  3185  	session, err := mgo.Dial("localhost:40001")
  3186  	c.Assert(err, IsNil)
  3187  	defer session.Close()
  3188  
  3189  	coll := session.DB("mydb").C("mycoll")
  3190  
  3191  	err = coll.EnsureIndexKey("a")
  3192  	c.Assert(err, IsNil)
  3193  
  3194  	err = coll.EnsureIndex(mgo.Index{Key: []string{"b"}, Name: "a"})
  3195  	c.Assert(err, IsNil)
  3196  
  3197  	err = coll.DropIndexName("a")
  3198  	c.Assert(err, IsNil)
  3199  
  3200  	sysidx := session.DB("mydb").C("system.indexes")
  3201  
  3202  	err = sysidx.Find(M{"name": "a_1"}).One(nil)
  3203  	c.Assert(err, IsNil)
  3204  
  3205  	err = sysidx.Find(M{"name": "a"}).One(nil)
  3206  	c.Assert(err, Equals, mgo.ErrNotFound)
  3207  
  3208  	err = coll.DropIndexName("a_1")
  3209  	c.Assert(err, IsNil)
  3210  
  3211  	err = sysidx.Find(M{"name": "a_1"}).One(nil)
  3212  	c.Assert(err, Equals, mgo.ErrNotFound)
  3213  
  3214  	err = coll.DropIndexName("a_1")
  3215  	c.Assert(err, ErrorMatches, "index not found.*")
  3216  }
  3217  
  3218  func (s *S) TestEnsureIndexCaching(c *C) {
  3219  	session, err := mgo.Dial("localhost:40001")
  3220  	c.Assert(err, IsNil)
  3221  	defer session.Close()
  3222  
  3223  	coll := session.DB("mydb").C("mycoll")
  3224  
  3225  	err = coll.EnsureIndexKey("a")
  3226  	c.Assert(err, IsNil)
  3227  
  3228  	mgo.ResetStats()
  3229  
  3230  	// Second EnsureIndex should be cached and do nothing.
  3231  	err = coll.EnsureIndexKey("a")
  3232  	c.Assert(err, IsNil)
  3233  
  3234  	stats := mgo.GetStats()
  3235  	c.Assert(stats.SentOps, Equals, 0)
  3236  
  3237  	// Resetting the cache should make it contact the server again.
  3238  	session.ResetIndexCache()
  3239  
  3240  	err = coll.EnsureIndexKey("a")
  3241  	c.Assert(err, IsNil)
  3242  
  3243  	stats = mgo.GetStats()
  3244  	c.Assert(stats.SentOps > 0, Equals, true)
  3245  
  3246  	// Dropping the index should also drop the cached index key.
  3247  	err = coll.DropIndex("a")
  3248  	c.Assert(err, IsNil)
  3249  
  3250  	mgo.ResetStats()
  3251  
  3252  	err = coll.EnsureIndexKey("a")
  3253  	c.Assert(err, IsNil)
  3254  
  3255  	stats = mgo.GetStats()
  3256  	c.Assert(stats.SentOps > 0, Equals, true)
  3257  }
  3258  
  3259  func (s *S) TestEnsureIndexGetIndexes(c *C) {
  3260  	session, err := mgo.Dial("localhost:40001")
  3261  	c.Assert(err, IsNil)
  3262  	defer session.Close()
  3263  
  3264  	coll := session.DB("mydb").C("mycoll")
  3265  
  3266  	err = coll.EnsureIndexKey("-b")
  3267  	c.Assert(err, IsNil)
  3268  
  3269  	err = coll.EnsureIndexKey("a")
  3270  	c.Assert(err, IsNil)
  3271  
  3272  	// Obsolete.
  3273  	err = coll.EnsureIndexKey("@c")
  3274  	c.Assert(err, IsNil)
  3275  
  3276  	err = coll.EnsureIndexKey("$2d:d")
  3277  	c.Assert(err, IsNil)
  3278  
  3279  	// Try to exercise cursor logic. 2.8.0-rc3 still ignores this.
  3280  	session.SetBatch(2)
  3281  
  3282  	indexes, err := coll.Indexes()
  3283  	c.Assert(err, IsNil)
  3284  
  3285  	c.Assert(indexes[0].Name, Equals, "_id_")
  3286  	c.Assert(indexes[1].Name, Equals, "a_1")
  3287  	c.Assert(indexes[1].Key, DeepEquals, []string{"a"})
  3288  	c.Assert(indexes[2].Name, Equals, "b_-1")
  3289  	c.Assert(indexes[2].Key, DeepEquals, []string{"-b"})
  3290  	c.Assert(indexes[3].Name, Equals, "c_2d")
  3291  	c.Assert(indexes[3].Key, DeepEquals, []string{"$2d:c"})
  3292  	c.Assert(indexes[4].Name, Equals, "d_2d")
  3293  	c.Assert(indexes[4].Key, DeepEquals, []string{"$2d:d"})
  3294  }
  3295  
  3296  func (s *S) TestEnsureIndexNameCaching(c *C) {
  3297  	session, err := mgo.Dial("localhost:40001")
  3298  	c.Assert(err, IsNil)
  3299  	defer session.Close()
  3300  
  3301  	coll := session.DB("mydb").C("mycoll")
  3302  
  3303  	err = coll.EnsureIndex(mgo.Index{Key: []string{"a"}, Name: "custom"})
  3304  	c.Assert(err, IsNil)
  3305  
  3306  	mgo.ResetStats()
  3307  
  3308  	// Second EnsureIndex should be cached and do nothing.
  3309  	err = coll.EnsureIndexKey("a")
  3310  	c.Assert(err, IsNil)
  3311  
  3312  	err = coll.EnsureIndex(mgo.Index{Key: []string{"a"}, Name: "custom"})
  3313  	c.Assert(err, IsNil)
  3314  
  3315  	stats := mgo.GetStats()
  3316  	c.Assert(stats.SentOps, Equals, 0)
  3317  
  3318  	// Resetting the cache should make it contact the server again.
  3319  	session.ResetIndexCache()
  3320  
  3321  	err = coll.EnsureIndex(mgo.Index{Key: []string{"a"}, Name: "custom"})
  3322  	c.Assert(err, IsNil)
  3323  
  3324  	stats = mgo.GetStats()
  3325  	c.Assert(stats.SentOps > 0, Equals, true)
  3326  
  3327  	// Dropping the index should also drop the cached index key.
  3328  	err = coll.DropIndexName("custom")
  3329  	c.Assert(err, IsNil)
  3330  
  3331  	mgo.ResetStats()
  3332  
  3333  	err = coll.EnsureIndex(mgo.Index{Key: []string{"a"}, Name: "custom"})
  3334  	c.Assert(err, IsNil)
  3335  
  3336  	stats = mgo.GetStats()
  3337  	c.Assert(stats.SentOps > 0, Equals, true)
  3338  }
  3339  
  3340  func (s *S) TestEnsureIndexEvalGetIndexes(c *C) {
  3341  	session, err := mgo.Dial("localhost:40001")
  3342  	c.Assert(err, IsNil)
  3343  	defer session.Close()
  3344  
  3345  	coll := session.DB("mydb").C("mycoll")
  3346  
  3347  	err = session.Run(bson.D{{"eval", "db.getSiblingDB('mydb').mycoll.ensureIndex({b: -1})"}}, nil)
  3348  	c.Assert(err, IsNil)
  3349  	err = session.Run(bson.D{{"eval", "db.getSiblingDB('mydb').mycoll.ensureIndex({a: 1})"}}, nil)
  3350  	c.Assert(err, IsNil)
  3351  	err = session.Run(bson.D{{"eval", "db.getSiblingDB('mydb').mycoll.ensureIndex({c: -1, e: 1})"}}, nil)
  3352  	c.Assert(err, IsNil)
  3353  	err = session.Run(bson.D{{"eval", "db.getSiblingDB('mydb').mycoll.ensureIndex({d: '2d'})"}}, nil)
  3354  	c.Assert(err, IsNil)
  3355  
  3356  	indexes, err := coll.Indexes()
  3357  	c.Assert(err, IsNil)
  3358  
  3359  	c.Assert(indexes[0].Name, Equals, "_id_")
  3360  	c.Assert(indexes[1].Name, Equals, "a_1")
  3361  	c.Assert(indexes[1].Key, DeepEquals, []string{"a"})
  3362  	c.Assert(indexes[2].Name, Equals, "b_-1")
  3363  	c.Assert(indexes[2].Key, DeepEquals, []string{"-b"})
  3364  	c.Assert(indexes[3].Name, Equals, "c_-1_e_1")
  3365  	c.Assert(indexes[3].Key, DeepEquals, []string{"-c", "e"})
  3366  	if s.versionAtLeast(2, 2) {
  3367  		c.Assert(indexes[4].Name, Equals, "d_2d")
  3368  		c.Assert(indexes[4].Key, DeepEquals, []string{"$2d:d"})
  3369  	} else {
  3370  		c.Assert(indexes[4].Name, Equals, "d_")
  3371  		c.Assert(indexes[4].Key, DeepEquals, []string{"$2d:d"})
  3372  	}
  3373  }
  3374  
  3375  var testTTL = flag.Bool("test-ttl", false, "test TTL collections (may take 1 minute)")
  3376  
  3377  func (s *S) TestEnsureIndexExpireAfter(c *C) {
  3378  	session, err := mgo.Dial("localhost:40001")
  3379  	c.Assert(err, IsNil)
  3380  	defer session.Close()
  3381  
  3382  	session.SetSafe(nil)
  3383  
  3384  	coll := session.DB("mydb").C("mycoll")
  3385  
  3386  	err = coll.Insert(M{"n": 1, "t": time.Now().Add(-120 * time.Second)})
  3387  	c.Assert(err, IsNil)
  3388  	err = coll.Insert(M{"n": 2, "t": time.Now()})
  3389  	c.Assert(err, IsNil)
  3390  
  3391  	// Should fail since there are duplicated entries.
  3392  	index := mgo.Index{
  3393  		Key:         []string{"t"},
  3394  		ExpireAfter: 1 * time.Minute,
  3395  	}
  3396  
  3397  	err = coll.EnsureIndex(index)
  3398  	c.Assert(err, IsNil)
  3399  
  3400  	indexes, err := coll.Indexes()
  3401  	c.Assert(err, IsNil)
  3402  	c.Assert(indexes[1].Name, Equals, "t_1")
  3403  	c.Assert(indexes[1].ExpireAfter, Equals, 1*time.Minute)
  3404  
  3405  	if *testTTL {
  3406  		worked := false
  3407  		stop := time.Now().Add(70 * time.Second)
  3408  		for time.Now().Before(stop) {
  3409  			n, err := coll.Count()
  3410  			c.Assert(err, IsNil)
  3411  			if n == 1 {
  3412  				worked = true
  3413  				break
  3414  			}
  3415  			c.Assert(n, Equals, 2)
  3416  			c.Logf("Still has 2 entries...")
  3417  			time.Sleep(1 * time.Second)
  3418  		}
  3419  		if !worked {
  3420  			c.Fatalf("TTL index didn't work")
  3421  		}
  3422  	}
  3423  }
  3424  
  3425  func (s *S) TestDistinct(c *C) {
  3426  	session, err := mgo.Dial("localhost:40001")
  3427  	c.Assert(err, IsNil)
  3428  	defer session.Close()
  3429  
  3430  	coll := session.DB("mydb").C("mycoll")
  3431  
  3432  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3433  		coll.Insert(M{"n": i})
  3434  	}
  3435  
  3436  	var result []int
  3437  	err = coll.Find(M{"n": M{"$gt": 2}}).Sort("n").Distinct("n", &result)
  3438  
  3439  	sort.IntSlice(result).Sort()
  3440  	c.Assert(result, DeepEquals, []int{3, 4, 6})
  3441  }
  3442  
  3443  func (s *S) TestMapReduce(c *C) {
  3444  	session, err := mgo.Dial("localhost:40001")
  3445  	c.Assert(err, IsNil)
  3446  	defer session.Close()
  3447  
  3448  	coll := session.DB("mydb").C("mycoll")
  3449  
  3450  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3451  		coll.Insert(M{"n": i})
  3452  	}
  3453  
  3454  	job := &mgo.MapReduce{
  3455  		Map:    "function() { emit(this.n, 1); }",
  3456  		Reduce: "function(key, values) { return Array.sum(values); }",
  3457  	}
  3458  	var result []struct {
  3459  		Id    int "_id"
  3460  		Value int
  3461  	}
  3462  
  3463  	info, err := coll.Find(M{"n": M{"$gt": 2}}).MapReduce(job, &result)
  3464  	c.Assert(err, IsNil)
  3465  	c.Assert(info.InputCount, Equals, 4)
  3466  	c.Assert(info.EmitCount, Equals, 4)
  3467  	c.Assert(info.OutputCount, Equals, 3)
  3468  	c.Assert(info.VerboseTime, IsNil)
  3469  
  3470  	expected := map[int]int{3: 1, 4: 2, 6: 1}
  3471  	for _, item := range result {
  3472  		c.Logf("Item: %#v", &item)
  3473  		c.Assert(item.Value, Equals, expected[item.Id])
  3474  		expected[item.Id] = -1
  3475  	}
  3476  }
  3477  
  3478  func (s *S) TestMapReduceFinalize(c *C) {
  3479  	session, err := mgo.Dial("localhost:40001")
  3480  	c.Assert(err, IsNil)
  3481  	defer session.Close()
  3482  
  3483  	coll := session.DB("mydb").C("mycoll")
  3484  
  3485  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3486  		coll.Insert(M{"n": i})
  3487  	}
  3488  
  3489  	job := &mgo.MapReduce{
  3490  		Map:      "function() { emit(this.n, 1) }",
  3491  		Reduce:   "function(key, values) { return Array.sum(values) }",
  3492  		Finalize: "function(key, count) { return {count: count} }",
  3493  	}
  3494  	var result []struct {
  3495  		Id    int "_id"
  3496  		Value struct{ Count int }
  3497  	}
  3498  	_, err = coll.Find(nil).MapReduce(job, &result)
  3499  	c.Assert(err, IsNil)
  3500  
  3501  	expected := map[int]int{1: 1, 2: 2, 3: 1, 4: 2, 6: 1}
  3502  	for _, item := range result {
  3503  		c.Logf("Item: %#v", &item)
  3504  		c.Assert(item.Value.Count, Equals, expected[item.Id])
  3505  		expected[item.Id] = -1
  3506  	}
  3507  }
  3508  
  3509  func (s *S) TestMapReduceToCollection(c *C) {
  3510  	session, err := mgo.Dial("localhost:40001")
  3511  	c.Assert(err, IsNil)
  3512  	defer session.Close()
  3513  
  3514  	coll := session.DB("mydb").C("mycoll")
  3515  
  3516  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3517  		coll.Insert(M{"n": i})
  3518  	}
  3519  
  3520  	job := &mgo.MapReduce{
  3521  		Map:    "function() { emit(this.n, 1); }",
  3522  		Reduce: "function(key, values) { return Array.sum(values); }",
  3523  		Out:    "mr",
  3524  	}
  3525  
  3526  	info, err := coll.Find(nil).MapReduce(job, nil)
  3527  	c.Assert(err, IsNil)
  3528  	c.Assert(info.InputCount, Equals, 7)
  3529  	c.Assert(info.EmitCount, Equals, 7)
  3530  	c.Assert(info.OutputCount, Equals, 5)
  3531  	c.Assert(info.Collection, Equals, "mr")
  3532  	c.Assert(info.Database, Equals, "mydb")
  3533  
  3534  	expected := map[int]int{1: 1, 2: 2, 3: 1, 4: 2, 6: 1}
  3535  	var item *struct {
  3536  		Id    int "_id"
  3537  		Value int
  3538  	}
  3539  	mr := session.DB("mydb").C("mr")
  3540  	iter := mr.Find(nil).Iter()
  3541  	for iter.Next(&item) {
  3542  		c.Logf("Item: %#v", &item)
  3543  		c.Assert(item.Value, Equals, expected[item.Id])
  3544  		expected[item.Id] = -1
  3545  	}
  3546  	c.Assert(iter.Close(), IsNil)
  3547  }
  3548  
  3549  func (s *S) TestMapReduceToOtherDb(c *C) {
  3550  	session, err := mgo.Dial("localhost:40001")
  3551  	c.Assert(err, IsNil)
  3552  	defer session.Close()
  3553  
  3554  	coll := session.DB("mydb").C("mycoll")
  3555  
  3556  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3557  		coll.Insert(M{"n": i})
  3558  	}
  3559  
  3560  	job := &mgo.MapReduce{
  3561  		Map:    "function() { emit(this.n, 1); }",
  3562  		Reduce: "function(key, values) { return Array.sum(values); }",
  3563  		Out:    bson.D{{"replace", "mr"}, {"db", "otherdb"}},
  3564  	}
  3565  
  3566  	info, err := coll.Find(nil).MapReduce(job, nil)
  3567  	c.Assert(err, IsNil)
  3568  	c.Assert(info.InputCount, Equals, 7)
  3569  	c.Assert(info.EmitCount, Equals, 7)
  3570  	c.Assert(info.OutputCount, Equals, 5)
  3571  	c.Assert(info.Collection, Equals, "mr")
  3572  	c.Assert(info.Database, Equals, "otherdb")
  3573  
  3574  	expected := map[int]int{1: 1, 2: 2, 3: 1, 4: 2, 6: 1}
  3575  	var item *struct {
  3576  		Id    int "_id"
  3577  		Value int
  3578  	}
  3579  	mr := session.DB("otherdb").C("mr")
  3580  	iter := mr.Find(nil).Iter()
  3581  	for iter.Next(&item) {
  3582  		c.Logf("Item: %#v", &item)
  3583  		c.Assert(item.Value, Equals, expected[item.Id])
  3584  		expected[item.Id] = -1
  3585  	}
  3586  	c.Assert(iter.Close(), IsNil)
  3587  }
  3588  
  3589  func (s *S) TestMapReduceOutOfOrder(c *C) {
  3590  	session, err := mgo.Dial("localhost:40001")
  3591  	c.Assert(err, IsNil)
  3592  	defer session.Close()
  3593  
  3594  	coll := session.DB("mydb").C("mycoll")
  3595  
  3596  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3597  		coll.Insert(M{"n": i})
  3598  	}
  3599  
  3600  	job := &mgo.MapReduce{
  3601  		Map:    "function() { emit(this.n, 1); }",
  3602  		Reduce: "function(key, values) { return Array.sum(values); }",
  3603  		Out:    bson.M{"a": "a", "z": "z", "replace": "mr", "db": "otherdb", "b": "b", "y": "y"},
  3604  	}
  3605  
  3606  	info, err := coll.Find(nil).MapReduce(job, nil)
  3607  	c.Assert(err, IsNil)
  3608  	c.Assert(info.Collection, Equals, "mr")
  3609  	c.Assert(info.Database, Equals, "otherdb")
  3610  }
  3611  
  3612  func (s *S) TestMapReduceScope(c *C) {
  3613  	session, err := mgo.Dial("localhost:40001")
  3614  	c.Assert(err, IsNil)
  3615  	defer session.Close()
  3616  
  3617  	coll := session.DB("mydb").C("mycoll")
  3618  
  3619  	coll.Insert(M{"n": 1})
  3620  
  3621  	job := &mgo.MapReduce{
  3622  		Map:    "function() { emit(this.n, x); }",
  3623  		Reduce: "function(key, values) { return Array.sum(values); }",
  3624  		Scope:  M{"x": 42},
  3625  	}
  3626  
  3627  	var result []bson.M
  3628  	_, err = coll.Find(nil).MapReduce(job, &result)
  3629  	c.Assert(len(result), Equals, 1)
  3630  	c.Assert(result[0]["value"], Equals, 42.0)
  3631  }
  3632  
  3633  func (s *S) TestMapReduceVerbose(c *C) {
  3634  	session, err := mgo.Dial("localhost:40001")
  3635  	c.Assert(err, IsNil)
  3636  	defer session.Close()
  3637  
  3638  	coll := session.DB("mydb").C("mycoll")
  3639  
  3640  	for i := 0; i < 100; i++ {
  3641  		err = coll.Insert(M{"n": i})
  3642  		c.Assert(err, IsNil)
  3643  	}
  3644  
  3645  	job := &mgo.MapReduce{
  3646  		Map:     "function() { emit(this.n, 1); }",
  3647  		Reduce:  "function(key, values) { return Array.sum(values); }",
  3648  		Verbose: true,
  3649  	}
  3650  
  3651  	info, err := coll.Find(nil).MapReduce(job, nil)
  3652  	c.Assert(err, IsNil)
  3653  	c.Assert(info.VerboseTime, NotNil)
  3654  }
  3655  
  3656  func (s *S) TestMapReduceLimit(c *C) {
  3657  	session, err := mgo.Dial("localhost:40001")
  3658  	c.Assert(err, IsNil)
  3659  	defer session.Close()
  3660  
  3661  	coll := session.DB("mydb").C("mycoll")
  3662  
  3663  	for _, i := range []int{1, 4, 6, 2, 2, 3, 4} {
  3664  		coll.Insert(M{"n": i})
  3665  	}
  3666  
  3667  	job := &mgo.MapReduce{
  3668  		Map:    "function() { emit(this.n, 1); }",
  3669  		Reduce: "function(key, values) { return Array.sum(values); }",
  3670  	}
  3671  
  3672  	var result []bson.M
  3673  	_, err = coll.Find(nil).Limit(3).MapReduce(job, &result)
  3674  	c.Assert(err, IsNil)
  3675  	c.Assert(len(result), Equals, 3)
  3676  }
  3677  
  3678  func (s *S) TestBuildInfo(c *C) {
  3679  	session, err := mgo.Dial("localhost:40001")
  3680  	c.Assert(err, IsNil)
  3681  	defer session.Close()
  3682  
  3683  	info, err := session.BuildInfo()
  3684  	c.Assert(err, IsNil)
  3685  
  3686  	var v []int
  3687  	for i, a := range strings.Split(info.Version, ".") {
  3688  		for _, token := range []string{"-rc", "-pre"} {
  3689  			if i == 2 && strings.Contains(a, token) {
  3690  				a = a[:strings.Index(a, token)]
  3691  				info.VersionArray[len(info.VersionArray)-1] = 0
  3692  			}
  3693  		}
  3694  		n, err := strconv.Atoi(a)
  3695  		c.Assert(err, IsNil)
  3696  		v = append(v, n)
  3697  	}
  3698  	for len(v) < 4 {
  3699  		v = append(v, 0)
  3700  	}
  3701  
  3702  	c.Assert(info.VersionArray, DeepEquals, v)
  3703  	c.Assert(info.GitVersion, Matches, "[a-z0-9]+")
  3704  
  3705  	if s.versionAtLeast(3, 2) {
  3706  		// It was deprecated in 3.2.
  3707  		c.Assert(info.SysInfo, Equals, "")
  3708  	} else {
  3709  		c.Assert(info.SysInfo, Matches, ".*[0-9:]+.*")
  3710  	}
  3711  	if info.Bits != 32 && info.Bits != 64 {
  3712  		c.Fatalf("info.Bits is %d", info.Bits)
  3713  	}
  3714  	if info.MaxObjectSize < 8192 {
  3715  		c.Fatalf("info.MaxObjectSize seems too small: %d", info.MaxObjectSize)
  3716  	}
  3717  }
  3718  
  3719  func (s *S) TestZeroTimeRoundtrip(c *C) {
  3720  	session, err := mgo.Dial("localhost:40001")
  3721  	c.Assert(err, IsNil)
  3722  	defer session.Close()
  3723  
  3724  	var d struct{ T time.Time }
  3725  	conn := session.DB("mydb").C("mycoll")
  3726  	err = conn.Insert(d)
  3727  	c.Assert(err, IsNil)
  3728  
  3729  	var result bson.M
  3730  	err = conn.Find(nil).One(&result)
  3731  	c.Assert(err, IsNil)
  3732  	t, isTime := result["t"].(time.Time)
  3733  	c.Assert(isTime, Equals, true)
  3734  	c.Assert(t, Equals, time.Time{})
  3735  }
  3736  
  3737  func (s *S) TestFsyncLock(c *C) {
  3738  	session, err := mgo.Dial("localhost:40001")
  3739  	c.Assert(err, IsNil)
  3740  	defer session.Close()
  3741  
  3742  	clone := session.Clone()
  3743  	defer clone.Close()
  3744  
  3745  	err = session.FsyncLock()
  3746  	c.Assert(err, IsNil)
  3747  
  3748  	done := make(chan time.Time)
  3749  	go func() {
  3750  		time.Sleep(3 * time.Second)
  3751  		now := time.Now()
  3752  		err := session.FsyncUnlock()
  3753  		c.Check(err, IsNil)
  3754  		done <- now
  3755  	}()
  3756  
  3757  	err = clone.DB("mydb").C("mycoll").Insert(bson.M{"n": 1})
  3758  	unlocked := time.Now()
  3759  	unlocking := <-done
  3760  	c.Assert(err, IsNil)
  3761  
  3762  	c.Assert(unlocked.After(unlocking), Equals, true)
  3763  }
  3764  
  3765  func (s *S) TestFsync(c *C) {
  3766  	session, err := mgo.Dial("localhost:40001")
  3767  	c.Assert(err, IsNil)
  3768  	defer session.Close()
  3769  
  3770  	// Not much to do here. Just a smoke check.
  3771  	err = session.Fsync(false)
  3772  	c.Assert(err, IsNil)
  3773  	err = session.Fsync(true)
  3774  	c.Assert(err, IsNil)
  3775  }
  3776  
  3777  func (s *S) TestRepairCursor(c *C) {
  3778  	if !s.versionAtLeast(2, 7) {
  3779  		c.Skip("RepairCursor only works on 2.7+")
  3780  	}
  3781  
  3782  	session, err := mgo.Dial("localhost:40001")
  3783  	c.Assert(err, IsNil)
  3784  	defer session.Close()
  3785  	session.SetBatch(2)
  3786  
  3787  	coll := session.DB("mydb").C("mycoll3")
  3788  	err = coll.DropCollection()
  3789  
  3790  	ns := []int{0, 10, 20, 30, 40, 50}
  3791  	for _, n := range ns {
  3792  		coll.Insert(M{"n": n})
  3793  	}
  3794  
  3795  	repairIter := coll.Repair()
  3796  
  3797  	c.Assert(repairIter.Err(), IsNil)
  3798  
  3799  	result := struct{ N int }{}
  3800  	resultCounts := map[int]int{}
  3801  	for repairIter.Next(&result) {
  3802  		resultCounts[result.N]++
  3803  	}
  3804  
  3805  	c.Assert(repairIter.Next(&result), Equals, false)
  3806  	c.Assert(repairIter.Err(), IsNil)
  3807  	c.Assert(repairIter.Close(), IsNil)
  3808  
  3809  	// Verify that the results of the repair cursor are valid.
  3810  	// The repair cursor can return multiple copies
  3811  	// of the same document, so to check correctness we only
  3812  	// need to verify that at least 1 of each document was returned.
  3813  
  3814  	for _, key := range ns {
  3815  		c.Assert(resultCounts[key] > 0, Equals, true)
  3816  	}
  3817  }
  3818  
  3819  func (s *S) TestPipeIter(c *C) {
  3820  	if !s.versionAtLeast(2, 1) {
  3821  		c.Skip("Pipe only works on 2.1+")
  3822  	}
  3823  
  3824  	session, err := mgo.Dial("localhost:40001")
  3825  	c.Assert(err, IsNil)
  3826  	defer session.Close()
  3827  
  3828  	coll := session.DB("mydb").C("mycoll")
  3829  
  3830  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  3831  	for _, n := range ns {
  3832  		coll.Insert(M{"n": n})
  3833  	}
  3834  
  3835  	pipe := coll.Pipe([]M{{"$match": M{"n": M{"$gte": 42}}}})
  3836  
  3837  	// Ensure cursor logic is working by forcing a small batch.
  3838  	pipe.Batch(2)
  3839  
  3840  	// Smoke test for AllowDiskUse.
  3841  	pipe.AllowDiskUse()
  3842  
  3843  	iter := pipe.Iter()
  3844  	result := struct{ N int }{}
  3845  	for i := 2; i < 7; i++ {
  3846  		ok := iter.Next(&result)
  3847  		c.Assert(ok, Equals, true)
  3848  		c.Assert(result.N, Equals, ns[i])
  3849  	}
  3850  
  3851  	c.Assert(iter.Next(&result), Equals, false)
  3852  	c.Assert(iter.Close(), IsNil)
  3853  }
  3854  
  3855  func (s *S) TestPipeAll(c *C) {
  3856  	if !s.versionAtLeast(2, 1) {
  3857  		c.Skip("Pipe only works on 2.1+")
  3858  	}
  3859  
  3860  	session, err := mgo.Dial("localhost:40001")
  3861  	c.Assert(err, IsNil)
  3862  	defer session.Close()
  3863  
  3864  	coll := session.DB("mydb").C("mycoll")
  3865  
  3866  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  3867  	for _, n := range ns {
  3868  		err := coll.Insert(M{"n": n})
  3869  		c.Assert(err, IsNil)
  3870  	}
  3871  
  3872  	var result []struct{ N int }
  3873  	err = coll.Pipe([]M{{"$match": M{"n": M{"$gte": 42}}}}).All(&result)
  3874  	c.Assert(err, IsNil)
  3875  	for i := 2; i < 7; i++ {
  3876  		c.Assert(result[i-2].N, Equals, ns[i])
  3877  	}
  3878  }
  3879  
  3880  func (s *S) TestPipeOne(c *C) {
  3881  	if !s.versionAtLeast(2, 1) {
  3882  		c.Skip("Pipe only works on 2.1+")
  3883  	}
  3884  
  3885  	session, err := mgo.Dial("localhost:40001")
  3886  	c.Assert(err, IsNil)
  3887  	defer session.Close()
  3888  
  3889  	coll := session.DB("mydb").C("mycoll")
  3890  	coll.Insert(M{"a": 1, "b": 2})
  3891  
  3892  	result := struct{ A, B int }{}
  3893  
  3894  	pipe := coll.Pipe([]M{{"$project": M{"a": 1, "b": M{"$add": []interface{}{"$b", 1}}}}})
  3895  	err = pipe.One(&result)
  3896  	c.Assert(err, IsNil)
  3897  	c.Assert(result.A, Equals, 1)
  3898  	c.Assert(result.B, Equals, 3)
  3899  
  3900  	pipe = coll.Pipe([]M{{"$match": M{"a": 2}}})
  3901  	err = pipe.One(&result)
  3902  	c.Assert(err, Equals, mgo.ErrNotFound)
  3903  }
  3904  
  3905  func (s *S) TestPipeExplain(c *C) {
  3906  	if !s.versionAtLeast(2, 1) {
  3907  		c.Skip("Pipe only works on 2.1+")
  3908  	}
  3909  
  3910  	session, err := mgo.Dial("localhost:40001")
  3911  	c.Assert(err, IsNil)
  3912  	defer session.Close()
  3913  
  3914  	coll := session.DB("mydb").C("mycoll")
  3915  	coll.Insert(M{"a": 1, "b": 2})
  3916  
  3917  	pipe := coll.Pipe([]M{{"$project": M{"a": 1, "b": M{"$add": []interface{}{"$b", 1}}}}})
  3918  
  3919  	// The explain command result changes across versions.
  3920  	var result struct{ Ok int }
  3921  	err = pipe.Explain(&result)
  3922  	c.Assert(err, IsNil)
  3923  	c.Assert(result.Ok, Equals, 1)
  3924  }
  3925  
  3926  func (s *S) TestBatch1Bug(c *C) {
  3927  	session, err := mgo.Dial("localhost:40001")
  3928  	c.Assert(err, IsNil)
  3929  	defer session.Close()
  3930  
  3931  	coll := session.DB("mydb").C("mycoll")
  3932  
  3933  	for i := 0; i < 3; i++ {
  3934  		err := coll.Insert(M{"n": i})
  3935  		c.Assert(err, IsNil)
  3936  	}
  3937  
  3938  	var ns []struct{ N int }
  3939  	err = coll.Find(nil).Batch(1).All(&ns)
  3940  	c.Assert(err, IsNil)
  3941  	c.Assert(len(ns), Equals, 3)
  3942  
  3943  	session.SetBatch(1)
  3944  	err = coll.Find(nil).All(&ns)
  3945  	c.Assert(err, IsNil)
  3946  	c.Assert(len(ns), Equals, 3)
  3947  }
  3948  
  3949  func (s *S) TestInterfaceIterBug(c *C) {
  3950  	session, err := mgo.Dial("localhost:40001")
  3951  	c.Assert(err, IsNil)
  3952  	defer session.Close()
  3953  
  3954  	coll := session.DB("mydb").C("mycoll")
  3955  
  3956  	for i := 0; i < 3; i++ {
  3957  		err := coll.Insert(M{"n": i})
  3958  		c.Assert(err, IsNil)
  3959  	}
  3960  
  3961  	var result interface{}
  3962  
  3963  	i := 0
  3964  	iter := coll.Find(nil).Sort("n").Iter()
  3965  	for iter.Next(&result) {
  3966  		c.Assert(result.(bson.M)["n"], Equals, i)
  3967  		i++
  3968  	}
  3969  	c.Assert(iter.Close(), IsNil)
  3970  }
  3971  
  3972  func (s *S) TestFindIterCloseKillsCursor(c *C) {
  3973  	session, err := mgo.Dial("localhost:40001")
  3974  	c.Assert(err, IsNil)
  3975  	defer session.Close()
  3976  
  3977  	cursors := serverCursorsOpen(session)
  3978  
  3979  	coll := session.DB("mydb").C("mycoll")
  3980  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  3981  	for _, n := range ns {
  3982  		err = coll.Insert(M{"n": n})
  3983  		c.Assert(err, IsNil)
  3984  	}
  3985  
  3986  	iter := coll.Find(nil).Batch(2).Iter()
  3987  	c.Assert(iter.Next(bson.M{}), Equals, true)
  3988  
  3989  	c.Assert(iter.Close(), IsNil)
  3990  	c.Assert(serverCursorsOpen(session), Equals, cursors)
  3991  }
  3992  
  3993  func (s *S) TestFindIterDoneWithBatches(c *C) {
  3994  	session, err := mgo.Dial("localhost:40001")
  3995  	c.Assert(err, IsNil)
  3996  	defer session.Close()
  3997  
  3998  	coll := session.DB("mydb").C("mycoll")
  3999  
  4000  	ns := []int{40, 41, 42, 43, 44, 45, 46}
  4001  	for _, n := range ns {
  4002  		coll.Insert(M{"n": n})
  4003  	}
  4004  
  4005  	iter := coll.Find(M{"n": M{"$gte": 42}}).Sort("$natural").Prefetch(0).Batch(2).Iter()
  4006  	result := struct{ N int }{}
  4007  	for i := 2; i < 7; i++ {
  4008  		// first check will be with pending local record;
  4009  		// second will be with open cursor ID but no local
  4010  		// records
  4011  		c.Assert(iter.Done(), Equals, false)
  4012  		ok := iter.Next(&result)
  4013  		c.Assert(ok, Equals, true, Commentf("err=%v", err))
  4014  	}
  4015  
  4016  	c.Assert(iter.Done(), Equals, true)
  4017  	ok := iter.Next(&result)
  4018  	c.Assert(ok, Equals, false)
  4019  	c.Assert(iter.Close(), IsNil)
  4020  }
  4021  
  4022  func (s *S) TestFindIterDoneErr(c *C) {
  4023  	session, err := mgo.Dial("localhost:40002")
  4024  	c.Assert(err, IsNil)
  4025  	defer session.Close()
  4026  
  4027  	coll := session.DB("mydb").C("mycoll")
  4028  	iter := coll.Find(nil).Iter()
  4029  
  4030  	result := struct{}{}
  4031  	ok := iter.Next(&result)
  4032  	c.Assert(iter.Done(), Equals, true)
  4033  	c.Assert(ok, Equals, false)
  4034  	c.Assert(iter.Err(), ErrorMatches, "unauthorized.*|not authorized.*")
  4035  }
  4036  
  4037  func (s *S) TestFindIterDoneNotFound(c *C) {
  4038  	session, err := mgo.Dial("localhost:40001")
  4039  	c.Assert(err, IsNil)
  4040  	defer session.Close()
  4041  
  4042  	coll := session.DB("mydb").C("mycoll")
  4043  
  4044  	result := struct{ A, B int }{}
  4045  	iter := coll.Find(M{"a": 1}).Iter()
  4046  	ok := iter.Next(&result)
  4047  	c.Assert(ok, Equals, false)
  4048  	c.Assert(iter.Done(), Equals, true)
  4049  }
  4050  
  4051  func (s *S) TestLogReplay(c *C) {
  4052  	session, err := mgo.Dial("localhost:40001")
  4053  	c.Assert(err, IsNil)
  4054  	defer session.Close()
  4055  
  4056  	coll := session.DB("mydb").C("mycoll")
  4057  	for i := 0; i < 5; i++ {
  4058  		err = coll.Insert(M{"ts": time.Now()})
  4059  		c.Assert(err, IsNil)
  4060  	}
  4061  
  4062  	iter := coll.Find(nil).LogReplay().Iter()
  4063  	if s.versionAtLeast(2, 6) {
  4064  		// This used to fail in 2.4. Now it's just a smoke test.
  4065  		c.Assert(iter.Err(), IsNil)
  4066  	} else {
  4067  		c.Assert(iter.Next(bson.M{}), Equals, false)
  4068  		c.Assert(iter.Err(), ErrorMatches, "no ts field in query")
  4069  	}
  4070  }
  4071  
  4072  func (s *S) TestSetCursorTimeout(c *C) {
  4073  	session, err := mgo.Dial("localhost:40001")
  4074  	c.Assert(err, IsNil)
  4075  	defer session.Close()
  4076  
  4077  	coll := session.DB("mydb").C("mycoll")
  4078  	err = coll.Insert(M{"n": 42})
  4079  
  4080  	// This is just a smoke test. Won't wait 10 minutes for an actual timeout.
  4081  
  4082  	session.SetCursorTimeout(0)
  4083  
  4084  	var result struct{ N int }
  4085  	iter := coll.Find(nil).Iter()
  4086  	c.Assert(iter.Next(&result), Equals, true)
  4087  	c.Assert(result.N, Equals, 42)
  4088  	c.Assert(iter.Next(&result), Equals, false)
  4089  }
  4090  
  4091  func (s *S) TestNewIterNoServer(c *C) {
  4092  	session, err := mgo.Dial("localhost:40001")
  4093  	c.Assert(err, IsNil)
  4094  	defer session.Close()
  4095  
  4096  	data, err := bson.Marshal(bson.M{"a": 1})
  4097  
  4098  	coll := session.DB("mydb").C("mycoll")
  4099  	iter := coll.NewIter(nil, []bson.Raw{{3, data}}, 42, nil)
  4100  
  4101  	var result struct{ A int }
  4102  	ok := iter.Next(&result)
  4103  	c.Assert(ok, Equals, true)
  4104  	c.Assert(result.A, Equals, 1)
  4105  
  4106  	ok = iter.Next(&result)
  4107  	c.Assert(ok, Equals, false)
  4108  
  4109  	c.Assert(iter.Err(), ErrorMatches, "server not available")
  4110  }
  4111  
  4112  func (s *S) TestNewIterNoServerPresetErr(c *C) {
  4113  	session, err := mgo.Dial("localhost:40001")
  4114  	c.Assert(err, IsNil)
  4115  	defer session.Close()
  4116  
  4117  	data, err := bson.Marshal(bson.M{"a": 1})
  4118  
  4119  	coll := session.DB("mydb").C("mycoll")
  4120  	iter := coll.NewIter(nil, []bson.Raw{{3, data}}, 42, fmt.Errorf("my error"))
  4121  
  4122  	var result struct{ A int }
  4123  	ok := iter.Next(&result)
  4124  	c.Assert(ok, Equals, true)
  4125  	c.Assert(result.A, Equals, 1)
  4126  
  4127  	ok = iter.Next(&result)
  4128  	c.Assert(ok, Equals, false)
  4129  
  4130  	c.Assert(iter.Err(), ErrorMatches, "my error")
  4131  }
  4132  
  4133  func (s *S) TestBypassValidation(c *C) {
  4134  	if !s.versionAtLeast(3, 2) {
  4135  		c.Skip("validation supported on 3.2+")
  4136  	}
  4137  	session, err := mgo.Dial("localhost:40001")
  4138  	c.Assert(err, IsNil)
  4139  	defer session.Close()
  4140  
  4141  	coll := session.DB("mydb").C("mycoll")
  4142  	err = coll.Insert(M{"n": 1})
  4143  	c.Assert(err, IsNil)
  4144  
  4145  	err = coll.Database.Run(bson.D{
  4146  		{"collMod", "mycoll"},
  4147  		{"validator", M{"s": M{"$type": "string"}}},
  4148  	}, nil)
  4149  	c.Assert(err, IsNil)
  4150  
  4151  	err = coll.Insert(M{"n": 2})
  4152  	c.Assert(err, ErrorMatches, "Document failed validation")
  4153  
  4154  	err = coll.Update(M{"n": 1}, M{"n": 10})
  4155  	c.Assert(err, ErrorMatches, "Document failed validation")
  4156  
  4157  	session.SetBypassValidation(true)
  4158  
  4159  	err = coll.Insert(M{"n": 3})
  4160  	c.Assert(err, IsNil)
  4161  
  4162  	err = coll.Update(M{"n": 3}, M{"n": 4})
  4163  	c.Assert(err, IsNil)
  4164  
  4165  	// Ensure this still works. Shouldn't be affected.
  4166  	err = coll.Remove(M{"n": 1})
  4167  	c.Assert(err, IsNil)
  4168  
  4169  	var result struct{ N int }
  4170  	var ns []int
  4171  	iter := coll.Find(nil).Iter()
  4172  	for iter.Next(&result) {
  4173  		ns = append(ns, result.N)
  4174  	}
  4175  	c.Assert(iter.Err(), IsNil)
  4176  	sort.Ints(ns)
  4177  	c.Assert(ns, DeepEquals, []int{4})
  4178  }
  4179  
  4180  func (s *S) TestVersionAtLeast(c *C) {
  4181  	tests := [][][]int{
  4182  		{{3, 2, 1}, {3, 2, 0}},
  4183  		{{3, 2, 1}, {3, 2}},
  4184  		{{3, 2, 1}, {2, 5, 5, 5}},
  4185  		{{3, 2, 1}, {2, 5, 5}},
  4186  		{{3, 2, 1}, {2, 5}},
  4187  	}
  4188  	for _, pair := range tests {
  4189  		bi := mgo.BuildInfo{VersionArray: pair[0]}
  4190  		c.Assert(bi.VersionAtLeast(pair[1]...), Equals, true)
  4191  
  4192  		bi = mgo.BuildInfo{VersionArray: pair[0]}
  4193  		c.Assert(bi.VersionAtLeast(pair[0]...), Equals, true)
  4194  
  4195  		bi = mgo.BuildInfo{VersionArray: pair[1]}
  4196  		c.Assert(bi.VersionAtLeast(pair[1]...), Equals, true)
  4197  
  4198  		bi = mgo.BuildInfo{VersionArray: pair[1]}
  4199  		c.Assert(bi.VersionAtLeast(pair[0]...), Equals, false)
  4200  	}
  4201  }
  4202  
  4203  // --------------------------------------------------------------------------
  4204  // Some benchmarks that require a running database.
  4205  
  4206  func (s *S) BenchmarkFindIterRaw(c *C) {
  4207  	session, err := mgo.Dial("localhost:40001")
  4208  	c.Assert(err, IsNil)
  4209  	defer session.Close()
  4210  
  4211  	coll := session.DB("mydb").C("mycoll")
  4212  	doc := bson.D{
  4213  		{"f2", "a short string"},
  4214  		{"f3", bson.D{{"1", "one"}, {"2", 2.0}}},
  4215  		{"f4", []string{"a", "b", "c", "d", "e", "f", "g"}},
  4216  	}
  4217  
  4218  	for i := 0; i < c.N+1; i++ {
  4219  		err := coll.Insert(doc)
  4220  		c.Assert(err, IsNil)
  4221  	}
  4222  
  4223  	session.SetBatch(c.N)
  4224  
  4225  	var raw bson.Raw
  4226  	iter := coll.Find(nil).Iter()
  4227  	iter.Next(&raw)
  4228  	c.ResetTimer()
  4229  	i := 0
  4230  	for iter.Next(&raw) {
  4231  		i++
  4232  	}
  4233  	c.StopTimer()
  4234  	c.Assert(iter.Err(), IsNil)
  4235  	c.Assert(i, Equals, c.N)
  4236  }