class TestCharmStore(TestCase): def entities_response(self, url, request): self.assertEqual( url.geturl(), 'http://example.com/meta/' + 'any?include=id&id=wordpress&id=mysql') return { 'status_code': 200, 'content': b'{"wordpress":"wordpress","mysql":"mysql"}'} def setUp(self): self.cs = CharmStore('http://example.com') def test_init(self): self.assertEqual(self.cs.url, 'http://example.com') def test_entity(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entity_full_id(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM_ID) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entity_reference(self): with HTTMock(entity_200): data = self.cs.charm( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entities(self): with HTTMock(self.entities_response): response = self.cs.entities(['wordpress', 'mysql']) self.assertEqual( {u'wordpress': u'wordpress', u'mysql': u'mysql'}, response) def test_entities_reference(self): with HTTMock(self.entities_response): response = self.cs.entities( [references.Reference.from_string('wordpress'), references.Reference.from_string('mysql')]) self.assertEqual( {u'wordpress': u'wordpress', u'mysql': u'mysql'}, response) def test_entities_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound) as cm: self.cs.entities(['not-found']) self.assertEqual( 'http://example.com/meta/any?include=id&id=not-found', cm.exception.args[0] ) def test_charm_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_charm_error_id(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM_ID) def test_charm_error_407(self): with HTTMock(entity_407): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_config(self): with HTTMock(config_200): data = self.cs.config(SAMPLE_CHARM) self.assertEqual({'exists': True}, data) def test_config_reference(self): with HTTMock(config_200): data = self.cs.config( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'exists': True}, data) def test_config_error(self): with HTTMock(config_404): with self.assertRaises(EntityNotFound): self.cs.config(SAMPLE_CHARM) def test_archive_url(self): with HTTMock(manifest_200): data = self.cs.archive_url(SAMPLE_CHARM) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_archive_url_reference(self): with HTTMock(manifest_200): data = self.cs.archive_url( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_file_good(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM) self.assertEqual({ u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_good_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({ u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_error(self): with HTTMock(manifest_404): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM) def test_file_one_file(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM, filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_error(self): with HTTMock(manifest_200): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM, filename='does.not.exist.md') def test_file_read_file(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files( SAMPLE_CHARM, filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_reference(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_error(self): with HTTMock(manifest_200): with HTTMock(file_404): with self.assertRaises(EntityNotFound): self.cs.files( SAMPLE_CHARM, filename='readme.md', read_file=True) def test_entityId(self): with HTTMock(id_200): charm_id = self.cs.entityId('bar') self.assertEqual('foo/bar', charm_id) def test_entityId_reference(self): with HTTMock(id_200): charm_id = self.cs.entityId( references.Reference.from_string('bar')) self.assertEqual('foo/bar', charm_id) def test_ids_no_charm(self): with HTTMock(id_404): with self.assertRaises(EntityNotFound): self.cs.entityId('baz') def test_search(self): with HTTMock(search_200): results = self.cs.search('foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list(self): with HTTMock(list_200): results = self.cs.list() self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_escaped(self): with HTTMock(search_200_escaped): results = self.cs.search('&foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.search('foo') self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/search?text=foo ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_list_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.list() self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/list ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_search_limit(self): with HTTMock(search_limit_200): results = self.cs.search('foo', limit=1) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_autocomplete(self): with HTTMock(search_autocomplete_200): results = self.cs.search( 'foo', autocomplete=True) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_includes(self): with HTTMock(search_includes_200): results = self.cs.search( 'foo', includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_includes(self): with HTTMock(list_includes_200): results = self.cs.list(includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_type(self): with HTTMock(search_type_200): results = self.cs.search('foo', doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_list_type(self): with HTTMock(list_type_200): results = self.cs.list(doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_search_tags(self): with HTTMock(search_tags_200): results = self.cs.search('foo', tags='databases') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_tags(self): with HTTMock(search_multiple_tags_200): results = self.cs.search('foo', tags=['databases', 'applications']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_series(self): with HTTMock(search_series_200): results = self.cs.search('foo', series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_series(self): with HTTMock(list_series_200): results = self.cs.list(series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_series(self): with HTTMock(search_multiple_series_200): results = self.cs.search('foo', series=['trusty', 'precise']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_owner(self): with HTTMock(search_owner_200): results = self.cs.search('', owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_list_owner(self): with HTTMock(search_owner_200): results = self.cs.list(owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_charm_icon_url(self): entity_id = 'mongodb' url = self.cs.charm_icon_url(entity_id) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_url_reference(self): entity_id = 'mongodb' url = self.cs.charm_icon_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_ok(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon(entity_id) self.assertEqual('icon', icon) def test_charm_icon_ok_reference(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon( references.Reference.from_string(entity_id)) self.assertEqual('icon', icon) def test_charm_icon_bad(self): entity_id = 'precise/mysql-1' with HTTMock(icon_404): with self.assertRaises(EntityNotFound): self.cs.charm_icon(entity_id) def test_bundle_visualization_url(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_ok(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization(entity_id) self.assertEqual('diagram', diagram) def test_bundle_visualization_bad(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_404): with self.assertRaises(EntityNotFound): self.cs.bundle_visualization(entity_id) def test_bundle_visualization_reference(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization( references.Reference.from_string(entity_id)) self.assertEqual('diagram', diagram) def test_entity_readme_url(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_entity_readme_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_readme_not_found(self): # A 404 not found error is returned when the readme cannot be found. with HTTMock(readme_404): with self.assertRaises(EntityNotFound): self.cs.entity_readme_content('precise/mysql-1') def test_readme_content(self): with HTTMock(readme_200): content = self.cs.entity_readme_content('precise/mysql-1') self.assertEqual('This is the readme', content) def test_readme_content_reference(self): with HTTMock(readme_200): content = self.cs.entity_readme_content( references.Reference.from_string('precise/mysql-1')) self.assertEqual('This is the readme', content) def test_debug(self): with HTTMock(debug_200): debug_data = self.cs.debug() self.assertEqual('all clear', debug_data['status']) def test_fetch_macaroon_successful(self): with HTTMock(fetch_macaroon_200): results = self.cs.fetch_macaroon() self.assertEqual('{"mymacaroon": "something"}', results) def test_fetch_macaroon_not_found(self): with HTTMock(fetch_macaroon_404): with self.assertRaises(EntityNotFound) as cm: self.cs.fetch_macaroon() self.assertEqual(cm.exception.args, ('http://example.com/macaroon',)) def test_search_with_macaroon(self): with HTTMock(search_200_with_macaroon): self.cs.macaroons = "[macaroon1, macaroon2]" results = self.cs.search('foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_with_macaroon(self): with HTTMock(search_200_with_macaroon): self.cs.macaroons = "[macaroon1, macaroon2]" results = self.cs.list() self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_timeout(self): with HTTMock(search_timeout): with self.assertRaises(ServerError) as cm: self.cs.search('foo') message = cm.exception.args[0] self.assertTrue('Request timed out' in message) def test_resource_url(self): entity_id = 'mongodb' url = self.cs.resource_url(entity_id, "myresource", "22") self.assertEqual('http://example.com/mongodb/resource/myresource/22', url)
class TestCharmStore(TestCase): def entities_response(self, url, request): self.assertEqual( url.geturl(), 'http://example.com/meta/' + 'any?include=id&id=wordpress&id=mysql') return { 'status_code': 200, 'content': b'{"wordpress":"wordpress","mysql":"mysql"}'} def setUp(self): self.cs = CharmStore('http://example.com') def test_init(self): self.assertEqual(self.cs.url, 'http://example.com') def test_entity(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entity_full_id(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM_ID) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entity_reference(self): with HTTMock(entity_200): data = self.cs.charm( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entities(self): with HTTMock(self.entities_response): response = self.cs.entities(['wordpress', 'mysql']) self.assertEqual( {u'wordpress': u'wordpress', u'mysql': u'mysql'}, response) def test_entities_reference(self): with HTTMock(self.entities_response): response = self.cs.entities( [references.Reference.from_string('wordpress'), references.Reference.from_string('mysql')]) self.assertEqual( {u'wordpress': u'wordpress', u'mysql': u'mysql'}, response) def test_entities_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound) as cm: self.cs.entities(['not-found']) self.assertEqual( 'http://example.com/meta/any?include=id&id=not-found', cm.exception.args[0] ) def test_charm_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_charm_error_id(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM_ID) def test_charm_error_407(self): with HTTMock(entity_407): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_config(self): with HTTMock(config_200): data = self.cs.config(SAMPLE_CHARM) self.assertEqual({'exists': True}, data) def test_config_reference(self): with HTTMock(config_200): data = self.cs.config( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'exists': True}, data) def test_config_error(self): with HTTMock(config_404): with self.assertRaises(EntityNotFound): self.cs.config(SAMPLE_CHARM) def test_archive_url(self): with HTTMock(manifest_200): data = self.cs.archive_url(SAMPLE_CHARM) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_archive_url_reference(self): with HTTMock(manifest_200): data = self.cs.archive_url( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_file_good(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM) self.assertEqual({ u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_good_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({ u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_error(self): with HTTMock(manifest_404): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM) def test_file_one_file(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM, filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_error(self): with HTTMock(manifest_200): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM, filename='does.not.exist.md') def test_file_read_file(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files( SAMPLE_CHARM, filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_reference(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_error(self): with HTTMock(manifest_200): with HTTMock(file_404): with self.assertRaises(EntityNotFound): self.cs.files( SAMPLE_CHARM, filename='readme.md', read_file=True) def test_entityId(self): with HTTMock(id_200): charm_id = self.cs.entityId('bar') self.assertEqual('foo/bar', charm_id) def test_entityId_reference(self): with HTTMock(id_200): charm_id = self.cs.entityId( references.Reference.from_string('bar')) self.assertEqual('foo/bar', charm_id) def test_ids_no_charm(self): with HTTMock(id_404): with self.assertRaises(EntityNotFound): self.cs.entityId('baz') def test_search(self): with HTTMock(search_200): results = self.cs.search('foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list(self): with HTTMock(list_200): results = self.cs.list() self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_escaped(self): with HTTMock(search_200_escaped): results = self.cs.search('&foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.search('foo') self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/search?text=foo ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_list_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.list() self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/list ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_search_limit(self): with HTTMock(search_limit_200): results = self.cs.search('foo', limit=1) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_autocomplete(self): with HTTMock(search_autocomplete_200): results = self.cs.search( 'foo', autocomplete=True) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_includes(self): with HTTMock(search_includes_200): results = self.cs.search( 'foo', includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_includes(self): with HTTMock(list_includes_200): results = self.cs.list(includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_type(self): with HTTMock(search_type_200): results = self.cs.search('foo', doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_list_type(self): with HTTMock(list_type_200): results = self.cs.list(doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_search_tags(self): with HTTMock(search_tags_200): results = self.cs.search('foo', tags='databases') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_tags(self): with HTTMock(search_multiple_tags_200): results = self.cs.search('foo', tags=['databases', 'applications']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_series(self): with HTTMock(search_series_200): results = self.cs.search('foo', series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_series(self): with HTTMock(list_series_200): results = self.cs.list(series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_series(self): with HTTMock(search_multiple_series_200): results = self.cs.search('foo', series=['trusty', 'precise']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_owner(self): with HTTMock(search_owner_200): results = self.cs.search('', owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_list_owner(self): with HTTMock(search_owner_200): results = self.cs.list(owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_charm_icon_url(self): entity_id = 'mongodb' url = self.cs.charm_icon_url(entity_id) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_url_reference(self): entity_id = 'mongodb' url = self.cs.charm_icon_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_ok(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon(entity_id) self.assertEqual('icon', icon) def test_charm_icon_ok_reference(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon( references.Reference.from_string(entity_id)) self.assertEqual('icon', icon) def test_charm_icon_bad(self): entity_id = 'precise/mysql-1' with HTTMock(icon_404): with self.assertRaises(EntityNotFound): self.cs.charm_icon(entity_id) def test_bundle_visualization_url(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_ok(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization(entity_id) self.assertEqual('diagram', diagram) def test_bundle_visualization_bad(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_404): with self.assertRaises(EntityNotFound): self.cs.bundle_visualization(entity_id) def test_bundle_visualization_reference(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization( references.Reference.from_string(entity_id)) self.assertEqual('diagram', diagram) def test_entity_readme_url(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_entity_readme_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_readme_not_found(self): # A 404 not found error is returned when the readme cannot be found. with HTTMock(readme_404): with self.assertRaises(EntityNotFound): self.cs.entity_readme_content('precise/mysql-1') def test_readme_content(self): with HTTMock(readme_200): content = self.cs.entity_readme_content('precise/mysql-1') self.assertEqual('This is the readme', content) def test_readme_content_reference(self): with HTTMock(readme_200): content = self.cs.entity_readme_content( references.Reference.from_string('precise/mysql-1')) self.assertEqual('This is the readme', content) def test_debug(self): with HTTMock(debug_200): debug_data = self.cs.debug() self.assertEqual('all clear', debug_data['status']) def test_timeout(self): with HTTMock(search_timeout): with self.assertRaises(ServerError) as cm: self.cs.search('foo') message = cm.exception.args[0] self.assertTrue('Request timed out' in message) def test_resource_url(self): entity_id = 'mongodb' url = self.cs.resource_url(entity_id, "myresource", "22") self.assertEqual('http://example.com/mongodb/resource/myresource/22', url)
class TestCharmStore(TestCase): def entities_response(self, url, request): self.assertEqual( url.geturl(), 'http://example.com/meta/' + 'any?include=id&id=wordpress&id=mysql') return { 'status_code': 200, 'content': b'{"wordpress":"wordpress","mysql":"mysql"}' } def setUp(self): self.cs = CharmStore('http://example.com') def test_init(self): self.assertEqual(self.cs.url, 'http://example.com') def test_entity(self): tests = [{ 'about': 'default includes', 'want_query': ('include=bundle-machine-count&include=bundle-metadata&' 'include=bundle-unit-count&include=charm-actions&' 'include=charm-config&include=charm-metadata&' 'include=common-info&include=extra-info&include=owner&' 'include=published&include=resources&' 'include=supported-series&include=terms&include=stats'), }, { 'about': 'custom includes', 'kwargs': { 'includes': ['foo', 'bar'] }, 'want_query': 'include=foo&include=bar&include=stats', }, { 'about': 'custom includes and no stats', 'kwargs': { 'includes': ['foo'], 'include_stats': False }, 'want_query': 'include=foo', }, { 'about': 'custom includes and get files', 'kwargs': { 'includes': [], 'get_files': True }, 'want_query': 'include=manifest&include=stats', }, { 'about': 'default includes, no stats, with files', 'kwargs': { 'get_files': True, 'include_stats': False }, 'want_query': ('include=bundle-machine-count&include=bundle-metadata&' 'include=bundle-unit-count&include=charm-actions&' 'include=charm-config&include=charm-metadata&' 'include=common-info&include=extra-info&include=owner&' 'include=published&include=resources&' 'include=supported-series&include=terms&include=manifest'), }] for test in tests: # TODO(frankban): use subtests here when switching to Python 3. logging.debug(test['about']) self.check_entity(test.get('kwargs', {}), test.get('want_query', '')) def check_entity(self, kwargs, want_query): @urlmatch(path=ID_PATH) def handler(url, request): self.assertEqual(request.method, 'GET') self.assertEqual(url.path, '/precise/mysql-1/meta/any') self.assertEqual(url.query, want_query) return {'status_code': 200, 'content': {'result': 'foo'}} with HTTMock(handler): data = self.cs.entity(SAMPLE_CHARM_ID, **kwargs) self.assertEqual(data, {'result': 'foo'}) def test_charm(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_charm_full_id(self): with HTTMock(entity_200): data = self.cs.charm(SAMPLE_CHARM_ID) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_charm_reference(self): with HTTMock(entity_200): data = self.cs.charm( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'Meta': {'charm-metadata': {'exists': True}}}, data) def test_entities(self): with HTTMock(self.entities_response): response = self.cs.entities(['wordpress', 'mysql']) self.assertEqual({ u'wordpress': u'wordpress', u'mysql': u'mysql' }, response) def test_entities_reference(self): with HTTMock(self.entities_response): response = self.cs.entities([ references.Reference.from_string('wordpress'), references.Reference.from_string('mysql') ]) self.assertEqual({ u'wordpress': u'wordpress', u'mysql': u'mysql' }, response) def test_entities_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound) as cm: self.cs.entities(['not-found']) self.assertEqual( 'http://example.com/meta/any?include=id&id=not-found', cm.exception.args[0]) def test_charm_error(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_charm_error_id(self): with HTTMock(entity_404): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM_ID) def test_charm_error_407(self): with HTTMock(entity_407): with self.assertRaises(EntityNotFound): self.cs.charm(SAMPLE_CHARM) def test_config(self): with HTTMock(config_200): data = self.cs.config(SAMPLE_CHARM) self.assertEqual({'exists': True}, data) def test_config_reference(self): with HTTMock(config_200): data = self.cs.config( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual({'exists': True}, data) def test_config_error(self): with HTTMock(config_404): with self.assertRaises(EntityNotFound): self.cs.config(SAMPLE_CHARM) def test_archive_url(self): with HTTMock(manifest_200): data = self.cs.archive_url(SAMPLE_CHARM) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_archive_url_reference(self): with HTTMock(manifest_200): data = self.cs.archive_url( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual(u'http://example.com/precise/mysql-1/archive', data) def test_file_good(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM) self.assertEqual( { u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_good_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM)) self.assertEqual( { u'icon.svg': u'http://example.com/precise/mysql-1/archive/icon.svg', u'README.md': u'http://example.com/precise/mysql-1/archive/README.md' }, data) def test_file_error(self): with HTTMock(manifest_404): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM) def test_file_one_file(self): with HTTMock(manifest_200): data = self.cs.files(SAMPLE_CHARM, filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_reference(self): with HTTMock(manifest_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md') self.assertEqual( u'http://example.com/precise/mysql-1/archive/README.md', data) def test_file_one_file_error(self): with HTTMock(manifest_200): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM, filename='does.not.exist.md') def test_file_read_file(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files(SAMPLE_CHARM, filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_reference(self): with HTTMock(manifest_200): with HTTMock(file_200): data = self.cs.files( references.Reference.from_string(SAMPLE_CHARM), filename='README.md', read_file=True) self.assertEqual('This is a file.', data) def test_file_read_file_error(self): with HTTMock(manifest_200): with HTTMock(file_404): with self.assertRaises(EntityNotFound): self.cs.files(SAMPLE_CHARM, filename='readme.md', read_file=True) def test_entityId(self): with HTTMock(id_200): charm_id = self.cs.entityId('bar') self.assertEqual('foo/bar', charm_id) def test_entityId_reference(self): with HTTMock(id_200): charm_id = self.cs.entityId( references.Reference.from_string('bar')) self.assertEqual('foo/bar', charm_id) def test_ids_no_charm(self): with HTTMock(id_404): with self.assertRaises(EntityNotFound): self.cs.entityId('baz') def test_search(self): with HTTMock(search_200): results = self.cs.search('foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list(self): with HTTMock(list_200): results = self.cs.list() self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_escaped(self): with HTTMock(search_200_escaped): results = self.cs.search('&foo') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.search('foo') self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/search?text=foo ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_list_400(self): with patch('theblues.charmstore.logging.error') as log_mocked: with HTTMock(search_400): with self.assertRaises(ServerError) as cm: self.cs.list() self.assertEqual(400, cm.exception.args[0]) log_mocked.assert_called_with( 'Error during request: http://example.com/list ' 'status code:(400) message: ' '{"Message": "invalid parameter: user", "Code": "bad request"}') def test_search_limit(self): with HTTMock(search_limit_200): results = self.cs.search('foo', limit=1) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_autocomplete(self): with HTTMock(search_autocomplete_200): results = self.cs.search('foo', autocomplete=True) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_includes(self): with HTTMock(search_includes_200): results = self.cs.search( 'foo', includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_includes(self): with HTTMock(list_includes_200): results = self.cs.list(includes=['archive-size', 'charm-metadata']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_type(self): with HTTMock(search_type_200): results = self.cs.search('foo', doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_list_type(self): with HTTMock(list_type_200): results = self.cs.list(doc_type='bundle') self.assertEqual([{'Id': 'cs:bundle/mediawiki-single-7'}], results) def test_search_tags(self): with HTTMock(search_tags_200): results = self.cs.search('foo', tags='databases') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_tags(self): with HTTMock(search_multiple_tags_200): results = self.cs.search('foo', tags=['databases', 'applications']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_series(self): with HTTMock(search_series_200): results = self.cs.search('foo', series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_list_series(self): with HTTMock(list_series_200): results = self.cs.list(series='precise') self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_multiple_series(self): with HTTMock(search_multiple_series_200): results = self.cs.search('foo', series=['trusty', 'precise']) self.assertEqual([{'Id': 'cs:foo/bar-0'}], results) def test_search_owner(self): with HTTMock(search_owner_200): results = self.cs.search('', owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_list_owner(self): with HTTMock(search_owner_200): results = self.cs.list(owner='hatch') self.assertEqual([{"Id": "cs:foo/bar-0"}], results) def test_charm_icon_url(self): entity_id = 'mongodb' url = self.cs.charm_icon_url(entity_id) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_url_reference(self): entity_id = 'mongodb' url = self.cs.charm_icon_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb/icon.svg', url) def test_charm_icon_ok(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon(entity_id) self.assertEqual('icon', icon) def test_charm_icon_ok_reference(self): entity_id = 'precise/mysql-1' with HTTMock(icon_200): icon = self.cs.charm_icon( references.Reference.from_string(entity_id)) self.assertEqual('icon', icon) def test_charm_icon_bad(self): entity_id = 'precise/mysql-1' with HTTMock(icon_404): with self.assertRaises(EntityNotFound): self.cs.charm_icon(entity_id) def test_bundle_visualization_url(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.bundle_visualization_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/diagram.svg', url) def test_bundle_visualization_ok(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization(entity_id) self.assertEqual('diagram', diagram) def test_bundle_visualization_bad(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_404): with self.assertRaises(EntityNotFound): self.cs.bundle_visualization(entity_id) def test_bundle_visualization_reference(self): entity_id = 'mongodb-cluster' with HTTMock(diagram_200): diagram = self.cs.bundle_visualization( references.Reference.from_string(entity_id)) self.assertEqual('diagram', diagram) def test_entity_readme_url(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url(entity_id) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_entity_readme_url_reference(self): entity_id = 'mongodb-cluster' url = self.cs.entity_readme_url( references.Reference.from_string(entity_id)) self.assertEqual('http://example.com/mongodb-cluster/readme', url) def test_readme_not_found(self): # A 404 not found error is returned when the readme cannot be found. with HTTMock(readme_404): with self.assertRaises(EntityNotFound): self.cs.entity_readme_content('precise/mysql-1') def test_readme_content(self): with HTTMock(readme_200): content = self.cs.entity_readme_content('precise/mysql-1') self.assertEqual('This is the readme', content) def test_readme_content_reference(self): with HTTMock(readme_200): content = self.cs.entity_readme_content( references.Reference.from_string('precise/mysql-1')) self.assertEqual('This is the readme', content) def test_debug(self): with HTTMock(debug_200): debug_data = self.cs.debug() self.assertEqual('all clear', debug_data['status']) def test_timeout(self): with HTTMock(search_timeout): with self.assertRaises(ServerError) as cm: self.cs.search('foo') message = cm.exception.args[0] self.assertTrue('Request timed out' in message) def test_resource_url(self): entity_id = 'mongodb' url = self.cs.resource_url(entity_id, "myresource", "22") self.assertEqual('http://example.com/mongodb/resource/myresource/22', url)