def test_system_js(self):
        db = self.client.pymongo_test
        db.system.js.remove()

        self.assertEqual(0, db.system.js.count())
        db.system_js.add = "function(a, b) { return a + b; }"
        self.assertEqual("add", db.system.js.find_one()["_id"])
        self.assertEqual(1, db.system.js.count())
        self.assertEqual(6, db.system_js.add(1, 5))
        del db.system_js.add
        self.assertEqual(0, db.system.js.count())

        db.system_js["add"] = "function(a, b) { return a + b; }"
        self.assertEqual("add", db.system.js.find_one()["_id"])
        self.assertEqual(1, db.system.js.count())
        self.assertEqual(6, db.system_js["add"](1, 5))
        del db.system_js["add"]
        self.assertEqual(0, db.system.js.count())

        if version.at_least(db.connection, (1, 3, 2, -1)):
            self.assertRaises(OperationFailure, db.system_js.add, 1, 5)

        # TODO right now CodeWScope doesn't work w/ system js
        # db.system_js.scope = Code("return hello;", {"hello": 8})
        # self.assertEqual(8, db.system_js.scope())

        self.assertRaises(OperationFailure, db.system_js.non_existant)

        # XXX: Broken in V8, works in SpiderMonkey
        # Use 1.2.9999 instead of 1.3.0 in order to catch 1.3.0-pre-
        if not version.tokumx_at_least(db.connection, (1, 2, 9999)):
            db.system_js.no_param = Code("return 5;")
            self.assertEqual(5, db.system_js.no_param())
    def test_fsync_lock_unlock(self):
        c = get_client()
        if is_mongos(c):
            raise SkipTest('fsync/lock not supported by mongos')
        if not version.at_least(c, (2, 0)) and server_started_with_auth(c):
            raise SkipTest('Requires server >= 2.0 to test with auth')

        res = c.admin.command('getCmdLineOpts')
        if '--master' in res['argv'] and version.at_least(c, (2, 3, 0)):
            raise SkipTest('SERVER-7714')

        self.assertFalse(c.is_locked)
        # async flushing not supported on windows...
        if sys.platform not in ('cygwin', 'win32'):
            c.fsync(async=True)
            self.assertFalse(c.is_locked)
        if not version.tokumx_at_least(c, (1,3,9999)):
            c.fsync(lock=True)
            self.assertTrue(c.is_locked)
            locked = True
            c.unlock()
            for _ in xrange(5):
                locked = c.is_locked
                if not locked:
                    break
                time.sleep(1)
            self.assertFalse(locked)
    def test_system_js(self):
        db = self.client.pymongo_test
        db.system.js.remove()

        self.assertEqual(0, db.system.js.count())
        db.system_js.add = "function(a, b) { return a + b; }"
        self.assertEqual('add', db.system.js.find_one()['_id'])
        self.assertEqual(1, db.system.js.count())
        self.assertEqual(6, db.system_js.add(1, 5))
        del db.system_js.add
        self.assertEqual(0, db.system.js.count())

        db.system_js['add'] = "function(a, b) { return a + b; }"
        self.assertEqual('add', db.system.js.find_one()['_id'])
        self.assertEqual(1, db.system.js.count())
        self.assertEqual(6, db.system_js['add'](1, 5))
        del db.system_js['add']
        self.assertEqual(0, db.system.js.count())

        if version.at_least(db.connection, (1, 3, 2, -1)):
            self.assertRaises(OperationFailure, db.system_js.add, 1, 5)

        # TODO right now CodeWScope doesn't work w/ system js
        # db.system_js.scope = Code("return hello;", {"hello": 8})
        # self.assertEqual(8, db.system_js.scope())

        self.assertRaises(OperationFailure, db.system_js.non_existant)

        # XXX: Broken in V8, works in SpiderMonkey
        # Use 1.2.9999 instead of 1.3.0 in order to catch 1.3.0-pre-
        if not version.tokumx_at_least(db.connection, (1, 2, 9999)):
            db.system_js.no_param = Code("return 5;")
            self.assertEqual(5, db.system_js.no_param())
    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()
    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()