18d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi#!/usr/bin env python
28d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
38d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom tests.compat import mock, unittest
48d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom httpretty import HTTPretty
58d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
68d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport json
78d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport requests
88d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
98d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.cloudsearch.search import SearchConnection, SearchServiceException
108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.compat import six, map
118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi KandoiHOSTNAME = "search-demo-userdomain.us-east-1.cloudsearch.amazonaws.com"
138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi KandoiFULL_URL = 'http://%s/2011-02-01/search' % HOSTNAME
148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchSearchBaseTest(unittest.TestCase):
178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    hits = [
198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12341',
218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 1',
228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12342',
258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 2',
268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12343',
298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 3',
308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12344',
338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 4',
348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12345',
378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 5',
388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12346',
418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 6',
428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        {
448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'id': '12347',
458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'title': 'Document 7',
468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    ]
488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    content_type = "text/xml"
508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response_status = 200
518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def get_args(self, requestline):
538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        (_, request, _) = requestline.split(b" ")
548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        (_, request) = request.split(b"?", 1)
558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = six.moves.urllib.parse.parse_qs(request)
568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        return args
578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def setUp(self):
598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        HTTPretty.enable()
608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        body = self.response
618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        if not isinstance(body, bytes):
638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            body = json.dumps(body).encode('utf-8')
648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        HTTPretty.register_uri(HTTPretty.GET, FULL_URL,
668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                               body=body,
678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                               content_type=self.content_type,
688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                               status=self.response_status)
698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def tearDown(self):
718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        HTTPretty.disable()
728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchSearchTest(CloudSearchSearchBaseTest):
748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response = {
758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'rank': '-text_relevance',
768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'match-expr': "Test",
778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'hits': {
788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'found': 30,
798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'start': 0,
808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'hit': CloudSearchSearchBaseTest.hits
818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            },
828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'info': {
838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'rid': 'b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08',
848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'time-ms': 2,
858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'cpu-time-ms': 0
868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        }
878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    }
898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_qsearch(self):
918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test')
948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'q'], [b"Test"])
988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'start'], [b"0"])
998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'size'], [b"10"])
1008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_bqsearch(self):
1028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(bq="'Test'")
1058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'bq'], [b"'Test'"])
1098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_search_details(self):
1118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', size=50, start=20)
1148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'q'], [b"Test"])
1188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'size'], [b"50"])
1198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'start'], [b"20"])
1208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_single(self):
1228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet=["Author"])
1258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet'], [b"Author"])
1298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_multiple(self):
1318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet=["author", "cat"])
1348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet'], [b"author,cat"])
1388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_constraint_single(self):
1408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(
1438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            q='Test',
1448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            facet_constraints={'author': "'John Smith','Mark Smith'"})
1458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-constraints'],
1498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                         [b"'John Smith','Mark Smith'"])
1508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_constraint_multiple(self):
1528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(
1558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            q='Test',
1568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            facet_constraints={'author': "'John Smith','Mark Smith'",
1578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                               'category': "'News','Reviews'"})
1588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-constraints'],
1628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                         [b"'John Smith','Mark Smith'"])
1638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-category-constraints'],
1648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                         [b"'News','Reviews'"])
1658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_sort_single(self):
1678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet_sort={'author': 'alpha'})
1708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-sort'], [b'alpha'])
1748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_facet_sort_multiple(self):
1768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet_sort={'author': 'alpha',
1798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                                            'cat': 'count'})
1808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-sort'], [b'alpha'])
1848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-cat-sort'], [b'count'])
1858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_top_n_single(self):
1878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet_top_n={'author': 5})
1908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
1928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-top-n'], [b'5'])
1948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_top_n_multiple(self):
1968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
1978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
1988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', facet_top_n={'author': 5, 'cat': 10})
1998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-author-top-n'], [b'5'])
2038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'facet-cat-top-n'], [b'10'])
2048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_rank_single(self):
2068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', rank=["date"])
2098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'rank'], [b'date'])
2138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_rank_multiple(self):
2158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', rank=["date", "score"])
2188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'rank'], [b'date,score'])
2228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_result_fields_single(self):
2248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', return_fields=['author'])
2278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'return-fields'], [b'author'])
2318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_result_fields_multiple(self):
2338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', return_fields=['author', 'title'])
2368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b'return-fields'], [b'author,title'])
2408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_t_field_single(self):
2428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', t={'year': '2001..2007'})
2458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b't-year'], [b'2001..2007'])
2498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_t_field_multiple(self):
2518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search.search(q='Test', t={'year': '2001..2007', 'score': '10..50'})
2548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        args = self.get_args(HTTPretty.last_request.raw_requestline)
2568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b't-year'], [b'2001..2007'])
2588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(args[b't-score'], [b'10..50'])
2598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_meta(self):
2618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check returned metadata is parsed correctly"""
2628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test')
2658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        # These rely on the default response which is fed into HTTPretty
2678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.rank, "-text_relevance")
2688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.match_expression, "Test")
2698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_info(self):
2718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check num_pages_needed is calculated correctly"""
2728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test')
2758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        # This relies on the default response which is fed into HTTPretty
2778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.num_pages_needed, 3.0)
2788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_matched(self):
2808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """
2818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        Check that information objects are passed back through the API
2828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        correctly.
2838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """
2848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        query = search.build_query(q='Test')
2868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search(query)
2888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.search_service, search)
2908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.query, query)
2918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_hits(self):
2938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check that documents are parsed properly from AWS"""
2948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
2958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test')
2978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
2988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        hits = list(map(lambda x: x['id'], results.docs))
2998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        # This relies on the default response which is fed into HTTPretty
3018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(
3028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            hits, ["12341", "12342", "12343", "12344",
3038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                   "12345", "12346", "12347"])
3048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_iterator(self):
3068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check the results iterator"""
3078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test')
3108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results_correct = iter(["12341", "12342", "12343", "12344",
3118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                                "12345", "12346", "12347"])
3128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        for x in results:
3138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            self.assertEqual(x['id'], next(results_correct))
3148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_results_internal_consistancy(self):
3178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check the documents length matches the iterator details"""
3188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test')
3218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(len(results), len(results.docs))
3238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_search_nextpage(self):
3258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        """Check next page query is correct"""
3268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        query1 = search.build_query(q='Test')
3288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        query2 = search.build_query(q='Test')
3298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search(query2)
3318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.next_page().query.start,
3338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                         query1.start + query1.size)
3348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(query1.q, query2.q)
3358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchSearchFacetTest(CloudSearchSearchBaseTest):
3378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response = {
3388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'rank': '-text_relevance',
3398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'match-expr': "Test",
3408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'hits': {
3418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'found': 30,
3428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'start': 0,
3438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'hit': CloudSearchSearchBaseTest.hits
3448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            },
3458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'info': {
3468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'rid': 'b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08',
3478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'time-ms': 2,
3488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'cpu-time-ms': 0
3498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        },
3508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        'facets': {
3518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'tags': {},
3528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'animals': {'constraints': [{'count': '2', 'value': 'fish'}, {'count': '1', 'value': 'lions'}]},
3538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        }
3548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    }
3558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_cloudsearch_search_facets(self):
3578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        #self.response['facets'] = {'tags': {}}
3588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        results = search.search(q='Test', facet=['tags'])
3628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertTrue('tags' not in results.facets)
3648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.assertEqual(results.facets['animals'], {u'lions': u'1', u'fish': u'2'})
3658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchNonJsonTest(CloudSearchSearchBaseTest):
3688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response = b'<html><body><h1>500 Internal Server Error</h1></body></html>'
3698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response_status = 500
3708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    content_type = 'text/xml'
3718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_response(self):
3738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        with self.assertRaises(SearchServiceException):
3768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            search.search(q='Test')
3778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchUnauthorizedTest(CloudSearchSearchBaseTest):
3808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response = b'<html><body><h1>403 Forbidden</h1>foo bar baz</body></html>'
3818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    response_status = 403
3828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    content_type = 'text/html'
3838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_response(self):
3858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        search = SearchConnection(endpoint=HOSTNAME)
3868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        with self.assertRaisesRegexp(SearchServiceException, 'foo bar baz'):
3888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            search.search(q='Test')
3898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass FakeResponse(object):
3928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    status_code = 405
3938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    content = b''
3948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass CloudSearchConnectionTest(unittest.TestCase):
3978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    cloudsearch = True
3988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
3998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def setUp(self):
4008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        super(CloudSearchConnectionTest, self).setUp()
4018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        self.conn = SearchConnection(
4028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            endpoint='test-domain.cloudsearch.amazonaws.com'
4038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        )
4048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi    def test_expose_additional_error_info(self):
4068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        mpo = mock.patch.object
4078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        fake = FakeResponse()
4088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        fake.content = b'Nopenopenope'
4098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        # First, in the case of a non-JSON, non-403 error.
4118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        with mpo(requests, 'get', return_value=fake) as mock_request:
4128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            with self.assertRaises(SearchServiceException) as cm:
4138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                self.conn.search(q='not_gonna_happen')
4148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            self.assertTrue('non-json response' in str(cm.exception))
4168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            self.assertTrue('Nopenopenope' in str(cm.exception))
4178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        # Then with JSON & an 'error' key within.
4198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        fake.content = json.dumps({
4208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            'error': "Something went wrong. Oops."
4218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        }).encode('utf-8')
4228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi        with mpo(requests, 'get', return_value=fake) as mock_request:
4248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            with self.assertRaises(SearchServiceException) as cm:
4258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi                self.conn.search(q='no_luck_here')
4268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi
4278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            self.assertTrue('Unknown error' in str(cm.exception))
4288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi            self.assertTrue('went wrong. Oops' in str(cm.exception))
429