Revision 7578ab0a test/ganeti.qlang_unittest.py

b/test/ganeti.qlang_unittest.py
26 26
from ganeti import utils
27 27
from ganeti import errors
28 28
from ganeti import qlang
29
from ganeti import query
29 30

  
30 31
import testutils
31 32

  
......
47 48
               ["|", ["=", "xyz", "a"], ["=", "xyz", "b"], ["=", "xyz", "c"]])
48 49

  
49 50

  
51
class TestParseFilter(unittest.TestCase):
52
  def setUp(self):
53
    self.parser = qlang.BuildFilterParser()
54

  
55
  def _Test(self, filter_, expected):
56
    self.assertEqual(qlang.ParseFilter(filter_, parser=self.parser), expected)
57

  
58
  def test(self):
59
    self._Test("name==\"foobar\"", [qlang.OP_EQUAL, "name", "foobar"])
60
    self._Test("name=='foobar'", [qlang.OP_EQUAL, "name", "foobar"])
61

  
62
    self._Test("valA==1 and valB==2 or valC==3",
63
               [qlang.OP_OR,
64
                [qlang.OP_AND, [qlang.OP_EQUAL, "valA", 1],
65
                               [qlang.OP_EQUAL, "valB", 2]],
66
                [qlang.OP_EQUAL, "valC", 3]])
67

  
68
    self._Test(("(name\n==\"foobar\") and (xyz==\"va)ue\" and k == 256 or"
69
                " x ==\t\"y\"\n) and mc"),
70
               [qlang.OP_AND,
71
                [qlang.OP_EQUAL, "name", "foobar"],
72
                [qlang.OP_OR,
73
                 [qlang.OP_AND, [qlang.OP_EQUAL, "xyz", "va)ue"],
74
                                [qlang.OP_EQUAL, "k", 256]],
75
                 [qlang.OP_EQUAL, "x", "y"]],
76
                [qlang.OP_TRUE, "mc"]])
77

  
78
    self._Test("(xyz==\"v\" or k == 256 and x == \"y\")",
79
               [qlang.OP_OR,
80
                [qlang.OP_EQUAL, "xyz", "v"],
81
                [qlang.OP_AND, [qlang.OP_EQUAL, "k", 256],
82
                               [qlang.OP_EQUAL, "x", "y"]]])
83

  
84
    self._Test("valA==1 and valB==2 and valC==3",
85
               [qlang.OP_AND, [qlang.OP_EQUAL, "valA", 1],
86
                              [qlang.OP_EQUAL, "valB", 2],
87
                              [qlang.OP_EQUAL, "valC", 3]])
88
    self._Test("master or field",
89
               [qlang.OP_OR, [qlang.OP_TRUE, "master"],
90
                             [qlang.OP_TRUE, "field"]])
91
    self._Test("mem == 128", [qlang.OP_EQUAL, "mem", 128])
92
    self._Test("negfield != -1", [qlang.OP_NOT_EQUAL, "negfield", -1])
93
    self._Test("master", [qlang.OP_TRUE, "master"])
94
    self._Test("not master", [qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
95
    for op in ["not", "and", "or"]:
96
      self._Test("%sxyz" % op, [qlang.OP_TRUE, "%sxyz" % op])
97
      self._Test("not %sxyz" % op,
98
                 [qlang.OP_NOT, [qlang.OP_TRUE, "%sxyz" % op]])
99
      self._Test("  not \t%sfoo" % op,
100
                 [qlang.OP_NOT, [qlang.OP_TRUE, "%sfoo" % op]])
101
      self._Test("%sname =~ m/abc/" % op,
102
                 [qlang.OP_REGEXP, "%sname" % op, "abc"])
103
    self._Test("master and not other",
104
               [qlang.OP_AND, [qlang.OP_TRUE, "master"],
105
                              [qlang.OP_NOT, [qlang.OP_TRUE, "other"]]])
106
    self._Test("not (master or other == 4)",
107
               [qlang.OP_NOT,
108
                [qlang.OP_OR, [qlang.OP_TRUE, "master"],
109
                              [qlang.OP_EQUAL, "other", 4]]])
110
    self._Test("some==\"val\\\"ue\"", [qlang.OP_EQUAL, "some", "val\\\"ue"])
111
    self._Test("123 in ips", [qlang.OP_CONTAINS, "ips", 123])
112
    self._Test("99 not in ips", [qlang.OP_NOT, [qlang.OP_CONTAINS, "ips", 99]])
113
    self._Test("\"a\" in valA and \"b\" not in valB",
114
               [qlang.OP_AND, [qlang.OP_CONTAINS, "valA", "a"],
115
                              [qlang.OP_NOT, [qlang.OP_CONTAINS, "valB", "b"]]])
116

  
117
    self._Test("name =~ m/test/", [qlang.OP_REGEXP, "name", "test"])
118
    self._Test("name =~ m/^node.*example.com$/i",
119
               [qlang.OP_REGEXP, "name", "(?i)^node.*example.com$"])
120
    self._Test("(name =~ m/^node.*example.com$/s and master) or pip =~ |^3.*|",
121
               [qlang.OP_OR,
122
                [qlang.OP_AND,
123
                 [qlang.OP_REGEXP, "name", "(?s)^node.*example.com$"],
124
                 [qlang.OP_TRUE, "master"]],
125
                [qlang.OP_REGEXP, "pip", "^3.*"]])
126
    for flags in ["si", "is", "ssss", "iiiisiii"]:
127
      self._Test("name =~ m/gi/%s" % flags,
128
                 [qlang.OP_REGEXP, "name", "(?%s)gi" % "".join(sorted(flags))])
129

  
130
    for i in qlang._KNOWN_REGEXP_DELIM:
131
      self._Test("name =~ m%stest%s" % (i, i),
132
                 [qlang.OP_REGEXP, "name", "test"])
133
      self._Test("name !~ m%stest%s" % (i, i),
134
                 [qlang.OP_NOT, [qlang.OP_REGEXP, "name", "test"]])
135
      self._Test("not\tname =~ m%stest%s" % (i, i),
136
                 [qlang.OP_NOT, [qlang.OP_REGEXP, "name", "test"]])
137
      self._Test("notname =~ m%stest%s" % (i, i),
138
                 [qlang.OP_REGEXP, "notname", "test"])
139

  
140
  def testAllFields(self):
141
    for name in frozenset(i for d in query.ALL_FIELD_LISTS for i in d.keys()):
142
      self._Test("%s == \"value\"" % name, [qlang.OP_EQUAL, name, "value"])
143

  
144
  def testError(self):
145
    # Invalid field names, meaning no boolean check is done
146
    tests = ["#invalid!filter#", "m/x/,"]
147

  
148
    # Unknown regexp flag
149
    tests.append("name=~m#a#g")
150

  
151
    # Incomplete regexp group
152
    tests.append("name=~^[^")
153

  
154
    # Valid flag, but in uppercase
155
    tests.append("asdf =~ m|abc|I")
156

  
157
    # Non-matching regexp delimiters
158
    tests.append("name =~ /foobarbaz#")
159

  
160
    for filter_ in tests:
161
      try:
162
        qlang.ParseFilter(filter_, parser=self.parser)
163
      except errors.QueryFilterParseError, err:
164
        self.assertEqual(len(err.GetDetails()), 3)
165
      else:
166
        self.fail("Invalid filter '%s' did not raise exception" % filter_)
167

  
168

  
50 169
if __name__ == "__main__":
51 170
  testutils.GanetiTestProgram()

Also available in: Unified diff