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