Package TestON :: Package bin :: Module cli
[hide private]
[frames] | no frames]

Source Code for Module TestON.bin.cli

  1  #!/usr/bin/env python 
  2  ''' 
  3  Created on 20-Dec-2012 
  4       
  5  @author: Anil Kumar (anilkumar.s@paxterrasolutions.com) 
  6   
  7  cli will provide the CLI shell for teston framework. 
  8   
  9  ''' 
 10   
 11   
 12  """ 
 13  A simple command-line interface for TestON. 
 14   
 15  The TestON CLI provides a simple console which 
 16  makes it easy to launch the test. For example, the command run will execute the test. 
 17   
 18  teston> run test DpctlTest 
 19  Several useful commands are provided. 
 20  """ 
 21   
 22  from subprocess import call 
 23  from cmd import Cmd 
 24  from os import isatty 
 25  import sys 
 26  import re 
 27  import os 
 28  import time 
 29  import threading 
 30  import __builtin__ 
 31  import pprint 
 32  dump = pprint.PrettyPrinter(indent=4) 
 33  __builtin__.testthread = False 
 34  introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)" 
 35   
 36  path = re.sub("teston$", "", os.getcwd()) 
 37  sys.path.append(path+"/Core") 
 38  sys.path.append("../") 
 39  from core.teston import *  
 40   
41 -class CLI( threading.Thread,Cmd,object ):
42 "command-line interface to execute the test." 43 44 prompt = 'teston> ' 45
46 - def __init__( self, teston, stdin=sys.stdin ):
47 self.teston = teston 48 49 self._mainevent = threading.Event() 50 threading.Thread.__init__(self) 51 self.main_stop = False 52 self.locals = { 'test': teston } 53 self.stdin = stdin 54 Cmd.__init__( self ) 55 self.pause = False 56 self.stop = False 57 __builtin__.cli = self
58
59 - def emptyline( self ):
60 "Don't repeat last command when you hit return." 61 pass
62 63 helpStr = ( 64 " teston help" 65 ) 66
67 - def do_help( self, line ):
68 "Describe available CLI commands." 69 Cmd.do_help( self, line ) 70 if line is '': 71 output( self.helpStr )
72 - def do_run(self,args):
73 ''' 74 run command will execute the test with following optional command line arguments 75 logdir <directory to store logs in> 76 testcases <list of testcases separated by comma or range of testcases separated by hypen> 77 mail <mail-id or list of mail-ids seperated by comma> 78 example 1, to execute the examples specified in the ~/examples diretory. 79 ''' 80 args = args.split() 81 options = {} 82 options = self.parseArgs(args,options) 83 options = dictToObj(options) 84 if not testthread: 85 test = TestThread(options) 86 test.start() 87 else : 88 print main.TEST+ " test execution paused, please resume that before executing to another test"
89
90 - def do_resume(self, line):
91 ''' 92 resume command will continue the execution of paused test. 93 teston>resume 94 [2013-01-07 23:03:44.640723] [PoxTest] [STEP] 1.1: Checking the host reachability using pingHost 95 2013-01-07 23:03:44,858 - PoxTest - INFO - Expected Prompt Found 96 .... 97 ''' 98 if testthread: 99 testthread.play() 100 else : 101 print "There is no test to resume"
102
103 - def do_nextstep(self,line):
104 ''' 105 nextstep will execute the next-step of the paused test and 106 it will pause the test after finishing of step. 107 108 teston> nextstep 109 Will pause the test's execution, after completion of this step..... 110 111 teston> [2013-01-07 21:24:26.286601] [PoxTest] [STEP] 1.8: Checking the host reachability using pingHost 112 2013-01-07 21:24:26,455 - PoxTest - INFO - Expected Prompt Found 113 ..... 114 teston> 115 116 ''' 117 if testthread: 118 main.log.info("Executing the nextstep, Will pause test execution, after completion of the step") 119 testthread.play() 120 time.sleep(.1) 121 testthread.pause() 122 else: 123 print "There is no paused test "
124
125 - def do_dumpvar(self,line):
126 ''' 127 dumpvar will print all the test data in raw format. 128 usgae : 129 teston>dumpvar main 130 Here 'main' will be the test object. 131 132 teston>dumpvar params 133 here 'params' will be the parameters specified in the params file. 134 135 teston>dumpvar topology 136 here 'topology' will be topology specification of the test specified in topo file. 137 ''' 138 if testthread: 139 if line == "main": 140 dump.pprint(vars(main)) 141 else : 142 try : 143 dump.pprint(vars(main)[line]) 144 except KeyError,e: 145 print e 146 else : 147 print "There is no paused test "
148
149 - def do_currentcase(self,line):
150 ''' 151 currentcase will return the current case in the test execution. 152 153 teston>currentcase 154 Currently executing test case is: 2 155 156 ''' 157 if testthread: 158 print "Currently executing test case is: "+str(main.CurrentTestCaseNumber) 159 else : 160 print "There is no paused test "
161 162
163 - def do_currentstep(self,line):
164 ''' 165 currentstep will return the current step in the test execution. 166 167 teston>currentstep 168 Currently executing test step is: 2.3 169 ''' 170 if testthread: 171 print "Currently executing test step is: "+str(main.CurrentTestCaseNumber)+'.'+str(main.stepCount) 172 else : 173 print "There is no paused test "
174 175
176 - def do_stop(self,line):
177 ''' 178 Will stop the paused test, if any ! 179 ''' 180 if testthread: 181 testthread.stop() 182 183 return 'exited by user command'
184
185 - def do_gettest(self,line):
186 ''' 187 gettest will return the test name which is under execution or recently executed. 188 189 Test under execution: 190 teston>gettest 191 Currently executing Test is: PoxTest 192 193 Test recently executed: 194 Recently executed test is: MininetTest 195 ''' 196 try : 197 if testthread : 198 print "Currently executing Test is: "+main.TEST 199 else : 200 print "Recently executed test is: "+main.TEST 201 202 except NameError: 203 print "There is no previously executed Test"
204
205 - def do_showlog(self,line):
206 ''' 207 showlog will show the test's Log 208 teston>showlog 209 Last executed test's log is : //home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_42_11/PoxTest_07_Jan_2013_21_42_11.log 210 ..... 211 teston>showlog 212 Currently executing Test's log is: /home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_46_58/PoxTest_07_Jan_2013_21_46_58.log 213 ..... 214 ''' 215 try : 216 if testthread : 217 print "Currently executing Test's log is: "+main.LogFileName 218 219 else : 220 print "Last executed test's log is : "+main.LogFileName 221 222 logFile = main.LogFileName 223 logFileHandler = open(logFile, 'r') 224 for msg in logFileHandler.readlines() : 225 print msg, 226 227 logFileHandler.close() 228 229 except NameError: 230 print "There is no previously executed Test"
231 232 233
234 - def parseArgs(self,args,options):
235 ''' 236 This will parse the command line arguments. 237 ''' 238 options = self.initOptions(options) 239 try : 240 for index, option in enumerate(args): 241 if index > 0 : 242 if re.match("logdir|mail|example|testdir|testcases", option, flags = 0): 243 index = index+1 244 options[option] = args[index] 245 options = self.testcasesInRange(index,option,args,options) 246 else : 247 options['testname'] = option 248 except IndexError,e: 249 print e 250 251 return options
252
253 - def initOptions(self,options):
254 ''' 255 This will initialize the commandline options. 256 ''' 257 options['logdir'] = None 258 options['mail'] = None 259 options['example'] = None 260 options['testdir'] = None 261 options['testcases'] = None 262 return options
263
264 - def testcasesInRange(self,index,option,args,options):
265 ''' 266 This method will handle testcases list,specified in range [1-10]. 267 ''' 268 if re.match("testcases",option,1): 269 testcases = [] 270 args[index] = re.sub("\[|\]","",args[index],0) 271 m = re.match("(\d+)\-(\d+)",args[index],flags=0) 272 if m: 273 start_case = eval(m.group(1)) 274 end_case = eval(m.group(2)) 275 if (start_case <= end_case): 276 i = start_case 277 while i <= end_case: 278 testcases.append(i) 279 i= i+1 280 else : 281 print "Please specify testcases properly like 1-5" 282 else : 283 options[option] = args[index] 284 return options 285 options[option] = str(testcases) 286 287 return options
288
289 - def cmdloop(self, intro=introduction):
290 print introduction 291 while True: 292 try: 293 super(CLI, self).cmdloop(intro="") 294 self.postloop() 295 except KeyboardInterrupt: 296 testthread.pause()
297
298 - def do_echo( self, line ):
299 ''' 300 Echoing of given input. 301 ''' 302 output(line)
303
304 - def do_sh( self, line ):
305 ''' 306 Run an external shell command 307 sh pwd 308 sh ifconfig etc. 309 ''' 310 call( line, shell=True )
311 312
313 - def do_py( self, line ):
314 ''' 315 Evaluate a Python expression. 316 317 py main.log.info("Sample Log Information") 318 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information 319 320 ''' 321 try: 322 exec( line ) 323 except Exception, e: 324 output( str( e ) + '\n' )
325
326 - def do_interpret(self,line):
327 ''' 328 interpret will translate the single line openspeak statement to equivalent python script. 329 330 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed" 331 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed") 332 333 ''' 334 from core import openspeak 335 ospk = openspeak.OpenSpeak() 336 try : 337 translated_code = ospk.interpret(text=line) 338 print translated_code 339 except AttributeError, e: 340 print 'Dynamic params are not allowed in single statement translations'
341
342 - def do_do (self,line):
343 ''' 344 Do will translate and execute the openspeak statement for the paused test. 345 do <OpenSpeak statement> 346 ''' 347 if testthread: 348 from core import openspeak 349 ospk = openspeak.OpenSpeak() 350 try : 351 translated_code = ospk.interpret(text=line) 352 eval(translated_code) 353 except (AttributeError,SyntaxError), e: 354 print 'Dynamic params are not allowed in single statement translations' 355 else : 356 print "Do will translate and execute the openspeak statement for the paused test.\nPlease use interpret to translate the OpenSpeak statement."
357
358 - def do_compile(self,line):
359 ''' 360 compile will translate the openspeak (.ospk) file into TestON test script (python). 361 It will receive the openspeak file path as input and will generate 362 equivalent test-script file in the same directory. 363 364 usage: 365 ----- 366 teston>compile /home/openflow/TestON/PoxTest.ospk 367 368 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py 369 ''' 370 from core import openspeak 371 openspeak = openspeak.OpenSpeak() 372 openspeakfile = line 373 if os.path.exists(openspeakfile) : 374 openspeak.compiler(openspeakfile=openspeakfile,writetofile=1) 375 print "Auto-generated test-script file is "+ re.sub("ospk","py",openspeakfile,0) 376 else: 377 print 'There is no such file : '+line
378
379 - def do_exit( self, _line ):
380 "Exit" 381 if testthread: 382 testthread.stop() 383 384 sys.exit() 385 386 return 'exited by user command'
387
388 - def do_quit( self, line ):
389 "Exit" 390 return self.do_exit( line )
391
392 - def do_EOF( self, line ):
393 "Exit" 394 output( '\n' ) 395 return self.do_exit( line )
396
397 - def isatty( self ):
398 "Is our standard input a tty?" 399 return isatty( self.stdin.fileno() )
400
401 - def do_source( self, line ):
402 ''' 403 Read shell commands from an input file and execute them sequentially. 404 cmdsource.txt : 405 406 "pwd 407 ls " 408 409 teston>source /home/openflow/cmdsource.txt 410 /home/openflow/TestON/bin/ 411 cli.py __init__.py 412 413 ''' 414 415 args = line.split() 416 if len(args) != 1: 417 error( 'usage: source <file>\n' ) 418 return 419 try: 420 self.inputFile = open( args[ 0 ] ) 421 while True: 422 line = self.inputFile.readline() 423 if len( line ) > 0: 424 call( line, shell=True ) 425 else: 426 break 427 except IOError: 428 error( 'error reading file %s\n' % args[ 0 ] )
429
430 - def do_updatedriver(self,line):
431 ''' 432 updatedriver will update the given driver name which exists into mentioned config file. 433 It will receive two optional arguments : 434 435 1. Config File Path 436 2. Drivers List to be updated. 437 438 Default : config file = "~/TestON/config/updatedriver" , 439 Driver List = all drivers specified in config file . 440 ''' 441 args = line.split() 442 config = '' 443 drivers = '' 444 try : 445 for index, option in enumerate(args): 446 if option == 'config': 447 index = index + 1 448 config = args[index] 449 elif option == 'drivers' : 450 index = index + 1 451 drivers = args[index] 452 except IndexError: 453 pass 454 import updatedriver 455 converter = updatedriver.UpdateDriver() 456 457 if config == '': 458 path = re.sub("(bin)$", "", os.getcwd()) 459 config = path + "/config/updatedriver.cfg" 460 configDict = converter.configparser(config) 461 462 else : 463 converter.configparser(config) 464 configDict = converter.configparser(config) 465 466 467 converter.writeDriver(drivers)
468 469 470 471
472 - def do_time( self, line ):
473 "Measure time taken for any command in TestON." 474 start = time.time() 475 self.onecmd(line) 476 elapsed = time.time() - start 477 self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
478
479 - def default( self, line ):
480 """Called on an input line when the command prefix is not recognized.""" 481 first, args, line = self.parseline( line ) 482 if not args: 483 return 484 if args and len(args) > 0 and args[ -1 ] == '\n': 485 args = args[ :-1 ] 486 rest = args.split( ' ' ) 487 488 error( '*** Unknown command: %s\n' % first )
489 490 491
492 -class TestThread(threading.Thread):
493 ''' 494 TestThread class will handle the test execution and will communicate with the thread in the do_run. 495 '''
496 - def __init__(self,options):
497 self._stopevent = threading.Event() 498 threading.Thread.__init__(self) 499 self.is_stop = False 500 self.options = options 501 __builtin__.testthread = self
502
503 - def run(self):
504 ''' 505 Will execute the test. 506 ''' 507 while not self.is_stop : 508 if not self._stopevent.isSet(): 509 self.test_on = TestON(self.options) 510 try : 511 if self.test_on.init_result: 512 result = self.test_on.run() 513 if not self.is_stop : 514 result = self.test_on.cleanup() 515 self.is_stop = True 516 except(KeyboardInterrupt): 517 print "Recevied Interrupt,cleaning-up the logs and drivers before exiting" 518 result = self.test_on.cleanup() 519 self.is_stop = True 520 521 __builtin__.testthread = False
522
523 - def pause(self):
524 ''' 525 Will pause the test. 526 ''' 527 print "Will pause the test's execution, after completion of this step.....\n\n\n\n" 528 cli.pause = True 529 self._stopevent.set()
530
531 - def play(self):
532 ''' 533 Will resume the paused test. 534 ''' 535 self._stopevent.clear() 536 cli.pause = False
537
538 - def stop(self):
539 ''' 540 Will stop the test execution. 541 ''' 542 543 print "Stopping the test" 544 self.is_stop = True 545 cli.stop = True 546 __builtin__.testthread = False
547
548 -def output(msg):
549 ''' 550 Simply, print the message in console 551 ''' 552 print msg
553
554 -def error(msg):
555 ''' 556 print the error message. 557 ''' 558 print msg
559
560 -def dictToObj(dictionary):
561 ''' 562 This will facilitates the converting of the dictionary to the object. 563 This method will help to send options as object format to the test. 564 ''' 565 if isinstance(dictionary, list): 566 dictionary = [dictToObj(x) for x in dictionary] 567 if not isinstance(dictionary, dict): 568 return dictionary 569 class Convert(object): 570 pass
571 obj = Convert() 572 for k in dictionary: 573 obj.__dict__[k] = dictToObj(dictionary[k]) 574 return obj 575 576 577 if __name__ == '__main__': 578 if len(sys.argv) > 1: 579 CLI("test").onecmd(' '.join(sys.argv[1:])) 580 else: 581 CLI("test").cmdloop() 582