def test_document_class(self):
        c = MongoClient(host, port)
        db = c.pymongo_test
        db.test.insert({"x": 1})

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertEqual(dict, c.document_class)
            self.assertTrue(isinstance(db.test.find_one(), dict))
            self.assertFalse(isinstance(db.test.find_one(), SON))

            c.document_class = SON
            db = c.pymongo_test

            self.assertEqual(SON, c.document_class)
            self.assertTrue(isinstance(db.test.find_one(), SON))
            self.assertFalse(isinstance(db.test.find_one(as_class=dict), SON))

            c = MongoClient(host, port, document_class=SON)
            db = c.pymongo_test

            self.assertEqual(SON, c.document_class)
            self.assertTrue(isinstance(db.test.find_one(), SON))
            self.assertFalse(isinstance(db.test.find_one(as_class=dict), SON))

            c.document_class = dict
            db = c.pymongo_test

            self.assertEqual(dict, c.document_class)
            self.assertTrue(isinstance(db.test.find_one(), dict))
            self.assertFalse(isinstance(db.test.find_one(), SON))
        finally:
            ctx.exit()
    def test_base_object(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            c = self.client
            self.assertFalse(c.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(c.safe)
            self.assertEqual({}, c.get_lasterror_options())
            db = c.pymongo_test
            self.assertFalse(db.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(db.safe)
            self.assertEqual({}, db.get_lasterror_options())
            coll = db.test
            coll.drop()
            self.assertFalse(coll.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(coll.safe)
            self.assertEqual({}, coll.get_lasterror_options())
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            self.assertTrue(bool(cursor._Cursor__read_preference))

            w = 1 + len(self.slaves)
            wtimeout=10000 # Wait 10 seconds for replication to complete
            c.set_lasterror_options(w=w, wtimeout=wtimeout)
            self.assertFalse(c.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(c.safe)
            self.assertEqual({'w': w, 'wtimeout': wtimeout}, c.get_lasterror_options())
            db = c.pymongo_test
            self.assertFalse(db.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(db.safe)
            self.assertEqual({'w': w, 'wtimeout': wtimeout}, db.get_lasterror_options())
            coll = db.test
            self.assertFalse(coll.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(coll.safe)
            self.assertEqual({'w': w, 'wtimeout': wtimeout},
                             coll.get_lasterror_options())
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            self.assertTrue(bool(cursor._Cursor__read_preference))

            coll.insert({'foo': 'bar'})
            self.assertEqual(1, coll.find({'foo': 'bar'}).count())
            self.assertTrue(coll.find({'foo': 'bar'}))
            coll.remove({'foo': 'bar'})
            self.assertEqual(0, coll.find({'foo': 'bar'}).count())

            c.safe = False
            c.unset_lasterror_options()
            self.assertFalse(self.client.slave_okay)
            self.assertTrue(bool(self.client.read_preference))
            self.assertFalse(self.client.safe)
            self.assertEqual({}, self.client.get_lasterror_options())
        finally:
            ctx.exit()
예제 #3
0
    def test_gridfs_secondary(self):
        primary_host, primary_port = self.primary
        primary_connection = MongoClient(primary_host, primary_port)

        secondary_host, secondary_port = self.secondaries[0]
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            for secondary_connection in [
                    MongoClient(secondary_host,
                                secondary_port,
                                slave_okay=True),
                    MongoClient(secondary_host,
                                secondary_port,
                                read_preference=ReadPreference.SECONDARY),
            ]:
                primary_connection.pymongo_test.drop_collection("fs.files")
                primary_connection.pymongo_test.drop_collection("fs.chunks")

                # Should detect it's connected to secondary and not attempt to
                # create index
                fs = gridfs.GridFS(secondary_connection.pymongo_test)

                # This won't detect secondary, raises error
                self.assertRaises(ConnectionFailure, fs.put, b('foo'))
        finally:
            ctx.exit()
예제 #4
0
    def setUp(self):
        self.master = MongoClient(host, port)

        self.slaves = []
        try:
            self.slaves.append(
                MongoClient(host2,
                            port2,
                            read_preference=ReadPreference.SECONDARY))
        except ConnectionFailure:
            pass

        try:
            self.slaves.append(
                MongoClient(host3,
                            port3,
                            read_preference=ReadPreference.SECONDARY))
        except ConnectionFailure:
            pass

        if not self.slaves:
            raise SkipTest("Not connected to master-slave set")

        self.ctx = catch_warnings()
        warnings.simplefilter("ignore", DeprecationWarning)
        self.client = MasterSlaveConnection(self.master, self.slaves)
        self.db = self.client.pymongo_test
    def test_auto_start_request(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            for bad_horrible_value in (None, 5, 'hi!'):
                self.assertRaises(
                    (TypeError, ConfigurationError),
                    lambda: get_client(auto_start_request=bad_horrible_value)
                )

            # auto_start_request should default to False
            client = get_client()
            self.assertFalse(client.auto_start_request)

            client = get_client(auto_start_request=True)
            self.assertTrue(client.auto_start_request)

            # Assure we acquire a request socket.
            client.pymongo_test.test.find_one()
            self.assertTrue(client.in_request())
            pool = get_pool(client)
            self.assertRequestSocket(pool)
            self.assertSameSock(pool)

            client.end_request()
            self.assertNoRequest(pool)
            self.assertDifferentSock(pool)

            # Trigger auto_start_request
            client.pymongo_test.test.find_one()
            self.assertRequestSocket(pool)
            self.assertSameSock(pool)
        finally:
            ctx.exit()
    def test_command_read_pref_warning(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("error", UserWarning)
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertRaises(
                UserWarning, self.c.pymongo_test.command, "ping", read_preference=ReadPreference.SECONDARY
            )
            try:
                self.c.pymongo_test.command("dbStats", read_preference=ReadPreference.SECONDARY_PREFERRED)
            except UserWarning:
                self.fail("Shouldn't have raised UserWarning.")

            primary = MongoClient(host, port)
            try:
                primary.pymongo_test.command("ping", read_preference=ReadPreference.SECONDARY_PREFERRED)
            except UserWarning:
                self.fail("Shouldn't have raised UserWarning.")

            secondary_addr = iter(self.c.secondaries).next()
            secondary = MongoClient(*secondary_addr)
            msclient = MasterSlaveConnection(primary, [secondary])
            self.assertRaises(
                UserWarning, msclient.pymongo_test.command, "ping", read_preference=ReadPreference.SECONDARY
            )
            try:
                msclient.pymongo_test.command("dbStats", read_preference=ReadPreference.SECONDARY_PREFERRED)
            except UserWarning:
                self.fail("Shouldn't have raised UserWarning.")
        finally:
            ctx.exit()
예제 #7
0
    def test_aggregate_command_with_out(self):
        if not version.at_least(self.c, (2, 5, 2)):
            raise SkipTest("Aggregation with $out requires MongoDB >= 2.5.2")

        # Tests aggregate command when pipeline contains $out.
        self.c.pymongo_test.test.insert({"x": 1, "y": 1}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 1, "y": 2}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 2, "y": 1}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 2, "y": 2}, w=self.w)

        # Aggregate with $out always goes to primary, doesn't obey read prefs.
        # Test aggregate command sent directly to db.command.
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.command(
                "aggregate", "test",
                pipeline=[{"$match": {"x": 1}}, {"$out": "agg_out"}]
            ))

            # Test aggregate when sent through the collection aggregate function.
            self._test_fn(False, lambda: self.c.pymongo_test.test.aggregate(
                [{"$match": {"x": 2}}, {"$out": "agg_out"}]
            ))
        finally:
            ctx.exit()

        self.c.pymongo_test.drop_collection("test")
        self.c.pymongo_test.drop_collection("agg_out")
    def test_init_disconnected(self):
        c = MongoClient(host, port, _connect=False)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertIsInstance(c.is_primary, bool)
            self.assertIsInstance(c.is_mongos, bool)
            self.assertIsInstance(c.max_pool_size, int)
            self.assertIsInstance(c.use_greenlets, bool)
            self.assertIsInstance(c.nodes, frozenset)
            self.assertIsInstance(c.auto_start_request, bool)
            self.assertEqual(dict, c.get_document_class())
            self.assertIsInstance(c.tz_aware, bool)
            self.assertIsInstance(c.max_bson_size, int)
            self.assertIsInstance(c.min_wire_version, int)
            self.assertIsInstance(c.max_wire_version, int)
            self.assertIsInstance(c.max_write_batch_size, int)
            self.assertEqual(None, c.host)
            self.assertEqual(None, c.port)
        finally:
            ctx.exit()

        c.pymongo_test.test.find_one()  # Auto-connect.
        self.assertEqual((host, port), c.address)

        if version.at_least(c, (2, 5, 4, -1)):
            self.assertTrue(c.max_wire_version > 0)
        else:
            self.assertEqual(c.max_wire_version, 0)
        self.assertTrue(c.min_wire_version >= 0)

        bad_host = "somedomainthatdoesntexist.org"
        c = MongoClient(bad_host, port, connectTimeoutMS=1, _connect=False)
        self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one)
    def test_client_read_preference(self):
        preferences = (
            Primary(), Secondary([{'dc': 'ny'}]), Nearest([{'dc': 'ny'}, {}]))
        tags = [{'foo': 'bar'}]
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            for pref in preferences:
                client = MongoClient(read_preference=pref, connect=False)
                self.assertEqual(client.read_preference, pref.mode)
                self.assertEqual(client.tag_sets, pref.tag_sets)

                client = MongoClient(
                    read_preference=pref, tag_sets=tags, connect=False)
                self.assertEqual(client.read_preference, pref.mode)
                self.assertEqual(client.tag_sets, pref.tag_sets)

                client = MongoReplicaSetClient(
                    read_preference=pref, replicaSet='foo', connect=False)
                self.assertEqual(client.read_preference, pref.mode)
                self.assertEqual(client.tag_sets, pref.tag_sets)

                client = MongoReplicaSetClient(
                    read_preference=pref, tag_sets=tags,
                    replicaSet='foo', connect=False)
                self.assertEqual(client.read_preference, pref.mode)
                self.assertEqual(client.tag_sets, pref.tag_sets)
        finally:
            ctx.exit()
    def test_backport_latency_validation(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertEqual(17, self._get_client(
                localThresholdMS=17
            ).secondary_acceptable_latency_ms)

            self.assertEqual(42, self._get_client(
                secondaryAcceptableLatencyMS=42
            ).local_threshold_ms)

            self.assertEqual(666, self._get_client(
                localThresholdMS=666
            ).local_threshold_ms)

            self.assertEqual(0, self._get_client(
                localthresholdms=0
            ).local_threshold_ms)

            self.assertRaises(ConfigurationError,
                              self._get_client,
                              localthresholdms=-1)
        finally:
            ctx.exit()
    def test_backport_localthresholdms_uri(self):
        uri = "mongodb://%s:%s" % (host, port)
        lt_uri = "mongodb://%s:%d/?localThresholdMS=10" % (host, port)
        sl_uri = ("mongodb://%s:%d/?secondaryAcceptableLatencyMS=10" %
                  (host, port))
        lt_sl_uri = ("mongodb://%s:%d/?localThresholdMS=10;"
                     "secondaryAcceptableLatencyMS=8" % (host, port))

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            # Just localThresholdMS
            client = MongoClient(uri)
            self.assertEqual(client.secondary_acceptable_latency_ms, 15)
            self.assertEqual(client.local_threshold_ms, 15)
            client = MongoClient(uri, localThresholdMS=10)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(uri, localThresholdMS=10,
                                 secondaryAcceptableLatencyMS=8)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)

            # URI options take precedence over kwargs but localThresholdMS
            # takes precedence over secondaryAcceptableLatencyMS always. Test
            # to make sure the precedence is correct between URI vs. kwargs.
            client = MongoClient(lt_uri)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(lt_uri, localThresholdMS=8)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(lt_uri, secondaryAcceptableLatencyMS=8)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(lt_uri, localThresholdMS=8,
                                 secondaryAcceptableLatencyMS=6)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)

            client = MongoClient(sl_uri, secondaryAcceptableLatencyMS=8)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(sl_uri, localThresholdMS=10)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(sl_uri, localThresholdMS=10,
                                 secondaryAcceptableLatencyMS=6)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)

            client = MongoClient(lt_sl_uri)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
            client = MongoClient(lt_sl_uri, localThresholdMS=8,
                                 secondaryAcceptableLatencyMS=4)
            self.assertEqual(client.secondary_acceptable_latency_ms, 10)
            self.assertEqual(client.local_threshold_ms, 10)
        finally:
            ctx.exit()
예제 #12
0
    def test_cursor_transfer(self):

        # This is just a test, don't try this at home...
        self.db.test.remove({})
        self.db.test.insert({'_id': i} for i in xrange(200))

        class CManager(CursorManager):
            def __init__(self, connection):
                super(CManager, self).__init__(connection)

            def close(self, dummy):
                # Do absolutely nothing...
                pass

        client = self.db.connection
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            client.set_cursor_manager(CManager)

            docs = []
            cursor = self.db.test.find().batch_size(10)
            docs.append(cursor.next())
            cursor.close()
            docs.extend(cursor)
            self.assertEqual(len(docs), 10)
            cmd_cursor = {'id': cursor.cursor_id, 'firstBatch': []}
            ccursor = CommandCursor(cursor.collection, cmd_cursor,
                                    cursor.conn_id, retrieved=cursor.retrieved)
            docs.extend(ccursor)
            self.assertEqual(len(docs), 200)
        finally:
            client.set_cursor_manager(CursorManager)
            ctx.exit()
예제 #13
0
    def test_cursor_transfer(self):

        # This is just a test, don't try this at home...
        self.db.test.remove({})
        self.db.test.insert({'_id': i} for i in xrange(200))

        class CManager(CursorManager):
            def __init__(self, connection):
                super(CManager, self).__init__(connection)

            def close(self, dummy):
                # Do absolutely nothing...
                pass

        client = self.db.connection
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            client.set_cursor_manager(CManager)

            docs = []
            cursor = self.db.test.find().batch_size(10)
            docs.append(cursor.next())
            cursor.close()
            docs.extend(cursor)
            self.assertEqual(len(docs), 10)
            cmd_cursor = {'id': cursor.cursor_id, 'firstBatch': []}
            ccursor = CommandCursor(cursor.collection, cmd_cursor,
                                    cursor.conn_id, retrieved=cursor.retrieved)
            docs.extend(ccursor)
            self.assertEqual(len(docs), 200)
        finally:
            client.set_cursor_manager(CursorManager)
            ctx.exit()
    def test_drop_collection(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.drop_collection("some_collection"))

            self._test_fn(False, lambda: self.c.pymongo_test.some_collection.drop())
        finally:
            ctx.exit()
    def test_alive(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertTrue(get_client().alive())

            client = MongoClient('doesnt exist', _connect=False)
            self.assertFalse(client.alive())
        finally:
            ctx.exit()
예제 #16
0
    def test_replica_set_connection(self):
        c = ReplicaSetConnection(pair, replicaSet=self.name)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertTrue(c.auto_start_request)
            self.assertEqual(None, c.max_pool_size)
            self.assertFalse(c.slave_okay)
            self.assertFalse(c.safe)
            self.assertEqual({}, c.get_lasterror_options())

            # ReplicaSetConnection's writes are unacknowledged by default
            doc = {"_id": ObjectId()}
            coll = c.pymongo_test.write_concern_test
            coll.drop()
            coll.insert(doc)
            coll.insert(doc)

            c = ReplicaSetConnection(
                "mongodb://%s:%s/?replicaSet=%s&safe=true" %
                (host, port, self.name))

            self.assertTrue(c.safe)
        finally:
            ctx.exit()

        # To preserve legacy ReplicaSetConnection's behavior, max_size should
        # be None. Pool should handle this without error.
        pool = get_pool(c)
        self.assertEqual(None, pool.max_size)
        c.end_request()

        # To preserve legacy ReplicaSetConnection's behavior, max_size should
        # be None. Pool should handle this without error.
        rs_state = c._MongoReplicaSetClient__rs_state
        pool = rs_state.primary_member.pool
        self.assertEqual(None, pool.max_size)
        c.end_request()

        # ReplicaSetConnection's network_timeout argument is translated into
        # socketTimeoutMS
        self.assertEqual(
            123,
            ReplicaSetConnection(
                pair, replicaSet=self.name,
                network_timeout=123)._MongoReplicaSetClient__net_timeout)

        for network_timeout in 'foo', 0, -1:
            self.assertRaises(ConfigurationError,
                              ReplicaSetConnection,
                              pair,
                              replicaSet=self.name,
                              network_timeout=network_timeout)
 def test_use_greenlets(self):
     ctx = catch_warnings()
     try:
         warnings.simplefilter("ignore", DeprecationWarning)
         self.assertFalse(MongoClient(host, port).use_greenlets)
         if thread_util.have_gevent:
             self.assertTrue(
                 MongoClient(
                     host, port, use_greenlets=True).use_greenlets)
     finally:
         ctx.exit()
 def test_primary_with_tags(self):
     # Tags not allowed with PRIMARY
     ctx = catch_warnings()
     try:
         warnings.simplefilter("ignore", DeprecationWarning)
         self.assertRaises(
             ConfigurationError,
             self._get_client,
             tag_sets=[{'dc': 'ny'}])
     finally:
         ctx.exit()
예제 #19
0
    def test_create_collection(self):
        # Collections should be created on primary, obviously
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.command(
                'create', 'some_collection%s' % random.randint(0, sys.maxint)))

            self._test_fn(False, lambda: self.c.pymongo_test.create_collection(
                'some_collection%s' % random.randint(0, sys.maxint)))
        finally:
            ctx.exit()
    def test_drop_collection(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(
                False,
                lambda: self.c.pymongo_test.drop_collection('some_collection'))

            self._test_fn(False,
                          lambda: self.c.pymongo_test.some_collection.drop())
        finally:
            ctx.exit()
예제 #21
0
 def test_command_read_pref_warning(self):
     ctx = catch_warnings()
     try:
         warnings.simplefilter("error", UserWarning)
         self.assertRaises(UserWarning, self.client.pymongo_test.command,
                           'ping', read_preference=ReadPreference.SECONDARY)
         try:
             self.client.pymongo_test.command('dbStats',
                 read_preference=ReadPreference.SECONDARY_PREFERRED)
         except UserWarning:
             self.fail("Shouldn't have raised UserWarning.")
     finally:
         ctx.exit()
예제 #22
0
 def test_command_read_pref_warning(self):
     ctx = catch_warnings()
     try:
         warnings.simplefilter("error", UserWarning)
         self.assertRaises(UserWarning, self.client.pymongo_test.command,
                           'ping', read_preference=ReadPreference.SECONDARY)
         try:
             self.client.pymongo_test.command('dbStats',
                 read_preference=ReadPreference.SECONDARY_PREFERRED)
         except UserWarning:
             self.fail("Shouldn't have raised UserWarning.")
     finally:
         ctx.exit()
    def test_from_uri(self):
        c = MongoClient(host, port)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertEqual(c, MongoClient("mongodb://%s:%d" % (host, port)))
            self.assertTrue(MongoClient(
                "mongodb://%s:%d" % (host, port), slave_okay=True).slave_okay)
            self.assertTrue(MongoClient(
                "mongodb://%s:%d/?slaveok=true;w=2" % (host, port)).slave_okay)
        finally:
            ctx.exit()
예제 #24
0
    def test_from_uri(self):
        c = MongoClient(host, port)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertEqual(c, MongoClient("mongodb://%s:%d" % (host, port)))
            self.assertTrue(MongoClient(
                "mongodb://%s:%d" % (host, port), slave_okay=True).slave_okay)
            self.assertTrue(MongoClient(
                "mongodb://%s:%d/?slaveok=true;w=2" % (host, port)).slave_okay)
        finally:
            ctx.exit()
예제 #25
0
    def test_map_reduce(self):
        # mapreduce fails if no collection
        self.c.pymongo_test.test.insert({}, w=self.w)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.test.map_reduce(
                'function() { }', 'function() { }', 'mr_out'))
        finally:
            ctx.exit()

        self._test_fn(True, lambda: self.c.pymongo_test.test.map_reduce(
            'function() { }', 'function() { }', {'inline': 1}))
    def test_create_collection(self):
        # Collections should be created on primary, obviously
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(
                False, lambda: self.c.pymongo_test.command(
                    'create', 'some_collection%s' % random.randint(
                        0, sys.maxint)))

            self._test_fn(
                False, lambda: self.c.pymongo_test.create_collection(
                    'some_collection%s' % random.randint(0, sys.maxint)))
        finally:
            ctx.exit()
예제 #27
0
    def test_last_status(self):
        db = self.client.pymongo_test

        db.test.remove({})
        db.test.save({"i": 1})

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            db.test.update({"i": 1}, {"$set": {"i": 2}}, w=0)
            self.assertTrue(db.last_status()["updatedExisting"])

            db.test.update({"i": 1}, {"$set": {"i": 500}}, w=0)
            self.assertFalse(db.last_status()["updatedExisting"])
        finally:
            ctx.exit()
예제 #28
0
    def test_last_status(self):
        db = self.client.pymongo_test

        db.test.remove({})
        db.test.save({"i": 1})

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            db.test.update({"i": 1}, {"$set": {"i": 2}}, w=0)
            self.assertTrue(db.last_status()["updatedExisting"])

            db.test.update({"i": 1}, {"$set": {"i": 500}}, w=0)
            self.assertFalse(db.last_status()["updatedExisting"])
        finally:
            ctx.exit()
    def test_map_reduce(self):
        # mapreduce fails if no collection
        self.c.pymongo_test.test.insert({}, w=self.w)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(
                False, lambda: self.c.pymongo_test.test.map_reduce(
                    'function() { }', 'function() { }', 'mr_out'))
        finally:
            ctx.exit()

        self._test_fn(
            True, lambda: self.c.pymongo_test.test.map_reduce(
                'function() { }', 'function() { }', {'inline': 1}))
    def test_map_reduce_command(self):
        raise SkipTest("map reduce doesn't run on secondaries")
        # mapreduce fails if no collection
        self.c.pymongo_test.test.insert({}, w=self.w)

        # Non-inline mapreduce always goes to primary, doesn't obey read prefs.
        # Test with command in a SON and with kwargs
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(
                False, lambda: self.c.pymongo_test.command(
                    SON([('mapreduce', 'test'), ('map', 'function() { }'),
                         ('reduce', 'function() { }'), ('out', 'mr_out')])))

            self._test_fn(
                False,
                lambda: self.c.pymongo_test.command('mapreduce',
                                                    'test',
                                                    map='function() { }',
                                                    reduce='function() { }',
                                                    out='mr_out'))

            self._test_fn(
                False, lambda: self.c.pymongo_test.command(
                    'mapreduce',
                    'test',
                    map='function() { }',
                    reduce='function() { }',
                    out={'replace': 'some_collection'}))
        finally:
            ctx.exit()

        # Inline mapreduce obeys read prefs
        self._test_fn(
            True, lambda: self.c.pymongo_test.command('mapreduce',
                                                      'test',
                                                      map='function() { }',
                                                      reduce='function() { }',
                                                      out={'inline': True}))

        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('mapreduce', 'test'), ('map', 'function() { }'),
                     ('reduce', 'function() { }'), ('out', {
                         'inline': True
                     })])))
    def test_backport_localthresholdms_kwarg(self):
        # Test that localThresholdMS takes precedence over
        # secondaryAcceptableLatencyMS.
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            client = MockClient(
                standalones=[],
                members=[],
                mongoses=['a:1', 'b:2', 'c:3'],
                host='a:1,b:2,c:3',
                localThresholdMS=7,
                secondaryAcceptableLatencyMS=0)

            self.assertEqual(7, client.secondary_acceptable_latency_ms)
            self.assertEqual(7, client.local_threshold_ms)
            # No error
            client.db.collection.find_one()

            client = MockClient(
                standalones=[],
                members=[],
                mongoses=['a:1', 'b:2', 'c:3'],
                host='a:1,b:2,c:3',
                localThresholdMS=0,
                secondaryAcceptableLatencyMS=15)

            self.assertEqual(0, client.secondary_acceptable_latency_ms)
            self.assertEqual(0, client.local_threshold_ms)

            # Test that using localThresholdMS works in the same way as using
            # secondaryAcceptableLatencyMS.
            client.db.collection.find_one()
            # Our chosen mongos goes down.
            client.kill_host('%s:%s' % client.address)
            try:
                client.db.collection.find_one()
            except:
                pass
            # No error
            client.db.collection.find_one()
        finally:
            ctx.exit()
    def test_replica_set_connection(self):
        c = ReplicaSetConnection(pair, replicaSet=self.name)

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertTrue(c.auto_start_request)
            self.assertEqual(None, c.max_pool_size)
            self.assertFalse(c.slave_okay)
            self.assertFalse(c.safe)
            self.assertEqual({}, c.get_lasterror_options())

            # ReplicaSetConnection's writes are unacknowledged by default
            doc = {"_id": ObjectId()}
            coll = c.pymongo_test.write_concern_test
            coll.drop()
            coll.insert(doc)
            coll.insert(doc)

            c = ReplicaSetConnection("mongodb://%s:%s/?replicaSet=%s&safe=true" % (
                host, port, self.name))

            self.assertTrue(c.safe)
        finally:
            ctx.exit()

        # To preserve legacy ReplicaSetConnection's behavior, max_size should
        # be None. Pool should handle this without error.
        pool = get_pool(c)
        self.assertEqual(None, pool.max_size)
        c.end_request()

        # ReplicaSetConnection's network_timeout argument is translated into
        # socketTimeoutMS
        self.assertEqual(123, ReplicaSetConnection(
            pair, replicaSet=self.name, network_timeout=123
        )._MongoReplicaSetClient__net_timeout)

        for network_timeout in 'foo', 0, -1:
            self.assertRaises(
                ConfigurationError,
                ReplicaSetConnection, pair, replicaSet=self.name,
                network_timeout=network_timeout)
    def _test_fn(self, obedient, fn):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            if not obedient:
                for mode in modes:
                    self.c.read_preference = mode

                    # Run it a few times to make sure we don't just get lucky
                    # the first time.
                    for _ in range(10):
                        self.assertExecutedOn('primary', self.c, fn)
            else:
                for mode, expected_state in [
                        (ReadPreference.PRIMARY, 'primary'),
                        (ReadPreference.PRIMARY_PREFERRED, 'primary'),
                        (ReadPreference.SECONDARY, 'secondary'),
                        (ReadPreference.SECONDARY_PREFERRED, 'secondary'),
                        (ReadPreference.NEAREST, 'any')]:
                    self.c.read_preference = mode
                    for _ in range(10):
                        if expected_state in ('primary', 'secondary'):
                            self.assertExecutedOn(expected_state, self.c, fn)
                        elif expected_state == 'any':
                            used = set()
                            for _ in range(1000):
                                member = self.executed_on_which_member(
                                    self.c, fn)
                                used.add(member.host)
                                if len(used) == len(self.c.secondaries) + 1:
                                    # Success
                                    break

                            unused = self.c.secondaries.union(
                                set([self.c.primary])
                            ).difference(used)
                            if unused:
                                self.fail(
                                    "Some members not used for NEAREST: %s" % (
                                        unused))
        finally:
            ctx.exit()
    def test_aggregate_command_with_out(self):
        if not version.at_least(self.c, (2, 5, 2)):
            raise SkipTest("Aggregation with $out requires MongoDB >= 2.5.2")

        # Tests aggregate command when pipeline contains $out.
        self.c.pymongo_test.test.insert({"x": 1, "y": 1}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 1, "y": 2}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 2, "y": 1}, w=self.w)
        self.c.pymongo_test.test.insert({"x": 2, "y": 2}, w=self.w)

        # Aggregate with $out always goes to primary, doesn't obey read prefs.
        # Test aggregate command sent directly to db.command.
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(
                False,
                lambda: self.c.pymongo_test.command("aggregate",
                                                    "test",
                                                    pipeline=[{
                                                        "$match": {
                                                            "x": 1
                                                        }
                                                    }, {
                                                        "$out": "agg_out"
                                                    }]))

            # Test aggregate when sent through the collection aggregate function.
            self._test_fn(
                False,
                lambda: self.c.pymongo_test.test.aggregate([{
                    "$match": {
                        "x": 2
                    }
                }, {
                    "$out": "agg_out"
                }]))
        finally:
            ctx.exit()

        self.c.pymongo_test.drop_collection("test")
        self.c.pymongo_test.drop_collection("agg_out")
예제 #35
0
    def test_mongo_replica_set_client(self):
        c = MongoClient(pair)
        ismaster = c.admin.command('ismaster')
        if 'setName' in ismaster:
            setname = str(ismaster.get('setName'))
        else:
            raise SkipTest("Not connected to a replica set.")
        m = MongoReplicaSetClient(pair, replicaSet=setname, w=0)
        coll = m.pymongo_test.write_concern_test
        coll.drop()

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            doc = {"_id": ObjectId()}
            coll.insert(doc)
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertTrue(coll.insert(doc))
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoReplicaSetClient(pair, replicaSet=setname)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertRaises(OperationFailure, coll.insert, doc)
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s" %
                                      (pair, setname))
            self.assertTrue(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertRaises(OperationFailure, coll.insert, doc)
            m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s;w=0" %
                                      (pair, setname))
            self.assertFalse(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc))
        finally:
            ctx.exit()
예제 #36
0
    def test_kill_cursors_warning(self):
        # If kill_cursors is called while the client is disconnected, it
        # can't risk taking the lock to reconnect, in case it's being called
        # from Cursor.__del__, see PYTHON-799. Test that it shows a warning
        # in this case.
        client = MongoClient(host, port)
        collection = client.pymongo_test.test
        collection.insert({} for _ in range(4))
        cursor = collection.find().batch_size(1)
        cursor.next()
        client.disconnect()
        ctx = catch_warnings()
        try:
            warnings.simplefilter("error", UserWarning)
            self.assertRaises(UserWarning, cursor.close)
        finally:
            ctx.exit()

        # Reconnect.
        collection.find_one()
        cursor.close()
    def setUp(self):
        self.master = MongoClient(host, port)

        self.slaves = []
        try:
            self.slaves.append(MongoClient(host2, port2, read_preference=ReadPreference.SECONDARY))
        except ConnectionFailure:
            pass

        try:
            self.slaves.append(MongoClient(host3, port3, read_preference=ReadPreference.SECONDARY))
        except ConnectionFailure:
            pass

        if not self.slaves:
            raise SkipTest("Not connected to master-slave set")

        self.ctx = catch_warnings()
        warnings.simplefilter("ignore", DeprecationWarning)
        self.client = MasterSlaveConnection(self.master, self.slaves)
        self.db = self.client.pymongo_test
예제 #38
0
    def test_copy_db(self):
        c = self._get_client()
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertRaises(TypeError, c.copy_database, 4, "foo")
            self.assertRaises(TypeError, c.copy_database, "foo", 4)
            self.assertRaises(InvalidName, c.copy_database, "foo", "$foo")

            c.pymongo_test.test.drop()
            c.pymongo_test.test.insert({"foo": "bar"})

            c.drop_database("pymongo_test1")
            self.assertFalse("pymongo_test1" in c.database_names())

            c.copy_database("pymongo_test", "pymongo_test1")
            self.assertTrue("pymongo_test1" in c.database_names())
            self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])
            c.drop_database("pymongo_test1")
        finally:
            ctx.exit()
    def test_kill_cursors_warning(self):
        # If kill_cursors is called while the client is disconnected, it
        # can't risk taking the lock to reconnect, in case it's being called
        # from Cursor.__del__, see PYTHON-799. Test that it shows a warning
        # in this case.
        client = MongoClient(host, port)
        collection = client.pymongo_test.test
        collection.insert({} for _ in range(4))
        cursor = collection.find().batch_size(1)
        cursor.next()
        client.close()
        ctx = catch_warnings()
        try:
            warnings.simplefilter("error", UserWarning)
            self.assertRaises(UserWarning, cursor.close)
        finally:
            ctx.exit()

        # Reconnect.
        collection.find_one()
        cursor.close()
예제 #40
0
    def test_mongo_replica_set_client(self):
        c = MongoClient(pair)
        ismaster = c.admin.command('ismaster')
        if 'setName' in ismaster:
            setname = str(ismaster.get('setName'))
        else:
            raise SkipTest("Not connected to a replica set.")
        m = MongoReplicaSetClient(pair, replicaSet=setname, w=0)
        coll = m.pymongo_test.write_concern_test
        coll.drop()

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            doc = {"_id": ObjectId()}
            coll.insert(doc)
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertTrue(coll.insert(doc))
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoReplicaSetClient(pair, replicaSet=setname)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertRaises(OperationFailure, coll.insert, doc)
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s" % (pair, setname))
            self.assertTrue(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertRaises(OperationFailure, coll.insert, doc)
            m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s;w=0" % (pair, setname))
            self.assertFalse(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc))
        finally:
            ctx.exit()
예제 #41
0
    def test_only_secondary_ok_commands_have_read_prefs(self):
        c = get_client(read_preference=ReadPreference.SECONDARY)
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            is_mongos = utils.is_mongos(c)
        finally:
            ctx.exit()
        if not is_mongos:
            raise SkipTest("Only mongos have read_prefs added to the spec")

        # Ensure secondary_ok_commands have readPreference
        for cmd in secondary_ok_commands:
            if cmd == 'mapreduce':  # map reduce is a special case
                continue
            command = SON([(cmd, 1)])
            cursor = c.pymongo_test["$cmd"].find(command.copy())
            # White-listed commands also have to be wrapped in $query
            command = SON([('$query', command)])
            command['$readPreference'] = {'mode': 'secondary'}
            self.assertEqual(command, cursor._Cursor__query_spec())

        # map_reduce inline should have read prefs
        command = SON([('mapreduce', 'test'), ('out', {'inline': 1})])
        cursor = c.pymongo_test["$cmd"].find(command.copy())
        # White-listed commands also have to be wrapped in $query
        command = SON([('$query', command)])
        command['$readPreference'] = {'mode': 'secondary'}
        self.assertEqual(command, cursor._Cursor__query_spec())

        # map_reduce that outputs to a collection shouldn't have read prefs
        command = SON([('mapreduce', 'test'), ('out', {'mrtest': 1})])
        cursor = c.pymongo_test["$cmd"].find(command.copy())
        self.assertEqual(command, cursor._Cursor__query_spec())

        # Other commands shouldn't be changed
        for cmd in ('drop', 'create', 'any-future-cmd'):
            command = SON([(cmd, 1)])
            cursor = c.pymongo_test["$cmd"].find(command.copy())
            self.assertEqual(command, cursor._Cursor__query_spec())
    def test_only_secondary_ok_commands_have_read_prefs(self):
        c = get_client(read_preference=ReadPreference.SECONDARY)
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            is_mongos = utils.is_mongos(c)
        finally:
            ctx.exit()
        if not is_mongos:
            raise SkipTest("Only mongos have read_prefs added to the spec")

        # Ensure secondary_ok_commands have readPreference
        for cmd in secondary_ok_commands:
            if cmd == 'mapreduce':  # map reduce is a special case
                continue
            command = SON([(cmd, 1)])
            cursor = c.pymongo_test["$cmd"].find(command.copy())
            # White-listed commands also have to be wrapped in $query
            command = SON([('$query', command)])
            command['$readPreference'] = {'mode': 'secondary'}
            self.assertEqual(command, cursor._Cursor__query_spec())

        # map_reduce inline should have read prefs
        command = SON([('mapreduce', 'test'), ('out', {'inline': 1})])
        cursor = c.pymongo_test["$cmd"].find(command.copy())
        # White-listed commands also have to be wrapped in $query
        command = SON([('$query', command)])
        command['$readPreference'] = {'mode': 'secondary'}
        self.assertEqual(command, cursor._Cursor__query_spec())

        # map_reduce that outputs to a collection shouldn't have read prefs
        command = SON([('mapreduce', 'test'), ('out', {'mrtest': 1})])
        cursor = c.pymongo_test["$cmd"].find(command.copy())
        self.assertEqual(command, cursor._Cursor__query_spec())

        # Other commands shouldn't be changed
        for cmd in ('drop', 'create', 'any-future-cmd'):
            command = SON([(cmd, 1)])
            cursor = c.pymongo_test["$cmd"].find(command.copy())
            self.assertEqual(command, cursor._Cursor__query_spec())
예제 #43
0
    def test_copy_db(self):
        c = MongoClient(host, port)
        # Due to SERVER-2329, databases may not disappear
        # from a master in a master-slave pair.
        if server_is_master_with_slave(c):
            raise SkipTest("SERVER-2329")

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertRaises(TypeError, c.copy_database, 4, "foo")
            self.assertRaises(TypeError, c.copy_database, "foo", 4)
            self.assertRaises(InvalidName, c.copy_database, "foo", "$foo")

            c.pymongo_test.test.drop()
            c.pymongo_test.test.insert({"foo": "bar"})

            c.drop_database("pymongo_test1")
            self.assertFalse("pymongo_test1" in c.database_names())

            c.copy_database("pymongo_test", "pymongo_test1")
            self.assertTrue("pymongo_test1" in c.database_names())
            self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])
            c.drop_database("pymongo_test1")

            # XXX - SERVER-15318
            if not (version.at_least(c, (2, 6, 4)) and is_mongos(c)):
                self.assertFalse(c.in_request())
                c.copy_database("pymongo_test", "pymongo_test1",
                                "%s:%d" % (host, port))
                # copy_database() didn't accidentally restart the request
                self.assertFalse(c.in_request())

                self.assertTrue("pymongo_test1" in c.database_names())
                self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])

            c.drop_database("pymongo_test1")
        finally:
            ctx.exit()
    def test_uuid_queries(self):
        if not should_test_uuid:
            raise SkipTest("No uuid module")

        c = get_client()
        coll = c.pymongo_test.test
        coll.drop()

        uu = uuid.uuid4()
        # Wrap uu.bytes in binary_type to work
        # around http://bugs.python.org/issue7380.
        coll.insert({'uuid': Binary(binary_type(uu.bytes), 3)})
        self.assertEqual(1, coll.count())

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            # Test UUIDLegacy queries.
            coll.uuid_subtype = 4
            self.assertEqual(0, coll.find({'uuid': uu}).count())
            cur = coll.find({'uuid': UUIDLegacy(uu)})
            self.assertEqual(1, cur.count())
            retrieved = cur.next()
            self.assertEqual(uu, retrieved['uuid'])

            # Test regular UUID queries (using subtype 4).
            coll.insert({'uuid': uu})
            self.assertEqual(2, coll.count())
            cur = coll.find({'uuid': uu})
            self.assertEqual(1, cur.count())
            retrieved = cur.next()
            self.assertEqual(uu, retrieved['uuid'])

            # Test both.
            cur = coll.find({'uuid': {'$in': [uu, UUIDLegacy(uu)]}})
            self.assertEqual(2, cur.count())
            coll.drop()
        finally:
            ctx.exit()
    def test_copy_db(self):
        c = MongoClient(host, port)
        # Due to SERVER-2329, databases may not disappear
        # from a master in a master-slave pair.
        if server_is_master_with_slave(c):
            raise SkipTest("SERVER-2329")

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            self.assertRaises(TypeError, c.copy_database, 4, "foo")
            self.assertRaises(TypeError, c.copy_database, "foo", 4)
            self.assertRaises(InvalidName, c.copy_database, "foo", "$foo")

            c.pymongo_test.test.drop()
            c.pymongo_test.test.insert({"foo": "bar"})

            c.drop_database("pymongo_test1")
            self.assertFalse("pymongo_test1" in c.database_names())

            c.copy_database("pymongo_test", "pymongo_test1")
            self.assertTrue("pymongo_test1" in c.database_names())
            self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])
            c.drop_database("pymongo_test1")

            # XXX - SERVER-15318
            if not (version.at_least(c, (2, 6, 4)) and is_mongos(c)):
                self.assertFalse(c.in_request())
                c.copy_database("pymongo_test", "pymongo_test1",
                                "%s:%d" % (host, port))
                # copy_database() didn't accidentally restart the request
                self.assertFalse(c.in_request())

                self.assertTrue("pymongo_test1" in c.database_names())
                self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])

            c.drop_database("pymongo_test1")
        finally:
            ctx.exit()
예제 #46
0
    def test_mongo_client(self):
        m = MongoClient(pair, w=0)
        coll = m.pymongo_test.write_concern_test
        coll.drop()

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            doc = {"_id": ObjectId()}
            coll.insert(doc)
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertTrue(coll.insert(doc))
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoClient(pair)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc, safe=False))
            self.assertTrue(coll.insert(doc, w=0))
            self.assertRaises(OperationFailure, coll.insert, doc)
            self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
            self.assertRaises(OperationFailure, coll.insert, doc, w=1)

            m = MongoClient("mongodb://%s/" % (pair,))
            self.assertTrue(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertRaises(OperationFailure, coll.insert, doc)
            m = MongoClient("mongodb://%s/?w=0" % (pair,))
            self.assertFalse(m.safe)
            coll = m.pymongo_test.write_concern_test
            self.assertTrue(coll.insert(doc))
        finally:
            ctx.exit()

        # Equality tests
        self.assertEqual(m, MongoClient("mongodb://%s/?w=0" % (pair,)))
        self.assertFalse(m != MongoClient("mongodb://%s/?w=0" % (pair,)))
예제 #47
0
    def test_errors(self):
        if is_mongos(self.client):
            raise SkipTest('getpreverror not supported by mongos')
        db = self.client.pymongo_test
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            db.reset_error_history()
            self.assertEqual(None, db.error())
            self.assertEqual(None, db.previous_error())

            db.command("forceerror", check=False)
            self.assertTrue(db.error())
            self.assertTrue(db.previous_error())

            db.command("forceerror", check=False)
            self.assertTrue(db.error())
            prev_error = db.previous_error()
            self.assertEqual(prev_error["nPrev"], 1)
            del prev_error["nPrev"]
            prev_error.pop("lastOp", None)
            error = db.error()
            error.pop("lastOp", None)
            # getLastError includes "connectionId" in recent
            # server versions, getPrevError does not.
            error.pop("connectionId", None)
            self.assertEqual(error, prev_error)

            db.test.find_one()
            self.assertEqual(None, db.error())
            self.assertTrue(db.previous_error())
            self.assertEqual(db.previous_error()["nPrev"], 2)

            db.reset_error_history()
            self.assertEqual(None, db.error())
            self.assertEqual(None, db.previous_error())
        finally:
            ctx.exit()
예제 #48
0
    def test_errors(self):
        if is_mongos(self.client):
            raise SkipTest('getpreverror not supported by mongos')
        db = self.client.pymongo_test
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            db.reset_error_history()
            self.assertEqual(None, db.error())
            self.assertEqual(None, db.previous_error())

            db.command("forceerror", check=False)
            self.assertTrue(db.error())
            self.assertTrue(db.previous_error())

            db.command("forceerror", check=False)
            self.assertTrue(db.error())
            prev_error = db.previous_error()
            self.assertEqual(prev_error["nPrev"], 1)
            del prev_error["nPrev"]
            prev_error.pop("lastOp", None)
            error = db.error()
            error.pop("lastOp", None)
            # getLastError includes "connectionId" in recent
            # server versions, getPrevError does not.
            error.pop("connectionId", None)
            self.assertEqual(error, prev_error)

            db.test.find_one()
            self.assertEqual(None, db.error())
            self.assertTrue(db.previous_error())
            self.assertEqual(db.previous_error()["nPrev"], 2)

            db.reset_error_history()
            self.assertEqual(None, db.error())
            self.assertEqual(None, db.previous_error())
        finally:
            ctx.exit()
예제 #49
0
    def test_authenticate_add_remove_user(self):
        authed_client = auth_context.client
        db = authed_client.pymongo_test

        # Configuration errors
        self.assertRaises(ValueError, db.add_user, "user", '')
        self.assertRaises(TypeError, db.add_user, "user", 'password', 15)
        self.assertRaises(ConfigurationError, db.add_user, "user", 'password',
                          'True')
        self.assertRaises(ConfigurationError,
                          db.add_user,
                          "user",
                          'password',
                          True,
                          roles=['read'])

        if version.at_least(authed_client, (2, 5, 3, -1)):
            ctx = catch_warnings()
            try:
                warnings.simplefilter("error", DeprecationWarning)
                self.assertRaises(DeprecationWarning, db.add_user, "user",
                                  "password")
                self.assertRaises(DeprecationWarning, db.add_user, "user",
                                  "password", True)
            finally:
                ctx.exit()

            self.assertRaises(ConfigurationError,
                              db.add_user,
                              "user",
                              "password",
                              digestPassword=True)

        authed_client.admin.add_user("admin", "password")
        self.client.admin.authenticate("admin", "password")
        db = self.client.pymongo_test

        try:
            # Add / authenticate / remove
            db.add_user("mike", "password")
            self.assertRaises(TypeError, db.authenticate, 5, "password")
            self.assertRaises(TypeError, db.authenticate, "mike", 5)
            self.assertRaises(OperationFailure, db.authenticate, "mike",
                              "not a real password")
            self.assertRaises(OperationFailure, db.authenticate, "faker",
                              "password")
            self.assertTrue(db.authenticate("mike", "password"))
            db.logout()
            self.assertTrue(db.authenticate(u"mike", u"password"))
            db.remove_user("mike")
            db.logout()

            self.assertRaises(OperationFailure, db.authenticate, "mike",
                              "password")

            # Add / authenticate / change password
            self.assertRaises(OperationFailure, db.authenticate, "Gustave",
                              u"Dor\xe9")
            db.add_user("Gustave", u"Dor\xe9")
            self.assertTrue(db.authenticate("Gustave", u"Dor\xe9"))
            db.add_user("Gustave", "password")
            db.logout()
            self.assertRaises(OperationFailure, db.authenticate, "Gustave",
                              u"Dor\xe9")
            self.assertTrue(db.authenticate("Gustave", u"password"))

            if not version.at_least(authed_client, (2, 5, 3, -1)):
                # Add a readOnly user
                db.add_user("Ross", "password", read_only=True)
                db.logout()
                self.assertTrue(db.authenticate("Ross", u"password"))
                self.assertTrue(
                    db.system.users.find({
                        "readOnly": True
                    }).count())
                db.logout()

        # Cleanup
        finally:
            remove_all_users(db)
            self.client.admin.remove_user("admin")
            self.client.admin.logout()
    def test_command(self):
        # Test generic 'command' method. Some commands obey read preference,
        # most don't.
        # Disobedient commands, always go to primary
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.command('ping'))
            self._test_fn(False, lambda: self.c.admin.command('buildinfo'))
        finally:
            ctx.exit()

        # Obedient commands.
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'group', {
                    'ns': 'test',
                    'key': {
                        'a': 1
                    },
                    '$reduce': 'function(obj, prev) { }',
                    'initial': {}
                }))

        self._test_fn(True, lambda: self.c.pymongo_test.command('dbStats'))

        # collStats fails if no collection
        self.c.pymongo_test.test.insert({}, w=self.w)
        self._test_fn(True,
                      lambda: self.c.pymongo_test.command('collStats', 'test'))

        # Count
        self._test_fn(True,
                      lambda: self.c.pymongo_test.command('count', 'test'))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'count', 'test', query={'a': 1}))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('count', 'test'), ('query', {
                    'a': 1
                })])))

        # Distinct
        self._test_fn(
            True,
            lambda: self.c.pymongo_test.command('distinct', 'test', key='a'))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'distinct', 'test', key='a', query={'a': 1}))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('distinct', 'test'), ('key', 'a'), ('query', {
                    'a': 1
                })])))

        # Geo stuff.
        self.c.pymongo_test.test.create_index([('location', '2d')])

        self.c.pymongo_test.test.create_index([('location', 'geoHaystack'),
                                               ('key', 1)],
                                              bucketSize=100)

        # Attempt to await replication of indexes replicated.
        self.c.pymongo_test.test2.insert({}, w=self.w)
        self.c.pymongo_test.test2.remove({}, w=self.w)

        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'geoNear', 'test', near=[0, 0]))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('geoNear', 'test'), ('near', [0, 0])])))

        self._test_fn(
            True,
            lambda: self.c.pymongo_test.command('geoSearch',
                                                'test',
                                                near=[33, 33],
                                                maxDistance=6,
                                                search={'type': 'restaurant'},
                                                limit=30))

        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('geoSearch', 'test'), ('near', [33, 33]),
                     ('maxDistance', 6), ('search', {
                         'type': 'restaurant'
                     }), ('limit', 30)])))

        if version.at_least(self.c, (2, 1, 0)):
            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    SON([('aggregate', 'test'), ('pipeline', [])])))
    def test_command(self):
        # Test generic 'command' method. Some commands obey read preference,
        # most don't.
        # Disobedient commands, always go to primary
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", UserWarning)
            self._test_fn(False, lambda: self.c.pymongo_test.command('ping'))
            self._test_fn(False, lambda: self.c.admin.command('buildinfo'))
        finally:
            ctx.exit()

        # Obedient commands.
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'group', {
                    'ns': 'test',
                    'key': {
                        'a': 1
                    },
                    '$reduce': 'function(obj, prev) { }',
                    'initial': {}
                }))

        self._test_fn(True, lambda: self.c.pymongo_test.command('dbStats'))

        # collStats fails if no collection
        self.c.pymongo_test.test.insert({}, w=self.w)
        time.sleep(1)  # wait for slaves to apply
        self._test_fn(True,
                      lambda: self.c.pymongo_test.command('collStats', 'test'))

        # Count
        self._test_fn(True,
                      lambda: self.c.pymongo_test.command('count', 'test'))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'count', 'test', query={'a': 1}))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('count', 'test'), ('query', {
                    'a': 1
                })])))

        # Distinct
        self._test_fn(
            True,
            lambda: self.c.pymongo_test.command('distinct', 'test', key='a'))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                'distinct', 'test', key='a', query={'a': 1}))
        self._test_fn(
            True, lambda: self.c.pymongo_test.command(
                SON([('distinct', 'test'), ('key', 'a'), ('query', {
                    'a': 1
                })])))

        if version.tokumx_at_least(
                self.c,
            (2, )) and not version.tokumx_at_least(self.c, (2, 0, 9999)):
            # Geo stuff. Make sure a 2d index is created and replicated
            self.c.pymongo_test.system.indexes.insert(
                {
                    'key': {
                        'location': '2d'
                    },
                    'ns': 'pymongo_test.test',
                    'name': 'location_2d'
                },
                w=self.w)

            self.c.pymongo_test.system.indexes.insert(SON([
                ('ns', 'pymongo_test.test'),
                ('key', SON([('location', 'geoHaystack'), ('key', 1)])),
                ('bucketSize', 100),
                ('name', 'location_geoHaystack'),
            ]),
                                                      w=self.w)

            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    'geoNear', 'test', near=[0, 0]))
            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    SON([('geoNear', 'test'), ('near', [0, 0])])))

            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    'geoSearch',
                    'test',
                    near=[33, 33],
                    maxDistance=6,
                    search={'type': 'restaurant'},
                    limit=30))

            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    SON([('geoSearch', 'test'), ('near', [33, 33]),
                         ('maxDistance', 6), ('search', {
                             'type': 'restaurant'
                         }), ('limit', 30)])))

        if version.at_least(self.c, (2, 1, 0)):
            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    SON([('aggregate', 'test'), ('pipeline', [])])))

        # Text search.
        if version.at_least(self.c, (2, 3, 2)) and version.tokumx_at_least(
                self.c, (2, 2)):
            ctx = catch_warnings()
            try:
                warnings.simplefilter("ignore", UserWarning)
                utils.enable_text_search(self.c)
            finally:
                ctx.exit()
            db = self.c.pymongo_test

            # Only way to create an index and wait for all members to build it.
            index = {
                'ns': 'pymongo_test.test',
                'name': 't_text',
                'key': {
                    't': 'text'
                }
            }

            db.system.indexes.insert(index,
                                     manipulate=False,
                                     check_keys=False,
                                     w=self.w)

            self._test_fn(
                True, lambda: self.c.pymongo_test.command(
                    SON([('text', 'test'), ('search', 'foo')])))

            self.c.pymongo_test.test.drop_indexes()
예제 #52
0
    def test_authenticate_add_remove_user(self):
        if (is_mongos(self.client) and not
            version.at_least(self.client, (2, 0, 0))):
            raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0")
        if is_mongos(self.client):
            raise SkipTest("Auth fails on sharding due to write concern race, see Tokutek/mongo#77")
        if not server_started_with_auth(self.client):
            raise SkipTest('Authentication is not enabled on server')

        db = self.client.pymongo_test

        # Configuration errors
        self.assertRaises(ValueError, db.add_user, "user", '')
        self.assertRaises(TypeError, db.add_user, "user", 'password', 15)
        self.assertRaises(ConfigurationError, db.add_user,
                          "user", 'password', 'True')
        self.assertRaises(ConfigurationError, db.add_user,
                          "user", 'password', True, roles=['read'])

        if version.at_least(self.client, (2, 5, 3, -1)):
            ctx = catch_warnings()
            try:
                warnings.simplefilter("error", DeprecationWarning)
                self.assertRaises(DeprecationWarning, db.add_user,
                                  "user", "password")
                self.assertRaises(DeprecationWarning, db.add_user,
                                  "user", "password", True)
            finally:
                ctx.exit()

            self.assertRaises(ConfigurationError, db.add_user,
                              "user", "password", digestPassword=True)

        self.client.admin.add_user("admin", "password")
        self.client.admin.authenticate("admin", "password")

        try:
            # Add / authenticate / remove
            db.add_user("mike", "password")
            self.assertRaises(TypeError, db.authenticate, 5, "password")
            self.assertRaises(TypeError, db.authenticate, "mike", 5)
            self.assertRaises(OperationFailure,
                              db.authenticate, "mike", "not a real password")
            self.assertRaises(OperationFailure,
                              db.authenticate, "faker", "password")
            self.assertTrue(db.authenticate("mike", "password"))
            db.logout()
            self.assertTrue(db.authenticate(u"mike", u"password"))
            db.remove_user("mike")
            db.logout()

            self.assertRaises(OperationFailure,
                              db.authenticate, "mike", "password")

            # Add / authenticate / change password
            self.assertRaises(OperationFailure,
                              db.authenticate, "Gustave", u"Dor\xe9")
            db.add_user("Gustave", u"Dor\xe9")
            self.assertTrue(db.authenticate("Gustave", u"Dor\xe9"))
            db.add_user("Gustave", "password")
            db.logout()
            self.assertRaises(OperationFailure,
                              db.authenticate, "Gustave", u"Dor\xe9")
            self.assertTrue(db.authenticate("Gustave", u"password"))

            if not version.at_least(self.client, (2, 5, 3, -1)):
                # Add a readOnly user
                db.add_user("Ross", "password", read_only=True)
                db.logout()
                self.assertTrue(db.authenticate("Ross", u"password"))
                self.assertTrue(db.system.users.find({"readOnly": True}).count())
                db.logout()

        # Cleanup
        finally:
            remove_all_users(db)
            self.client.admin.remove_user("admin")
            self.client.admin.logout()
예제 #53
0
    def test_base_object(self):
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            c = self.client
            self.assertFalse(c.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(c.safe)
            self.assertEqual({}, c.get_lasterror_options())
            db = c.pymongo_test
            self.assertFalse(db.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(db.safe)
            self.assertEqual({}, db.get_lasterror_options())
            coll = db.test
            coll.drop()
            self.assertFalse(coll.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(coll.safe)
            self.assertEqual({}, coll.get_lasterror_options())
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            self.assertTrue(bool(cursor._Cursor__read_preference))

            w = 1 + len(self.slaves)
            wtimeout = 10000  # Wait 10 seconds for replication to complete
            c.set_lasterror_options(w=w, wtimeout=wtimeout)
            self.assertFalse(c.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(c.safe)
            self.assertEqual({
                'w': w,
                'wtimeout': wtimeout
            }, c.get_lasterror_options())
            db = c.pymongo_test
            self.assertFalse(db.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(db.safe)
            self.assertEqual({
                'w': w,
                'wtimeout': wtimeout
            }, db.get_lasterror_options())
            coll = db.test
            self.assertFalse(coll.slave_okay)
            self.assertTrue(bool(c.read_preference))
            self.assertTrue(coll.safe)
            self.assertEqual({
                'w': w,
                'wtimeout': wtimeout
            }, coll.get_lasterror_options())
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            self.assertTrue(bool(cursor._Cursor__read_preference))

            coll.insert({'foo': 'bar'})
            self.assertEqual(1, coll.find({'foo': 'bar'}).count())
            self.assertTrue(coll.find({'foo': 'bar'}))
            coll.remove({'foo': 'bar'})
            self.assertEqual(0, coll.find({'foo': 'bar'}).count())

            c.safe = False
            c.unset_lasterror_options()
            self.assertFalse(self.client.slave_okay)
            self.assertTrue(bool(self.client.read_preference))
            self.assertFalse(self.client.safe)
            self.assertEqual({}, self.client.get_lasterror_options())
        finally:
            ctx.exit()
    def test_mongos_connection(self):
        c = get_client()
        is_mongos = utils.is_mongos(c)

        # Test default mode, PRIMARY
        cursor = c.pymongo_test.test.find()
        if is_mongos:
            # We only set $readPreference if it's something other than
            # PRIMARY to avoid problems with mongos versions that don't
            # support read preferences.
            self.assertEqual(
                None,
                cursor._Cursor__query_spec().get('$readPreference'))
        else:
            self.assertFalse('$readPreference' in cursor._Cursor__query_spec())

        # Copy these constants for brevity
        PRIMARY_PREFERRED = ReadPreference.PRIMARY_PREFERRED
        SECONDARY = ReadPreference.SECONDARY
        SECONDARY_PREFERRED = ReadPreference.SECONDARY_PREFERRED
        NEAREST = ReadPreference.NEAREST
        SLAVE_OKAY = _QUERY_OPTIONS['slave_okay']

        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            # Test non-PRIMARY modes which can be combined with tags
            for kwarg, value, mongos_mode in (('read_preference',
                                               PRIMARY_PREFERRED,
                                               'primaryPreferred'),
                                              ('read_preference', SECONDARY,
                                               'secondary'),
                                              ('read_preference',
                                               SECONDARY_PREFERRED,
                                               'secondaryPreferred'),
                                              ('read_preference', NEAREST,
                                               'nearest'),
                                              ('slave_okay', True,
                                               'secondaryPreferred'),
                                              ('slave_okay', False,
                                               'primary')):
                for tag_sets in (None, [{}]):
                    # Create a client e.g. with read_preference=NEAREST or
                    # slave_okay=True
                    c = get_client(tag_sets=tag_sets, **{kwarg: value})

                    self.assertEqual(is_mongos, c.is_mongos)
                    cursor = c.pymongo_test.test.find()
                    if is_mongos:
                        # We don't set $readPreference for SECONDARY_PREFERRED
                        # unless tags are in use. slaveOkay has the same effect.
                        if mongos_mode == 'secondaryPreferred':
                            self.assertEqual(
                                None,
                                cursor._Cursor__query_spec().get(
                                    '$readPreference'))

                            self.assertTrue(cursor._Cursor__query_options()
                                            & SLAVE_OKAY)

                        # Don't send $readPreference for PRIMARY either
                        elif mongos_mode == 'primary':
                            self.assertEqual(
                                None,
                                cursor._Cursor__query_spec().get(
                                    '$readPreference'))

                            self.assertFalse(cursor._Cursor__query_options()
                                             & SLAVE_OKAY)
                        else:
                            self.assertEqual({'mode': mongos_mode},
                                             cursor._Cursor__query_spec().get(
                                                 '$readPreference'))

                            self.assertTrue(cursor._Cursor__query_options()
                                            & SLAVE_OKAY)
                    else:
                        self.assertFalse(
                            '$readPreference' in cursor._Cursor__query_spec())

                for tag_sets in (
                    [{
                        'dc': 'la'
                    }],
                    [{
                        'dc': 'la'
                    }, {
                        'dc': 'sf'
                    }],
                    [{
                        'dc': 'la'
                    }, {
                        'dc': 'sf'
                    }, {}],
                ):
                    if kwarg == 'slave_okay':
                        # Can't use tags with slave_okay True or False, need a
                        # real read preference
                        self.assertRaises(ConfigurationError,
                                          get_client,
                                          tag_sets=tag_sets,
                                          **{kwarg: value})

                        continue

                    c = get_client(tag_sets=tag_sets, **{kwarg: value})

                    self.assertEqual(is_mongos, c.is_mongos)
                    cursor = c.pymongo_test.test.find()
                    if is_mongos:
                        self.assertEqual(
                            {
                                'mode': mongos_mode,
                                'tags': tag_sets
                            },
                            cursor._Cursor__query_spec().get(
                                '$readPreference'))
                    else:
                        self.assertFalse(
                            '$readPreference' in cursor._Cursor__query_spec())
        finally:
            ctx.exit()
예제 #55
0
    def test_baseobject(self):

        ctx = catch_warnings()
        try:
            warnings.simplefilter("error", UserWarning)
            self.assertRaises(UserWarning, lambda:
                    MongoClient(host, port, wtimeout=1000, w=0))
            try:
                MongoClient(host, port, wtimeout=1000, w=1)
            except UserWarning:
                self.fail()

            try:
                MongoClient(host, port, wtimeout=1000)
            except UserWarning:
                self.fail()
        finally:
            ctx.exit()

        # Connection tests
        ctx = catch_warnings()
        try:
            warnings.simplefilter("ignore", DeprecationWarning)
            c = Connection(pair)
            self.assertFalse(c.slave_okay)
            self.assertFalse(c.safe)
            self.assertEqual({}, c.get_lasterror_options())
            db = c.pymongo_test
            db.drop_collection("test")
            self.assertFalse(db.slave_okay)
            self.assertFalse(db.safe)
            self.assertEqual({}, db.get_lasterror_options())
            coll = db.test
            self.assertFalse(coll.slave_okay)
            self.assertFalse(coll.safe)
            self.assertEqual({}, coll.get_lasterror_options())

            self.assertEqual((False, {}), coll._get_write_mode())
            coll.safe = False
            coll.write_concern.update(w=1)
            self.assertEqual((True, {}), coll._get_write_mode())
            coll.write_concern.update(w=3)
            self.assertEqual((True, {'w': 3}), coll._get_write_mode())

            coll.safe = True
            coll.write_concern.update(w=0)
            self.assertEqual((False, {}), coll._get_write_mode())

            coll = db.test
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            cursor = coll.find(slave_okay=True)
            self.assertTrue(cursor._Cursor__slave_okay)

            # MongoClient test
            c = MongoClient(pair)
            self.assertFalse(c.slave_okay)
            self.assertTrue(c.safe)
            self.assertEqual({}, c.get_lasterror_options())
            db = c.pymongo_test
            db.drop_collection("test")
            self.assertFalse(db.slave_okay)
            self.assertTrue(db.safe)
            self.assertEqual({}, db.get_lasterror_options())
            coll = db.test
            self.assertFalse(coll.slave_okay)
            self.assertTrue(coll.safe)
            self.assertEqual({}, coll.get_lasterror_options())

            self.assertEqual((True, {}), coll._get_write_mode())
            coll.safe = False
            coll.write_concern.update(w=1)
            self.assertEqual((True, {}), coll._get_write_mode())
            coll.write_concern.update(w=3)
            self.assertEqual((True, {'w': 3}), coll._get_write_mode())

            coll.safe = True
            coll.write_concern.update(w=0)
            self.assertEqual((False, {}), coll._get_write_mode())

            coll = db.test
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            cursor = coll.find(slave_okay=True)
            self.assertTrue(cursor._Cursor__slave_okay)

            # Setting any safe operations overrides explicit safe
            self.assertTrue(MongoClient(host, port, wtimeout=1000, safe=False).safe)

            c = MongoClient(pair, slaveok=True, w='majority',
                            wtimeout=300, fsync=True, j=True)
            self.assertTrue(c.slave_okay)
            self.assertTrue(c.safe)
            d = {'w': 'majority', 'wtimeout': 300, 'fsync': True, 'j': True}
            self.assertEqual(d, c.get_lasterror_options())
            db = c.pymongo_test
            self.assertTrue(db.slave_okay)
            self.assertTrue(db.safe)
            self.assertEqual(d, db.get_lasterror_options())
            coll = db.test
            self.assertTrue(coll.slave_okay)
            self.assertTrue(coll.safe)
            self.assertEqual(d, coll.get_lasterror_options())
            cursor = coll.find()
            self.assertTrue(cursor._Cursor__slave_okay)
            cursor = coll.find(slave_okay=False)
            self.assertFalse(cursor._Cursor__slave_okay)

            c = MongoClient('mongodb://%s/?'
                           'w=2;wtimeoutMS=300;fsync=true;'
                           'journal=true' % (pair,))
            self.assertTrue(c.safe)
            d = {'w': 2, 'wtimeout': 300, 'fsync': True, 'j': True}
            self.assertEqual(d, c.get_lasterror_options())

            c = MongoClient('mongodb://%s/?'
                           'slaveok=true;w=1;wtimeout=300;'
                           'fsync=true;j=true' % (pair,))
            self.assertTrue(c.slave_okay)
            self.assertTrue(c.safe)
            d = {'w': 1, 'wtimeout': 300, 'fsync': True, 'j': True}
            self.assertEqual(d, c.get_lasterror_options())
            self.assertEqual(d, c.write_concern)
            db = c.pymongo_test
            self.assertTrue(db.slave_okay)
            self.assertTrue(db.safe)
            self.assertEqual(d, db.get_lasterror_options())
            self.assertEqual(d, db.write_concern)
            coll = db.test
            self.assertTrue(coll.slave_okay)
            self.assertTrue(coll.safe)
            self.assertEqual(d, coll.get_lasterror_options())
            self.assertEqual(d, coll.write_concern)
            cursor = coll.find()
            self.assertTrue(cursor._Cursor__slave_okay)
            cursor = coll.find(slave_okay=False)
            self.assertFalse(cursor._Cursor__slave_okay)

            c.unset_lasterror_options()
            self.assertTrue(c.slave_okay)
            self.assertTrue(c.safe)
            c.safe = False
            self.assertFalse(c.safe)
            c.slave_okay = False
            self.assertFalse(c.slave_okay)
            self.assertEqual({}, c.get_lasterror_options())
            self.assertEqual({}, c.write_concern)
            db = c.pymongo_test
            self.assertFalse(db.slave_okay)
            self.assertFalse(db.safe)
            self.assertEqual({}, db.get_lasterror_options())
            self.assertEqual({}, db.write_concern)
            coll = db.test
            self.assertFalse(coll.slave_okay)
            self.assertFalse(coll.safe)
            self.assertEqual({}, coll.get_lasterror_options())
            self.assertEqual({}, coll.write_concern)
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            cursor = coll.find(slave_okay=True)
            self.assertTrue(cursor._Cursor__slave_okay)

            coll.set_lasterror_options(fsync=True)
            self.assertEqual({'fsync': True}, coll.get_lasterror_options())
            self.assertEqual({'fsync': True}, coll.write_concern)
            self.assertEqual({}, db.get_lasterror_options())
            self.assertEqual({}, db.write_concern)
            self.assertFalse(db.safe)
            self.assertEqual({}, c.get_lasterror_options())
            self.assertEqual({}, c.write_concern)
            self.assertFalse(c.safe)

            db.set_lasterror_options(w='majority')
            self.assertEqual({'fsync': True}, coll.get_lasterror_options())
            self.assertEqual({'fsync': True}, coll.write_concern)
            self.assertEqual({'w': 'majority'}, db.get_lasterror_options())
            self.assertEqual({'w': 'majority'}, db.write_concern)
            self.assertEqual({}, c.get_lasterror_options())
            self.assertEqual({}, c.write_concern)
            self.assertFalse(c.safe)
            db.slave_okay = True
            self.assertTrue(db.slave_okay)
            self.assertFalse(c.slave_okay)
            self.assertFalse(coll.slave_okay)
            cursor = coll.find()
            self.assertFalse(cursor._Cursor__slave_okay)
            cursor = db.coll2.find()
            self.assertTrue(cursor._Cursor__slave_okay)
            cursor = db.coll2.find(slave_okay=False)
            self.assertFalse(cursor._Cursor__slave_okay)

            self.assertRaises(ConfigurationError, coll.set_lasterror_options, foo=20)
            self.assertRaises(TypeError, coll._BaseObject__set_slave_okay, 20)
            self.assertRaises(TypeError, coll._BaseObject__set_safe, 20)

            coll.remove()
            self.assertEqual(None, coll.find_one(slave_okay=True))
            coll.unset_lasterror_options()
            coll.set_lasterror_options(w=4, wtimeout=10)
            # Fails if we don't have 4 active nodes or we don't have replication...
            self.assertRaises(OperationFailure, coll.insert, {'foo': 'bar'})
            # Succeeds since we override the lasterror settings per query.
            self.assertTrue(coll.insert({'foo': 'bar'}, fsync=True))
            drop_collections(db)
        finally:
            ctx.exit()