class SearchTests(TestCase): def setUp(self): provideUtility(SolrConnectionConfig(), ISolrConnectionConfig) self.mngr = SolrConnectionManager() self.mngr.setHost(active=True) self.conn = self.mngr.getConnection() self.search = Search() self.search.manager = self.mngr def tearDown(self): self.mngr.closeConnection() self.mngr.setHost(active=False) def testSimpleSearch(self): schema = getData('schema.xml') search = getData('search_response.txt') request = getData('search_request.txt') output = fakehttp(self.conn, schema, search) # fake responses query = self.search.buildQuery(id='[* TO *]') results = self.search(query, rows=10, wt='xml', indent='on').results() normalize = lambda x: sorted(x.split('&')) # sort request params self.assertEqual(normalize(output.get(skip=1)), normalize(request)) self.assertEqual(results.numFound, '1') self.assertEqual(len(results), 1) match = results[0] self.assertEqual(match.id, '500') self.assertEqual(match.name, 'python test doc') self.assertEqual(match.popularity, 0) self.assertEqual(match.sku, '500') self.assertEqual(match.timestamp, DateTime('2008-02-29 16:11:46.998 GMT'))
class TestBuildQuery(TestCase): def setUp(self): provideUtility(SolrConnectionConfig(), ISolrConnectionConfig) self.mngr = SolrConnectionManager() self.mngr.setHost(active=True) conn = self.mngr.getConnection() fakehttp(conn, getData('plone_schema.xml')) # fake schema response self.mngr.getSchema() # read and cache the schema self.search = Search() self.search.manager = self.mngr # Patch buildQuery method self.search.buildQuery = buildQueryAndParameters.__get__( self.search, self.search.__class__) def tearDown(self): self.mngr.closeConnection() self.mngr.setHost(active=False) def build_query(self, *args, **kwargs): query = self.search.buildQuery(*args, **kwargs)[0] return ' '.join(sorted(query.values())) def test_simple_path_query(self): self.assertEquals('+path_parents:\\/spam\\/and\\/eggs', self.build_query(path_parents='/spam/and/eggs')) def test_path_list_query(self): self.assertEquals('+path_parents:("\\/spam" OR "\\/eggs")', self.build_query(path_parents=['/spam', '/eggs'])) def test_slash_in_searchabletext(self): self.assertEquals('+SearchableText:spam\\/eggs', self.build_query(SearchableText='spam/eggs')) def test_queries_with_path_and_depth_should_be_escaped(self): self.assertEquals( '+path_depth:[4 TO 6] AND +path_parents:\\/spam\\/and\\/eggs', self.build_query( path_parents=set(['+path_depth:[4 TO 6] AND ' '+path_parents:/spam/and/eggs'])))
class TestBuildQuery(TestCase): def setUp(self): provideUtility(SolrConnectionConfig(), ISolrConnectionConfig) self.mngr = SolrConnectionManager() self.mngr.setHost(active=True) conn = self.mngr.getConnection() fakehttp(conn, getData('plone_schema.xml')) # fake schema response self.mngr.getSchema() # read and cache the schema self.search = Search() self.search.manager = self.mngr # Patch buildQuery method self.search.buildQuery = buildQuery.__get__(self.search, self.search.__class__) def tearDown(self): self.mngr.closeConnection() self.mngr.setHost(active=False) def build_query(self, *args, **kwargs): query = self.search.buildQuery(*args, **kwargs) return ' '.join(sorted(query.values())) def test_simple_path_query(self): self.assertEquals('+path_parents:\\/spam\\/and\\/eggs', self.build_query(path_parents='/spam/and/eggs')) def test_path_list_query(self): self.assertEquals('+path_parents:(\\/spam OR \\/eggs)', self.build_query(path_parents=['/spam', '/eggs'])) def test_slash_in_searchabletext(self): self.assertEquals('+SearchableText:spam\\/eggs', self.build_query(SearchableText='spam/eggs')) def test_queries_with_path_and_depth_should_be_escaped(self): self.assertEquals( '+path_depth:[4 TO 6] AND +path_parents:\\/spam\\/and\\/eggs', self.build_query(path_parents=set( ['+path_depth:[4 TO 6] AND ' '+path_parents:/spam/and/eggs'])))
def testUnavailableSchema(self): provideUtility(SolrConnectionConfig(), ISolrConnectionConfig) search = Search() search.manager = SolrConnectionManager() self.assertEqual(search.buildQuery('foo'), {}) self.assertEqual(search.buildQuery(name='foo'), {})
class QueryTests(TestCase): def setUp(self): provideUtility(SolrConnectionConfig(), ISolrConnectionConfig) self.mngr = SolrConnectionManager() self.mngr.setHost(active=True) conn = self.mngr.getConnection() fakehttp(conn, getData('schema.xml')) # fake schema response self.mngr.getSchema() # read and cache the schema self.search = Search() self.search.manager = self.mngr def tearDown(self): self.mngr.closeConnection() self.mngr.setHost(active=False) def bq(self, *args, **kw): query = self.search.buildQuery(*args, **kw) return ' '.join(sorted(query.values())) def testSimpleQueries(self): bq = self.bq self.assertEqual(bq('foo'), '+foo') self.assertEqual(bq('foo*'), '+foo*') self.assertEqual(bq('foo!'), '+foo\\!') self.assertEqual(bq('(foo)'), '+foo') self.assertEqual(bq('(foo...'), '+foo...') self.assertEqual(bq('foo bar'), '+(foo bar)') self.assertEqual(bq('*****@*****.**'), '*****@*****.**') self.assertEqual(bq(name='foo'), '+name:foo') self.assertEqual(bq(name='foo*'), '+name:foo*') self.assertEqual(bq(name='foo bar'), '+name:(foo bar)') self.assertEqual(bq(name='*****@*****.**'), '+name:[email protected]') self.assertEqual(bq(name=' '), '') # Whitespace is removed self.assertEqual(bq(name=''), '') def testMultiValueQueries(self): bq = self.bq self.assertEqual(bq(('foo', 'bar')), '+(foo OR bar)') self.assertEqual(bq(('foo', 'bar*')), '+(foo OR bar*)') self.assertEqual(bq(('foo bar', 'hmm')), '+("foo bar" OR hmm)') self.assertEqual(bq(('foø bar', 'hmm')), '+("fo\xc3\xb8 bar" OR hmm)') self.assertEqual(bq(('"foo bar"', 'hmm')), '+("foo bar" OR hmm)') self.assertEqual(bq(name=['foo', 'bar']), '+name:(foo OR bar)') self.assertEqual(bq(name=['foo', 'bar*']), '+name:(foo OR bar*)') self.assertEqual(bq(name=['foo bar', 'hmm']), '+name:("foo bar" OR hmm)') def testMultiArgumentQueries(self): bq = self.bq self.assertEqual(bq('foo', name='bar'), '+foo +name:bar') self.assertEqual(bq('foo', name=('bar', 'hmm')), '+foo +name:(bar OR hmm)') self.assertEqual(bq('foo', name=('foo bar', 'hmm')), '+foo +name:("foo bar" OR hmm)') self.assertEqual(bq(name='foo', cat='bar'), '+cat:bar +name:foo') self.assertEqual(bq(name='foo', cat=['bar', 'hmm']), '+cat:(bar OR hmm) +name:foo') self.assertEqual(bq(name='foo', cat=['foo bar', 'hmm']), '+cat:("foo bar" OR hmm) +name:foo') self.assertEqual(bq('foo', name=' '), '+foo') # empty value for a name should return no results like in ZCatalog, so # empty query is returned self.assertEqual(bq('foo', name=''), '') def testInvalidArguments(self): bq = self.bq self.assertEqual(bq(title='foo'), '') self.assertEqual(bq(title='foo', name='bar'), '+name:bar') self.assertEqual(bq('bar', title='foo'), '+bar') def testUnicodeArguments(self): bq = self.bq self.assertEqual(bq(u'foo'), '+foo') self.assertEqual(bq(u'foø'), '+fo\xc3\xb8') self.assertEqual(bq(u'*****@*****.**'), '*****@*****.**') self.assertEqual(bq(name=['foo', u'bar']), '+name:(foo OR bar)') self.assertEqual(bq(name=['foo', u'bär']), '+name:(foo OR b\xc3\xa4r)') self.assertEqual(bq(name='foo', cat=(u'bar', 'hmm')), '+cat:(bar OR hmm) +name:foo') self.assertEqual(bq(name='foo', cat=(u'bär', 'hmm')), '+cat:(b\xc3\xa4r OR hmm) +name:foo') self.assertEqual(bq(name=u'*****@*****.**', cat='spammer'), '+cat:spammer +name:[email protected]') def testQuotedQueries(self): bq = self.bq self.assertEqual(bq('"foo"'), '+"foo"') self.assertEqual(bq('foo'), '+foo') self.assertEqual(bq('"foo*"'), '+"foo\*"') self.assertEqual(bq('foo*'), '+foo*') self.assertEqual(bq('"+foo"'), '+"\+foo"') self.assertEqual(bq('+foo'), '+foo') self.assertEqual(bq('"foo bar"'), '+"foo bar"') self.assertEqual(bq('foo bar'), '+(foo bar)') self.assertEqual(bq('"foo bar?"'), '+"foo bar\?"') self.assertEqual(bq('foo bar?'), '+(foo bar?)') self.assertEqual(bq('-foo +bar'), '+(-foo +bar)') self.assertEqual(bq('"-foo +bar"'), '+"\-foo \+bar"') self.assertEqual(bq('foo-bar'), '+"foo\\-bar"') self.assertEqual(bq('"foo-bar"'), '+"foo\-bar"') self.assertEqual(bq(name='"foo"'), '+name:"foo"') self.assertEqual(bq(name='"foo bar'), '+name:(\\"foo bar)') self.assertEqual(bq(name='"foo bar*'), '+name:(\\"foo bar\\*)') self.assertEqual(bq(name='-foo', timestamp='[* TO NOW]'), '+name:-foo +timestamp:[* TO NOW]') self.assertEqual(bq(name='"*****@*****.**"'), '+name:"*****@*****.**"') self.assertEqual(bq(name='" "'), '+name:" "') self.assertEqual(bq(name='""'), '+name:\\"\\"') def testComplexQueries(self): bq = self.bq self.assertEqual(bq('foo', name='"herb*"', cat=(u'bär', '"-hmm"')), '+cat:(b\xc3\xa4r OR "\-hmm") +foo +name:"herb\*"') self.assertEqual(bq('foo', name='herb*', cat=(u'bär', '-hmm')), '+cat:(b\xc3\xa4r OR -hmm) +foo +name:herb*') def testBooleanQueries(self): bq = self.bq self.assertEqual(bq(inStock=True), '+inStock:true') self.assertEqual(bq(inStock=False), '+inStock:false') def testBooleanCriteriaQuoting(self): bq = self.bq self.assertEqual( bq(inStock=[1, True, '1', 'True']), '+inStock:true') self.assertEqual( bq(inStock=[0, '', False, '0', 'False', None, (), [], {}, MV]), '+inStock:false') self.assertEqual(bq(inStock=True), '+inStock:true') self.assertEqual(bq(inStock=1), '+inStock:true') self.assertEqual(bq(inStock='0'), '+inStock:false') self.assertEqual(bq(inStock=[True, False]), '') self.assertEqual(bq(inStock=[1, MV]), '') def testLiterateQueries(self): bq = self.bq self.assertEqual(bq(name=set(['bar'])), 'bar') self.assertEqual(bq(name=set(['foo OR bar'])), 'foo OR bar') self.assertEqual(bq(name=set(['(foo OR bar)'])), '(foo OR bar)') self.assertEqual(bq(name=set(['(Title:foo^10 OR Description:foo)'])), '(Title:foo^10 OR Description:foo)') self.failUnless(bq(name=set(['foo', 'bar'])) in ['(foo OR bar)', '(bar OR foo)']) self.failUnless(bq(name=set(['foo!', '+bar:camp'])) in ['(foo! OR +bar:camp)', '(+bar:camp OR foo!)'])