def test_all_dbs(self):
     mock_resp = mock.Mock()
     mock_resp.raise_for_status = mock.Mock()
     mock_resp.json = mock.Mock()
     mock_resp.json.return_value = ['db1', 'db2']
     self.mock_instance.get.return_value = mock_resp
     c = CouchDB(self.username, self.password, url=self.url)
     c.connect()
     self.assertEqual(c.all_dbs(), mock_resp.json.return_value)
     self.assertTrue(mock_resp.raise_for_status.called)
    def test_getitem(self):
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()
        c['a'] = c._DATABASE_CLASS(c, 'a')
        c['b'] = c._DATABASE_CLASS(c, 'b')

        self.assertTrue(isinstance(c['a'], c._DATABASE_CLASS))
        self.assertTrue(isinstance(c['b'], c._DATABASE_CLASS))
        self.assertRaises(KeyError, c.__getitem__, 'd')

        with mock.patch('cloudant.account.CouchDatabase.exists') as mock_exists:
            mock_exists.return_value = True
            self.assertTrue(isinstance(c['c'], c._DATABASE_CLASS))
 def setUp(self):
     """
     Set up test attributes for CouchDB Account tests
     """
     self.user = os.environ['COUCHDB_USER']
     self.pwd = os.environ['COUCHDB_PASSWORD']
     self.url = os.environ['COUCHDB_URL']
     self.client = CouchDB(self.user, self.pwd, url=self.url)
    def test_db_updates(self):
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()
        updates_feed = """
            {"dbname": "somedb3", "type": "created", "account": "bob", "seq": "3-g1AAAABteJzLYWBgYMxgTmFQSElKzi9KdUhJMtHLTc1NzTcwMNdLzskvTUnMK9HLSy3JAapkSmTIY2H4DwRZGcyJzLlAIfa0tKQUQ2NTIkzIAgD_wSJc"}
            {"dbname": "somedb2", "type": "updated", "account": "bob", "seq": "4-g1AAAABteJzLYWBgYMxgTmFQSElKzi9KdUhJMtHLTc1NzTcwMNdLzskvTUnMK9HLSy3JAapkSmTIY2H4DwRZGcyJLLlAIfa0tKQUQ2NTIkzIAgAAASJd"}
            {"dbname": "somedb1", "type": "deleted", "account": "bob", "seq": "9-g1AAAABteJzLYWBgYMxgTmFQSElKzi9KdUhJMtHLTc1NzTcwMNdLzskvTUnMK9HLSy3JAapkSmTIY2H4DwRZGcyJnLlAIfa0tKQUQ2NTIkzIAgAA9iJi"}
            {"dbname": "somedb2", "type": "created", "account": "bob", "seq": "11-g1AAAABteJzLYWBgYMxgTmFQSElKzi9KdUhJMtHLTc1NzTcwMNdLzskvTUnMK9HLSy3JAapkSmTIY2H4DwRZGcyJ3LlAIfa0tKQUQ2NTIkzIAgABWCJk"}
            {"dbname": "somedb1", "type": "updated", "account": "bob", "seq": "12-g1AAAABteJzLYWBgYMxgTmFQSElKzi9KdUhJMtHLTc1NzTcwMNdLzskvTUnMK9HLSy3JAapkSmTIY2H4DwRZGcyJPLlAIfa0tKQUQ2NTIkzIAgABiSJl"}
        """
        with mock.patch('cloudant.account.Feed') as mock_feed:
            feed = (x.strip() for x in updates_feed.split('\n'))
            mock_feed.__iter__ = mock.MagicMock()
            mock_feed.return_value = feed

            updates = [u for u in c.db_updates()]

            self.assertEqual(len(updates), 5)
    def test_get(self):
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()

        c['a'] = c._DATABASE_CLASS(c, 'a')

        self.assertEqual(c.get('a'), c['a'])
        self.assertEqual(c.get('d', None), None)

        with mock.patch('cloudant.account.CouchDatabase.exists') as mock_exists:
            mock_exists.return_value = True
            self.assertTrue(isinstance(c.get('b', remote=True), c._DATABASE_CLASS))

        self.assertTrue(c.get('d', None, remote=True) is None)
 def test_keys(self):
     c = CouchDB(self.username, self.password, url=self.url)
     c.connect()
     c.all_dbs = mock.Mock()
     c.all_dbs.return_value = ['db1', 'db2']
     self.assertListEqual(list(c.keys()), [])
     self.assertEqual(c.keys(remote=True), c.all_dbs.return_value)
    def test_setitem(self):
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()
        self.assertRaises(CloudantException, c.__setitem__, 'c', 'womp')

        value = c._DATABASE_CLASS(c, 'a')
        c.__setitem__('c', value)
        self.assertTrue(c['c'] == value)

        value.exists = mock.Mock()
        value.exists.return_value = False
        value.create = mock.Mock()
        c.__setitem__('c', value, remote=True)
        self.assertTrue(value.create.called)
        self.assertTrue(c['c'] == value)
    def test_create_delete_methods(self):

        mock_resp = mock.Mock()
        mock_resp.json = mock.Mock()
        mock_resp.json.return_value = {}
        mock_resp.text = "mock response"
        mock_resp.status_code = 201

        mock_del = mock.Mock()
        mock_del.status_code = 200

        mock_get = mock.Mock()
        mock_get.status_code = 404

        self.mock_instance.put.return_value = mock_resp
        self.mock_instance.delete.return_value = mock_del
        self.mock_instance.get.return_value = mock_get

        # instantiate and connect
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()
        self.assertTrue(self.mock_session.called)
        # create db call
        c.create_database("unittest")
        self.mock_instance.get.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/unittest') ]
        )
        self.mock_instance.put.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/unittest') ]
        )

        # delete db call
        mock_get.reset_mocks()
        mock_get.status_code = 200
        c.delete_database("unittest")
        self.mock_instance.get.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/unittest') ]
        )

        self.mock_instance.delete.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/unittest') ]
        )

        # create existing db fails
        mock_get.reset_mocks()
        mock_get.status_code = 200
        self.assertRaises(CloudantException, c.create_database, "unittest")

        # delete non-existing db fails
        mock_get.reset_mocks()
        mock_get.status_code = 404
        self.assertRaises(CloudantException, c.delete_database, "unittest")
    def test_delitem(self):
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()
        c.delete_database = mock.Mock()

        c['a'] = c._DATABASE_CLASS(c, 'a')
        c['b'] = c._DATABASE_CLASS(c, 'b')

        del c['a']
        self.assertTrue('b' in c)
        self.assertTrue('a' not in c)

        c.__delitem__('b', remote=True)
        self.assertTrue(c.delete_database.called)
    def test_session_calls(self):
        """test session related methods"""
        c = CouchDB(self.username, self.password, url=self.url)
        c.connect()

        self.assertTrue(self.mock_session.called)

        self.assertEqual(
            self.mock_instance.auth,
            (self.username, self.password)
        )
        self.assertEqual(
            self.mock_instance.headers,
            {}
        )

        self.assertEqual('COOKIE', c.session_cookie())

        self.assertTrue(self.mock_instance.get.called)
        self.mock_instance.get.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/_session') ]
        )

        self.assertTrue(self.mock_instance.post.called)
        self.mock_instance.post.assert_has_calls(
            [ mock.call(
                  'http://127.0.0.1:5984/_session',
                  headers={'Content-Type': 'application/x-www-form-urlencoded'},
                  data={'password': '******', 'name': 'steve'}
            ) ]
        )

        c.disconnect()
        self.assertTrue(self.mock_instance.delete.called)
        self.mock_instance.delete.assert_has_calls(
            [ mock.call('http://127.0.0.1:5984/_session') ]
        )
 def test_basic_auth_str(self):
     c = CouchDB(self.username, self.password, url=self.url)
     auth_str = c.basic_auth_str()
     self.assertTrue(auth_str.startswith("Basic"))
     self.assertFalse(auth_str.endswith("Basic "))
     self.assertFalse(auth_str.endswith("Basic"))
class CouchDBAccountTests(unittest.TestCase):
    """
    CouchDB Class unit tests
    """

    @classmethod
    def setUpClass(self):
        """
        Set up CouchDB instance to be used by all tests

        If no user is specified then, assuming Admin Party and we
          need to create a user to run the CouchDB tests.
          
        Note: Admin Party is currently unsupported.
        """
        if os.environ.get('COUCHDB_URL') is None:
            os.environ['COUCHDB_URL'] = 'http://127.0.0.1:5984'

        if os.environ.get('COUCHDB_USER') is None:
            os.environ['COUCHDB_USER_CREATED'] = '1'
            os.environ['COUCHDB_USER'] = '******'.format(
                unicode(uuid.uuid4())
                )
            os.environ['COUCHDB_PASSWORD'] = '******'
            resp = requests.put(
                '{0}/_config/admins/{1}'.format(
                    os.environ['COUCHDB_URL'],
                    os.environ['COUCHDB_USER']
                    ),
                data='"{0}"'.format(os.environ['COUCHDB_PASSWORD'])
                )
            resp.raise_for_status()

    @classmethod
    def tearDownClass(self):
        """
        Clean up CouchDB instance once all tests are complete
        """
        if os.environ.get('COUCHDB_USER_CREATED') is not None:
            resp = requests.delete(
                '{0}://{1}:{2}@{3}/_config/admins/{4}'.format(
                    os.environ['COUCHDB_URL'].split('://', 1)[0],
                    os.environ['COUCHDB_USER'],
                    os.environ['COUCHDB_PASSWORD'],
                    os.environ['COUCHDB_URL'].split('://', 1)[1],
                    os.environ['COUCHDB_USER']
                    )
                )
            resp.raise_for_status()

    def setUp(self):
        """
        Set up test attributes for CouchDB Account tests
        """
        self.user = os.environ['COUCHDB_USER']
        self.pwd = os.environ['COUCHDB_PASSWORD']
        self.url = os.environ['COUCHDB_URL']
        self.client = CouchDB(self.user, self.pwd, url=self.url)

    def tearDown(self):
        """
        Ensure the client is new for each test
        """
        del self.client

    def dbname(self, database_name='account-unit-test-db'):
        return '{0}-{1}'.format(database_name, unicode(uuid.uuid4()))

    def test_constructor_with_url(self):
        """
        Test instantiating an account object using a URL
        """
        self.assertEqual(
            self.client.cloudant_url,
            self.url
            )
        self.assertEqual(self.client.encoder, json.JSONEncoder)
        self.assertIsNone(self.client.r_session)

    def test_connect(self):
        """
        Test connect and disconnect functionality
        """
        try:
            self.client.connect()
            self.assertIsInstance(self.client.r_session, requests.Session)
            self.assertEqual(self.client.r_session.auth, (self.user, self.pwd))
        finally:
            self.client.disconnect()
            self.assertIsNone(self.client.r_session)

    def test_session(self):
        """
        Test getting session information
        """
        try:
            self.client.connect()
            session = self.client.session()
            self.assertEqual(session['userCtx']['name'], self.user)
        finally:
            self.client.disconnect()

    def test_session_cookie(self):
        """
        Test getting the session cookie
        """
        try:
            self.client.connect()
            self.assertIsNotNone(self.client.session_cookie())
        finally:
            self.client.disconnect()

    def test_basic_auth_str(self):
        """
        Test getting the basic authentication string
        """
        try:
            self.client.connect()
            expected = 'Basic {0}'.format(
                base64.urlsafe_b64encode("{0}:{1}".format(self.user, self.pwd))
                )
            self.assertEqual(
                self.client.basic_auth_str(),
                expected
                )
        finally:
            self.client.disconnect()

    def test_all_dbs(self):
        """
        Test getting a list of all of the databases in the account
        """
        dbnames = []
        for _ in range(3):
            dbnames.append(self.dbname())
        try:
            self.client.connect()
            for dbname in dbnames:
                self.client.create_database(dbname)
            self.assertTrue(set(dbnames).issubset(self.client.all_dbs()))
        finally:
            for dbname in dbnames:
                self.client.delete_database(dbname)
            self.client.disconnect()

    def test_create_delete_database(self):
        """
        Test database creation and deletion
        """
        try:
            self.client.connect()
            dbname = self.dbname()
            # Create database
            db = self.client.create_database(dbname)
            self.assertTrue(db.exists())
            # Delete database
            self.assertIsNone(self.client.delete_database(dbname))
            self.assertFalse(db.exists())
        finally:
            self.client.disconnect()

    def test_create_existing_database(self):
        """
        Test creation of already existing database
        """
        dbname = self.dbname()
        try:
            self.client.connect()
            self.client.create_database(dbname)
            self.client.create_database(dbname, throw_on_exists=True)
            self.fail('Above statement should raise a CloudantException')
        except CloudantException, err:
            self.assertEqual(
                str(err),
                'Database {0} already exists'.format(dbname)
                )
        finally: