def test_match(self): parser = QueryLanguage() #------------------------------------------------------------------------------------------------------ # Check that when field is outside range (less than lower bound), match() returns false #------------------------------------------------------------------------------------------------------ field = 'voltage' lower_bound = 5 upper_bound = 10 instrument = 'instrument_1' search_string1 = "SEARCH '%s' VALUES FROM %s TO %s FROM '%s'"\ % (field, lower_bound, upper_bound, instrument) query = parser.parse(search_string1) event = ExampleDetectableEvent('TestEvent', voltage=4) self.assertFalse(QueryLanguage.match(event, query['query'])) #------------------------------------------------------------------------------------------------------ # Check that when field is outside range (is higher than upper bound), match() returns false #------------------------------------------------------------------------------------------------------ event = ExampleDetectableEvent('TestEvent', voltage=11) self.assertFalse(QueryLanguage.match(event, query['query'])) #------------------------------------------------------------------------------------------------------ # Check that when field is inside range, match() returns true #------------------------------------------------------------------------------------------------------ event = ExampleDetectableEvent('TestEvent', voltage=6) self.assertTrue(QueryLanguage.match(event, query['query'])) #------------------------------------------------------------------------------------------------------ # Check that when field is exactly of the value mentioned in a query, match() returns true #------------------------------------------------------------------------------------------------------ value = 15 search_string2 = "search '%s' is '%s' from '%s'" % (field, value, instrument) query = parser.parse(search_string2) event = ExampleDetectableEvent('TestEvent', voltage=15) self.assertTrue(QueryLanguage.match(event, query['query'])) #------------------------------------------------------------------------------------------------------ # Check that when value is not exactly what is mentioned in a query, match() returns false #------------------------------------------------------------------------------------------------------ event = ExampleDetectableEvent('TestEvent', voltage=14) self.assertFalse(QueryLanguage.match(event, query['query']))
def setUp(self): super(QueryLanguageUnitTest,self).setUp() self.parser = QueryLanguage()
class QueryLanguageUnitTest(PyonTestCase): def setUp(self): super(QueryLanguageUnitTest,self).setUp() self.parser = QueryLanguage() def test_basic_search(self): test_string = 'SEARCH "model" IS "high" FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'high') self.assertTrue(struct.query.index == 'instrument.model') self.assertTrue(struct.query.field == 'model') def test_single_quote_search(self): test_string = "SEARCH 'model' IS 'high' FROM 'instrument.model'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'high') self.assertTrue(struct.query.index == 'instrument.model') self.assertTrue(struct.query.field == 'model') def test_bad_search(self): with self.assertRaises(BadRequest): self.parser.parse('BAD STRING') def test_caseless_literal(self): test_string = 'search "cache" is "empty" from "bins"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'empty') self.assertTrue(struct.query.field == 'cache') self.assertTrue(struct.query.index == 'bins') def test_range_query(self): test_string = 'SEARCH "model" VALUES FROM 1.14 TO 1024 FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query['range']['from'] == 1.14) self.assertTrue(struct.query['range']['to'] == 1024, '%s\n%s' % (self.parser.tokens, struct)) def test_belongs_to(self): test_string = 'BELONGS TO "resourceID"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.association == 'resourceID') def test_simple_compound(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and search 'model' values from 3.1415 to 69 from 'weapons'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'throwable') self.assertTrue(struct.query.field == 'instrument.model') self.assertTrue(struct.query.index == 'indexID') self.assertTrue(struct['and'][0]['range']['from']== 3.1415) self.assertTrue(struct['and'][0]['range']['to'] == 69) def test_association_search(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and belongs to 'rsn'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'instrument.model') self.assertTrue(struct.query.value == 'throwable') self.assertTrue(struct.query.index == 'indexID') self.assertTrue(struct['and'][0]['association'] == 'rsn') def test_union_search(self): test_string = "search 'instrument.family' is 'submersible' from 'devices' or search 'model' is 'abc1*' from 'instruments'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'instrument.family') self.assertTrue(struct.query.value == 'submersible') self.assertTrue(struct.query.index == 'devices') self.assertTrue(struct['or'][0].field == 'model') self.assertTrue(struct['or'][0].value == 'abc1*') self.assertTrue(struct['or'][0].index == 'instruments') def test_collection_search(self): test_string = "in 'collectionID'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.collection == 'collectionID') def test_order_by(self): test_string = "search 'field' is 'value' from 'index' order by 'blah' limit 2" test_reverse_string = "search 'field' is 'value' from 'index' limit 2 order by 'blah'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'field') self.assertTrue(struct.query.value == 'value') self.assertTrue(struct.query.index == 'index') self.assertTrue(struct.order == {'blah' : 'asc'}) self.assertTrue(struct.limit == 2) retval = self.parser.parse(test_reverse_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'field') self.assertTrue(struct.query.value == 'value') self.assertTrue(struct.query.index == 'index') self.assertTrue(struct.order == {'blah' : 'asc'}) self.assertTrue(struct.limit == 2) def test_offset(self): test_string = "search 'field' is 'value' from 'index' skip 3" retval = self.parser.parse(test_string) self.assertTrue(retval == {'and':[], 'or':[], 'query':{'field':'field', 'index':'index', 'value':'value'}, 'offset':3}) def test_geo_distance(self): test_string = "search 'location' geo distance 20 km from lat 20 lon 30.0 from 'index'" retval = self.parser.parse(test_string) self.assertTrue(retval == {'and':[], 'or':[], 'query':{'lat':20.0, 'lon':30.0, 'units':'km', 'field':'location', 'index':'index', 'dist':20.0}}, '%s' % retval) def test_geo_bbox(self): test_string = "search 'location' geo box top-left lat 40 lon 0 bottom-right lat 0 lon 40 from 'index'" retval = self.parser.parse(test_string) self.assertTrue(retval == {'and':[], 'or':[], 'query':{'field':'location', 'top_left':[0.0, 40.0], 'bottom_right': [40.0, 0.0], 'index':'index'}}) def test_time_search(self): test_string = "search 'ts_timestamp' time from '2012-01-01' to '2012-02-01' from 'index'" retval = self.parser.parse(test_string) self.assertTrue(retval == {'and':[], 'or':[], 'query':{'field':'ts_timestamp', 'time':{'from':'2012-01-01', 'to':'2012-02-01'}, 'index':'index'}}) def test_open_range(self): test_string = 'SEARCH "model" VALUES FROM 1.14 FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query['range']['from'] == 1.14) def test_open_time_search(self): test_string = "search 'ts_timestamp' time from '2012-01-01' from 'index'" retval = self.parser.parse(test_string) self.assertTrue(retval == {'and':[], 'or':[], 'query':{'field':'ts_timestamp', 'time':{'from':'2012-01-01'}, 'index':'index'}}) def test_extensive(self): cases = [ ( "SEARCH 'model' IS 'abc*' FROM 'models' AND BELONGS TO 'platformDeviceID'", {'and':[{'association':'platformDeviceID'}], 'or':[], 'query':{'field':'model', 'value':'abc*', 'index':'models'}}), ( "SEARCH 'model' IS 'sbc*' FROM 'devices' AND BELONGS TO 'platformDeviceID' ORDER BY 'name' LIMIT 30", {'and':[{'association':'platformDeviceID'}],'or':[],'query':{'field':'model', 'value':'sbc*', 'index':'devices'}, 'order':{'name':'asc'}, 'limit':30}), ( "SEARCH 'runtime' VALUES FROM 1. TO 100 FROM 'devices' AND BELONGS TO 'RSN'", {'and':[{'association':'RSN'}], 'or': [], 'query':{'field':'runtime', 'range':{'from':1, 'to':100}, 'index':'devices'}}), ( "BELONGS TO 'org'", {'and':[], 'or':[], 'query':{'association':'org'}}), ] for case in cases: retval = self.parser.parse(case[0]) self.assertTrue(retval == case[1], 'Expected %s, received %s' % (case[1], retval)) def test_fuzzy_search(self): test_string = "search 'description' like 'products' from 'index'" retval = self.parser.parse(test_string) self.assertEquals(retval, {'and':[], 'or':[], 'query':{'field':'description', 'fuzzy':'products', 'index':'index'}}) def test_match_search(self): test_string = "search 'description' match 'products' from 'index'" retval = self.parser.parse(test_string) self.assertEquals(retval, {'and':[], 'or':[], 'query':{'field':'description', 'match':'products', 'index':'index'}}) def test_owner_search(self): test_string = "search 'description' like 'products' from 'index' and has 'abc123'" retval = self.parser.parse(test_string) self.assertEquals(retval, {'and':[{'owner':'abc123'}], 'or':[], 'query':{'field':'description', 'fuzzy':'products', 'index':'index'}}) def test_time_bounds_search(self): test_string = "search 'nominal_datetime' timebounds from '2012-01-01' to '2013-04-04' from 'index'" retval = self.parser.parse(test_string) self.assertEquals(retval, {'and':[], 'or':[], 'query':{'field':'nominal_datetime', 'time_bounds':{'from':'2012-01-01', 'to':'2013-04-04'}, 'index':'index'}}) def test_vertical_bounds_search(self): test_string = "search 'geospatial_bounds' vertical from 0.5 to 10.2 from 'index'" retval = self.parser.parse(test_string) self.assertEquals(retval, {'and':[], 'or':[], 'query':{'field':'geospatial_bounds', 'vertical_bounds':{'from':0.5, 'to':10.2}, 'index':'index'}})
def setUp(self): super(QueryLanguageUnitTest, self).setUp() self.parser = QueryLanguage()
class QueryLanguageUnitTest(PyonTestCase): def setUp(self): super(QueryLanguageUnitTest, self).setUp() self.parser = QueryLanguage() def test_basic_search(self): test_string = 'SEARCH "model" IS "high" FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'high') self.assertTrue(struct.query.index == 'instrument.model') self.assertTrue(struct.query.field == 'model') def test_single_quote_search(self): test_string = "SEARCH 'model' IS 'high' FROM 'instrument.model'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'high') self.assertTrue(struct.query.index == 'instrument.model') self.assertTrue(struct.query.field == 'model') def test_bad_search(self): with self.assertRaises(BadRequest): self.parser.parse('BAD STRING') def test_caseless_literal(self): test_string = 'search "cache" is "empty" from "bins"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'empty') self.assertTrue(struct.query.field == 'cache') self.assertTrue(struct.query.index == 'bins') def test_range_query(self): test_string = 'SEARCH "model" VALUES FROM 1.14 TO 1024 FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query['range']['from'] == 1.14) self.assertTrue(struct.query['range']['to'] == 1024, '%s\n%s' % (self.parser.tokens, struct)) def test_belongs_to(self): test_string = 'BELONGS TO "resourceID"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.association == 'resourceID') def test_simple_compound(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and search 'model' values from 3.1415 to 69 from 'weapons'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == 'throwable') self.assertTrue(struct.query.field == 'instrument.model') self.assertTrue(struct.query.index == 'indexID') self.assertTrue(struct['and'][0]['range']['from'] == 3.1415) self.assertTrue(struct['and'][0]['range']['to'] == 69) def test_association_search(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and belongs to 'rsn'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'instrument.model') self.assertTrue(struct.query.value == 'throwable') self.assertTrue(struct.query.index == 'indexID') print struct self.assertTrue(struct['and'][0]['association'] == 'rsn') def test_union_search(self): test_string = "search 'instrument.family' is 'submersible' from 'devices' or search 'model' is 'abc1*' from 'instruments'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'instrument.family') self.assertTrue(struct.query.value == 'submersible') self.assertTrue(struct.query.index == 'devices') self.assertTrue(struct['or'][0].field == 'model') self.assertTrue(struct['or'][0].value == 'abc1*') self.assertTrue(struct['or'][0].index == 'instruments') def test_collection_search(self): test_string = "in 'collectionID'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.collection == 'collectionID') def test_order_by(self): test_string = "search 'field' is 'value' from 'index' order by 'blah' limit 2" test_reverse_string = "search 'field' is 'value' from 'index' limit 2 order by 'blah'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'field') self.assertTrue(struct.query.value == 'value') self.assertTrue(struct.query.index == 'index') self.assertTrue(struct.query.order == {'blah': 'asc'}) self.assertTrue(struct.query.limit == 2) retval = self.parser.parse(test_reverse_string) struct = DotDict(retval) self.assertTrue(struct.query.field == 'field') self.assertTrue(struct.query.value == 'value') self.assertTrue(struct.query.index == 'index') self.assertTrue(struct.query.order == {'blah': 'asc'}) self.assertTrue(struct.query.limit == 2) def test_offset(self): test_string = "search 'field' is 'value' from 'index' skip 3" retval = self.parser.parse(test_string) self.assertTrue( retval == { 'and': [], 'or': [], 'query': { 'field': 'field', 'index': 'index', 'value': 'value', 'offset': 3 } }) def test_geo_distance(self): test_string = "search 'location' geo distance 20 km from lat 20 lon 30.0 from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { 'and': [], 'or': [], 'query': { 'lat': 20.0, 'lon': 30.0, 'units': 'km', 'field': 'location', 'index': 'index', 'dist': 20.0 } }, '%s' % retval) def test_geo_bbox(self): test_string = "search 'location' geo box top-left lat 40 lon 0 bottom-right lat 0 lon 40 from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { 'and': [], 'or': [], 'query': { 'field': 'location', 'top_left': [0.0, 40.0], 'bottom_right': [40.0, 0.0], 'index': 'index' } }) def test_extensive(self): cases = [ ("SEARCH 'model' IS 'abc*' FROM 'models' AND BELONGS TO 'platformDeviceID'", { 'and': [{ 'association': 'platformDeviceID' }], 'or': [], 'query': { 'field': 'model', 'value': 'abc*', 'index': 'models' } }), ("SEARCH 'model' IS 'sbc*' FROM 'devices' ORDER BY 'name' LIMIT 30 AND BELONGS TO 'platformDeviceID'", { 'and': [{ 'association': 'platformDeviceID' }], 'or': [], 'query': { 'field': 'model', 'value': 'sbc*', 'index': 'devices', 'order': { 'name': 'asc' }, 'limit': 30 } }), ("SEARCH 'runtime' VALUES FROM 1. TO 100 FROM 'devices' AND BELONGS TO 'RSN'", { 'and': [{ 'association': 'RSN' }], 'or': [], 'query': { 'field': 'runtime', 'range': { 'from': 1, 'to': 100 }, 'index': 'devices' } }), ("BELONGS TO 'org'", { 'and': [], 'or': [], 'query': { 'association': 'org' } }), ] for case in cases: retval = self.parser.parse(case[0]) self.assertTrue(retval == case[1], 'Expected %s, received %s' % (case[1], retval))
def test_evaluate_condition(self): parser = QueryLanguage() #------------------------------------------------------------------------------------------------------ # Set up the search strings for different queries: # These include main query, a list of or queries and a list of and queries #------------------------------------------------------------------------------------------------------ field = 'voltage' instrument = 'instrument' #------------------------------------------------------------------------------------------------------ # main query #------------------------------------------------------------------------------------------------------ lower_bound = 5 upper_bound = 10 search_string1 = "SEARCH '%s' VALUES FROM %s TO %s FROM '%s'"\ % (field, lower_bound, upper_bound, instrument) #------------------------------------------------------------------------------------------------------ # or queries #------------------------------------------------------------------------------------------------------ value = 15 search_string2 = "or search '%s' is '%s' from '%s'" % (field, value, instrument) value = 17 search_string3 = "or search '%s' is '%s' from '%s'" % (field, value, instrument) lower_bound = 20 upper_bound = 30 search_string4 = "or SEARCH '%s' VALUES FROM %s TO %s FROM '%s'"\ % (field, lower_bound, upper_bound, instrument) #------------------------------------------------------------------------------------------------------ # and queries #------------------------------------------------------------------------------------------------------ lower_bound = 5 upper_bound = 6 search_string5 = "and SEARCH '%s' VALUES FROM %s TO %s FROM '%s'"\ % (field, lower_bound, upper_bound, instrument) lower_bound = 6 upper_bound = 7 search_string6 = "and SEARCH '%s' VALUES FROM %s TO %s FROM '%s'"\ % (field, lower_bound, upper_bound, instrument) #------------------------------------------------------------------------------------------------------ # Construct queries by parsing different search strings and test the evaluate_condition() # for each such complex query #------------------------------------------------------------------------------------------------------ search_string = search_string1+search_string2+search_string3+search_string4+search_string5+search_string6 query = parser.parse(search_string) # the main query as well as the 'and' queries pass for this case event = ExampleDetectableEvent('TestEvent', voltage=6) self.assertTrue(QueryLanguage.evaluate_condition(event, query)) # check true conditions. If any one of the 'or' conditions passes, evaluate_condition() # will return True event = ExampleDetectableEvent('TestEvent', voltage=15) self.assertTrue(QueryLanguage.evaluate_condition(event, query)) event = ExampleDetectableEvent('TestEvent', voltage=17) self.assertTrue(QueryLanguage.evaluate_condition(event, query)) event = ExampleDetectableEvent('TestEvent', voltage=25) self.assertTrue(QueryLanguage.evaluate_condition(event, query)) # check fail conditions arising from the 'and' condition (happens if any one of the 'and' conditions fail) # note: the 'and' queries are attached to the main query event = ExampleDetectableEvent('TestEvent', voltage=5) self.assertFalse(QueryLanguage.evaluate_condition(event, query)) event = ExampleDetectableEvent('TestEvent', voltage=7) self.assertFalse(QueryLanguage.evaluate_condition(event, query)) event = ExampleDetectableEvent('TestEvent', voltage=9) self.assertFalse(QueryLanguage.evaluate_condition(event, query))
class QueryLanguageUnitTest(PyonTestCase): def setUp(self): super(QueryLanguageUnitTest, self).setUp() self.parser = QueryLanguage() def test_basic_search(self): test_string = 'SEARCH "model" IS "high" FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == "high") self.assertTrue(struct.query.index == "instrument.model") self.assertTrue(struct.query.field == "model") def test_single_quote_search(self): test_string = "SEARCH 'model' IS 'high' FROM 'instrument.model'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == "high") self.assertTrue(struct.query.index == "instrument.model") self.assertTrue(struct.query.field == "model") def test_bad_search(self): with self.assertRaises(BadRequest): self.parser.parse("BAD STRING") def test_caseless_literal(self): test_string = 'search "cache" is "empty" from "bins"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == "empty") self.assertTrue(struct.query.field == "cache") self.assertTrue(struct.query.index == "bins") def test_range_query(self): test_string = 'SEARCH "model" VALUES FROM 1.14 TO 1024 FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query["range"]["from"] == 1.14) self.assertTrue(struct.query["range"]["to"] == 1024, "%s\n%s" % (self.parser.tokens, struct)) def test_belongs_to(self): test_string = 'BELONGS TO "resourceID"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.association == "resourceID") def test_simple_compound(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and search 'model' values from 3.1415 to 69 from 'weapons'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.value == "throwable") self.assertTrue(struct.query.field == "instrument.model") self.assertTrue(struct.query.index == "indexID") self.assertTrue(struct["and"][0]["range"]["from"] == 3.1415) self.assertTrue(struct["and"][0]["range"]["to"] == 69) def test_association_search(self): test_string = "search 'instrument.model' is 'throwable' from 'indexID' and belongs to 'rsn'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == "instrument.model") self.assertTrue(struct.query.value == "throwable") self.assertTrue(struct.query.index == "indexID") self.assertTrue(struct["and"][0]["association"] == "rsn") def test_union_search(self): test_string = ( "search 'instrument.family' is 'submersible' from 'devices' or search 'model' is 'abc1*' from 'instruments'" ) retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == "instrument.family") self.assertTrue(struct.query.value == "submersible") self.assertTrue(struct.query.index == "devices") self.assertTrue(struct["or"][0].field == "model") self.assertTrue(struct["or"][0].value == "abc1*") self.assertTrue(struct["or"][0].index == "instruments") def test_collection_search(self): test_string = "in 'collectionID'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.collection == "collectionID") def test_order_by(self): test_string = "search 'field' is 'value' from 'index' order by 'blah' limit 2" test_reverse_string = "search 'field' is 'value' from 'index' limit 2 order by 'blah'" retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query.field == "field") self.assertTrue(struct.query.value == "value") self.assertTrue(struct.query.index == "index") self.assertTrue(struct.query.order == {"blah": "asc"}) self.assertTrue(struct.query.limit == 2) retval = self.parser.parse(test_reverse_string) struct = DotDict(retval) self.assertTrue(struct.query.field == "field") self.assertTrue(struct.query.value == "value") self.assertTrue(struct.query.index == "index") self.assertTrue(struct.query.order == {"blah": "asc"}) self.assertTrue(struct.query.limit == 2) def test_offset(self): test_string = "search 'field' is 'value' from 'index' skip 3" retval = self.parser.parse(test_string) self.assertTrue( retval == {"and": [], "or": [], "query": {"field": "field", "index": "index", "value": "value", "offset": 3}} ) def test_geo_distance(self): test_string = "search 'location' geo distance 20 km from lat 20 lon 30.0 from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { "and": [], "or": [], "query": {"lat": 20.0, "lon": 30.0, "units": "km", "field": "location", "index": "index", "dist": 20.0}, }, "%s" % retval, ) def test_geo_bbox(self): test_string = "search 'location' geo box top-left lat 40 lon 0 bottom-right lat 0 lon 40 from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { "and": [], "or": [], "query": {"field": "location", "top_left": [0.0, 40.0], "bottom_right": [40.0, 0.0], "index": "index"}, } ) def test_time_search(self): test_string = "search 'ts_timestamp' time from '2012-01-01' to '2012-02-01' from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { "and": [], "or": [], "query": { "field": "ts_timestamp", "time": {"from": "2012-01-01", "to": "2012-02-01"}, "index": "index", }, } ) def test_open_range(self): test_string = 'SEARCH "model" VALUES FROM 1.14 FROM "instrument.model"' retval = self.parser.parse(test_string) struct = DotDict(retval) self.assertTrue(struct.query["range"]["from"] == 1.14) def test_open_time_search(self): test_string = "search 'ts_timestamp' time from '2012-01-01' from 'index'" retval = self.parser.parse(test_string) self.assertTrue( retval == { "and": [], "or": [], "query": {"field": "ts_timestamp", "time": {"from": "2012-01-01"}, "index": "index"}, } ) def test_extensive(self): cases = [ ( "SEARCH 'model' IS 'abc*' FROM 'models' AND BELONGS TO 'platformDeviceID'", { "and": [{"association": "platformDeviceID"}], "or": [], "query": {"field": "model", "value": "abc*", "index": "models"}, }, ), ( "SEARCH 'model' IS 'sbc*' FROM 'devices' ORDER BY 'name' LIMIT 30 AND BELONGS TO 'platformDeviceID'", { "and": [{"association": "platformDeviceID"}], "or": [], "query": { "field": "model", "value": "sbc*", "index": "devices", "order": {"name": "asc"}, "limit": 30, }, }, ), ( "SEARCH 'runtime' VALUES FROM 1. TO 100 FROM 'devices' AND BELONGS TO 'RSN'", { "and": [{"association": "RSN"}], "or": [], "query": {"field": "runtime", "range": {"from": 1, "to": 100}, "index": "devices"}, }, ), ("BELONGS TO 'org'", {"and": [], "or": [], "query": {"association": "org"}}), ] for case in cases: retval = self.parser.parse(case[0]) self.assertTrue(retval == case[1], "Expected %s, received %s" % (case[1], retval)) def test_fuzzy_search(self): test_string = "search 'description' like 'products' from 'index'" retval = self.parser.parse(test_string) self.assertEquals( retval, {"and": [], "or": [], "query": {"field": "description", "fuzzy": "products", "index": "index"}} ) def test_match_search(self): test_string = "search 'description' match 'products' from 'index'" retval = self.parser.parse(test_string) self.assertEquals( retval, {"and": [], "or": [], "query": {"field": "description", "match": "products", "index": "index"}} ) def test_owner_search(self): test_string = "search 'description' like 'products' from 'index' and has 'abc123'" retval = self.parser.parse(test_string) self.assertEquals( retval, { "and": [{"owner": "abc123"}], "or": [], "query": {"field": "description", "fuzzy": "products", "index": "index"}, }, ) def test_time_bounds_search(self): test_string = "search 'nominal_datetime' timebounds from '2012-01-01' to '2013-04-04' from 'index'" retval = self.parser.parse(test_string) self.assertEquals( retval, { "and": [], "or": [], "query": { "field": "nominal_datetime", "time_bounds": {"from": "2012-01-01", "to": "2013-04-04"}, "index": "index", }, }, ) def test_vertical_bounds_search(self): test_string = "search 'geospatial_bounds' vertical from 0.5 to 10.2 from 'index'" retval = self.parser.parse(test_string) self.assertEquals( retval, { "and": [], "or": [], "query": {"field": "geospatial_bounds", "vertical_bounds": {"from": 0.5, "to": 10.2}, "index": "index"}, }, )