forked from alonho/pql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaggregation_tests.py
168 lines (121 loc) · 5.4 KB
/
aggregation_tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from unittest import TestCase
from bson import SON
import pymongo
import pql
class PqlAggregationTest(TestCase):
def compare(self, expression, expected):
self.assertEqual(pql.AggregationParser().parse(expression), expected)
class PqlAggregationPipesTest(PqlAggregationTest):
def test_match(self):
self.assertEqual(pql.match('a == 1'), [{'$match': {'a': 1}}])
def test_group(self):
for group_func in pql.AggregationGroupParser.GROUP_FUNCTIONS:
self.assertEqual(pql.group(_id='foo', total=group_func + '(bar)'),
[{'$group': {'_id': '$foo', 'total': {'$' + group_func: '$bar'}}}])
def test_invalid_group(self):
with self.assertRaises(pql.ParseError):
pql.group(_id='foo', total='bar(1)')
with self.assertRaises(pql.ParseError):
pql.group(_id='foo', total='min(1, 2)')
def test_project(self):
self.assertEqual(pql.project(foo='bar', a='b + c'),
[{'$project': {'foo': '$bar', 'a': {'$add': ['$b', '$c']}}}])
def test_skip(self):
self.assertEqual(pql.skip(3), [{'$skip': 3}])
def test_limit(self):
self.assertEqual(pql.limit(2), [{'$limit': 2}])
def test_unwind(self):
self.assertEqual(pql.unwind('foo'), [{'$unwind': '$foo'}])
def test_sort(self):
self.assertEqual(pql.sort('a'), [{'$sort': SON([('a', pymongo.ASCENDING)])}])
self.assertEqual(pql.sort(['a', '-b', '+c']),
[{'$sort': SON([('a', pymongo.ASCENDING),
('b', pymongo.DESCENDING),
('c', pymongo.ASCENDING)])}])
class PqlAggregationDataTypesTest(PqlAggregationTest):
def test_bool(self):
self.compare('True', True)
self.compare('true', True)
self.compare('False', False)
self.compare('false', False)
self.compare('None', None)
self.compare('null', None)
class PqlAggregationSimpleProjectionTest(PqlAggregationTest):
def test(self):
self.compare('a', '$a')
def test_nested(self):
self.compare('a.b.c', '$a.b.c')
class PqlAggregationLogicTest(PqlAggregationTest):
def test_and(self):
self.compare('a and b', {'$and': ['$a', '$b']})
def test_or(self):
self.compare('a or b', {'$or': ['$a', '$b']})
def test_not(self):
self.compare('not a', {'$not': '$a'})
class PqlAggregationBoolTest(PqlAggregationTest):
def test_cmp(self):
self.compare('cmp(a, "bar")', {'$cmp': ['$a', 'bar']})
def test_eq(self):
self.compare('a == 0', {'$eq': ['$a', 0]})
def test_gt(self):
self.compare('a > 0', {'$gt': ['$a', 0]})
def test_gte(self):
self.compare('a >= 0', {'$gte': ['$a', 0]})
def test_lt(self):
self.compare('a < 0', {'$lt': ['$a', 0]})
def test_lte(self):
self.compare('a <= 0', {'$lte': ['$a', 0]})
def test_ne(self):
self.compare('a != 0', {'$ne': ['$a', 0]})
class PqlAggregationArithmicTest(PqlAggregationTest):
def test_add(self):
self.compare('a + 1', {'$add': ['$a', 1]})
def test_divide(self):
self.compare('a / 1', {'$divide': ['$a', 1]})
def test_mod(self):
self.compare('a % 1', {'$mod': ['$a', 1]})
def test_multiply(self):
self.compare('a * 1', {'$multiply': ['$a', 1]})
def test_subtract(self):
self.compare('a - 1', {'$subtract': ['$a', 1]})
class PqlAggregationStringTest(PqlAggregationTest):
def test_concat(self):
self.compare('concat("foo", "bar", b)', {'$concat': ['foo', 'bar', '$b']})
def test_strcasecmp(self):
self.compare('strcasecmp("foo", b)', {'$strcasecmp': ['foo', '$b']})
def test_substr(self):
self.compare('substr("foo", 1, 2)', {'$substr': ['foo', 1, 2]})
def test_toLower(self):
self.compare('toLower(a)', {'$toLower': ['$a']})
def test_toUpper(self):
self.compare('toUpper(a)', {'$toUpper': ['$a']})
class PqlAggregationDateTest(PqlAggregationTest):
def test(self):
for func in ['dayOfYear', 'dayOfMonth', 'dayOfWeek',
'year', 'month', 'week',
'hour', 'minute', 'second', 'millisecond']:
self.compare('{0}(a)'.format(func), {'${0}'.format(func): ['$a']})
class PqlConditionTest(PqlAggregationTest):
def test_if(self):
self.compare('a if b > 3 else c', {'$cond': [{'$gt': ['$b', 3]}, '$a', '$c']})
def test_if_null(self):
self.compare('ifnull(a + b, 100)', {'$ifnull': [{'$add': ['$a', '$b']}, 100]})
class PqlAggregationSanityTest(PqlAggregationTest):
def test(self):
self.compare('a + b / c - 3 * 4 == 1',
{'$eq': [
{'$subtract': [{'$add': ['$a', {'$divide': ['$b', '$c']}]},
{'$multiply': [3, 4]}]},
1]})
class PqlAggregationErrorsTest(PqlAggregationTest):
def test_invalid_num_args(self):
with self.assertRaises(pql.ParseError):
self.compare('ifnull(1)', None)
with self.assertRaises(pql.ParseError):
self.compare('ifnull()', None)
def test_invalid_func(self):
with self.assertRaises(pql.ParseError):
self.compare('foo(10)', None)
def test_invalid_comparators(self):
with self.assertRaises(pql.ParseError):
self.compare('1 < a < 3', None)