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
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 = 'relax_errors.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 = split(path, '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 = None
252 self._mode = None
253
254
255 self._script_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 if mode == 'script' and self._mode == 'script' and self.locked():
280
281 self._script_nest += 1
282
283
284 if self._fake_lock:
285 self.log.write("Nested by %s (to level %s)\n" % (name, self._script_nest))
286 self.log.flush()
287
288
289 return
290
291
292 if self.locked() and self._mode == 'script' and mode == 'auto-analysis':
293
294 if self._fake_lock:
295 self.log.write("Skipped unlocking of '%s' lock by '%s'\n" % (self._name, name))
296 self.log.flush()
297
298
299 self._auto_from_script = True
300
301
302 return
303
304
305 self._name = name
306 self._mode = mode
307
308
309 if self._fake_lock:
310 self.log.write("Acquired by %s\n" % self._name)
311 self.log.flush()
312 return
313
314
315 lock = self._lock.acquire()
316
317
318 status = Status()
319 status.observers.exec_lock.notify()
320
321
322 return lock
323
324
326 """Simulate the Lock.locked() mechanism."""
327
328
329 if self._fake_lock:
330 if self._name:
331 return True
332 else:
333 return False
334
335
336 return self._lock.locked()
337
338
340 """Simulate the Lock.release() mechanism."""
341
342
343 if self._status.debug:
344 sys.stdout.write("debug> Execution lock: Release by '%s' ('%s' mode).\n" % (self._name, self._mode))
345
346
347 if self._script_nest:
348
349 if self._fake_lock:
350 self.log.write("Script termination, nest decrement (%s -> %s)\n" % (self._script_nest, self._script_nest-1))
351 self.log.flush()
352
353
354 self._script_nest -= 1
355
356
357 return
358
359
360 if self._auto_from_script:
361
362 if self._fake_lock:
363 self.log.write("Auto-analysis launched from script, skipping release.\n")
364 self.log.flush()
365
366
367 self._auto_from_script = False
368
369
370 return
371
372
373 self._name = None
374 self._mode = None
375
376
377 if self._fake_lock:
378
379 text = 'Release'
380
381
382 if hasattr(self, 'test_name'):
383 text = text + 'd by %s' % self.test_name
384
385
386 self.log.write("%s\n\n" % text)
387 self.log.flush()
388 return
389
390
391 release = self._lock.release()
392
393
394 status = Status()
395 status.observers.exec_lock.notify()
396
397
398 return release
399
400
401
403 """The observer design pattern base class."""
404
406 """Set up the object.
407
408 @keyword name: The special name for the observer object, used in debugging.
409 @type name: str
410 """
411
412
413 self._name = name
414
415
416 self._callback = {}
417
418
419 self._keys = []
420
421
422 self._status = Status()
423
424
426 """Notify all observers of the state change."""
427
428
429 for key in self._keys:
430
431 if self._status.debug:
432 sys.stdout.write("debug> Observer: '%s' notifying '%s'.\n" % (self._name, key))
433
434
435 self._callback[key]()
436
437
439 """Register a method to be called when the state changes.
440
441 @param key: The key to identify the observer's method.
442 @type key: str
443 @param method: The observer's method to be called after a state change.
444 @type method: method
445 """
446
447
448 if key in self._keys:
449 raise RelaxError("The observer '%s' already exists." % key)
450
451
452 if self._status.debug:
453 sys.stdout.write("debug> Observer: '%s' registering '%s'.\n" % (self._name, key))
454
455
456 self._callback[key] = method
457
458
459 self._keys.append(key)
460
461
463 """Reset the object."""
464
465
466 if self._status.debug:
467 sys.stdout.write("debug> Resetting observer '%s'.\n" % self._name)
468
469
470 self._callback = {}
471
472
473 self._keys = []
474
475
477 """Unregister the method corresponding to the key.
478
479 @param key: The key to identify the observer's method.
480 @type key: str
481 """
482
483
484 if self._status.debug:
485 sys.stdout.write("debug> Observer: '%s' unregistering '%s'.\n" % (self._name, key))
486
487
488 if key not in self._keys:
489 if self._status.debug:
490 sys.stdout.write("debug> The key '%s' does not exist.\n" % key)
491 return
492
493
494 self._callback.pop(key)
495
496
497 self._keys.remove(key)
498
499
500
502 """A type of locking object for relax."""
503
504 - def __init__(self, name='unknown', fake_lock=False):
505 """Set up the lock-like object.
506
507 @keyword name: The special name for the lock, used in debugging.
508 @type name: str
509 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
510 @type fake_lock: bool
511 """
512
513
514 self.name = name
515 self._fake_lock = fake_lock
516
517
518 self._lock = RLock()
519
520
521 self._status = Status()
522
523
524 if self._fake_lock:
525
526 self._lock_level = 0
527
528
529 - def acquire(self, acquirer='unknown'):
530 """Simulate the RLock.acquire() mechanism.
531
532 @keyword acquirer: The optional name of the acquirer.
533 @type acquirer: str
534 """
535
536
537 if self._status.debug:
538 sys.stdout.write("debug> Lock '%s': Acquisition by '%s'.\n" % (self.name, acquirer))
539
540
541 if self._fake_lock:
542
543 self._lock_level += 1
544
545
546 if self._lock_level > 1:
547 raise
548
549
550 return
551
552
553 lock = self._lock.acquire()
554
555
556 return lock
557
558
560 """Simulate the RLock.locked() mechanism."""
561
562
563 return self._lock.locked()
564
565
566 - def release(self, acquirer='unknown'):
567 """Simulate the RLock.release() mechanism.
568
569 @keyword acquirer: The optional name of the acquirer.
570 @type acquirer: str
571 """
572
573
574 if self._status.debug:
575 sys.stdout.write("debug> Lock '%s': Release by '%s'.\n" % (self.name, acquirer))
576
577
578 if self._fake_lock:
579
580 self._lock_level -= 1
581
582
583 return
584
585
586 release = self._lock.release()
587
588
589 return release
590
591
592
594 """The container for holding all the observer objects."""
595
597 """Print out info about all the status objects."""
598
599
600 blacklist = list(self.__class__.__dict__.keys() + dict.__dict__.keys())
601
602
603 for name in dir(self):
604
605 if name in blacklist:
606 continue
607
608
609 obj = getattr(self, name)
610
611
612 print("Observer '%s' keys: %s" % (obj._name, obj._keys))
613