1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module containing the status singleton object."""
25
26
27 from os import F_OK, access
28 from os.path import sep
29 import platform
30 from re import search
31 import sys
32 from threading import Lock, RLock
33
34
35 from compat import Queue
36 from lib.errors import RelaxError
37
38
40 """The relax status singleton class."""
41
42
43 _instance = None
44
68
69
71 """Determine, with a bit of magic, the relax installation path.
72
73 @return: The relax installation path. With a Mac OS X app, this will be the path to the 'Resources'.
74 @rtype: str
75 """
76
77
78 file_to_find = 'compat.py'
79
80
81 for path in sys.path:
82
83 if access(path + sep + file_to_find, F_OK):
84 return path
85
86
87 for path in sys.path:
88
89 if search('Resources', path):
90
91 bits = path.split('Resources')
92 mac_path = bits[0] + 'Resources'
93
94
95 return mac_path
96
97
98 return sys.path[0]
99
100
102 """Initialise all the status data structures."""
103
104
105 self.exec_lock = Exec_lock()
106
107
108 self.pipe_lock = Relax_lock(name='pipe_lock')
109
110
111 self.spin_lock = Relax_lock(name='spin_lock')
112
113
114 self.exception_queue = Queue()
115
116
117 self.auto_analysis = {}
118 self.current_analysis = None
119
120
121 self.controller_max_entries = 100000
122
123
124 self.skipped_tests = []
125 """The skipped tests list. Each element should be a list of the test case name, the missing Python module, and the name of the test suite category (i.e. 'system' or 'unit')."""
126
127
128 self._setup_observers()
129
130
131 if platform.uname()[0] in ['Windows', 'Microsoft']:
132 self.text_width = 79
133 else:
134 self.text_width = 100
135
136
138 """Set up all the observer objects."""
139
140
141 self.observers = Observer_container()
142
143
144 self.observers.auto_analyses = Observer('auto_analyses')
145
146
147 self.observers.pipe_alteration = Observer('pipe_alteration')
148
149
150 self.observers.gui_uf = Observer('gui_uf')
151
152
153 self.observers.gui_analysis = Observer('gui_analysis')
154
155
156 self.observers.reset = Observer('reset')
157
158
159 self.observers.exec_lock = Observer('exec_lock')
160
161
162 self.observers.result_file = Observer('result_file')
163
164
165 self.observers.state_load = Observer('state_load')
166
167
169 """Initialise a status container for an auto-analysis.
170
171 @param name: The unique name of the auto-analysis. This will act as a key.
172 @type name: str.
173 @param type: The type of auto-analysis.
174 @type type: str
175 """
176
177
178 self.auto_analysis[name] = Auto_analysis(name, type)
179
180
182 """Reset the status object to its initial state."""
183
184
185 self._setup()
186
187
188
190 """The auto-analysis status container."""
191
193 """Initialise the auto-analysis status object.
194
195 @param name: The unique name of the auto-analysis. This will act as a key.
196 @type name: str.
197 @param type: The type of auto-analysis.
198 @type type: str
199 """
200
201
202 self._status = Status()
203
204
205 self.__dict__['type'] = type
206
207
208 self.__dict__['fin'] = False
209
210
211 self.__dict__['mc_number'] = None
212
213
215 """Replacement __setattr__() method.
216
217 @param name: The name of the attribute.
218 @type name: str
219 @param value: The value of the attribute.
220 @type value: anything
221 """
222
223
224 self.__dict__[name] = value
225
226
227 self._status.observers.auto_analyses.notify()
228
229
230
232 """A type of locking object for locking execution of relax."""
233
235 """Set up the lock-like object.
236
237 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
238 @type fake_lock: bool
239 """
240
241
242 self._fake_lock = fake_lock
243
244
245 self._lock = Lock()
246
247
248 self._status = Status()
249
250
251 self._name = []
252 self._mode = []
253
254
255 self._nest = 0
256
257
258 self._auto_from_script = False
259
260
261 if self._fake_lock:
262 self.log = open('lock.log', 'w')
263
264
265 - def acquire(self, name, mode='script'):
266 """Simulate the Lock.acquire() mechanism.
267
268 @param name: The name of the locking code.
269 @type name: str
270 @keyword mode: The mode of the code trying to obtain the lock. This can be one of 'script' for the scripting interface or 'auto-analysis' for the auto-analyses.
271 @type mode: str
272 """
273
274
275 if self._status.debug:
276 sys.stdout.write("debug> Execution lock: Acquisition by '%s' ('%s' mode).\n" % (name, mode))
277
278
279 self._name.append(name)
280 self._mode.append(mode)
281
282
283 if self.locked():
284
285 self._nest += 1
286
287
288 if self._fake_lock:
289 self.log.write("Nested by %s (to level %s)\n" % (name, self._nest))
290 self.log.flush()
291
292
293 return
294
295
296 if self._fake_lock:
297 self.log.write("Acquired by %s\n" % self._name[-1])
298 self.log.flush()
299 return
300
301
302 lock = self._lock.acquire()
303
304
305 status = Status()
306 status.observers.exec_lock.notify()
307
308
309 return lock
310
311
313 """Simulate the Lock.locked() mechanism."""
314
315
316 if self._fake_lock:
317 if len(self._name):
318 return True
319 else:
320 return False
321
322
323 return self._lock.locked()
324
325
327 """Simulate the Lock.release() mechanism."""
328
329
330 if self._status.debug:
331 sys.stdout.write("debug> Execution lock: Release by '%s' ('%s' mode).\n" % (self._name[-1], self._mode[-1]))
332
333
334 self._name.pop(-1)
335 self._mode.pop(-1)
336
337
338 if self._nest:
339
340 if self._fake_lock:
341 self.log.write("Nested locking decrement (%s -> %s)\n" % (self._nest, self._nest-1))
342 self.log.flush()
343
344
345 self._nest -= 1
346
347
348 return
349
350
351 if self._fake_lock:
352
353 text = 'Release'
354
355
356 if hasattr(self, 'test_name'):
357 text = text + 'd by %s' % self.test_name
358
359
360 self.log.write("%s\n\n" % text)
361 self.log.flush()
362 return
363
364
365 release = self._lock.release()
366
367
368 status = Status()
369 status.observers.exec_lock.notify()
370
371
372 return release
373
374
375
377 """The observer design pattern base class."""
378
380 """Set up the object.
381
382 @keyword name: The special name for the observer object, used in debugging.
383 @type name: str
384 """
385
386
387 self._name = name
388
389
390 self._callback = {}
391 self._method_names = {}
392
393
394 self._keys = []
395
396
397 self._status = Status()
398
399
401 """Notify all observers of the state change."""
402
403
404 for key in self._keys:
405
406 if self._status.debug:
407 if self._method_names[key]:
408 sys.stdout.write("debug> Observer: '%s' notifying the '%s' method %s().\n" % (self._name, key, self._method_names[key]))
409 else:
410 sys.stdout.write("debug> Observer: '%s' notifying '%s'.\n" % (self._name, key))
411
412
413 self._callback[key]()
414
415
416 - def register(self, key, method, method_name=None):
417 """Register a method to be called when the state changes.
418
419 @param key: The key to identify the observer's method.
420 @type key: str
421 @param method: The observer's method to be called after a state change.
422 @type method: method
423 @keyword method_name: The optional method name used in debugging printouts.
424 @type method_name: str or None
425 """
426
427
428 if key in self._keys:
429 raise RelaxError("The observer '%s' already exists." % key)
430
431
432 if key == None:
433 raise RelaxError("The observer key must be supplied.")
434
435
436 if self._status.debug:
437 if method_name:
438 sys.stdout.write("debug> Observer: '%s' registering the '%s' method %s().\n" % (self._name, key, method_name))
439 else:
440 sys.stdout.write("debug> Observer: '%s' registering '%s'.\n" % (self._name, key))
441
442
443 self._callback[key] = method
444
445
446 self._method_names[key] = method_name
447
448
449 self._keys.append(key)
450
451
453 """Reset the object."""
454
455
456 if self._status.debug:
457 sys.stdout.write("debug> Resetting observer '%s'.\n" % self._name)
458
459
460 self._callback = {}
461
462
463 self._keys = []
464
465
467 """Unregister the method corresponding to the key.
468
469 @param key: The key to identify the observer's method.
470 @type key: str
471 """
472
473
474 if self._status.debug:
475 sys.stdout.write("debug> Observer: '%s' unregistering '%s'.\n" % (self._name, key))
476
477
478 if key not in self._keys:
479 if self._status.debug:
480 sys.stdout.write("debug> The key '%s' does not exist.\n" % key)
481 return
482
483
484 self._callback.pop(key)
485
486
487 self._method_names.pop(key)
488
489
490 self._keys.remove(key)
491
492
493
495 """A type of locking object for relax."""
496
497 - def __init__(self, name='unknown', fake_lock=False):
498 """Set up the lock-like object.
499
500 @keyword name: The special name for the lock, used in debugging.
501 @type name: str
502 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
503 @type fake_lock: bool
504 """
505
506
507 self.name = name
508 self._fake_lock = fake_lock
509
510
511 self._lock = RLock()
512
513
514 self._status = Status()
515
516
517 if self._fake_lock:
518
519 self._lock_level = 0
520
521
522 - def acquire(self, acquirer='unknown'):
523 """Simulate the RLock.acquire() mechanism.
524
525 @keyword acquirer: The optional name of the acquirer.
526 @type acquirer: str
527 """
528
529
530 if self._status.debug:
531 sys.stdout.write("debug> Lock '%s': Acquisition by '%s'.\n" % (self.name, acquirer))
532
533
534 if self._fake_lock:
535
536 self._lock_level += 1
537
538
539 if self._lock_level > 1:
540 raise
541
542
543 return
544
545
546 lock = self._lock.acquire()
547
548
549 return lock
550
551
553 """Simulate the RLock.locked() mechanism."""
554
555
556 return self._lock.locked()
557
558
559 - def release(self, acquirer='unknown'):
560 """Simulate the RLock.release() mechanism.
561
562 @keyword acquirer: The optional name of the acquirer.
563 @type acquirer: str
564 """
565
566
567 if self._status.debug:
568 sys.stdout.write("debug> Lock '%s': Release by '%s'.\n" % (self.name, acquirer))
569
570
571 if self._fake_lock:
572
573 self._lock_level -= 1
574
575
576 return
577
578
579 release = self._lock.release()
580
581
582 return release
583
584
585
587 """The container for holding all the observer objects."""
588
590 """Print out info about all the status objects."""
591
592
593 blacklist = list(self.__class__.__dict__.keys() + dict.__dict__.keys())
594
595
596 for name in dir(self):
597
598 if name in blacklist:
599 continue
600
601
602 obj = getattr(self, name)
603
604
605 print("Observer '%s' keys: %s" % (obj._name, obj._keys))
606