blob: b03fce7a29bc172e5e5f3389933a687cf3407e53 [file] [log] [blame]
Jon Hall06fd0df2021-01-25 15:50:06 -08001#!/usr/bin/env python2
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 )
Jon Halldbf562c2018-04-24 11:10:21 -0700284 sys.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700285
adminbae64d82013-08-01 10:50:15 -0700286 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700287
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700288 def initOptions( self, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000289 '''
adminbae64d82013-08-01 10:50:15 -0700290 This will initialize the commandline options.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000291 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700292 options[ 'logdir' ] = None
293 options[ 'mail' ] = None
294 options[ 'example' ] = None
295 options[ 'testdir' ] = None
296 options[ 'testcases' ] = None
297 options[ 'onoscell' ] = None
YPZhang1c89e762016-06-29 10:43:58 -0700298 # init params as a empty list
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700299 options[ 'params' ] = []
Jon Halld74d2952018-03-01 13:26:39 -0800300 options[ 'paramsFile' ] = None
301 options[ 'topoFile' ] = None
Jon Hall4ba53f02015-07-29 13:07:41 -0700302 return options
303
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700304 def testcasesInRange( self, index, option, args, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000305 '''
306 This method will handle testcases list,specified in range [1-10].
307 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700308 if re.match( "testcases", option, 1 ):
adminbae64d82013-08-01 10:50:15 -0700309 testcases = []
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700310 args[ index ] = re.sub( "\[|\]", "", args[ index ], 0 )
311 m = re.match( "(\d+)\-(\d+)", args[ index ], flags=0 )
adminbae64d82013-08-01 10:50:15 -0700312 if m:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700313 start_case = eval( m.group( 1 ) )
314 end_case = eval( m.group( 2 ) )
315 if ( start_case <= end_case ):
adminbae64d82013-08-01 10:50:15 -0700316 i = start_case
317 while i <= end_case:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700318 testcases.append( i )
319 i = i + 1
320 else:
adminbae64d82013-08-01 10:50:15 -0700321 print "Please specify testcases properly like 1-5"
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700322 else:
323 options[ option ] = args[ index ]
adminbae64d82013-08-01 10:50:15 -0700324 return options
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700325 options[ option ] = str( testcases )
Jon Hall4ba53f02015-07-29 13:07:41 -0700326
adminbae64d82013-08-01 10:50:15 -0700327 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700328
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700329 def cmdloop( self, intro=introduction ):
adminbae64d82013-08-01 10:50:15 -0700330 print introduction
331 while True:
332 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700333 super( CLI, self ).cmdloop( intro="" )
adminbae64d82013-08-01 10:50:15 -0700334 self.postloop()
335 except KeyboardInterrupt:
Jon Hall1306a562015-09-04 11:21:24 -0700336 if testthread:
337 testthread.pause()
338 else:
339 print "KeyboardInterrupt, Exiting."
340 sys.exit()
adminbae64d82013-08-01 10:50:15 -0700341
342 def do_echo( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000343 '''
adminbae64d82013-08-01 10:50:15 -0700344 Echoing of given input.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000345 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700346 output( line )
adminbae64d82013-08-01 10:50:15 -0700347
348 def do_sh( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000349 '''
adminbae64d82013-08-01 10:50:15 -0700350 Run an external shell command
351 sh pwd
352 sh ifconfig etc.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000353 '''
adminbae64d82013-08-01 10:50:15 -0700354 call( line, shell=True )
355
adminbae64d82013-08-01 10:50:15 -0700356 def do_py( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000357 '''
adminbae64d82013-08-01 10:50:15 -0700358 Evaluate a Python expression.
Jon Hall4ba53f02015-07-29 13:07:41 -0700359
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000360 py main.log.info("Sample Log Information")
adminbae64d82013-08-01 10:50:15 -0700361 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information
Jon Hall4ba53f02015-07-29 13:07:41 -0700362
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000363 '''
adminbae64d82013-08-01 10:50:15 -0700364 try:
365 exec( line )
Jon Hall1306a562015-09-04 11:21:24 -0700366 except Exception as e:
adminbae64d82013-08-01 10:50:15 -0700367 output( str( e ) + '\n' )
Jon Hall4ba53f02015-07-29 13:07:41 -0700368
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700369 def do_interpret( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000370 '''
adminbae64d82013-08-01 10:50:15 -0700371 interpret will translate the single line openspeak statement to equivalent python script.
Jon Hall4ba53f02015-07-29 13:07:41 -0700372
adminbae64d82013-08-01 10:50:15 -0700373 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed"
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000374 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed")
Jon Hall4ba53f02015-07-29 13:07:41 -0700375
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000376 '''
adminbae64d82013-08-01 10:50:15 -0700377 from core import openspeak
378 ospk = openspeak.OpenSpeak()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700379 try:
380 translated_code = ospk.interpret( text=line )
adminbae64d82013-08-01 10:50:15 -0700381 print translated_code
Jon Hall1306a562015-09-04 11:21:24 -0700382 except AttributeError as e:
adminbae64d82013-08-01 10:50:15 -0700383 print 'Dynamic params are not allowed in single statement translations'
Jon Hall4ba53f02015-07-29 13:07:41 -0700384
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700385 def do_do( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000386 '''
adminbae64d82013-08-01 10:50:15 -0700387 Do will translate and execute the openspeak statement for the paused test.
388 do <OpenSpeak statement>
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000389 '''
adminbae64d82013-08-01 10:50:15 -0700390 if testthread:
391 from core import openspeak
392 ospk = openspeak.OpenSpeak()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700393 try:
394 translated_code = ospk.interpret( text=line )
395 eval( translated_code )
Jon Hall1306a562015-09-04 11:21:24 -0700396 except ( AttributeError, SyntaxError ) as e:
397 print 'Dynamic params are not allowed in single statement translations:'
398 print e
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700399 else:
adminbae64d82013-08-01 10:50:15 -0700400 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 -0700401
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700402 def do_compile( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000403 '''
404 compile will translate the openspeak (.ospk) file into TestON test script (python).
Jon Hall4ba53f02015-07-29 13:07:41 -0700405 It will receive the openspeak file path as input and will generate
406 equivalent test-script file in the same directory.
407
adminbae64d82013-08-01 10:50:15 -0700408 usage:
409 -----
410 teston>compile /home/openflow/TestON/PoxTest.ospk
Jon Hall4ba53f02015-07-29 13:07:41 -0700411
adminbae64d82013-08-01 10:50:15 -0700412 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000413 '''
adminbae64d82013-08-01 10:50:15 -0700414 from core import openspeak
Jon Hall4ba53f02015-07-29 13:07:41 -0700415 openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700416 openspeakfile = line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700417 if os.path.exists( openspeakfile ):
418 openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
419 print "Auto-generated test-script file is " + re.sub( "ospk", "py", openspeakfile, 0 )
adminbae64d82013-08-01 10:50:15 -0700420 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700421 print 'There is no such file : ' + line
adminbae64d82013-08-01 10:50:15 -0700422
423 def do_exit( self, _line ):
424 "Exit"
425 if testthread:
426 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700427
adminbae64d82013-08-01 10:50:15 -0700428 sys.exit()
429
430 return 'exited by user command'
431
432 def do_quit( self, line ):
433 "Exit"
434 return self.do_exit( line )
435
436 def do_EOF( self, line ):
437 "Exit"
438 output( '\n' )
439 return self.do_exit( line )
440
441 def isatty( self ):
442 "Is our standard input a tty?"
443 return isatty( self.stdin.fileno() )
444
445 def do_source( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000446 '''
adminbae64d82013-08-01 10:50:15 -0700447 Read shell commands from an input file and execute them sequentially.
448 cmdsource.txt :
Jon Hall4ba53f02015-07-29 13:07:41 -0700449
adminbae64d82013-08-01 10:50:15 -0700450 "pwd
451 ls "
Jon Hall4ba53f02015-07-29 13:07:41 -0700452
adminbae64d82013-08-01 10:50:15 -0700453 teston>source /home/openflow/cmdsource.txt
454 /home/openflow/TestON/bin/
455 cli.py __init__.py
Jon Hall4ba53f02015-07-29 13:07:41 -0700456
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000457 '''
458
adminbae64d82013-08-01 10:50:15 -0700459 args = line.split()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700460 if len( args ) != 1:
adminbae64d82013-08-01 10:50:15 -0700461 error( 'usage: source <file>\n' )
462 return
463 try:
464 self.inputFile = open( args[ 0 ] )
465 while True:
466 line = self.inputFile.readline()
467 if len( line ) > 0:
468 call( line, shell=True )
469 else:
470 break
471 except IOError:
472 error( 'error reading file %s\n' % args[ 0 ] )
Jon Hall4ba53f02015-07-29 13:07:41 -0700473
adminbae64d82013-08-01 10:50:15 -0700474 def do_time( self, line ):
475 "Measure time taken for any command in TestON."
476 start = time.time()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700477 self.onecmd( line )
adminbae64d82013-08-01 10:50:15 -0700478 elapsed = time.time() - start
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700479 self.stdout.write( "*** Elapsed time: %0.6f secs\n" % elapsed )
adminbae64d82013-08-01 10:50:15 -0700480
481 def default( self, line ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000482 """Called on an input line when the command prefix is not recognized."""
adminbae64d82013-08-01 10:50:15 -0700483 first, args, line = self.parseline( line )
484 if not args:
485 return
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700486 if args and len( args ) > 0 and args[ -1 ] == '\n':
487 args = args[:-1 ]
adminbae64d82013-08-01 10:50:15 -0700488 rest = args.split( ' ' )
489
490 error( '*** Unknown command: %s\n' % first )
491
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700492class TestThread( threading.Thread ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000493 '''
adminbae64d82013-08-01 10:50:15 -0700494 TestThread class will handle the test execution and will communicate with the thread in the do_run.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000495 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700496 def __init__( self, options ):
adminbae64d82013-08-01 10:50:15 -0700497 self._stopevent = threading.Event()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700498 threading.Thread.__init__( self )
adminbae64d82013-08-01 10:50:15 -0700499 self.is_stop = False
500 self.options = options
501 __builtin__.testthread = self
502
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700503 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000504 '''
adminbae64d82013-08-01 10:50:15 -0700505 Will execute the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000506 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700507 while not self.is_stop:
adminbae64d82013-08-01 10:50:15 -0700508 if not self._stopevent.isSet():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700509 self.test_on = TestON( self.options )
510 try:
adminbae64d82013-08-01 10:50:15 -0700511 if self.test_on.init_result:
512 result = self.test_on.run()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700513 if not self.is_stop:
adminbae64d82013-08-01 10:50:15 -0700514 result = self.test_on.cleanup()
515 self.is_stop = True
Jon Hall1306a562015-09-04 11:21:24 -0700516 except KeyboardInterrupt:
517 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
adminbae64d82013-08-01 10:50:15 -0700518 result = self.test_on.cleanup()
519 self.is_stop = True
520
Jon Hall4ba53f02015-07-29 13:07:41 -0700521 __builtin__.testthread = False
adminbae64d82013-08-01 10:50:15 -0700522
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700523 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000524 '''
adminbae64d82013-08-01 10:50:15 -0700525 Will pause the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000526 '''
Jon Hall1306a562015-09-04 11:21:24 -0700527 if not cli.pause:
528 print "Will pause the test's execution, after completion of this step.....\n\n\n\n"
529 cli.pause = True
530 self._stopevent.set()
531 elif cli.pause and self.is_stop:
532 print "KeyboardInterrupt, Exiting."
533 self.test_on.exit()
534 else:
535 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
536 result = self.test_on.cleanup()
537 self.is_stop = True
adminbae64d82013-08-01 10:50:15 -0700538
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700539 def play( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000540 '''
adminbae64d82013-08-01 10:50:15 -0700541 Will resume the paused test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000542 '''
adminbae64d82013-08-01 10:50:15 -0700543 self._stopevent.clear()
544 cli.pause = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700545
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700546 def stop( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000547 '''
adminbae64d82013-08-01 10:50:15 -0700548 Will stop the test execution.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000549 '''
550
adminbae64d82013-08-01 10:50:15 -0700551 print "Stopping the test"
552 self.is_stop = True
553 cli.stop = True
554 __builtin__.testthread = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700555
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700556def output( msg ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000557 '''
adminbae64d82013-08-01 10:50:15 -0700558 Simply, print the message in console
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000559 '''
adminbae64d82013-08-01 10:50:15 -0700560 print msg
561
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700562def error( msg ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000563 '''
adminbae64d82013-08-01 10:50:15 -0700564 print the error message.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000565 '''
adminbae64d82013-08-01 10:50:15 -0700566 print msg
567
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700568def dictToObj( dictionary ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000569 '''
adminbae64d82013-08-01 10:50:15 -0700570 This will facilitates the converting of the dictionary to the object.
571 This method will help to send options as object format to the test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000572 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700573 if isinstance( dictionary, list ):
574 dictionary = [ dictToObj( x ) for x in dictionary ]
575 if not isinstance( dictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700576 return dictionary
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700577
578 class Convert( object ):
adminbae64d82013-08-01 10:50:15 -0700579 pass
580 obj = Convert()
581 for k in dictionary:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700582 obj.__dict__[ k ] = dictToObj( dictionary[ k ] )
adminbae64d82013-08-01 10:50:15 -0700583 return obj
584
585
586if __name__ == '__main__':
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700587 if len( sys.argv ) > 1:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700588 __builtin__.COLORS = True
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700589 CLI( "test" ).onecmd( ' '.join( sys.argv[ 1: ] ) )
adminbae64d82013-08-01 10:50:15 -0700590 else:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700591 __builtin__.COLORS = False
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700592 CLI( "test" ).cmdloop()