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