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