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