blob: 263d4b40c0cad9013390942cb8a310a0ca7a71e2 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00002'''
adminbae64d82013-08-01 10:50:15 -07003Created on 20-Dec-2012
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07004Copyright 2012 Open Networking Foundation
Jon Hall5f15fef2015-07-17 14:22:14 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000013 (at your option) any later version.
adminbae64d82013-08-01 10:50:15 -070014
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
Jon Hall4ba53f02015-07-29 13:07:41 -070021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
23
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000024'''
25
26
adminbae64d82013-08-01 10:50:15 -070027"""
28cli will provide the CLI shell for teston framework.
29
30A simple command-line interface for TestON.
31
32The TestON CLI provides a simple console which
33makes it easy to launch the test. For example, the command run will execute the test.
34
35teston> run test DpctlTest
36Several useful commands are provided.
37"""
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000038
adminbae64d82013-08-01 10:50:15 -070039from subprocess import call
40from cmd import Cmd
41from os import isatty
42import sys
43import re
44import os
45import time
46import threading
47import __builtin__
48import pprint
Jeremy Ronquillo696f4262017-10-17 10:56:26 -070049dump = pprint.PrettyPrinter( indent=4 )
adminbae64d82013-08-01 10:50:15 -070050__builtin__.testthread = False
51introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)"
Jon Hall0bde9ba2015-03-19 11:32:57 -070052__builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -070053
Jeremy Ronquillo696f4262017-10-17 10:56:26 -070054path = re.sub( "/bin$", "", sys.path[ 0 ] )
Jon Hall1dd5a0a2015-07-08 10:49:26 -070055sys.path.insert( 1, path )
Jon Hall0bde9ba2015-03-19 11:32:57 -070056from core.teston import *
adminbae64d82013-08-01 10:50:15 -070057
Jeremy Ronquillo696f4262017-10-17 10:56:26 -070058class CLI( threading.Thread, Cmd, object ):
adminbae64d82013-08-01 10:50:15 -070059 "command-line interface to execute the test."
60
61 prompt = 'teston> '
62
63 def __init__( self, teston, stdin=sys.stdin ):
64 self.teston = teston
Jon Hall0bde9ba2015-03-19 11:32:57 -070065
adminbae64d82013-08-01 10:50:15 -070066 self._mainevent = threading.Event()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -070067 threading.Thread.__init__( self )
adminbae64d82013-08-01 10:50:15 -070068 self.main_stop = False
69 self.locals = { 'test': teston }
70 self.stdin = stdin
71 Cmd.__init__( self )
72 self.pause = False
73 self.stop = False
74 __builtin__.cli = self
75
76 def emptyline( self ):
77 "Don't repeat last command when you hit return."
78 pass
79
80 helpStr = (
81 " teston help"
82 )
83
84 def do_help( self, line ):
85 "Describe available CLI commands."
86 Cmd.do_help( self, line )
87 if line is '':
88 output( self.helpStr )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -070089
90 def do_run( self, args ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000091 '''
adminbae64d82013-08-01 10:50:15 -070092 run command will execute the test with following optional command line arguments
93 logdir <directory to store logs in>
94 testcases <list of testcases separated by comma or range of testcases separated by hypen>
95 mail <mail-id or list of mail-ids seperated by comma>
96 example 1, to execute the examples specified in the ~/examples diretory.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000097 '''
Jon Hall1306a562015-09-04 11:21:24 -070098 try:
99 args = args.split()
100 options = {}
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700101 options = self.parseArgs( args, options )
102 options = dictToObj( options )
Jon Hall1306a562015-09-04 11:21:24 -0700103 if not testthread:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700104 test = TestThread( options )
Jon Hall1306a562015-09-04 11:21:24 -0700105 test.start()
106 while test.isAlive():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700107 test.join( 1 )
Jon Hall1306a562015-09-04 11:21:24 -0700108 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700109 print main.TEST + " test execution paused, please resume that before executing to another test"
Jon Hall1306a562015-09-04 11:21:24 -0700110 except KeyboardInterrupt, SystemExit:
111 print "Interrupt called, Exiting."
112 test._Thread__stop()
113 main.cleanup()
114 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700115
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700116 def do_resume( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000117 '''
adminbae64d82013-08-01 10:50:15 -0700118 resume command will continue the execution of paused test.
119 teston>resume
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000120 [2013-01-07 23:03:44.640723] [PoxTest] [STEP] 1.1: Checking the host reachability using pingHost
adminbae64d82013-08-01 10:50:15 -0700121 2013-01-07 23:03:44,858 - PoxTest - INFO - Expected Prompt Found
122 ....
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000123 '''
adminbae64d82013-08-01 10:50:15 -0700124 if testthread:
125 testthread.play()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700126 else:
adminbae64d82013-08-01 10:50:15 -0700127 print "There is no test to resume"
Jon Hall4ba53f02015-07-29 13:07:41 -0700128
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700129 def do_nextstep( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000130 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700131 nextstep will execute the next-step of the paused test and
adminbae64d82013-08-01 10:50:15 -0700132 it will pause the test after finishing of step.
Jon Hall4ba53f02015-07-29 13:07:41 -0700133
adminbae64d82013-08-01 10:50:15 -0700134 teston> nextstep
135 Will pause the test's execution, after completion of this step.....
Jon Hall4ba53f02015-07-29 13:07:41 -0700136
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000137 teston> [2013-01-07 21:24:26.286601] [PoxTest] [STEP] 1.8: Checking the host reachability using pingHost
adminbae64d82013-08-01 10:50:15 -0700138 2013-01-07 21:24:26,455 - PoxTest - INFO - Expected Prompt Found
139 .....
140 teston>
Jon Hall4ba53f02015-07-29 13:07:41 -0700141
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000142 '''
adminbae64d82013-08-01 10:50:15 -0700143 if testthread:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700144 main.log.info( "Executing the nextstep, Will pause test execution, after completion of the step" )
adminbae64d82013-08-01 10:50:15 -0700145 testthread.play()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700146 time.sleep( .1 )
adminbae64d82013-08-01 10:50:15 -0700147 testthread.pause()
148 else:
149 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700150
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700151 def do_dumpvar( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000152 '''
adminbae64d82013-08-01 10:50:15 -0700153 dumpvar will print all the test data in raw format.
Jon Hall4ba53f02015-07-29 13:07:41 -0700154 usgae :
adminbae64d82013-08-01 10:50:15 -0700155 teston>dumpvar main
156 Here 'main' will be the test object.
Jon Hall4ba53f02015-07-29 13:07:41 -0700157
158 teston>dumpvar params
adminbae64d82013-08-01 10:50:15 -0700159 here 'params' will be the parameters specified in the params file.
Jon Hall4ba53f02015-07-29 13:07:41 -0700160
adminbae64d82013-08-01 10:50:15 -0700161 teston>dumpvar topology
162 here 'topology' will be topology specification of the test specified in topo file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000163 '''
adminbae64d82013-08-01 10:50:15 -0700164 if testthread:
165 if line == "main":
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700166 dump.pprint( vars( main ) )
167 else:
168 try:
169 dump.pprint( vars( main )[ line ] )
Jon Hall1306a562015-09-04 11:21:24 -0700170 except KeyError as e:
adminbae64d82013-08-01 10:50:15 -0700171 print e
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700172 else:
adminbae64d82013-08-01 10:50:15 -0700173 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700174
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700175 def do_currentcase( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000176 '''
adminbae64d82013-08-01 10:50:15 -0700177 currentcase will return the current case in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700178
adminbae64d82013-08-01 10:50:15 -0700179 teston>currentcase
180 Currently executing test case is: 2
Jon Hall4ba53f02015-07-29 13:07:41 -0700181
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000182 '''
adminbae64d82013-08-01 10:50:15 -0700183 if testthread:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700184 print "Currently executing test case is: " + str( main.CurrentTestCaseNumber )
185 else:
adminbae64d82013-08-01 10:50:15 -0700186 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700187
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700188 def do_currentstep( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000189 '''
adminbae64d82013-08-01 10:50:15 -0700190 currentstep will return the current step in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700191
adminbae64d82013-08-01 10:50:15 -0700192 teston>currentstep
193 Currently executing test step is: 2.3
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000194 '''
adminbae64d82013-08-01 10:50:15 -0700195 if testthread:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700196 print "Currently executing test step is: " + str( main.CurrentTestCaseNumber ) + '.' + str( main.stepCount )
197 else:
adminbae64d82013-08-01 10:50:15 -0700198 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700199
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700200 def do_stop( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000201 '''
adminbae64d82013-08-01 10:50:15 -0700202 Will stop the paused test, if any !
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000203 '''
adminbae64d82013-08-01 10:50:15 -0700204 if testthread:
205 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700206
adminbae64d82013-08-01 10:50:15 -0700207 return 'exited by user command'
Jon Hall4ba53f02015-07-29 13:07:41 -0700208
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700209 def do_gettest( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000210 '''
adminbae64d82013-08-01 10:50:15 -0700211 gettest will return the test name which is under execution or recently executed.
Jon Hall4ba53f02015-07-29 13:07:41 -0700212
adminbae64d82013-08-01 10:50:15 -0700213 Test under execution:
Jon Hall4ba53f02015-07-29 13:07:41 -0700214 teston>gettest
adminbae64d82013-08-01 10:50:15 -0700215 Currently executing Test is: PoxTest
Jon Hall4ba53f02015-07-29 13:07:41 -0700216
adminbae64d82013-08-01 10:50:15 -0700217 Test recently executed:
218 Recently executed test is: MininetTest
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000219 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700220 try:
221 if testthread:
222 print "Currently executing Test is: " + main.TEST
223 else:
224 print "Recently executed test is: " + main.TEST
Jon Hall4ba53f02015-07-29 13:07:41 -0700225
adminbae64d82013-08-01 10:50:15 -0700226 except NameError:
227 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700228
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700229 def do_showlog( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000230 '''
adminbae64d82013-08-01 10:50:15 -0700231 showlog will show the test's Log
232 teston>showlog
233 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
234 .....
235 teston>showlog
236 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
237 .....
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000238 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700239 try:
240 if testthread:
241 print "Currently executing Test's log is: " + main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700242
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700243 else:
244 print "Last executed test's log is : " + main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700245
adminbae64d82013-08-01 10:50:15 -0700246 logFile = main.LogFileName
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700247 logFileHandler = open( logFile, 'r' )
248 for msg in logFileHandler.readlines():
adminbae64d82013-08-01 10:50:15 -0700249 print msg,
Jon Hall4ba53f02015-07-29 13:07:41 -0700250
adminbae64d82013-08-01 10:50:15 -0700251 logFileHandler.close()
Jon Hall4ba53f02015-07-29 13:07:41 -0700252
adminbae64d82013-08-01 10:50:15 -0700253 except NameError:
254 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700255
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700256 def parseArgs( self, args, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000257 '''
adminbae64d82013-08-01 10:50:15 -0700258 This will parse the command line arguments.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000259 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700260 options = self.initOptions( options )
261 try:
YPZhang16f6e562016-07-12 15:50:31 -0700262 index = 0
263 while index < len( args ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700264 option = args[ index ]
265 if index > 0:
Jon Halld74d2952018-03-01 13:26:39 -0800266 if re.match( "--params-file", option, flags=0 ):
267 # The more specific match must be before --params
268 options[ 'paramsFile' ] = args[ index + 1 ]
269 elif re.match( "--topo-file", option, flags=0 ):
270 options[ 'topoFile' ] = args[ index + 1 ]
271 elif re.match( "--params", option, flags=0 ):
YPZhang1c89e762016-06-29 10:43:58 -0700272 # check if there is a params
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700273 options[ 'params' ].append( args[ index + 1 ] )
Jon Halld74d2952018-03-01 13:26:39 -0800274 elif re.match( "logdir|mail|example|testdir|testcases|onoscell",
275 option, flags=0 ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700276 options[ option ] = args[ index + 1 ]
277 options = self.testcasesInRange( index + 1, option, args, options )
YPZhang16f6e562016-07-12 15:50:31 -0700278 index += 2
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700279 else:
280 options[ 'testname' ] = option
YPZhang16f6e562016-07-12 15:50:31 -0700281 index += 1
Jon Hall1306a562015-09-04 11:21:24 -0700282 except IndexError as e:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700283 print ( e )
YPZhang16f6e562016-07-12 15:50:31 -0700284 main.cleanup()
285 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700286
adminbae64d82013-08-01 10:50:15 -0700287 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700288
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700289 def initOptions( self, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000290 '''
adminbae64d82013-08-01 10:50:15 -0700291 This will initialize the commandline options.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000292 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700293 options[ 'logdir' ] = None
294 options[ 'mail' ] = None
295 options[ 'example' ] = None
296 options[ 'testdir' ] = None
297 options[ 'testcases' ] = None
298 options[ 'onoscell' ] = None
YPZhang1c89e762016-06-29 10:43:58 -0700299 # init params as a empty list
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700300 options[ 'params' ] = []
Jon Halld74d2952018-03-01 13:26:39 -0800301 options[ 'paramsFile' ] = None
302 options[ 'topoFile' ] = None
Jon Hall4ba53f02015-07-29 13:07:41 -0700303 return options
304
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700305 def testcasesInRange( self, index, option, args, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000306 '''
307 This method will handle testcases list,specified in range [1-10].
308 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700309 if re.match( "testcases", option, 1 ):
adminbae64d82013-08-01 10:50:15 -0700310 testcases = []
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700311 args[ index ] = re.sub( "\[|\]", "", args[ index ], 0 )
312 m = re.match( "(\d+)\-(\d+)", args[ index ], flags=0 )
adminbae64d82013-08-01 10:50:15 -0700313 if m:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700314 start_case = eval( m.group( 1 ) )
315 end_case = eval( m.group( 2 ) )
316 if ( start_case <= end_case ):
adminbae64d82013-08-01 10:50:15 -0700317 i = start_case
318 while i <= end_case:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700319 testcases.append( i )
320 i = i + 1
321 else:
adminbae64d82013-08-01 10:50:15 -0700322 print "Please specify testcases properly like 1-5"
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700323 else:
324 options[ option ] = args[ index ]
adminbae64d82013-08-01 10:50:15 -0700325 return options
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700326 options[ option ] = str( testcases )
Jon Hall4ba53f02015-07-29 13:07:41 -0700327
adminbae64d82013-08-01 10:50:15 -0700328 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700329
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700330 def cmdloop( self, intro=introduction ):
adminbae64d82013-08-01 10:50:15 -0700331 print introduction
332 while True:
333 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700334 super( CLI, self ).cmdloop( intro="" )
adminbae64d82013-08-01 10:50:15 -0700335 self.postloop()
336 except KeyboardInterrupt:
Jon Hall1306a562015-09-04 11:21:24 -0700337 if testthread:
338 testthread.pause()
339 else:
340 print "KeyboardInterrupt, Exiting."
341 sys.exit()
adminbae64d82013-08-01 10:50:15 -0700342
343 def do_echo( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000344 '''
adminbae64d82013-08-01 10:50:15 -0700345 Echoing of given input.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000346 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700347 output( line )
adminbae64d82013-08-01 10:50:15 -0700348
349 def do_sh( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000350 '''
adminbae64d82013-08-01 10:50:15 -0700351 Run an external shell command
352 sh pwd
353 sh ifconfig etc.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000354 '''
adminbae64d82013-08-01 10:50:15 -0700355 call( line, shell=True )
356
adminbae64d82013-08-01 10:50:15 -0700357 def do_py( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000358 '''
adminbae64d82013-08-01 10:50:15 -0700359 Evaluate a Python expression.
Jon Hall4ba53f02015-07-29 13:07:41 -0700360
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000361 py main.log.info("Sample Log Information")
adminbae64d82013-08-01 10:50:15 -0700362 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information
Jon Hall4ba53f02015-07-29 13:07:41 -0700363
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000364 '''
adminbae64d82013-08-01 10:50:15 -0700365 try:
366 exec( line )
Jon Hall1306a562015-09-04 11:21:24 -0700367 except Exception as e:
adminbae64d82013-08-01 10:50:15 -0700368 output( str( e ) + '\n' )
Jon Hall4ba53f02015-07-29 13:07:41 -0700369
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700370 def do_interpret( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000371 '''
adminbae64d82013-08-01 10:50:15 -0700372 interpret will translate the single line openspeak statement to equivalent python script.
Jon Hall4ba53f02015-07-29 13:07:41 -0700373
adminbae64d82013-08-01 10:50:15 -0700374 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed"
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000375 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed")
Jon Hall4ba53f02015-07-29 13:07:41 -0700376
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000377 '''
adminbae64d82013-08-01 10:50:15 -0700378 from core import openspeak
379 ospk = openspeak.OpenSpeak()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700380 try:
381 translated_code = ospk.interpret( text=line )
adminbae64d82013-08-01 10:50:15 -0700382 print translated_code
Jon Hall1306a562015-09-04 11:21:24 -0700383 except AttributeError as e:
adminbae64d82013-08-01 10:50:15 -0700384 print 'Dynamic params are not allowed in single statement translations'
Jon Hall4ba53f02015-07-29 13:07:41 -0700385
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700386 def do_do( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000387 '''
adminbae64d82013-08-01 10:50:15 -0700388 Do will translate and execute the openspeak statement for the paused test.
389 do <OpenSpeak statement>
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000390 '''
adminbae64d82013-08-01 10:50:15 -0700391 if testthread:
392 from core import openspeak
393 ospk = openspeak.OpenSpeak()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700394 try:
395 translated_code = ospk.interpret( text=line )
396 eval( translated_code )
Jon Hall1306a562015-09-04 11:21:24 -0700397 except ( AttributeError, SyntaxError ) as e:
398 print 'Dynamic params are not allowed in single statement translations:'
399 print e
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700400 else:
adminbae64d82013-08-01 10:50:15 -0700401 print "Do will translate and execute the openspeak statement for the paused test.\nPlease use interpret to translate the OpenSpeak statement."
Jon Hall4ba53f02015-07-29 13:07:41 -0700402
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700403 def do_compile( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000404 '''
405 compile will translate the openspeak (.ospk) file into TestON test script (python).
Jon Hall4ba53f02015-07-29 13:07:41 -0700406 It will receive the openspeak file path as input and will generate
407 equivalent test-script file in the same directory.
408
adminbae64d82013-08-01 10:50:15 -0700409 usage:
410 -----
411 teston>compile /home/openflow/TestON/PoxTest.ospk
Jon Hall4ba53f02015-07-29 13:07:41 -0700412
adminbae64d82013-08-01 10:50:15 -0700413 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000414 '''
adminbae64d82013-08-01 10:50:15 -0700415 from core import openspeak
Jon Hall4ba53f02015-07-29 13:07:41 -0700416 openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700417 openspeakfile = line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700418 if os.path.exists( openspeakfile ):
419 openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
420 print "Auto-generated test-script file is " + re.sub( "ospk", "py", openspeakfile, 0 )
adminbae64d82013-08-01 10:50:15 -0700421 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700422 print 'There is no such file : ' + line
adminbae64d82013-08-01 10:50:15 -0700423
424 def do_exit( self, _line ):
425 "Exit"
426 if testthread:
427 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700428
adminbae64d82013-08-01 10:50:15 -0700429 sys.exit()
430
431 return 'exited by user command'
432
433 def do_quit( self, line ):
434 "Exit"
435 return self.do_exit( line )
436
437 def do_EOF( self, line ):
438 "Exit"
439 output( '\n' )
440 return self.do_exit( line )
441
442 def isatty( self ):
443 "Is our standard input a tty?"
444 return isatty( self.stdin.fileno() )
445
446 def do_source( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000447 '''
adminbae64d82013-08-01 10:50:15 -0700448 Read shell commands from an input file and execute them sequentially.
449 cmdsource.txt :
Jon Hall4ba53f02015-07-29 13:07:41 -0700450
adminbae64d82013-08-01 10:50:15 -0700451 "pwd
452 ls "
Jon Hall4ba53f02015-07-29 13:07:41 -0700453
adminbae64d82013-08-01 10:50:15 -0700454 teston>source /home/openflow/cmdsource.txt
455 /home/openflow/TestON/bin/
456 cli.py __init__.py
Jon Hall4ba53f02015-07-29 13:07:41 -0700457
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000458 '''
459
adminbae64d82013-08-01 10:50:15 -0700460 args = line.split()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700461 if len( args ) != 1:
adminbae64d82013-08-01 10:50:15 -0700462 error( 'usage: source <file>\n' )
463 return
464 try:
465 self.inputFile = open( args[ 0 ] )
466 while True:
467 line = self.inputFile.readline()
468 if len( line ) > 0:
469 call( line, shell=True )
470 else:
471 break
472 except IOError:
473 error( 'error reading file %s\n' % args[ 0 ] )
Jon Hall4ba53f02015-07-29 13:07:41 -0700474
adminbae64d82013-08-01 10:50:15 -0700475 def do_time( self, line ):
476 "Measure time taken for any command in TestON."
477 start = time.time()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700478 self.onecmd( line )
adminbae64d82013-08-01 10:50:15 -0700479 elapsed = time.time() - start
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700480 self.stdout.write( "*** Elapsed time: %0.6f secs\n" % elapsed )
adminbae64d82013-08-01 10:50:15 -0700481
482 def default( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000483 """Called on an input line when the command prefix is not recognized."""
adminbae64d82013-08-01 10:50:15 -0700484 first, args, line = self.parseline( line )
485 if not args:
486 return
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700487 if args and len( args ) > 0 and args[ -1 ] == '\n':
488 args = args[:-1 ]
adminbae64d82013-08-01 10:50:15 -0700489 rest = args.split( ' ' )
490
491 error( '*** Unknown command: %s\n' % first )
492
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700493class TestThread( threading.Thread ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000494 '''
adminbae64d82013-08-01 10:50:15 -0700495 TestThread class will handle the test execution and will communicate with the thread in the do_run.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000496 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700497 def __init__( self, options ):
adminbae64d82013-08-01 10:50:15 -0700498 self._stopevent = threading.Event()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700499 threading.Thread.__init__( self )
adminbae64d82013-08-01 10:50:15 -0700500 self.is_stop = False
501 self.options = options
502 __builtin__.testthread = self
503
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700504 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000505 '''
adminbae64d82013-08-01 10:50:15 -0700506 Will execute the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000507 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700508 while not self.is_stop:
adminbae64d82013-08-01 10:50:15 -0700509 if not self._stopevent.isSet():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700510 self.test_on = TestON( self.options )
511 try:
adminbae64d82013-08-01 10:50:15 -0700512 if self.test_on.init_result:
513 result = self.test_on.run()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700514 if not self.is_stop:
adminbae64d82013-08-01 10:50:15 -0700515 result = self.test_on.cleanup()
516 self.is_stop = True
Jon Hall1306a562015-09-04 11:21:24 -0700517 except KeyboardInterrupt:
518 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
adminbae64d82013-08-01 10:50:15 -0700519 result = self.test_on.cleanup()
520 self.is_stop = True
521
Jon Hall4ba53f02015-07-29 13:07:41 -0700522 __builtin__.testthread = False
adminbae64d82013-08-01 10:50:15 -0700523
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700524 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000525 '''
adminbae64d82013-08-01 10:50:15 -0700526 Will pause the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000527 '''
Jon Hall1306a562015-09-04 11:21:24 -0700528 if not cli.pause:
529 print "Will pause the test's execution, after completion of this step.....\n\n\n\n"
530 cli.pause = True
531 self._stopevent.set()
532 elif cli.pause and self.is_stop:
533 print "KeyboardInterrupt, Exiting."
534 self.test_on.exit()
535 else:
536 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
537 result = self.test_on.cleanup()
538 self.is_stop = True
adminbae64d82013-08-01 10:50:15 -0700539
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700540 def play( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000541 '''
adminbae64d82013-08-01 10:50:15 -0700542 Will resume the paused test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000543 '''
adminbae64d82013-08-01 10:50:15 -0700544 self._stopevent.clear()
545 cli.pause = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700546
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700547 def stop( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000548 '''
adminbae64d82013-08-01 10:50:15 -0700549 Will stop the test execution.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000550 '''
551
adminbae64d82013-08-01 10:50:15 -0700552 print "Stopping the test"
553 self.is_stop = True
554 cli.stop = True
555 __builtin__.testthread = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700556
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700557def output( msg ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000558 '''
adminbae64d82013-08-01 10:50:15 -0700559 Simply, print the message in console
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000560 '''
adminbae64d82013-08-01 10:50:15 -0700561 print msg
562
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700563def error( msg ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000564 '''
adminbae64d82013-08-01 10:50:15 -0700565 print the error message.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000566 '''
adminbae64d82013-08-01 10:50:15 -0700567 print msg
568
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700569def dictToObj( dictionary ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000570 '''
adminbae64d82013-08-01 10:50:15 -0700571 This will facilitates the converting of the dictionary to the object.
572 This method will help to send options as object format to the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000573 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700574 if isinstance( dictionary, list ):
575 dictionary = [ dictToObj( x ) for x in dictionary ]
576 if not isinstance( dictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700577 return dictionary
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700578
579 class Convert( object ):
adminbae64d82013-08-01 10:50:15 -0700580 pass
581 obj = Convert()
582 for k in dictionary:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700583 obj.__dict__[ k ] = dictToObj( dictionary[ k ] )
adminbae64d82013-08-01 10:50:15 -0700584 return obj
585
586
587if __name__ == '__main__':
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700588 if len( sys.argv ) > 1:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700589 __builtin__.COLORS = True
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700590 CLI( "test" ).onecmd( ' '.join( sys.argv[ 1: ] ) )
adminbae64d82013-08-01 10:50:15 -0700591 else:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700592 __builtin__.COLORS = False
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700593 CLI( "test" ).cmdloop()