Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.workerpool_unittest.py @ 6760e4ed

History | View | Annotate | Download (5.5 kB)

1 76094e37 Michael Hanselmann
#!/usr/bin/python
2 76094e37 Michael Hanselmann
#
3 76094e37 Michael Hanselmann
4 76094e37 Michael Hanselmann
# Copyright (C) 2008 Google Inc.
5 76094e37 Michael Hanselmann
#
6 76094e37 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 76094e37 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 76094e37 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 76094e37 Michael Hanselmann
# (at your option) any later version.
10 76094e37 Michael Hanselmann
#
11 76094e37 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 76094e37 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 76094e37 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 76094e37 Michael Hanselmann
# General Public License for more details.
15 76094e37 Michael Hanselmann
#
16 76094e37 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 76094e37 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 76094e37 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 76094e37 Michael Hanselmann
# 02110-1301, USA.
20 76094e37 Michael Hanselmann
21 76094e37 Michael Hanselmann
22 76094e37 Michael Hanselmann
"""Script for unittesting the workerpool module"""
23 76094e37 Michael Hanselmann
24 76094e37 Michael Hanselmann
import unittest
25 76094e37 Michael Hanselmann
import threading
26 76094e37 Michael Hanselmann
import time
27 76094e37 Michael Hanselmann
import sys
28 76094e37 Michael Hanselmann
import zlib
29 76094e37 Michael Hanselmann
30 76094e37 Michael Hanselmann
from ganeti import workerpool
31 76094e37 Michael Hanselmann
32 25231ec5 Michael Hanselmann
import testutils
33 25231ec5 Michael Hanselmann
34 7ed3248b Guido Trotter
class CountingContext(object):
35 7ed3248b Guido Trotter
36 7ed3248b Guido Trotter
  def __init__(self):
37 7ed3248b Guido Trotter
    self._lock = threading.Condition(threading.Lock())
38 7ed3248b Guido Trotter
    self.done = 0
39 7ed3248b Guido Trotter
40 7ed3248b Guido Trotter
  def DoneTask(self):
41 7ed3248b Guido Trotter
    self._lock.acquire()
42 7ed3248b Guido Trotter
    try:
43 7ed3248b Guido Trotter
      self.done += 1
44 7ed3248b Guido Trotter
    finally:
45 7ed3248b Guido Trotter
      self._lock.release()
46 7ed3248b Guido Trotter
47 7ed3248b Guido Trotter
  def GetDoneTasks(self):
48 7ed3248b Guido Trotter
    self._lock.acquire()
49 7ed3248b Guido Trotter
    try:
50 7ed3248b Guido Trotter
      return self.done
51 7ed3248b Guido Trotter
    finally:
52 7ed3248b Guido Trotter
      self._lock.release()
53 7ed3248b Guido Trotter
54 7ed3248b Guido Trotter
  @staticmethod
55 7ed3248b Guido Trotter
  def UpdateChecksum(current, value):
56 7ed3248b Guido Trotter
    return zlib.adler32(str(value), current)
57 76094e37 Michael Hanselmann
58 7ed3248b Guido Trotter
59 7ed3248b Guido Trotter
class CountingBaseWorker(workerpool.BaseWorker):
60 7ed3248b Guido Trotter
61 7ed3248b Guido Trotter
  def RunTask(self, ctx, text):
62 7ed3248b Guido Trotter
    ctx.DoneTask()
63 76094e37 Michael Hanselmann
64 76094e37 Michael Hanselmann
65 76094e37 Michael Hanselmann
class ChecksumContext:
66 76094e37 Michael Hanselmann
  CHECKSUM_START = zlib.adler32("")
67 76094e37 Michael Hanselmann
68 76094e37 Michael Hanselmann
  def __init__(self):
69 76094e37 Michael Hanselmann
    self.lock = threading.Condition(threading.Lock())
70 76094e37 Michael Hanselmann
    self.checksum = self.CHECKSUM_START
71 76094e37 Michael Hanselmann
72 76094e37 Michael Hanselmann
  @staticmethod
73 76094e37 Michael Hanselmann
  def UpdateChecksum(current, value):
74 76094e37 Michael Hanselmann
    return zlib.adler32(str(value), current)
75 76094e37 Michael Hanselmann
76 76094e37 Michael Hanselmann
77 76094e37 Michael Hanselmann
class ChecksumBaseWorker(workerpool.BaseWorker):
78 76094e37 Michael Hanselmann
  def RunTask(self, ctx, number):
79 daba67c7 Michael Hanselmann
    name = "number%s" % number
80 daba67c7 Michael Hanselmann
    self.SetTaskName(name)
81 daba67c7 Michael Hanselmann
82 daba67c7 Michael Hanselmann
    # This assertion needs to be checked before updating the checksum. A
83 daba67c7 Michael Hanselmann
    # failing assertion will then cause the result to be wrong.
84 daba67c7 Michael Hanselmann
    assert self.getName() == ("%s/%s" % (self._worker_id, name))
85 daba67c7 Michael Hanselmann
86 76094e37 Michael Hanselmann
    ctx.lock.acquire()
87 76094e37 Michael Hanselmann
    try:
88 76094e37 Michael Hanselmann
      ctx.checksum = ctx.UpdateChecksum(ctx.checksum, number)
89 76094e37 Michael Hanselmann
    finally:
90 76094e37 Michael Hanselmann
      ctx.lock.release()
91 76094e37 Michael Hanselmann
92 76094e37 Michael Hanselmann
93 76094e37 Michael Hanselmann
class TestWorkerpool(unittest.TestCase):
94 76094e37 Michael Hanselmann
  """Workerpool tests"""
95 76094e37 Michael Hanselmann
96 7ed3248b Guido Trotter
  def testCounting(self):
97 7ed3248b Guido Trotter
    ctx = CountingContext()
98 7ed3248b Guido Trotter
    wp = workerpool.WorkerPool("Test", 3, CountingBaseWorker)
99 76094e37 Michael Hanselmann
    try:
100 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 3)
101 76094e37 Michael Hanselmann
102 f1501b3f Michael Hanselmann
      for i in range(10):
103 b2e8a4d9 Michael Hanselmann
        wp.AddTask((ctx, "Hello world %s" % i))
104 76094e37 Michael Hanselmann
105 76094e37 Michael Hanselmann
      wp.Quiesce()
106 76094e37 Michael Hanselmann
    finally:
107 76094e37 Michael Hanselmann
      wp.TerminateWorkers()
108 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 0)
109 76094e37 Michael Hanselmann
110 7ed3248b Guido Trotter
    self.assertEquals(ctx.GetDoneTasks(), 10)
111 7ed3248b Guido Trotter
112 76094e37 Michael Hanselmann
  def testNoTasks(self):
113 7ed3248b Guido Trotter
    wp = workerpool.WorkerPool("Test", 3, CountingBaseWorker)
114 76094e37 Michael Hanselmann
    try:
115 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 3)
116 76094e37 Michael Hanselmann
      self._CheckNoTasks(wp)
117 76094e37 Michael Hanselmann
    finally:
118 76094e37 Michael Hanselmann
      wp.TerminateWorkers()
119 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 0)
120 76094e37 Michael Hanselmann
121 76094e37 Michael Hanselmann
  def testNoTasksQuiesce(self):
122 7ed3248b Guido Trotter
    wp = workerpool.WorkerPool("Test", 3, CountingBaseWorker)
123 76094e37 Michael Hanselmann
    try:
124 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 3)
125 76094e37 Michael Hanselmann
      self._CheckNoTasks(wp)
126 76094e37 Michael Hanselmann
      wp.Quiesce()
127 76094e37 Michael Hanselmann
      self._CheckNoTasks(wp)
128 76094e37 Michael Hanselmann
    finally:
129 76094e37 Michael Hanselmann
      wp.TerminateWorkers()
130 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 0)
131 76094e37 Michael Hanselmann
132 76094e37 Michael Hanselmann
  def testChecksum(self):
133 76094e37 Michael Hanselmann
    # Tests whether all tasks are run and, since we're only using a single
134 76094e37 Michael Hanselmann
    # thread, whether everything is started in order.
135 89e2b4d2 Michael Hanselmann
    wp = workerpool.WorkerPool("Test", 1, ChecksumBaseWorker)
136 76094e37 Michael Hanselmann
    try:
137 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 1)
138 76094e37 Michael Hanselmann
139 76094e37 Michael Hanselmann
      ctx = ChecksumContext()
140 76094e37 Michael Hanselmann
      checksum = ChecksumContext.CHECKSUM_START
141 f1501b3f Michael Hanselmann
      for i in range(1, 100):
142 76094e37 Michael Hanselmann
        checksum = ChecksumContext.UpdateChecksum(checksum, i)
143 b2e8a4d9 Michael Hanselmann
        wp.AddTask((ctx, i))
144 76094e37 Michael Hanselmann
145 76094e37 Michael Hanselmann
      wp.Quiesce()
146 76094e37 Michael Hanselmann
147 76094e37 Michael Hanselmann
      self._CheckNoTasks(wp)
148 76094e37 Michael Hanselmann
149 76094e37 Michael Hanselmann
      # Check sum
150 76094e37 Michael Hanselmann
      ctx.lock.acquire()
151 76094e37 Michael Hanselmann
      try:
152 76094e37 Michael Hanselmann
        self.assertEqual(checksum, ctx.checksum)
153 76094e37 Michael Hanselmann
      finally:
154 76094e37 Michael Hanselmann
        ctx.lock.release()
155 76094e37 Michael Hanselmann
    finally:
156 76094e37 Michael Hanselmann
      wp.TerminateWorkers()
157 76094e37 Michael Hanselmann
      self._CheckWorkerCount(wp, 0)
158 76094e37 Michael Hanselmann
159 c2a8e8ba Guido Trotter
  def testAddManyTasks(self):
160 7ed3248b Guido Trotter
    ctx = CountingContext()
161 7ed3248b Guido Trotter
    wp = workerpool.WorkerPool("Test", 3, CountingBaseWorker)
162 c2a8e8ba Guido Trotter
    try:
163 c2a8e8ba Guido Trotter
      self._CheckWorkerCount(wp, 3)
164 c2a8e8ba Guido Trotter
165 7ed3248b Guido Trotter
      wp.AddManyTasks([(ctx, "Hello world %s" % i, ) for i in range(10)])
166 b2e8a4d9 Michael Hanselmann
      wp.AddTask((ctx, "A separate hello"))
167 b2e8a4d9 Michael Hanselmann
      wp.AddTask((ctx, "Once more, hi!"))
168 7ed3248b Guido Trotter
      wp.AddManyTasks([(ctx, "Hello world %s" % i, ) for i in range(10)])
169 c2a8e8ba Guido Trotter
170 c2a8e8ba Guido Trotter
      wp.Quiesce()
171 c2a8e8ba Guido Trotter
172 c2a8e8ba Guido Trotter
      self._CheckNoTasks(wp)
173 c2a8e8ba Guido Trotter
    finally:
174 c2a8e8ba Guido Trotter
      wp.TerminateWorkers()
175 c2a8e8ba Guido Trotter
      self._CheckWorkerCount(wp, 0)
176 c2a8e8ba Guido Trotter
177 7ed3248b Guido Trotter
    self.assertEquals(ctx.GetDoneTasks(), 22)
178 7ed3248b Guido Trotter
179 25e557a5 Guido Trotter
  def testManyTasksSequence(self):
180 25e557a5 Guido Trotter
    ctx = CountingContext()
181 25e557a5 Guido Trotter
    wp = workerpool.WorkerPool("Test", 3, CountingBaseWorker)
182 25e557a5 Guido Trotter
    try:
183 25e557a5 Guido Trotter
      self._CheckWorkerCount(wp, 3)
184 25e557a5 Guido Trotter
      self.assertRaises(AssertionError, wp.AddManyTasks,
185 25e557a5 Guido Trotter
                        ["Hello world %s" % i for i in range(10)])
186 25e557a5 Guido Trotter
      self.assertRaises(AssertionError, wp.AddManyTasks,
187 25e557a5 Guido Trotter
                        [i for i in range(10)])
188 25e557a5 Guido Trotter
189 25e557a5 Guido Trotter
      wp.AddManyTasks([(ctx, "Hello world %s" % i, ) for i in range(10)])
190 b2e8a4d9 Michael Hanselmann
      wp.AddTask((ctx, "A separate hello"))
191 25e557a5 Guido Trotter
192 25e557a5 Guido Trotter
      wp.Quiesce()
193 25e557a5 Guido Trotter
194 25e557a5 Guido Trotter
      self._CheckNoTasks(wp)
195 25e557a5 Guido Trotter
    finally:
196 25e557a5 Guido Trotter
      wp.TerminateWorkers()
197 25e557a5 Guido Trotter
      self._CheckWorkerCount(wp, 0)
198 25e557a5 Guido Trotter
199 25e557a5 Guido Trotter
    self.assertEquals(ctx.GetDoneTasks(), 11)
200 25e557a5 Guido Trotter
201 76094e37 Michael Hanselmann
  def _CheckNoTasks(self, wp):
202 76094e37 Michael Hanselmann
    wp._lock.acquire()
203 76094e37 Michael Hanselmann
    try:
204 76094e37 Michael Hanselmann
      # The task queue must be empty now
205 76094e37 Michael Hanselmann
      self.failUnless(not wp._tasks)
206 76094e37 Michael Hanselmann
    finally:
207 76094e37 Michael Hanselmann
      wp._lock.release()
208 76094e37 Michael Hanselmann
209 76094e37 Michael Hanselmann
  def _CheckWorkerCount(self, wp, num_workers):
210 76094e37 Michael Hanselmann
    wp._lock.acquire()
211 76094e37 Michael Hanselmann
    try:
212 76094e37 Michael Hanselmann
      self.assertEqual(len(wp._workers), num_workers)
213 76094e37 Michael Hanselmann
    finally:
214 76094e37 Michael Hanselmann
      wp._lock.release()
215 76094e37 Michael Hanselmann
216 76094e37 Michael Hanselmann
217 76094e37 Michael Hanselmann
if __name__ == '__main__':
218 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()