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