예제 #1
0
 def _process_directive(self, name, value, indent):
     # only top-level directives can be split off into jobs. Also, no jobs will be
     # split off if the max_jobs value is < 2. So under these conditions, we start
     # the directive directly within this process
     if self._we_are_child or self.top_unit != self or self._max_jobs < 2:
         return self._start_directive(name, value, indent)
     # if the max number of jobs is already running, wait for one to finish
     while len(self._child_jobs) >= self._max_jobs:
         _dprint(2, os.getpid(), "waiting for a child to finish")
         pid, status = os.wait()
         self._reap_child_process(pid, status)
     # create temporary log files for child process
     loggers = self._allocate_tmp_loggers()
     pid = os.fork()
     if pid:  # parent branch
         _dprint(2, os.getpid(), "forked off child", pid, "for", name,
                 value)
         self._child_jobs[pid] = loggers
         # ignore everything related to this directive
         self._ignore_until_indent = indent
     else:  # child branch
         self._we_are_child = True
         self._child_jobs = {}
         self._set_tmp_loggers(loggers)
         self._start_directive(name, value, indent)
예제 #2
0
 def _reap_child_process (self,pid,status):
   _dprint(2,os.getpid(),"child",pid,"exited with status",status);
   if pid not in self._child_jobs:
     raise RuntimeError,"unexpected child pid "+str(pid);
   loggers = self._child_jobs.pop(pid);
   self._merge_tmp_loggers(loggers);
   # fail if child did not return 0
   if status:
     self.fail("child process returns status %d"%status);
예제 #3
0
 def _start_directive (self,name,value,indent,ignore=False):
   _dprint(3,os.getpid(),"starting directive",name,value);
   # find class by that name
   tu_class = self.top_unit.Directives.get(name,None);
   if not callable(tu_class):
     raise Trut.ParseError,"unknown directive '%s'"%name;
   # create test unit
   self.top_unit = tu = tu_class(value,parent=self.top_unit);
   self._new_topunit(tu,indent);
예제 #4
0
 def _start_directive(self, name, value, indent, ignore=False):
     _dprint(3, os.getpid(), "starting directive", name, value)
     # find class by that name
     tu_class = self.top_unit.Directives.get(name, None)
     if not callable(tu_class):
         raise Trut.ParseError("unknown directive '%s'" % name)
     # create test unit
     self.top_unit = tu = tu_class(value, parent=self.top_unit)
     self._new_topunit(tu, indent)
예제 #5
0
 def _reap_child_process(self, pid, status):
     _dprint(2, os.getpid(), "child", pid, "exited with status", status)
     if pid not in self._child_jobs:
         raise RuntimeError("unexpected child pid " + str(pid))
     loggers = self._child_jobs.pop(pid)
     self._merge_tmp_loggers(loggers)
     # fail if child did not return 0
     if status:
         self.fail("child process returns status %d" % status)
예제 #6
0
 def execute(self):
     self.parent.compile_script(need_mqs=True)
     if self.parent.giveup():
         self.success("SKIP")
         return
     _dprint(1, "running TDL job", self.name)
     jobfunc = getattr(self._module, self.name, None)
     if not callable(jobfunc):
         self.fail("TDL job not found")
     jobfunc(self._mqs, None, wait=True)
예제 #7
0
 def log_exc(self, exctype, excvalue, exctb, level=0):
     """writes exception, if the specified level is <= the verbosity level we were created with."""
     # STDERR.write("***exc %s %d %d\n"%(exctype,level,self.verbose));
     if level <= self.verbose:
         _dprint(5, os.getpid(), "logging to file", self.fileobj, excvalue)
         traceback.print_exception(exctype,
                                   excvalue,
                                   exctb,
                                   limit=None,
                                   file=self.fileobj)
예제 #8
0
 def execute (self):
   self.parent.compile_script(need_mqs=True);
   if self.parent.giveup():
     self.success("SKIP");
     return;
   _dprint(1,"running TDL job",self.name);
   jobfunc = getattr(self._module,self.name,None);
   if not callable(jobfunc):
     self.fail("TDL job not found");
   jobfunc(self._mqs,None,wait=True);
예제 #9
0
 def __init__ (self,name,parent=None):
   _dprint(2,"new unit",name,self.__class__);
   self.name = name;
   self.parent = parent;
   self.failed = None;
   self._fail_logged = False;
   self._success_logged = False;
   # inherit parent's options, and persistence level (-1)
   if parent:
     self.options = dmi.record(**parent.options);
     self.persist = parent.persist - 1;
   else:
     self.options = dmi.record();
     self.persist = 0;
예제 #10
0
 def __init__(self, name, parent=None):
     _dprint(2, "new unit", name, self.__class__)
     self.name = name
     self.parent = parent
     self.failed = None
     self._fail_logged = False
     self._success_logged = False
     # inherit parent's options, and persistence level (-1)
     if parent:
         self.options = dmi.record(**parent.options)
         self.persist = parent.persist - 1
     else:
         self.options = dmi.record()
         self.persist = 0
예제 #11
0
 def merge_file (self,logfile):
   """merges the given file into our log.""";
   _dprint(2,"merging in logfile",logfile);
   if logfile is None:
     return None;
   if isinstance(logfile,str):
     self.fileobj.writelines(file(logfile,'r'));
   elif isinstance(logfile,file):
     # logfile.seek(0);
     # for line in logfile:
     #   _dprint(0,os.getpid(),"merging from",logfile,line);
     logfile.seek(0);
     self.fileobj.writelines(logfile);
   else:
     raise TypeError,"'logfile' should be a filename or a file object";
예제 #12
0
 def merge_file(self, logfile):
     """merges the given file into our log."""
     _dprint(2, "merging in logfile", logfile)
     if logfile is None:
         return None
     import six, io
     if isinstance(logfile, str):
         self.fileobj.writelines(open(logfile, 'r'))
     elif isinstance(logfile, file if six.PY2 else io.IOBase):
         # logfile.seek(0);
         # for line in logfile:
         #   _dprint(0,os.getpid(),"merging from",logfile,line);
         logfile.seek(0)
         self.fileobj.writelines(logfile)
     else:
         raise TypeError("'logfile' should be a filename or a file object")
예제 #13
0
 def log (self,message,status="",level=0,progress=False):
   """writes message and optional status, if the specified level is <= the verbosity
   level we were created with.""";
   if level > self.verbose:
     return;
   # progress messages only go to consoles
   if progress:
     if self._is_console:
       self.fileobj.write("%-70.70s\r"%message);
       self.fileobj.flush();
   # normal messages go according to level
   else:
     _dprint(5,os.getpid(),"logging to file",self.fileobj,level,message,status);
     if status:
       self.fileobj.write("%-70s [%s]\n"%(message,status));
     else:
       self.fileobj.write("%-80s\n"%message);
예제 #14
0
 def exec_top_unit (self):
   try:
     self.top_unit.execute();
   except:
     excinfo = sys.exc_info();
     self.log_exc(*excinfo);
     self.top_unit.fail(excinfo[1]);
   try:
     self.top_unit.cleanup();
   except:
     excinfo = sys.exc_info();
     self.log_exc(*excinfo);
     self.top_unit.fail(excinfo[1]);
   excinfo = None;
   clsname,name = self.top_unit.__class__.__name__,self.top_unit.name;
   _dprint(3,os.getpid(),"finished directive",clsname,name,"fail is",self.failed);
   self.top_unit = self.top_unit.parent;
   # if we are a child process, and we're finished with this unit, exit
   if self._we_are_child and self.top_unit == self:
     sys.exit(self.failed);
예제 #15
0
 def compile_script(self, need_mqs=False):
     """compiles the script, if not already compiled.
 If need_mqs=True, starts a meqserver and builds the tree as well"""
     if not self._module:
         self._compile_failed = True
         # will reset to False if all goes well\
         self.log_progress("compile")
         # start meqserver if required
         if (need_mqs or int(self.get_option("start_meqserver",
                                             0))) and not self._mqs:
             from Timba.Apps import meqserver
             # get multithreading option
             mt = int(self.get_option("multithreaded", 0))
             if mt > 1:
                 extra = ["-mt", str(mt)]
             else:
                 extra = []
             _dprint(1, "starting meqserver", extra)
             self._mqs = meqserver.default_mqs(wait_init=10, extra=extra)
         from Timba.TDL import Compile
         from Timba.TDL import TDLOptions
         # load config file
         tdlconf = self.get_option("tdlconf", ".tdl.conf")
         TDLOptions.config.read(tdlconf)
         TDLOptions.init_options(self.name, save=False)
         # compile TDL module
         _dprint(1, "compiling TDL script", self.name)
         try:
             (self._module, ns,
              msg) = Compile.compile_file(self._mqs, self.name)
         except:
             excinfo = sys.exc_info()
             self.log_exc(level=2, *excinfo)
             self.fail("compile failed")
             excinfo = None
             return
         # success
         self.log(msg, level=2)
         self.success("compile")
         self._compile_failed = False
     pass
예제 #16
0
 def compile_script (self,need_mqs=False):
   """compiles the script, if not already compiled.
   If need_mqs=True, starts a meqserver and builds the tree as well""";
   if not self._module:
     self._compile_failed = True;  # will reset to False if all goes well\
     self.log_progress("compile");
     # start meqserver if required
     if ( need_mqs or int(self.get_option("start_meqserver",0)) ) and not self._mqs:
       from Timba.Apps import meqserver
       # get multithreading option
       mt = int(self.get_option("multithreaded",0));
       if mt>1:
         extra = [ "-mt",str(mt) ];
       else:
         extra = []
       _dprint(1,"starting meqserver",extra);
       self._mqs = meqserver.default_mqs(wait_init=10,extra=extra);
     from Timba.TDL import Compile
     from Timba.TDL import TDLOptions
     # load config file
     tdlconf = self.get_option("tdlconf",".tdl.conf");
     TDLOptions.config.read(tdlconf);
     TDLOptions.init_options(self.name,save=False);
     # compile TDL module
     _dprint(1,"compiling TDL script",self.name);
     try:
       (self._module,ns,msg) = Compile.compile_file(self._mqs,self.name);
     except:
       excinfo = sys.exc_info();
       self.log_exc(level=2,*excinfo);
       self.fail("compile failed");
       excinfo = None;
       return;
     # success
     self.log(msg,level=2);
     self.success("compile");
     self._compile_failed = False;
   pass;
예제 #17
0
 def _process_directive (self,name,value,indent):
   # only top-level directives can be split off into jobs. Also, no jobs will be
   # split off if the max_jobs value is < 2. So under these conditions, we start
   # the directive directly within this process
   if self._we_are_child or self.top_unit != self or self._max_jobs < 2:
     return self._start_directive(name,value,indent);
   # if the max number of jobs is already running, wait for one to finish
   while len(self._child_jobs) >= self._max_jobs:
     _dprint(2,os.getpid(),"waiting for a child to finish");
     pid,status = os.wait();
     self._reap_child_process(pid,status);
   # create temporary log files for child process
   loggers = self._allocate_tmp_loggers();
   pid = os.fork();
   if pid:  # parent branch
     _dprint(2,os.getpid(),"forked off child",pid,"for",name,value);
     self._child_jobs[pid] = loggers;
     # ignore everything related to this directive
     self._ignore_until_indent = indent;
   else:    # child branch
     self._we_are_child = True;
     self._child_jobs = {};
     self._set_tmp_loggers(loggers);
     self._start_directive(name,value,indent);
예제 #18
0
 def cleanup (self):
   # terminate meqserver
   if self._mqs:
     _dprint(1,"halting meqserver");
     self._mqs.halt();
예제 #19
0
 def log_message (self,message,status,level=1,progress=False):
   _dprint(5,os.getpid(),"logging message",level,message,status);
   for logger in self.loggers:
     logger.log(message,status,level=level,progress=progress);
예제 #20
0
 def _reap_all_children(self):
     while self._child_jobs:
         _dprint(3, os.getpid(), "waiting for all children to finish")
         pid, status = os.wait()
         self._reap_child_process(pid, status)
예제 #21
0
 def log_exc (self,exctype,excvalue,exctb,level=0):
   """writes exception, if the specified level is <= the verbosity level we were created with.""";
   # STDERR.write("***exc %s %d %d\n"%(exctype,level,self.verbose));
   if level <= self.verbose:
     _dprint(5,os.getpid(),"logging to file",self.fileobj,excvalue);
     traceback.print_exception(exctype,excvalue,exctb,limit=None,file=self.fileobj);
예제 #22
0
 def log_message(self, message, status, level=1, progress=False):
     _dprint(5, os.getpid(), "logging message", level, message, status)
     for logger in self.loggers:
         logger.log(message, status, level=level, progress=progress)
예제 #23
0
 def execute(self):
     # log a message about running the tests, at level 10 (i.e. the "error"
     # level of the child units)
     self.log('start', level=10)
     self._new_topunit(self, -1)
     # cd to directory of file
     dirname = os.path.dirname(self.name)
     os.chdir(dirname)
     _dprint(1, "changing directory to", dirname)
     self._old_path = sys.path
     sys.path.append('.')
     _dprint(1, "running trut file", self.name)
     # parse file
     try:
         for line in open(os.path.basename(self.name)):
             # check for fails
             if self.giveup():
                 break
             # strip comments
             line = line.rstrip()
             line = _re_comment.sub('', line)
             _dprint(2, os.getpid(), "line is:", line)
             # find initial whitespace
             match_indent = _re_indent.match(line)
             if not match_indent:  # empty line
                 _dprint(3, os.getpid(), "empty line")
                 continue
             # get current indent level
             indent = len(match_indent.group(1).replace('\t', ' ' * 8))
             # get the remaining text, strip trailing space
             line = match_indent.group(2)
             _dprint(3, os.getpid(), "indent level", indent)
             # if this section is being processed by a child process, ignore
             if self._ignore_until_indent is not None and indent > self._ignore_until_indent:
                 _dprint(3, os.getpid(),
                         "ignoring line -- handled by child process"
                         "")
                 continue
             # check indent level and close all relevant stanzas
             self._check_indent(indent)
             # check for an Option = Value string
             match = _re_option.match(line)
             if match:
                 option = match.group(1)
                 value = match.group(2).rstrip()
                 _dprint(3, os.getpid(), "option", option, "=", value)
                 # the top stanza is the one to which this option pertains
                 self.top_unit.set_option(option, value)
                 continue
             # check for directive
             match = _re_directive.match(line)
             if match:
                 name = match.group(1)
                 value = match.group(2).rstrip()
                 self._process_directive(name, value, indent)
         # execute any remaining test units
         while self.top_unit != self and not self.giveup():
             self.exec_top_unit()
         # wait for child jobs to finish before reporting success or failure
         self._reap_all_children()
         # failure deferred due to persistency will be reported here
         self.success("finish")
     # catch exceptions and fail
     except:
         errtype, err, tb = sys.exc_info()
         # re-raise if exiting
         if isinstance(err, SystemExit):
             raise err
         # log
         self.log_exc(errtype, err, tb, level=0)
         tb = None
         # avoids garbage collection delay
         # kill children if interrupted
         if isinstance(err, KeyboardInterrupt):
             for pid in self._child_jobs.keys():
                 os.kill(pid, signal.SIGINT)
         self.fail(err)
         if self._we_are_child:
             sys.exit(2)
     # wait for any child jobs to finish
     self._reap_all_children()
예제 #24
0
 def log_exc(self, exctype, excvalue, exctb, level=1):
     _dprint(5, os.getpid(), "logging exception", excvalue)
     for logger in self.loggers:
         logger.log_exc(exctype, excvalue, exctb, level=level)
예제 #25
0
 def cleanup(self):
     # terminate meqserver
     if self._mqs:
         _dprint(1, "halting meqserver")
         self._mqs.halt()
예제 #26
0
 def log_exc (self,exctype,excvalue,exctb,level=1):
   _dprint(5,os.getpid(),"logging exception",excvalue);
   for logger in self.loggers:
     logger.log_exc(exctype,excvalue,exctb,level=level);
예제 #27
0
 def execute (self):
   # log a message about running the tests, at level 10 (i.e. the "error"
   # level of the child units)
   self.log('start',level=10);
   self._new_topunit(self,-1);
   # cd to directory of file
   dirname = os.path.dirname(self.name);
   os.chdir(dirname);
   _dprint(1,"changing directory to",dirname);
   self._old_path = sys.path;
   sys.path.append('.');
   _dprint(1,"running trut file",self.name);
   # parse file
   try:
     for line in file(os.path.basename(self.name)):
       # check for fails
       if self.giveup():
         break;
       # strip comments
       line = line.rstrip();
       line = _re_comment.sub('',line);
       _dprint(2,os.getpid(),"line is:",line);
       # find initial whitespace
       match_indent = _re_indent.match(line);
       if not match_indent:  # empty line
         _dprint(3,os.getpid(),"empty line");
         continue;
       # get current indent level
       indent = len(match_indent.group(1).replace('\t',' '*8));
       # get the remaining text, strip trailing space
       line = match_indent.group(2);
       _dprint(3,os.getpid(),"indent level",indent);
       # if this section is being processed by a child process, ignore
       if self._ignore_until_indent is not None and indent > self._ignore_until_indent:
         _dprint(3,os.getpid(),"ignoring line -- handled by child process""");
         continue;
       # check indent level and close all relevant stanzas
       self._check_indent(indent);
       # check for an Option = Value string
       match = _re_option.match(line);
       if match:
         option = match.group(1);
         value = match.group(2).rstrip();
         _dprint(3,os.getpid(),"option",option,"=",value);
         # the top stanza is the one to which this option pertains
         self.top_unit.set_option(option,value);
         continue;
       # check for directive
       match = _re_directive.match(line);
       if match:
         name = match.group(1);
         value = match.group(2).rstrip();
         self._process_directive(name,value,indent);
     # execute any remaining test units
     while self.top_unit != self and not self.giveup():
       self.exec_top_unit();
     # wait for child jobs to finish before reporting success or failure
     self._reap_all_children();
     # failure deferred due to persistency will be reported here
     self.success("finish");
   # catch exceptions and fail
   except:
     errtype,err,tb = sys.exc_info();
      # re-raise if exiting
     if isinstance(err,SystemExit):
       raise err;
     # log
     self.log_exc(errtype,err,tb,level=0);
     tb = None;  # avoids garbage collection delay
     # kill children if interrupted
     if isinstance(err,KeyboardInterrupt):
       for pid in self._child_jobs.iterkeys():
         os.kill(pid,signal.SIGINT);
     self.fail(err);
     if self._we_are_child:
       sys.exit(2);
   # wait for any child jobs to finish
   self._reap_all_children();
예제 #28
0
 def _reap_all_children(self):
   while self._child_jobs:
     _dprint(3,os.getpid(),"waiting for all children to finish");
     pid,status = os.wait();
     self._reap_child_process(pid,status);