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
173 self.observers.system_cwd_path = Observer('system_cwd_path')
174
175
177 """Initialise a status container for an auto-analysis.
178
179 @param name: The unique name of the auto-analysis. This will act as a key.
180 @type name: str.
181 @param type: The type of auto-analysis.
182 @type type: str
183 """
184
185
186 self.auto_analysis[name] = Auto_analysis(name, type)
187
188
190 """Reset the status object to its initial state."""
191
192
193 self._setup()
194
195
196
198 """The auto-analysis status container."""
199
201 """Initialise the auto-analysis status object.
202
203 @param name: The unique name of the auto-analysis. This will act as a key.
204 @type name: str.
205 @param type: The type of auto-analysis.
206 @type type: str
207 """
208
209
210 self._status = Status()
211
212
213 self.__dict__['type'] = type
214
215
216 self.__dict__['fin'] = False
217
218
219 self.__dict__['mc_number'] = None
220
221
223 """Replacement __setattr__() method.
224
225 @param name: The name of the attribute.
226 @type name: str
227 @param value: The value of the attribute.
228 @type value: anything
229 """
230
231
232 self.__dict__[name] = value
233
234
235 self._status.observers.auto_analyses.notify()
236
237
238
240 """A type of locking object for locking execution of relax."""
241
243 """Set up the lock-like object.
244
245 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
246 @type fake_lock: bool
247 """
248
249
250 self._fake_lock = fake_lock
251
252
253 self._lock = Lock()
254
255
256 self._status = Status()
257
258
259 self._name = []
260 self._mode = []
261
262
263 self._nest = 0
264
265
266 self._auto_from_script = False
267
268
269 if self._fake_lock:
270 self.log = open('lock.log', 'w')
271
272
273 - def acquire(self, name, mode='script'):
274 """Simulate the Lock.acquire() mechanism.
275
276 @param name: The name of the locking code.
277 @type name: str
278 @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.
279 @type mode: str
280 """
281
282
283 if self._status.debug:
284 sys.stdout.write("debug> Execution lock: Acquisition by '%s' ('%s' mode).\n" % (name, mode))
285
286
287 self._name.append(name)
288 self._mode.append(mode)
289
290
291 if self.locked():
292
293 self._nest += 1
294
295
296 if self._fake_lock:
297 self.log.write("Nested by %s (to level %s)\n" % (name, self._nest))
298 self.log.flush()
299
300
301 return
302
303
304 if self._fake_lock:
305 self.log.write("Acquired by %s\n" % self._name[-1])
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 len(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[-1], self._mode[-1]))
340
341
342 self._name.pop(-1)
343 self._mode.pop(-1)
344
345
346 if self._nest:
347
348 if self._fake_lock:
349 self.log.write("Nested locking decrement (%s -> %s)\n" % (self._nest, self._nest-1))
350 self.log.flush()
351
352
353 self._nest -= 1
354
355
356 return
357
358
359 if self._fake_lock:
360
361 text = 'Release'
362
363
364 if hasattr(self, 'test_name'):
365 text = text + 'd by %s' % self.test_name
366
367
368 self.log.write("%s\n\n" % text)
369 self.log.flush()
370 return
371
372
373 release = self._lock.release()
374
375
376 status = Status()
377 status.observers.exec_lock.notify()
378
379
380 return release
381
382
383
385 """The observer design pattern base class."""
386
388 """Set up the object.
389
390 @keyword name: The special name for the observer object, used in debugging.
391 @type name: str
392 """
393
394
395 self._name = name
396
397
398 self._callback = {}
399 self._method_names = {}
400
401
402 self._keys = []
403
404
405 self._status = Status()
406
407
409 """Notify all observers of the state change."""
410
411
412 for key in self._keys:
413
414 if self._status.debug:
415 if self._method_names[key]:
416 sys.stdout.write("debug> Observer: '%s' notifying the '%s' method %s().\n" % (self._name, key, self._method_names[key]))
417 else:
418 sys.stdout.write("debug> Observer: '%s' notifying '%s'.\n" % (self._name, key))
419
420
421 self._callback[key]()
422
423
424 - def register(self, key, method, method_name=None):
425 """Register a method to be called when the state changes.
426
427 @param key: The key to identify the observer's method.
428 @type key: str
429 @param method: The observer's method to be called after a state change.
430 @type method: method
431 @keyword method_name: The optional method name used in debugging printouts.
432 @type method_name: str or None
433 """
434
435
436 if key in self._keys:
437 raise RelaxError("The observer '%s' already exists." % key)
438
439
440 if key == None:
441 raise RelaxError("The observer key must be supplied.")
442
443
444 if self._status.debug:
445 if method_name:
446 sys.stdout.write("debug> Observer: '%s' registering the '%s' method %s().\n" % (self._name, key, method_name))
447 else:
448 sys.stdout.write("debug> Observer: '%s' registering '%s'.\n" % (self._name, key))
449
450
451 self._callback[key] = method
452
453
454 self._method_names[key] = method_name
455
456
457 self._keys.append(key)
458
459
461 """Reset the object."""
462
463
464 if self._status.debug:
465 sys.stdout.write("debug> Resetting observer '%s'.\n" % self._name)
466
467
468 self._callback = {}
469
470
471 self._keys = []
472
473
475 """Unregister the method corresponding to the key.
476
477 @param key: The key to identify the observer's method.
478 @type key: str
479 """
480
481
482 if self._status.debug:
483 sys.stdout.write("debug> Observer: '%s' unregistering '%s'.\n" % (self._name, key))
484
485
486 if key not in self._keys:
487 if self._status.debug:
488 sys.stdout.write("debug> The key '%s' does not exist.\n" % key)
489 return
490
491
492 self._callback.pop(key)
493
494
495 self._method_names.pop(key)
496
497
498 self._keys.remove(key)
499
500
501
503 """A type of locking object for relax."""
504
505 - def __init__(self, name='unknown', fake_lock=False):
506 """Set up the lock-like object.
507
508 @keyword name: The special name for the lock, used in debugging.
509 @type name: str
510 @keyword fake_lock: A flag which is True will allow this object to be debugged as the locking mechanism is turned off.
511 @type fake_lock: bool
512 """
513
514
515 self.name = name
516 self._fake_lock = fake_lock
517
518
519 self._lock = RLock()
520
521
522 self._status = Status()
523
524
525 if self._fake_lock:
526
527 self._lock_level = 0
528
529
530 - def acquire(self, acquirer='unknown'):
531 """Simulate the RLock.acquire() mechanism.
532
533 @keyword acquirer: The optional name of the acquirer.
534 @type acquirer: str
535 """
536
537
538 if self._status.debug:
539 sys.stdout.write("debug> Lock '%s': Acquisition by '%s'.\n" % (self.name, acquirer))
540
541
542 if self._fake_lock:
543
544 self._lock_level += 1
545
546
547 if self._lock_level > 1:
548 raise
549
550
551 return
552
553
554 lock = self._lock.acquire()
555
556
557 return lock
558
559
561 """Simulate the RLock.locked() mechanism."""
562
563
564 return self._lock.locked()
565
566
567 - def release(self, acquirer='unknown'):
568 """Simulate the RLock.release() mechanism.
569
570 @keyword acquirer: The optional name of the acquirer.
571 @type acquirer: str
572 """
573
574
575 if self._status.debug:
576 sys.stdout.write("debug> Lock '%s': Release by '%s'.\n" % (self.name, acquirer))
577
578
579 if self._fake_lock:
580
581 self._lock_level -= 1
582
583
584 return
585
586
587 release = self._lock.release()
588
589
590 return release
591
592
593
595 """The container for holding all the observer objects."""
596
598 """Print out info about all the status objects."""
599
600
601 blacklist = list(self.__class__.__dict__.keys()) + list(dict.__dict__.keys())
602
603
604 for name in dir(self):
605
606 if name in blacklist:
607 continue
608
609
610 obj = getattr(self, name)
611
612
613 print("Observer '%s' keys: %s" % (obj._name, obj._keys))
614