Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils.algo_unittest.py @ 8620f50e

History | View | Annotate | Download (8.9 kB)

1 4fd029cf Michael Hanselmann
#!/usr/bin/python
2 4fd029cf Michael Hanselmann
#
3 4fd029cf Michael Hanselmann
4 4fd029cf Michael Hanselmann
# Copyright (C) 2011 Google Inc.
5 4fd029cf Michael Hanselmann
#
6 4fd029cf Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 4fd029cf Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 4fd029cf Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 4fd029cf Michael Hanselmann
# (at your option) any later version.
10 4fd029cf Michael Hanselmann
#
11 4fd029cf Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 4fd029cf Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 4fd029cf Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4fd029cf Michael Hanselmann
# General Public License for more details.
15 4fd029cf Michael Hanselmann
#
16 4fd029cf Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 4fd029cf Michael Hanselmann
# along with this program; if not, write to the Free Software
18 4fd029cf Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 4fd029cf Michael Hanselmann
# 02110-1301, USA.
20 4fd029cf Michael Hanselmann
21 4fd029cf Michael Hanselmann
22 4fd029cf Michael Hanselmann
"""Script for testing ganeti.utils.algo"""
23 4fd029cf Michael Hanselmann
24 4fd029cf Michael Hanselmann
import unittest
25 4fd029cf Michael Hanselmann
import random
26 4fd029cf Michael Hanselmann
import operator
27 4fd029cf Michael Hanselmann
28 4fd029cf Michael Hanselmann
from ganeti import constants
29 4fd029cf Michael Hanselmann
from ganeti.utils import algo
30 4fd029cf Michael Hanselmann
31 4fd029cf Michael Hanselmann
import testutils
32 4fd029cf Michael Hanselmann
33 4fd029cf Michael Hanselmann
34 4fd029cf Michael Hanselmann
class TestUniqueSequence(unittest.TestCase):
35 4fd029cf Michael Hanselmann
  """Test case for UniqueSequence"""
36 4fd029cf Michael Hanselmann
37 4fd029cf Michael Hanselmann
  def _test(self, input, expected):
38 4fd029cf Michael Hanselmann
    self.assertEqual(algo.UniqueSequence(input), expected)
39 4fd029cf Michael Hanselmann
40 4fd029cf Michael Hanselmann
  def runTest(self):
41 4fd029cf Michael Hanselmann
    # Ordered input
42 4fd029cf Michael Hanselmann
    self._test([1, 2, 3], [1, 2, 3])
43 4fd029cf Michael Hanselmann
    self._test([1, 1, 2, 2, 3, 3], [1, 2, 3])
44 4fd029cf Michael Hanselmann
    self._test([1, 2, 2, 3], [1, 2, 3])
45 4fd029cf Michael Hanselmann
    self._test([1, 2, 3, 3], [1, 2, 3])
46 4fd029cf Michael Hanselmann
47 4fd029cf Michael Hanselmann
    # Unordered input
48 4fd029cf Michael Hanselmann
    self._test([1, 2, 3, 1, 2, 3], [1, 2, 3])
49 4fd029cf Michael Hanselmann
    self._test([1, 1, 2, 3, 3, 1, 2], [1, 2, 3])
50 4fd029cf Michael Hanselmann
51 4fd029cf Michael Hanselmann
    # Strings
52 4fd029cf Michael Hanselmann
    self._test(["a", "a"], ["a"])
53 4fd029cf Michael Hanselmann
    self._test(["a", "b"], ["a", "b"])
54 4fd029cf Michael Hanselmann
    self._test(["a", "b", "a"], ["a", "b"])
55 4fd029cf Michael Hanselmann
56 4fd029cf Michael Hanselmann
57 4fd029cf Michael Hanselmann
class TestFindDuplicates(unittest.TestCase):
58 4fd029cf Michael Hanselmann
  """Test case for FindDuplicates"""
59 4fd029cf Michael Hanselmann
60 4fd029cf Michael Hanselmann
  def _Test(self, seq, expected):
61 4fd029cf Michael Hanselmann
    result = algo.FindDuplicates(seq)
62 4fd029cf Michael Hanselmann
    self.assertEqual(result, algo.UniqueSequence(result))
63 4fd029cf Michael Hanselmann
    self.assertEqual(set(result), set(expected))
64 4fd029cf Michael Hanselmann
65 4fd029cf Michael Hanselmann
  def test(self):
66 4fd029cf Michael Hanselmann
    self._Test([], [])
67 4fd029cf Michael Hanselmann
    self._Test([1, 2, 3], [])
68 4fd029cf Michael Hanselmann
    self._Test([9, 8, 8, 0, 5, 1, 7, 0, 6, 7], [8, 0, 7])
69 4fd029cf Michael Hanselmann
    for exp in [[1, 2, 3], [3, 2, 1]]:
70 4fd029cf Michael Hanselmann
      self._Test([1, 1, 2, 2, 3, 3], exp)
71 4fd029cf Michael Hanselmann
72 4fd029cf Michael Hanselmann
    self._Test(["A", "a", "B"], [])
73 4fd029cf Michael Hanselmann
    self._Test(["a", "A", "a", "B"], ["a"])
74 4fd029cf Michael Hanselmann
    self._Test("Hello World out there!", ["e", " ", "o", "r", "t", "l"])
75 4fd029cf Michael Hanselmann
76 4fd029cf Michael Hanselmann
    self._Test(self._Gen(False), [])
77 4fd029cf Michael Hanselmann
    self._Test(self._Gen(True), range(1, 10))
78 4fd029cf Michael Hanselmann
79 4fd029cf Michael Hanselmann
  @staticmethod
80 4fd029cf Michael Hanselmann
  def _Gen(dup):
81 4fd029cf Michael Hanselmann
    for i in range(10):
82 4fd029cf Michael Hanselmann
      yield i
83 4fd029cf Michael Hanselmann
      if dup:
84 4fd029cf Michael Hanselmann
        for _ in range(i):
85 4fd029cf Michael Hanselmann
          yield i
86 4fd029cf Michael Hanselmann
87 4fd029cf Michael Hanselmann
88 4fd029cf Michael Hanselmann
class TestNiceSort(unittest.TestCase):
89 4fd029cf Michael Hanselmann
  def test(self):
90 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort([]), [])
91 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(["foo"]), ["foo"])
92 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(["bar", ""]), ["", "bar"])
93 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort([",", "."]), [",", "."])
94 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(["0.1", "0.2"]), ["0.1", "0.2"])
95 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(["0;099", "0,099", "0.1", "0.2"]),
96 4fd029cf Michael Hanselmann
                     ["0,099", "0.1", "0.2", "0;099"])
97 4fd029cf Michael Hanselmann
98 4fd029cf Michael Hanselmann
    data = ["a0", "a1", "a99", "a20", "a2", "b10", "b70", "b00", "0000"]
99 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(data),
100 4fd029cf Michael Hanselmann
                     ["0000", "a0", "a1", "a2", "a20", "a99",
101 4fd029cf Michael Hanselmann
                      "b00", "b10", "b70"])
102 4fd029cf Michael Hanselmann
103 4fd029cf Michael Hanselmann
    data = ["a0-0", "a1-0", "a99-10", "a20-3", "a0-4", "a99-3", "a09-2",
104 4fd029cf Michael Hanselmann
            "Z", "a9-1", "A", "b"]
105 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(data),
106 4fd029cf Michael Hanselmann
                     ["A", "Z", "a0-0", "a0-4", "a1-0", "a9-1", "a09-2",
107 4fd029cf Michael Hanselmann
                      "a20-3", "a99-3", "a99-10", "b"])
108 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(data, key=str.lower),
109 4fd029cf Michael Hanselmann
                     ["A", "a0-0", "a0-4", "a1-0", "a9-1", "a09-2",
110 4fd029cf Michael Hanselmann
                      "a20-3", "a99-3", "a99-10", "b", "Z"])
111 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(data, key=str.upper),
112 4fd029cf Michael Hanselmann
                     ["A", "a0-0", "a0-4", "a1-0", "a9-1", "a09-2",
113 4fd029cf Michael Hanselmann
                      "a20-3", "a99-3", "a99-10", "b", "Z"])
114 4fd029cf Michael Hanselmann
115 4fd029cf Michael Hanselmann
  def testLargeA(self):
116 4fd029cf Michael Hanselmann
    data = [
117 4fd029cf Michael Hanselmann
      "Eegah9ei", "xij88brTulHYAv8IEOyU", "3jTwJPtrXOY22bwL2YoW",
118 4fd029cf Michael Hanselmann
      "Z8Ljf1Pf5eBfNg171wJR", "WvNJd91OoXvLzdEiEXa6", "uHXAyYYftCSG1o7qcCqe",
119 4fd029cf Michael Hanselmann
      "xpIUJeVT1Rp", "KOt7vn1dWXi", "a07h8feON165N67PIE", "bH4Q7aCu3PUPjK3JtH",
120 4fd029cf Michael Hanselmann
      "cPRi0lM7HLnSuWA2G9", "KVQqLPDjcPjf8T3oyzjcOsfkb",
121 4fd029cf Michael Hanselmann
      "guKJkXnkULealVC8CyF1xefym", "pqF8dkU5B1cMnyZuREaSOADYx",
122 4fd029cf Michael Hanselmann
      ]
123 4fd029cf Michael Hanselmann
    self.assertEqual(algo.NiceSort(data), [
124 4fd029cf Michael Hanselmann
      "3jTwJPtrXOY22bwL2YoW", "Eegah9ei", "KOt7vn1dWXi",
125 4fd029cf Michael Hanselmann
      "KVQqLPDjcPjf8T3oyzjcOsfkb", "WvNJd91OoXvLzdEiEXa6",
126 4fd029cf Michael Hanselmann
      "Z8Ljf1Pf5eBfNg171wJR", "a07h8feON165N67PIE", "bH4Q7aCu3PUPjK3JtH",
127 4fd029cf Michael Hanselmann
      "cPRi0lM7HLnSuWA2G9", "guKJkXnkULealVC8CyF1xefym",
128 4fd029cf Michael Hanselmann
      "pqF8dkU5B1cMnyZuREaSOADYx", "uHXAyYYftCSG1o7qcCqe",
129 4fd029cf Michael Hanselmann
      "xij88brTulHYAv8IEOyU", "xpIUJeVT1Rp"
130 4fd029cf Michael Hanselmann
      ])
131 4fd029cf Michael Hanselmann
132 4fd029cf Michael Hanselmann
  def testLargeB(self):
133 4fd029cf Michael Hanselmann
    data = [
134 4fd029cf Michael Hanselmann
      "inst-0.0.0.0-0.0.0.0",
135 4fd029cf Michael Hanselmann
      "inst-0.1.0.0-0.0.0.0",
136 4fd029cf Michael Hanselmann
      "inst-0.2.0.0-0.0.0.0",
137 4fd029cf Michael Hanselmann
      "inst-0.2.1.0-0.0.0.0",
138 4fd029cf Michael Hanselmann
      "inst-0.2.2.0-0.0.0.0",
139 4fd029cf Michael Hanselmann
      "inst-0.2.2.0-0.0.0.9",
140 4fd029cf Michael Hanselmann
      "inst-0.2.2.0-0.0.3.9",
141 4fd029cf Michael Hanselmann
      "inst-0.2.2.0-0.2.0.9",
142 4fd029cf Michael Hanselmann
      "inst-0.2.2.0-0.9.0.9",
143 4fd029cf Michael Hanselmann
      "inst-0.20.2.0-0.0.0.0",
144 4fd029cf Michael Hanselmann
      "inst-0.20.2.0-0.9.0.9",
145 4fd029cf Michael Hanselmann
      "inst-10.020.2.0-0.9.0.10",
146 4fd029cf Michael Hanselmann
      "inst-15.020.2.0-0.9.1.00",
147 4fd029cf Michael Hanselmann
      "inst-100.020.2.0-0.9.0.9",
148 4fd029cf Michael Hanselmann
149 4fd029cf Michael Hanselmann
      # Only the last group, not converted to a number anymore, differs
150 4fd029cf Michael Hanselmann
      "inst-100.020.2.0a999",
151 4fd029cf Michael Hanselmann
      "inst-100.020.2.0b000",
152 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c10",
153 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c101",
154 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c2",
155 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c20",
156 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c3",
157 4fd029cf Michael Hanselmann
      "inst-100.020.2.0c39123",
158 4fd029cf Michael Hanselmann
      ]
159 4fd029cf Michael Hanselmann
160 4fd029cf Michael Hanselmann
    rnd = random.Random(16205)
161 4fd029cf Michael Hanselmann
    for _ in range(10):
162 4fd029cf Michael Hanselmann
      testdata = data[:]
163 4fd029cf Michael Hanselmann
      rnd.shuffle(testdata)
164 4fd029cf Michael Hanselmann
      assert testdata != data
165 4fd029cf Michael Hanselmann
      self.assertEqual(algo.NiceSort(testdata), data)
166 4fd029cf Michael Hanselmann
167 4fd029cf Michael Hanselmann
  class _CallCount:
168 4fd029cf Michael Hanselmann
    def __init__(self, fn):
169 4fd029cf Michael Hanselmann
      self.count = 0
170 4fd029cf Michael Hanselmann
      self.fn = fn
171 4fd029cf Michael Hanselmann
172 4fd029cf Michael Hanselmann
    def __call__(self, *args):
173 4fd029cf Michael Hanselmann
      self.count += 1
174 4fd029cf Michael Hanselmann
      return self.fn(*args)
175 4fd029cf Michael Hanselmann
176 4fd029cf Michael Hanselmann
  def testKeyfuncA(self):
177 4fd029cf Michael Hanselmann
    # Generate some random numbers
178 4fd029cf Michael Hanselmann
    rnd = random.Random(21131)
179 4fd029cf Michael Hanselmann
    numbers = [rnd.randint(0, 10000) for _ in range(999)]
180 4fd029cf Michael Hanselmann
    assert numbers != sorted(numbers)
181 4fd029cf Michael Hanselmann
182 4fd029cf Michael Hanselmann
    # Convert to hex
183 4fd029cf Michael Hanselmann
    data = [hex(i) for i in numbers]
184 4fd029cf Michael Hanselmann
    datacopy = data[:]
185 4fd029cf Michael Hanselmann
186 4fd029cf Michael Hanselmann
    keyfn = self._CallCount(lambda value: str(int(value, 16)))
187 4fd029cf Michael Hanselmann
188 4fd029cf Michael Hanselmann
    # Sort with key function converting hex to decimal
189 4fd029cf Michael Hanselmann
    result = algo.NiceSort(data, key=keyfn)
190 4fd029cf Michael Hanselmann
191 4fd029cf Michael Hanselmann
    self.assertEqual([hex(i) for i in sorted(numbers)], result)
192 4fd029cf Michael Hanselmann
    self.assertEqual(data, datacopy, msg="Input data was modified in NiceSort")
193 4fd029cf Michael Hanselmann
    self.assertEqual(keyfn.count, len(numbers),
194 4fd029cf Michael Hanselmann
                     msg="Key function was not called once per value")
195 4fd029cf Michael Hanselmann
196 4fd029cf Michael Hanselmann
  class _TestData:
197 4fd029cf Michael Hanselmann
    def __init__(self, name, value):
198 4fd029cf Michael Hanselmann
      self.name = name
199 4fd029cf Michael Hanselmann
      self.value = value
200 4fd029cf Michael Hanselmann
201 4fd029cf Michael Hanselmann
  def testKeyfuncB(self):
202 4fd029cf Michael Hanselmann
    rnd = random.Random(27396)
203 4fd029cf Michael Hanselmann
    data = []
204 4fd029cf Michael Hanselmann
    for i in range(123):
205 4fd029cf Michael Hanselmann
      v1 = rnd.randint(0, 5)
206 4fd029cf Michael Hanselmann
      v2 = rnd.randint(0, 5)
207 4fd029cf Michael Hanselmann
      data.append(self._TestData("inst-%s-%s-%s" % (v1, v2, i),
208 4fd029cf Michael Hanselmann
                                 (v1, v2, i)))
209 4fd029cf Michael Hanselmann
    rnd.shuffle(data)
210 4fd029cf Michael Hanselmann
    assert data != sorted(data, key=operator.attrgetter("name"))
211 4fd029cf Michael Hanselmann
212 4fd029cf Michael Hanselmann
    keyfn = self._CallCount(operator.attrgetter("name"))
213 4fd029cf Michael Hanselmann
214 4fd029cf Michael Hanselmann
    # Sort by name
215 4fd029cf Michael Hanselmann
    result = algo.NiceSort(data, key=keyfn)
216 4fd029cf Michael Hanselmann
217 4fd029cf Michael Hanselmann
    self.assertEqual(result, sorted(data, key=operator.attrgetter("value")))
218 4fd029cf Michael Hanselmann
    self.assertEqual(keyfn.count, len(data),
219 4fd029cf Michael Hanselmann
                     msg="Key function was not called once per value")
220 4fd029cf Michael Hanselmann
221 7d4da09e Michael Hanselmann
  def testNiceSortKey(self):
222 7d4da09e Michael Hanselmann
    self.assertEqual(algo.NiceSortKey(""),
223 7d4da09e Michael Hanselmann
                     ([None] * algo._SORTER_GROUPS) + [""])
224 7d4da09e Michael Hanselmann
    self.assertEqual(algo.NiceSortKey("Hello World"),
225 7d4da09e Michael Hanselmann
                     ["Hello World"] +
226 7d4da09e Michael Hanselmann
                     ([None] * int(algo._SORTER_GROUPS - 1)) + [""])
227 7d4da09e Michael Hanselmann
    self.assertEqual(algo.NiceSortKey("node1.net75.bld3.example.com"),
228 7d4da09e Michael Hanselmann
                     ["node", 1, ".net", 75, ".bld", 3, ".example.com",
229 7d4da09e Michael Hanselmann
                      None, ""])
230 7d4da09e Michael Hanselmann
231 4fd029cf Michael Hanselmann
232 0a9a0e5a René Nussbaumer
class TestInvertDict(unittest.TestCase):
233 0a9a0e5a René Nussbaumer
  def testInvertDict(self):
234 0a9a0e5a René Nussbaumer
    test_dict = { "foo": 1, "bar": 2, "baz": 5 }
235 0a9a0e5a René Nussbaumer
    self.assertEqual(algo.InvertDict(test_dict),
236 0a9a0e5a René Nussbaumer
                     { 1: "foo", 2: "bar", 5: "baz"})
237 0a9a0e5a René Nussbaumer
238 0a9a0e5a René Nussbaumer
239 7d444d59 Michael Hanselmann
class TimeMock:
240 7d444d59 Michael Hanselmann
  def __init__(self, values):
241 7d444d59 Michael Hanselmann
    self.values = values
242 7d444d59 Michael Hanselmann
243 7d444d59 Michael Hanselmann
  def __call__(self):
244 7d444d59 Michael Hanselmann
    return self.values.pop(0)
245 7d444d59 Michael Hanselmann
246 7d444d59 Michael Hanselmann
247 7d444d59 Michael Hanselmann
class TestRunningTimeout(unittest.TestCase):
248 7d444d59 Michael Hanselmann
  def setUp(self):
249 7d444d59 Michael Hanselmann
    self.time_fn = TimeMock([0.0, 0.3, 4.6, 6.5])
250 7d444d59 Michael Hanselmann
251 7d444d59 Michael Hanselmann
  def testRemainingFloat(self):
252 7d444d59 Michael Hanselmann
    timeout = algo.RunningTimeout(5.0, True, _time_fn=self.time_fn)
253 7d444d59 Michael Hanselmann
    self.assertAlmostEqual(timeout.Remaining(), 4.7)
254 7d444d59 Michael Hanselmann
    self.assertAlmostEqual(timeout.Remaining(), 0.4)
255 7d444d59 Michael Hanselmann
    self.assertAlmostEqual(timeout.Remaining(), -1.5)
256 7d444d59 Michael Hanselmann
257 7d444d59 Michael Hanselmann
  def testRemaining(self):
258 7d444d59 Michael Hanselmann
    self.time_fn = TimeMock([0, 2, 4, 5, 6])
259 7d444d59 Michael Hanselmann
    timeout = algo.RunningTimeout(5, True, _time_fn=self.time_fn)
260 7d444d59 Michael Hanselmann
    self.assertEqual(timeout.Remaining(), 3)
261 7d444d59 Michael Hanselmann
    self.assertEqual(timeout.Remaining(), 1)
262 7d444d59 Michael Hanselmann
    self.assertEqual(timeout.Remaining(), 0)
263 7d444d59 Michael Hanselmann
    self.assertEqual(timeout.Remaining(), -1)
264 7d444d59 Michael Hanselmann
265 7d444d59 Michael Hanselmann
  def testRemainingNonNegative(self):
266 7d444d59 Michael Hanselmann
    timeout = algo.RunningTimeout(5.0, False, _time_fn=self.time_fn)
267 7d444d59 Michael Hanselmann
    self.assertAlmostEqual(timeout.Remaining(), 4.7)
268 7d444d59 Michael Hanselmann
    self.assertAlmostEqual(timeout.Remaining(), 0.4)
269 7d444d59 Michael Hanselmann
    self.assertEqual(timeout.Remaining(), 0.0)
270 7d444d59 Michael Hanselmann
271 7d444d59 Michael Hanselmann
  def testNegativeTimeout(self):
272 7d444d59 Michael Hanselmann
    self.assertRaises(ValueError, algo.RunningTimeout, -1.0, True)
273 7d444d59 Michael Hanselmann
274 7d444d59 Michael Hanselmann
275 4fd029cf Michael Hanselmann
if __name__ == "__main__":
276 4fd029cf Michael Hanselmann
  testutils.GanetiTestProgram()