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