1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module containing the status singleton object."""
24
25
26 from os import F_OK, access
27 from os.path import sep
28 import platform
29 from re import search
30 import sys
31 from threading import Lock, RLock
32
33
34 from compat import Queue
35 from lib.errors import RelaxError
36
37
39 """The relax status singleton class."""
40
41
42 _instance = None
43
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 = 'compat.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 = path.split('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
163 self.observers.state_load = Observer('state_load')
164
165
167 """Initialise a status container for an auto-analysis.
168
169 @param name: The unique name of the auto-analysis. This will act as a key.
170 @type name: str.
171 @param type: The type of auto-analysis.
172 @type type: str
173 """
174
175
176 self.auto_analysis[name] = Auto_analysis(name, type)
177
178
180 """Reset the status object to its initial state."""
181
182
183 self._setup()
184
185
186
188 """The auto-analysis status container."""
189
191 """Initialise the auto-analysis status object.
192
193 @param name: The unique name of the auto-analysis. This will act as a key.
194 @type name: str.
195 @param type: The type of auto-analysis.
196 @type type: str
197 """
198
199
200 self._status = Status()
201
202
203 self.__dict__['type'] = type
204
205
206 self.__dict__['fin'] = False
207
208
209 self.__dict__['mc_number'] = None
210
211
213 """Replacement __setattr__() method.
214
215 @param name: The name of the attribute.
216 @type name: str
217 @param value: The value of the attribute.
218 @type value: anything
219 """
220
221
222 self.__dict__[name] = value
223
224
225 self._status.observers.auto_analyses.notify()
226
227
228
230 """A type of locking object for locking execution of relax."""
231
233 """Set up the lock-like object.
234
235 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
236 @type fake_lock: bool
237 """
238
239
240 self._fake_lock = fake_lock
241
242
243 self._lock = Lock()
244
245
246 self._status = Status()
247
248
249 self._name = []
250 self._mode = []
251
252
253 self._nest = 0
254
255
256 self._auto_from_script = False
257
258
259 if self._fake_lock:
260 self.log = open('lock.log', 'w')
261
262
263 - def acquire(self, name, mode='script'):
264 """Simulate the Lock.acquire() mechanism.
265
266 @param name: The name of the locking code.
267 @type name: str
268 @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.
269 @type mode: str
270 """
271
272
273 if self._status.debug:
274 sys.stdout.write("debug> Execution lock: Acquisition by '%s' ('%s' mode).\n" % (name, mode))
275
276
277 self._name.append(name)
278 self._mode.append(mode)
279
280
281 if self.locked():
282
283 self._nest += 1
284
285
286 if self._fake_lock:
287 self.log.write("Nested by %s (to level %s)\n" % (name, self._nest))
288 self.log.flush()
289
290
291 return
292
293
294 if self._fake_lock:
295 self.log.write("Acquired by %s\n" % self._name[-1])
296 self.log.flush()
297 return
298
299
300 lock = self._lock.acquire()
301
302
303 status = Status()
304 status.observers.exec_lock.notify()
305
306
307 return lock
308
309
311 """Simulate the Lock.locked() mechanism."""
312
313
314 if self._fake_lock:
315 if len(self._name):
316 return True
317 else:
318 return False
319
320
321 return self._lock.locked()
322
323
325 """Simulate the Lock.release() mechanism."""
326
327
328 if self._status.debug:
329 sys.stdout.write("debug> Execution lock: Release by '%s' ('%s' mode).\n" % (self._name[-1], self._mode[-1]))
330
331
332 self._name.pop(-1)
333 self._mode.pop(-1)
334
335
336 if self._nest:
337
338 if self._fake_lock:
339 self.log.write("Nested locking decrement (%s -> %s)\n" % (self._nest, self._nest-1))
340 self.log.flush()
341
342
343 self._nest -= 1
344
345
346 return
347
348
349 if self._fake_lock:
350
351 text = 'Release'
352
353
354 if hasattr(self, 'test_name'):
355 text = text + 'd by %s' % self.test_name
356
357
358 self.log.write("%s\n\n" % text)
359 self.log.flush()
360 return
361
362
363 release = self._lock.release()
364
365
366 status = Status()
367 status.observers.exec_lock.notify()
368
369
370 return release
371
372
373
375 """The observer design pattern base class."""
376
378 """Set up the object.
379
380 @keyword name: The special name for the observer object, used in debugging.
381 @type name: str
382 """
383
384
385 self._name = name
386
387
388 self._callback = {}
389 self._method_names = {}
390
391
392 self._keys = []
393
394
395 self._status = Status()
396
397
399 """Notify all observers of the state change."""
400
401
402 for key in self._keys:
403
404 if self._status.debug:
405 if self._method_names[key]:
406 sys.stdout.write("debug> Observer: '%s' notifying the '%s' method %s().\n" % (self._name, key, self._method_names[key]))
407 else:
408 sys.stdout.write("debug> Observer: '%s' notifying '%s'.\n" % (self._name, key))
409
410
411 self._callback[key]()
412
413
414 - def register(self, key, method, method_name=None):
415 """Register a method to be called when the state changes.
416
417 @param key: The key to identify the observer's method.
418 @type key: str
419 @param method: The observer's method to be called after a state change.
420 @type method: method
421 @keyword method_name: The optional method name used in debugging printouts.
422 @type method_name: str or None
423 """
424
425
426 if key in self._keys:
427 raise RelaxError("The observer '%s' already exists." % key)
428
429
430 if key == None:
431 raise RelaxError("The observer key must be supplied.")
432
433
434 if self._status.debug:
435 if method_name:
436 sys.stdout.write("debug> Observer: '%s' registering the '%s' method %s().\n" % (self._name, key, method_name))
437 else:
438 sys.stdout.write("debug> Observer: '%s' registering '%s'.\n" % (self._name, key))
439
440
441 self._callback[key] = method
442
443
444 self._method_names[key] = method_name
445
446
447 self._keys.append(key)
448
449
451 """Reset the object."""
452
453
454 if self._status.debug:
455 sys.stdout.write("debug> Resetting observer '%s'.\n" % self._name)
456
457
458 self._callback = {}
459
460
461 self._keys = []
462
463
465 """Unregister the method corresponding to the key.
466
467 @param key: The key to identify the observer's method.
468 @type key: str
469 """
470
471
472 if self._status.debug:
473 sys.stdout.write("debug> Observer: '%s' unregistering '%s'.\n" % (self._name, key))
474
475
476 if key not in self._keys:
477 if self._status.debug:
478 sys.stdout.write("debug> The key '%s' does not exist.\n" % key)
479 return
480
481
482 self._callback.pop(key)
483
484
485 self._method_names.pop(key)
486
487
488 self._keys.remove(key)
489
490
491
493 """A type of locking object for relax."""
494
495 - def __init__(self, name='unknown', fake_lock=False):
496 """Set up the lock-like object.
497
498 @keyword name: The special name for the lock, used in debugging.
499 @type name: str
500 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
501 @type fake_lock: bool
502 """
503
504
505 self.name = name
506 self._fake_lock = fake_lock
507
508
509 self._lock = RLock()
510
511
512 self._status = Status()
513
514
515 if self._fake_lock:
516
517 self._lock_level = 0
518
519
520 - def acquire(self, acquirer='unknown'):
521 """Simulate the RLock.acquire() mechanism.
522
523 @keyword acquirer: The optional name of the acquirer.
524 @type acquirer: str
525 """
526
527
528 if self._status.debug:
529 sys.stdout.write("debug> Lock '%s': Acquisition by '%s'.\n" % (self.name, acquirer))
530
531
532 if self._fake_lock:
533
534 self._lock_level += 1
535
536
537 if self._lock_level > 1:
538 raise
539
540
541 return
542
543
544 lock = self._lock.acquire()
545
546
547 return lock
548
549
551 """Simulate the RLock.locked() mechanism."""
552
553
554 return self._lock.locked()
555
556
557 - def release(self, acquirer='unknown'):
558 """Simulate the RLock.release() mechanism.
559
560 @keyword acquirer: The optional name of the acquirer.
561 @type acquirer: str
562 """
563
564
565 if self._status.debug:
566 sys.stdout.write("debug> Lock '%s': Release by '%s'.\n" % (self.name, acquirer))
567
568
569 if self._fake_lock:
570
571 self._lock_level -= 1
572
573
574 return
575
576
577 release = self._lock.release()
578
579
580 return release
581
582
583
585 """The container for holding all the observer objects."""
586
588 """Print out info about all the status objects."""
589
590
591 blacklist = list(self.__class__.__dict__.keys() + dict.__dict__.keys())
592
593
594 for name in dir(self):
595
596 if name in blacklist:
597 continue
598
599
600 obj = getattr(self, name)
601
602
603 print("Observer '%s' keys: %s" % (obj._name, obj._keys))
604