Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.qlang_unittest.py @ 83f2d5f6

History | View | Annotate | Download (7.6 kB)

1 a123dc19 Michael Hanselmann
#!/usr/bin/python
2 a123dc19 Michael Hanselmann
#
3 a123dc19 Michael Hanselmann
4 a123dc19 Michael Hanselmann
# Copyright (C) 2010 Google Inc.
5 a123dc19 Michael Hanselmann
#
6 a123dc19 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 a123dc19 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 a123dc19 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 a123dc19 Michael Hanselmann
# (at your option) any later version.
10 a123dc19 Michael Hanselmann
#
11 a123dc19 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 a123dc19 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a123dc19 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a123dc19 Michael Hanselmann
# General Public License for more details.
15 a123dc19 Michael Hanselmann
#
16 a123dc19 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 a123dc19 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 a123dc19 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a123dc19 Michael Hanselmann
# 02110-1301, USA.
20 a123dc19 Michael Hanselmann
21 a123dc19 Michael Hanselmann
22 a123dc19 Michael Hanselmann
"""Script for testing ganeti.qlang"""
23 a123dc19 Michael Hanselmann
24 a123dc19 Michael Hanselmann
import unittest
25 3f2f55bb Michael Hanselmann
import string
26 a123dc19 Michael Hanselmann
27 a123dc19 Michael Hanselmann
from ganeti import utils
28 a123dc19 Michael Hanselmann
from ganeti import errors
29 a123dc19 Michael Hanselmann
from ganeti import qlang
30 7578ab0a Michael Hanselmann
from ganeti import query
31 a123dc19 Michael Hanselmann
32 a123dc19 Michael Hanselmann
import testutils
33 a123dc19 Michael Hanselmann
34 a123dc19 Michael Hanselmann
35 60cba7f8 Michael Hanselmann
class TestMakeSimpleFilter(unittest.TestCase):
36 60cba7f8 Michael Hanselmann
  def _Test(self, field, names, expected, parse_exp=None):
37 60cba7f8 Michael Hanselmann
    if parse_exp is None:
38 60cba7f8 Michael Hanselmann
      parse_exp = names
39 60cba7f8 Michael Hanselmann
40 60cba7f8 Michael Hanselmann
    filter_ = qlang.MakeSimpleFilter(field, names)
41 60cba7f8 Michael Hanselmann
    self.assertEqual(filter_, expected)
42 60cba7f8 Michael Hanselmann
43 60cba7f8 Michael Hanselmann
  def test(self):
44 60cba7f8 Michael Hanselmann
    self._Test("name", None, None, parse_exp=[])
45 60cba7f8 Michael Hanselmann
    self._Test("name", [], None)
46 60cba7f8 Michael Hanselmann
    self._Test("name", ["node1.example.com"],
47 60cba7f8 Michael Hanselmann
               ["|", ["=", "name", "node1.example.com"]])
48 60cba7f8 Michael Hanselmann
    self._Test("xyz", ["a", "b", "c"],
49 60cba7f8 Michael Hanselmann
               ["|", ["=", "xyz", "a"], ["=", "xyz", "b"], ["=", "xyz", "c"]])
50 60cba7f8 Michael Hanselmann
51 60cba7f8 Michael Hanselmann
52 7578ab0a Michael Hanselmann
class TestParseFilter(unittest.TestCase):
53 7578ab0a Michael Hanselmann
  def setUp(self):
54 7578ab0a Michael Hanselmann
    self.parser = qlang.BuildFilterParser()
55 7578ab0a Michael Hanselmann
56 3f2f55bb Michael Hanselmann
  def _Test(self, filter_, expected, expect_filter=True):
57 3f2f55bb Michael Hanselmann
    if expect_filter:
58 3f2f55bb Michael Hanselmann
      self.assertTrue(qlang.MaybeFilter(filter_),
59 3f2f55bb Michael Hanselmann
                      msg="'%s' was not recognized as a filter" % filter_)
60 3f2f55bb Michael Hanselmann
    else:
61 3f2f55bb Michael Hanselmann
      self.assertFalse(qlang.MaybeFilter(filter_),
62 3f2f55bb Michael Hanselmann
                       msg=("'%s' should not be recognized as a filter" %
63 3f2f55bb Michael Hanselmann
                            filter_))
64 7578ab0a Michael Hanselmann
    self.assertEqual(qlang.ParseFilter(filter_, parser=self.parser), expected)
65 7578ab0a Michael Hanselmann
66 7578ab0a Michael Hanselmann
  def test(self):
67 7578ab0a Michael Hanselmann
    self._Test("name==\"foobar\"", [qlang.OP_EQUAL, "name", "foobar"])
68 7578ab0a Michael Hanselmann
    self._Test("name=='foobar'", [qlang.OP_EQUAL, "name", "foobar"])
69 7578ab0a Michael Hanselmann
70 7578ab0a Michael Hanselmann
    self._Test("valA==1 and valB==2 or valC==3",
71 7578ab0a Michael Hanselmann
               [qlang.OP_OR,
72 7578ab0a Michael Hanselmann
                [qlang.OP_AND, [qlang.OP_EQUAL, "valA", 1],
73 7578ab0a Michael Hanselmann
                               [qlang.OP_EQUAL, "valB", 2]],
74 7578ab0a Michael Hanselmann
                [qlang.OP_EQUAL, "valC", 3]])
75 7578ab0a Michael Hanselmann
76 7578ab0a Michael Hanselmann
    self._Test(("(name\n==\"foobar\") and (xyz==\"va)ue\" and k == 256 or"
77 7578ab0a Michael Hanselmann
                " x ==\t\"y\"\n) and mc"),
78 7578ab0a Michael Hanselmann
               [qlang.OP_AND,
79 7578ab0a Michael Hanselmann
                [qlang.OP_EQUAL, "name", "foobar"],
80 7578ab0a Michael Hanselmann
                [qlang.OP_OR,
81 7578ab0a Michael Hanselmann
                 [qlang.OP_AND, [qlang.OP_EQUAL, "xyz", "va)ue"],
82 7578ab0a Michael Hanselmann
                                [qlang.OP_EQUAL, "k", 256]],
83 7578ab0a Michael Hanselmann
                 [qlang.OP_EQUAL, "x", "y"]],
84 7578ab0a Michael Hanselmann
                [qlang.OP_TRUE, "mc"]])
85 7578ab0a Michael Hanselmann
86 7578ab0a Michael Hanselmann
    self._Test("(xyz==\"v\" or k == 256 and x == \"y\")",
87 7578ab0a Michael Hanselmann
               [qlang.OP_OR,
88 7578ab0a Michael Hanselmann
                [qlang.OP_EQUAL, "xyz", "v"],
89 7578ab0a Michael Hanselmann
                [qlang.OP_AND, [qlang.OP_EQUAL, "k", 256],
90 7578ab0a Michael Hanselmann
                               [qlang.OP_EQUAL, "x", "y"]]])
91 7578ab0a Michael Hanselmann
92 7578ab0a Michael Hanselmann
    self._Test("valA==1 and valB==2 and valC==3",
93 7578ab0a Michael Hanselmann
               [qlang.OP_AND, [qlang.OP_EQUAL, "valA", 1],
94 7578ab0a Michael Hanselmann
                              [qlang.OP_EQUAL, "valB", 2],
95 7578ab0a Michael Hanselmann
                              [qlang.OP_EQUAL, "valC", 3]])
96 7578ab0a Michael Hanselmann
    self._Test("master or field",
97 7578ab0a Michael Hanselmann
               [qlang.OP_OR, [qlang.OP_TRUE, "master"],
98 7578ab0a Michael Hanselmann
                             [qlang.OP_TRUE, "field"]])
99 7578ab0a Michael Hanselmann
    self._Test("mem == 128", [qlang.OP_EQUAL, "mem", 128])
100 7578ab0a Michael Hanselmann
    self._Test("negfield != -1", [qlang.OP_NOT_EQUAL, "negfield", -1])
101 3f2f55bb Michael Hanselmann
    self._Test("master", [qlang.OP_TRUE, "master"],
102 3f2f55bb Michael Hanselmann
               expect_filter=False)
103 7578ab0a Michael Hanselmann
    self._Test("not master", [qlang.OP_NOT, [qlang.OP_TRUE, "master"]])
104 7578ab0a Michael Hanselmann
    for op in ["not", "and", "or"]:
105 3f2f55bb Michael Hanselmann
      self._Test("%sxyz" % op, [qlang.OP_TRUE, "%sxyz" % op],
106 3f2f55bb Michael Hanselmann
                 expect_filter=False)
107 7578ab0a Michael Hanselmann
      self._Test("not %sxyz" % op,
108 7578ab0a Michael Hanselmann
                 [qlang.OP_NOT, [qlang.OP_TRUE, "%sxyz" % op]])
109 7578ab0a Michael Hanselmann
      self._Test("  not \t%sfoo" % op,
110 7578ab0a Michael Hanselmann
                 [qlang.OP_NOT, [qlang.OP_TRUE, "%sfoo" % op]])
111 7578ab0a Michael Hanselmann
      self._Test("%sname =~ m/abc/" % op,
112 7578ab0a Michael Hanselmann
                 [qlang.OP_REGEXP, "%sname" % op, "abc"])
113 7578ab0a Michael Hanselmann
    self._Test("master and not other",
114 7578ab0a Michael Hanselmann
               [qlang.OP_AND, [qlang.OP_TRUE, "master"],
115 7578ab0a Michael Hanselmann
                              [qlang.OP_NOT, [qlang.OP_TRUE, "other"]]])
116 7578ab0a Michael Hanselmann
    self._Test("not (master or other == 4)",
117 7578ab0a Michael Hanselmann
               [qlang.OP_NOT,
118 7578ab0a Michael Hanselmann
                [qlang.OP_OR, [qlang.OP_TRUE, "master"],
119 7578ab0a Michael Hanselmann
                              [qlang.OP_EQUAL, "other", 4]]])
120 7578ab0a Michael Hanselmann
    self._Test("some==\"val\\\"ue\"", [qlang.OP_EQUAL, "some", "val\\\"ue"])
121 7578ab0a Michael Hanselmann
    self._Test("123 in ips", [qlang.OP_CONTAINS, "ips", 123])
122 7578ab0a Michael Hanselmann
    self._Test("99 not in ips", [qlang.OP_NOT, [qlang.OP_CONTAINS, "ips", 99]])
123 7578ab0a Michael Hanselmann
    self._Test("\"a\" in valA and \"b\" not in valB",
124 7578ab0a Michael Hanselmann
               [qlang.OP_AND, [qlang.OP_CONTAINS, "valA", "a"],
125 7578ab0a Michael Hanselmann
                              [qlang.OP_NOT, [qlang.OP_CONTAINS, "valB", "b"]]])
126 7578ab0a Michael Hanselmann
127 7578ab0a Michael Hanselmann
    self._Test("name =~ m/test/", [qlang.OP_REGEXP, "name", "test"])
128 7578ab0a Michael Hanselmann
    self._Test("name =~ m/^node.*example.com$/i",
129 7578ab0a Michael Hanselmann
               [qlang.OP_REGEXP, "name", "(?i)^node.*example.com$"])
130 7578ab0a Michael Hanselmann
    self._Test("(name =~ m/^node.*example.com$/s and master) or pip =~ |^3.*|",
131 7578ab0a Michael Hanselmann
               [qlang.OP_OR,
132 7578ab0a Michael Hanselmann
                [qlang.OP_AND,
133 7578ab0a Michael Hanselmann
                 [qlang.OP_REGEXP, "name", "(?s)^node.*example.com$"],
134 7578ab0a Michael Hanselmann
                 [qlang.OP_TRUE, "master"]],
135 7578ab0a Michael Hanselmann
                [qlang.OP_REGEXP, "pip", "^3.*"]])
136 7578ab0a Michael Hanselmann
    for flags in ["si", "is", "ssss", "iiiisiii"]:
137 7578ab0a Michael Hanselmann
      self._Test("name =~ m/gi/%s" % flags,
138 7578ab0a Michael Hanselmann
                 [qlang.OP_REGEXP, "name", "(?%s)gi" % "".join(sorted(flags))])
139 7578ab0a Michael Hanselmann
140 7578ab0a Michael Hanselmann
    for i in qlang._KNOWN_REGEXP_DELIM:
141 7578ab0a Michael Hanselmann
      self._Test("name =~ m%stest%s" % (i, i),
142 7578ab0a Michael Hanselmann
                 [qlang.OP_REGEXP, "name", "test"])
143 7578ab0a Michael Hanselmann
      self._Test("name !~ m%stest%s" % (i, i),
144 7578ab0a Michael Hanselmann
                 [qlang.OP_NOT, [qlang.OP_REGEXP, "name", "test"]])
145 7578ab0a Michael Hanselmann
      self._Test("not\tname =~ m%stest%s" % (i, i),
146 7578ab0a Michael Hanselmann
                 [qlang.OP_NOT, [qlang.OP_REGEXP, "name", "test"]])
147 7578ab0a Michael Hanselmann
      self._Test("notname =~ m%stest%s" % (i, i),
148 7578ab0a Michael Hanselmann
                 [qlang.OP_REGEXP, "notname", "test"])
149 7578ab0a Michael Hanselmann
150 7578ab0a Michael Hanselmann
  def testAllFields(self):
151 7578ab0a Michael Hanselmann
    for name in frozenset(i for d in query.ALL_FIELD_LISTS for i in d.keys()):
152 7578ab0a Michael Hanselmann
      self._Test("%s == \"value\"" % name, [qlang.OP_EQUAL, name, "value"])
153 7578ab0a Michael Hanselmann
154 7578ab0a Michael Hanselmann
  def testError(self):
155 7578ab0a Michael Hanselmann
    # Invalid field names, meaning no boolean check is done
156 7578ab0a Michael Hanselmann
    tests = ["#invalid!filter#", "m/x/,"]
157 7578ab0a Michael Hanselmann
158 7578ab0a Michael Hanselmann
    # Unknown regexp flag
159 7578ab0a Michael Hanselmann
    tests.append("name=~m#a#g")
160 7578ab0a Michael Hanselmann
161 7578ab0a Michael Hanselmann
    # Incomplete regexp group
162 7578ab0a Michael Hanselmann
    tests.append("name=~^[^")
163 7578ab0a Michael Hanselmann
164 7578ab0a Michael Hanselmann
    # Valid flag, but in uppercase
165 7578ab0a Michael Hanselmann
    tests.append("asdf =~ m|abc|I")
166 7578ab0a Michael Hanselmann
167 7578ab0a Michael Hanselmann
    # Non-matching regexp delimiters
168 7578ab0a Michael Hanselmann
    tests.append("name =~ /foobarbaz#")
169 7578ab0a Michael Hanselmann
170 7578ab0a Michael Hanselmann
    for filter_ in tests:
171 7578ab0a Michael Hanselmann
      try:
172 7578ab0a Michael Hanselmann
        qlang.ParseFilter(filter_, parser=self.parser)
173 7578ab0a Michael Hanselmann
      except errors.QueryFilterParseError, err:
174 7578ab0a Michael Hanselmann
        self.assertEqual(len(err.GetDetails()), 3)
175 7578ab0a Michael Hanselmann
      else:
176 7578ab0a Michael Hanselmann
        self.fail("Invalid filter '%s' did not raise exception" % filter_)
177 7578ab0a Michael Hanselmann
178 7578ab0a Michael Hanselmann
179 3f2f55bb Michael Hanselmann
class TestMaybeFilter(unittest.TestCase):
180 3f2f55bb Michael Hanselmann
  def test(self):
181 3f2f55bb Michael Hanselmann
    self.assertTrue(qlang.MaybeFilter(""))
182 3f2f55bb Michael Hanselmann
    self.assertTrue(qlang.MaybeFilter("foo/bar"))
183 3f2f55bb Michael Hanselmann
    self.assertTrue(qlang.MaybeFilter("foo==bar"))
184 3f2f55bb Michael Hanselmann
185 3f2f55bb Michael Hanselmann
    for i in set("()!~" + string.whitespace) | qlang.FILTER_DETECTION_CHARS:
186 3f2f55bb Michael Hanselmann
      self.assertTrue(qlang.MaybeFilter(i),
187 3f2f55bb Michael Hanselmann
                      msg="%r not recognized as filter" % i)
188 3f2f55bb Michael Hanselmann
189 3f2f55bb Michael Hanselmann
    self.assertFalse(qlang.MaybeFilter("node1"))
190 3f2f55bb Michael Hanselmann
    self.assertFalse(qlang.MaybeFilter("n-o-d-e"))
191 3f2f55bb Michael Hanselmann
    self.assertFalse(qlang.MaybeFilter("n_o_d_e"))
192 3f2f55bb Michael Hanselmann
    self.assertFalse(qlang.MaybeFilter("node1.example.com"))
193 3f2f55bb Michael Hanselmann
    self.assertFalse(qlang.MaybeFilter("node1.example.com."))
194 3f2f55bb Michael Hanselmann
195 3f2f55bb Michael Hanselmann
196 a123dc19 Michael Hanselmann
if __name__ == "__main__":
197 a123dc19 Michael Hanselmann
  testutils.GanetiTestProgram()