Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.qlang_unittest.py @ 7578ab0a

History | View | Annotate | Download (6.6 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2010 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Script for testing ganeti.qlang"""
23

    
24
import unittest
25

    
26
from ganeti import utils
27
from ganeti import errors
28
from ganeti import qlang
29
from ganeti import query
30

    
31
import testutils
32

    
33

    
34
class TestMakeSimpleFilter(unittest.TestCase):
35
  def _Test(self, field, names, expected, parse_exp=None):
36
    if parse_exp is None:
37
      parse_exp = names
38

    
39
    filter_ = qlang.MakeSimpleFilter(field, names)
40
    self.assertEqual(filter_, expected)
41

    
42
  def test(self):
43
    self._Test("name", None, None, parse_exp=[])
44
    self._Test("name", [], None)
45
    self._Test("name", ["node1.example.com"],
46
               ["|", ["=", "name", "node1.example.com"]])
47
    self._Test("xyz", ["a", "b", "c"],
48
               ["|", ["=", "xyz", "a"], ["=", "xyz", "b"], ["=", "xyz", "c"]])
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

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