blob: 978c206b2db9b0a92fa21b36bd1eaf046aeade8c [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 22-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
Jon Hall65844a32015-03-09 19:09:37 -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 Hall65844a32015-03-09 19:09:37 -070021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
23
24
25teston is the main module.
26
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000027'''
28
adminbae64d82013-08-01 10:50:15 -070029import sys
30import getpass
31import os
32import re
33import __builtin__
34import new
35import xmldict
Jon Hall30b82fa2015-03-04 17:15:43 -080036import importlib
Jon Hall5b586732015-06-11 11:39:39 -070037import threading
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -070038import pdb
Jon Hall714eeba2015-09-29 17:53:10 -070039module = new.module( "test" )
adminbae64d82013-08-01 10:50:15 -070040import openspeak
Hari Krishnabe4b97b2015-07-15 12:19:43 -070041import subprocess
Jon Hall714eeba2015-09-29 17:53:10 -070042global path, drivers_path, core_path, tests_path, logs_path
Jon Hall44506242015-07-29 17:40:26 -070043location = os.path.abspath( os.path.dirname( __file__ ) )
44path = re.sub( "(core|bin)$", "", location )
Jon Hall714eeba2015-09-29 17:53:10 -070045drivers_path = path + "drivers"
46core_path = path + "core"
47tests_path = path + "tests"
48logs_path = path + "logs/"
adminbae64d82013-08-01 10:50:15 -070049config_path = path + "config/"
Jon Hall44506242015-07-29 17:40:26 -070050sys.path.append( path )
51sys.path.append( drivers_path )
52sys.path.append( core_path )
53sys.path.append( tests_path )
adminbae64d82013-08-01 10:50:15 -070054
55from core.utilities import Utilities
kelvin-onlabfb521662015-02-27 09:52:40 -080056from core.Thread import Thread
adminbae64d82013-08-01 10:50:15 -070057
Jon Hallca319892017-06-15 15:25:22 -070058class SkipCase( Exception ):
59 pass
60
adminbae64d82013-08-01 10:50:15 -070061class TestON:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000062 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -070063 TestON will initiate the specified test.
Jon Hall714eeba2015-09-29 17:53:10 -070064 The main tasks are:
kelvin-onlabf70fd542015-05-07 18:41:40 -070065 * Initiate the required Component handles for the test.
adminbae64d82013-08-01 10:50:15 -070066 * Create Log file Handles.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000067 '''
Jon Hall714eeba2015-09-29 17:53:10 -070068 def __init__( self, options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000069 '''
Jon Hall714eeba2015-09-29 17:53:10 -070070 Initialise the component handles specified in the topology file of
71 the specified test.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +000072 '''
adminbae64d82013-08-01 10:50:15 -070073 # Initialization of the variables.
74 __builtin__.main = self
adminbae64d82013-08-01 10:50:15 -070075 __builtin__.path = path
76 __builtin__.utilities = Utilities()
77 self.TRUE = 1
78 self.FALSE = 0
79 self.ERROR = -1
kelvin-onlabf70fd542015-05-07 18:41:40 -070080 self.NORESULT = 2
adminbae64d82013-08-01 10:50:15 -070081 self.FAIL = False
82 self.PASS = True
kelvin-onlabf70fd542015-05-07 18:41:40 -070083 self.CASERESULT = self.ERROR
84 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -070085 self.init_result = self.TRUE
86 self.testResult = "Summary"
kelvin-onlabf70fd542015-05-07 18:41:40 -070087 self.stepName = ""
88 self.stepCache = ""
Jon Halld61331b2015-02-17 16:35:47 -080089 self.EXPERIMENTAL_MODE = False
adminbae64d82013-08-01 10:50:15 -070090 self.test_target = None
91 self.lastcommand = None
Jon Halld61331b2015-02-17 16:35:47 -080092 self.testDir = tests_path
Jon Halld74d2952018-03-01 13:26:39 -080093 self.testsRoot = tests_path
Jon Halld61331b2015-02-17 16:35:47 -080094 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070095 self.parsingClass = "xmlparser"
96 self.parserPath = core_path + "/xmlparser"
97 self.loggerPath = core_path + "/logger"
98 self.loggerClass = "Logger"
99 self.logs_path = logs_path
100 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -0800101 self.Thread = Thread
Jon Hall5b586732015-06-11 11:39:39 -0700102 self.cleanupFlag = False
103 self.cleanupLock = threading.Lock()
Jon Hall0fc0d452015-07-14 09:49:58 -0700104 self.initiated = False
Devin Limec989792017-08-15 15:57:55 -0700105 self.executedCase = []
106 self.leftCase = []
107 self.failedCase = []
108 self.noResultCase = []
Jon Hall65844a32015-03-09 19:09:37 -0700109
Jon Hall25079782015-10-13 13:54:39 -0700110 self.config = self.configparser()
Jon Hall714eeba2015-09-29 17:53:10 -0700111 verifyOptions( options )
adminbae64d82013-08-01 10:50:15 -0700112 load_logger()
113 self.componentDictionary = {}
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700114 self.componentDictionary = self.topology[ 'COMPONENT' ]
Jon Hall714eeba2015-09-29 17:53:10 -0700115 self.driversList = []
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700116 if isinstance( self.componentDictionary, str ):
Jon Hall714eeba2015-09-29 17:53:10 -0700117 self.componentDictionary = dict( self.componentDictionary )
Jon Hall65844a32015-03-09 19:09:37 -0700118
Jon Hall714eeba2015-09-29 17:53:10 -0700119 for component in self.componentDictionary:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700120 self.driversList.append( self.componentDictionary[ component ][ 'type' ] )
Jon Hall65844a32015-03-09 19:09:37 -0700121
Jon Hall714eeba2015-09-29 17:53:10 -0700122 self.driversList = list( set( self.driversList ) ) # Removing duplicates.
adminbae64d82013-08-01 10:50:15 -0700123 # Checking the test_target option set for the component or not
Jon Hall714eeba2015-09-29 17:53:10 -0700124 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700125 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700126 if 'test_target' in self.componentDictionary[ component ].keys():
adminbae64d82013-08-01 10:50:15 -0700127 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700128
Jon Halld61331b2015-02-17 16:35:47 -0800129 # Checking for the openspeak file and test script
Jon Hall714eeba2015-09-29 17:53:10 -0700130 self.logger.initlog( self )
adminbae64d82013-08-01 10:50:15 -0700131
132 # Creating Drivers Handles
Jon Hall714eeba2015-09-29 17:53:10 -0700133 initString = "\n" + "*" * 30 + "\n CASE INIT \n" + "*" * 30 + "\n"
134 self.log.exact( initString )
adminbae64d82013-08-01 10:50:15 -0700135 self.driverObject = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700136 self.random_order = 111 # Random order id to connect the components
adminbae64d82013-08-01 10:50:15 -0700137 components_connect_order = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700138 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700139 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700140 if 'connect_order' not in self.componentDictionary[ component ].keys():
141 self.componentDictionary[ component ][ 'connect_order' ] = str( self.get_random() )
142 components_connect_order[ component ] = eval( self.componentDictionary[ component ][ 'connect_order' ] )
Jon Hall714eeba2015-09-29 17:53:10 -0700143 # Ordering components based on the connect order.
144 ordered_component_list = sorted( components_connect_order,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700145 key=lambda key: components_connect_order[ key ] )
adminbae64d82013-08-01 10:50:15 -0700146 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700147 for component in ordered_component_list:
Jon Hall714eeba2015-09-29 17:53:10 -0700148 self.componentInit( component )
adminbae64d82013-08-01 10:50:15 -0700149
Jon Hall714eeba2015-09-29 17:53:10 -0700150 def configparser( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000151 '''
152 It will parse the config file (teston.cfg) and return as dictionary
153 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700154 matchFileName = re.match( r'(.*)\.cfg', self.configFile, re.M | re.I )
adminbae64d82013-08-01 10:50:15 -0700155 if matchFileName:
Jon Hall714eeba2015-09-29 17:53:10 -0700156 xml = open( self.configFile ).read()
157 try:
158 self.configDict = xmldict.xml_to_dict( xml )
adminbae64d82013-08-01 10:50:15 -0700159 return self.configDict
Jon Hall1306a562015-09-04 11:21:24 -0700160 except IOError:
adminbae64d82013-08-01 10:50:15 -0700161 print "There is no such file to parse " + self.configFile
Jon Hall1306a562015-09-04 11:21:24 -0700162 else:
163 print "There is no such file to parse " + self.configFile
kelvin-onlabf70fd542015-05-07 18:41:40 -0700164
Jon Hall714eeba2015-09-29 17:53:10 -0700165 def componentInit( self, component ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000166 '''
adminbae64d82013-08-01 10:50:15 -0700167 This method will initialize specified component
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000168 '''
adminbae64d82013-08-01 10:50:15 -0700169 global driver_options
Jon Hall0fc0d452015-07-14 09:49:58 -0700170 self.initiated = False
Jon Hall714eeba2015-09-29 17:53:10 -0700171 self.log.info( "Creating component Handle: " + component )
Jon Halld61331b2015-02-17 16:35:47 -0800172 driver_options = {}
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700173 if 'COMPONENTS' in self.componentDictionary[ component ].keys():
174 driver_options = dict( self.componentDictionary[ component ][ 'COMPONENTS' ] )
175 driver_options[ 'name' ] = component
176 driverName = self.componentDictionary[ component ][ 'type' ]
177 driver_options[ 'type' ] = driverName
kelvin-onlabf70fd542015-05-07 18:41:40 -0700178
Jon Hall714eeba2015-09-29 17:53:10 -0700179 classPath = self.getDriverPath( driverName.lower() )
180 driverModule = importlib.import_module( classPath )
181 driverClass = getattr( driverModule, driverName )
adminbae64d82013-08-01 10:50:15 -0700182 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700183
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700184 if "OCN" in self.componentDictionary[ component ][ 'host' ] and\
Jon Hall714eeba2015-09-29 17:53:10 -0700185 main.onoscell:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700186 self.componentDictionary[ component ][ 'host' ] = main.mnIP
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700187
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700188 user_name = self.componentDictionary[ component ].get( 'user', getpass.getuser() )
189 ip_address = self.componentDictionary[ component ].get( 'host', 'localhost' )
190 pwd = self.componentDictionary[ component ].get( 'password', 'changeme' )
191 port = self.componentDictionary[ component ].get( 'port' )
Jon Hall714eeba2015-09-29 17:53:10 -0700192 connect_result = driverObject.connect( user_name=user_name,
193 ip_address=ip_address,
194 pwd=pwd,
195 port=port,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700196 options=driver_options )
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700197
adminbae64d82013-08-01 10:50:15 -0700198 if not connect_result:
Jon Hall714eeba2015-09-29 17:53:10 -0700199 self.log.error( "Exiting from the test execution because connecting to the " +
200 component + " component failed." )
Jon Halld61331b2015-02-17 16:35:47 -0800201 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700202
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700203 vars( self )[ component ] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700204 self.initiated = True
Jon Hallca319892017-06-15 15:25:22 -0700205 return driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700206
Jon Hall714eeba2015-09-29 17:53:10 -0700207 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000208 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700209 The Execution of the test script's cases listed in the Test params
210 file will be done here then update each test case result.
211 This method will return main.TRUE if it executed all the test cases
212 successfully, else will retun main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000213 '''
adminbae64d82013-08-01 10:50:15 -0700214 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700215 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700216 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800217 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700218 self.TOTAL_TC_NORESULT = 0
219 self.TOTAL_TC_FAIL = 0
220 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700221 self.TEST_ITERATION = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700222
223 # NOTE: number of main.step statements in the
224 # outer most level of the test case. used to
225 # execute code in smaller steps
226 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700227 self.CASERESULT = self.NORESULT
228
Jon Halld61331b2015-02-17 16:35:47 -0800229 import testparser
Jon Hall53c5e662016-04-13 16:06:56 -0700230 test = testparser.TestParser( main.testFile )
adminbae64d82013-08-01 10:50:15 -0700231 self.testscript = test.testscript
232 self.code = test.getStepCode()
Jon Hall714eeba2015-09-29 17:53:10 -0700233 repeat = int( self.params.get( 'repeat', 1 ) )
234 self.TOTAL_TC_PLANNED = len( self.testcases_list ) * repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700235
adminbae64d82013-08-01 10:50:15 -0700236 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700237 while repeat:
Devin Limec989792017-08-15 15:57:55 -0700238 self.leftCase.extend( self.testcases_list )
Jon Halla1185982014-09-15 14:55:10 -0700239 for self.CurrentTestCaseNumber in self.testcases_list:
Devin Limec989792017-08-15 15:57:55 -0700240 self.executedCase.append( self.leftCase.pop( 0 ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700241 result = self.runCase( self.CurrentTestCaseNumber )
242 repeat -= 1
adminbae64d82013-08-01 10:50:15 -0700243 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700244
Jon Halle234cc42015-08-31 15:26:47 -0700245 def runCase( self, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700246 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700247 self.CurrentTestCase = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700248
249 # List of step results in a case. ANDed together to get the result
250 self.stepResultsList = []
kelvin-onlabf70fd542015-05-07 18:41:40 -0700251 self.stepName = ""
Jon Hall783bbf92015-07-23 14:33:19 -0700252 self.caseExplanation = ""
adminbae64d82013-08-01 10:50:15 -0700253 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700254
255 # NOTE: number of main.step statements in the
256 # outer most level of the test case. used to
257 # execute code in smaller steps
258 self.stepCount = 0
259
260 # NOTE: This is the current number of main.step()'s executed
261 # in a case. Used for logging.
262 self.stepNumber = 0
adminbae64d82013-08-01 10:50:15 -0700263 self.EXPERIMENTAL_MODE = self.FALSE
264 self.addCaseHeader()
Devin Limec989792017-08-15 15:57:55 -0700265 self.log.debug( "Case Executed : " + str( self.executedCase ) )
266 self.log.debug( "Case to be executed : " + str( self.leftCase ) )
Jon Halle234cc42015-08-31 15:26:47 -0700267 self.testCaseNumber = str( testCaseNumber )
268 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700269 stopped = False
Jon Hall5a72b712015-09-28 12:20:59 -0700270 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700271 self.code[ self.testCaseNumber ]
Jon Halld61331b2015-02-17 16:35:47 -0800272 except KeyError:
Jon Halle234cc42015-08-31 15:26:47 -0700273 self.log.error( "There is no Test-Case " + self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800274 return self.FALSE
adminbae64d82013-08-01 10:50:15 -0700275 self.stepCount = 0
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700276 while self.stepCount < len( self.code[ self.testCaseNumber ].keys() ):
Jon Hall714eeba2015-09-29 17:53:10 -0700277 result = self.runStep( self.code, self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800278 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700279 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800280 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700281 continue
Jon Hall5a72b712015-09-28 12:20:59 -0700282 # stepResults format: ( stepNo[], stepName[], stepResult[], onFail[] )
283 stepResults = self.stepResultsList
Jon Halle234cc42015-08-31 15:26:47 -0700284 if not stopped:
285 if self.CASERESULT == self.TRUE or self.CASERESULT == self.FALSE:
Jon Hall714eeba2015-09-29 17:53:10 -0700286 # Result was already explitily set somewhere else like
287 # in skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700288 pass
Jon Hall5a72b712015-09-28 12:20:59 -0700289 elif all( self.TRUE == i for i in stepResults ):
kelvin-onlabf70fd542015-05-07 18:41:40 -0700290 # ALL PASSED
291 self.CASERESULT = self.TRUE
Jon Hall5a72b712015-09-28 12:20:59 -0700292 elif self.FALSE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700293 # AT LEAST ONE FAILED
294 self.CASERESULT = self.FALSE
Jon Hall5a72b712015-09-28 12:20:59 -0700295 elif self.TRUE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700296 # AT LEAST ONE PASSED
297 self.CASERESULT = self.TRUE
298 else:
299 self.CASERESULT = self.NORESULT
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700300 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.CASERESULT
Devin Limec989792017-08-15 15:57:55 -0700301 self.organizeResult( self.CurrentTestCaseNumber, self.CASERESULT )
Jon Hall714eeba2015-09-29 17:53:10 -0700302 self.logger.updateCaseResults( self )
Jon Hall783bbf92015-07-23 14:33:19 -0700303 self.log.wiki( "<p>" + self.caseExplanation + "</p>" )
304 self.log.summary( self.caseExplanation )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700305 self.log.wiki( "<ul>" )
acsmarse2d1ed12015-10-05 13:51:17 -0700306 subcaseMessage = False
kelvin-onlabf70fd542015-05-07 18:41:40 -0700307 for line in self.stepCache.splitlines():
acsmarse2d1ed12015-10-05 13:51:17 -0700308 if re.search( "[0-9]\.[0-9]", line ): # Step
309 if subcaseMessage: # End of Failure Message Printout
310 self.log.wiki( "</ul>\n" )
311 subcaseMessage = False
312 if re.search( " - PASS$", line ):
313 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
314 elif re.search( " - FAIL$", line ):
315 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
316 elif re.search( " - No Result$", line ):
317 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
318 else: # Substep
319 if not subcaseMessage: # Open Failure Message Printout
320 self.log.wiki( "<ul><li>" + line + "</li>\n" )
321 subcaseMessage = True
322 else: # Add to Failure Message Printout
323 self.log.wiki( "<li>" + line + "</li>\n" )
acsmars27e62dd2015-10-06 11:35:47 -0700324 if subcaseMessage: # End of Failure Message Printout for last item
325 self.log.wiki( "</ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700326 self.log.wiki( "</ul>" )
327 self.log.summary( self.stepCache )
328 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700329 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700330
Devin Limec989792017-08-15 15:57:55 -0700331 def organizeResult( self, caseNum, result ):
332 """
333 Organize the result and put the current number into either
334 failed/noResult lists.
335 * caseNum - number of the case
336 * result - result of the case
337 """
338 if result == main.FALSE:
339 self.failedCase.append( caseNum )
340 elif result == self.NORESULT:
341 self.noResultCase.append( caseNum )
342
Jon Hall714eeba2015-09-29 17:53:10 -0700343 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700344 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700345 try:
346 step = self.stepCount
347 # stepResults format: ( stepNo, stepName, stepResult, onFail )
348 # NOTE: This is needed to catch results of main.step()'s
349 # called inside functions or loops
350 self.stepResults = ( [], [], [], [] )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700351 exec code[ testCaseNumber ][ step ] in module.__dict__
adminbae64d82013-08-01 10:50:15 -0700352 self.stepCount = self.stepCount + 1
Jon Hall96b816f2015-11-03 12:00:56 -0800353 self.parseStepResults( testCaseNumber )
Jon Hallca319892017-06-15 15:25:22 -0700354 except SkipCase: # Raised in self.skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700355 self.log.warn( "Skipping the rest of CASE" +
356 str( testCaseNumber ) )
Jon Hall96b816f2015-11-03 12:00:56 -0800357 self.parseStepResults( testCaseNumber )
Jon Hall714eeba2015-09-29 17:53:10 -0700358 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700359 self.stepCache += "\t\t" + self.onFailMsg + "\n"
360 self.stepCount = self.stepCount + 1
361 return self.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000362 except StandardError as e:
Jon Hallc1606352015-10-06 14:51:36 -0700363 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700364 stepNo = self.stepResults[ 0 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700365 except IndexError:
366 stepNo = "<IndexError>"
367 main.log.warn( "Error trying to get step number. " +
368 "It is likely between step " +
Jon Hall6e709752016-02-01 13:38:46 -0800369 str( self.stepNumber ) + " and step " +
Jon Hallc1606352015-10-06 14:51:36 -0700370 str( self.stepNumber + 1 ) )
371 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700372 stepName = self.stepResults[ 1 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700373 except IndexError:
374 stepName = "<IndexError>"
375 self.log.error( "\nException in the following section of" +
376 " code: " + str( testCaseNumber ) + "." +
377 str( stepNo ) + ": " + stepName )
Jeremyd9e4eb12016-04-13 12:09:06 -0700378 self.log.error( str( e.__class__ ) + str( e.message ) )
adminbae64d82013-08-01 10:50:15 -0700379 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700380 self.logger.updateCaseResults( self )
381 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700382 self.log.wiki( "<ul>" )
383 for line in self.stepCache.splitlines():
384 if re.search( " - PASS$", line ):
385 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
386 elif re.search( " - FAIL$", line ):
387 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
388 elif re.search( " - No Result$", line ):
389 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700390 else: # Should only be on fail message
391 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700392 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700393 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700394 self.log.summary( self.stepCache )
395 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700396 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700397 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700398 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700399 if cli.stop:
400 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700401 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700402 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = "Stopped"
Jon Hall714eeba2015-09-29 17:53:10 -0700403 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700404 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700405 return self.FALSE
406
Jon Hall96b816f2015-11-03 12:00:56 -0800407 def parseStepResults( self, testCaseNumber ):
408 """
409 Parse throught the step results for the wiki
410 """
411 try:
412 # Iterate through each of the steps and print them
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700413 for index in range( len( self.stepResults[ 0 ] ) ):
Jon Hall96b816f2015-11-03 12:00:56 -0800414 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700415 stepNo = self.stepResults[ 0 ][ index ]
416 stepName = self.stepResults[ 1 ][ index ]
417 stepResult = self.stepResults[ 2 ][ index ]
418 onFail = self.stepResults[ 3 ][ index ]
Jon Hall96b816f2015-11-03 12:00:56 -0800419 self.stepCache += "\t" + str( testCaseNumber ) + "."
420 self.stepCache += str( stepNo ) + " "
421 self.stepCache += stepName + " - "
422 if stepResult == self.TRUE:
423 self.stepCache += "PASS\n"
424 elif stepResult == self.FALSE:
425 self.stepCache += "FAIL\n"
426 self.stepCache += "\t\t" + onFail + "\n"
427 else:
428 self.stepCache += "No Result\n"
429 self.stepResultsList.append( stepResult )
430 except Exception:
431 self.log.exception( "Error parsing step results" )
432
Jon Halle234cc42015-08-31 15:26:47 -0700433 def skipCase( self, result="DEFAULT", msg=None ):
434 """
435 Will skip the rest of the code in a test case. The case results will be
436 determined as normal based on completed assertions unless the result
437 argument is given.
438
439 Optional Arguments:
Jon Hall7c4f4302016-07-15 14:39:02 -0700440 result: Case insensitive string. Can be 'PASS' or 'FAIL' and will set
Jon Halle234cc42015-08-31 15:26:47 -0700441 the case result accordingly.
442 msg: Message to be printed when the case is skipped in the reports.
443 """
444 result = result.upper().strip()
445 if result == "PASS":
446 self.CASERESULT = self.TRUE
447 elif result == "FAIL":
448 self.CASERESULT = self.FALSE
449 self.onFailMsg = "Skipping the rest of this case. "
450 if msg:
451 self.onFailMsg += str( msg )
Jon Hallca319892017-06-15 15:25:22 -0700452 raise SkipCase
kelvin-onlabf70fd542015-05-07 18:41:40 -0700453
Jon Hall714eeba2015-09-29 17:53:10 -0700454 def addCaseHeader( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700455 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700456 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
457 self.log.exact( caseHeader )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700458 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700459 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700460 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700461 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700462
Jon Hall714eeba2015-09-29 17:53:10 -0700463 def addCaseFooter( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700464 stepNo = self.stepResults[ 0 ][ -2 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700465 if stepNo > 0:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700466 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700467 str( stepNo ) + ": " + str( self.stepName )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700468 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep + \
Jon Hall714eeba2015-09-29 17:53:10 -0700469 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700470
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700471 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700472 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700473
adminbae64d82013-08-01 10:50:15 -0700474 for driver in self.driversList:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700475 vars( self )[ driver ].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700476
Devin Limba37cdd2018-05-07 11:41:05 -0700477 def setCheckingPoint( self ):
478 '''
479 Using when running findPatchScript.sh. This function needs to be placed
480 on the point that has the problem.
481
482 For example, if you see unusual behavior or from the portion of the code,
483 this is where you need to put with the conditional statement.
484 If some of the latency result is much greater than usual, have if statement
485 that checks if the result is greater than some point and include this function.
486
487 This will mark the 0 to findPatchResult.txt in /tmp/ and exit the test.
488 Then from findPatchScript, it will move onto the next commit and re-run the
489 test.
490 '''
491 self.log.error( "Reached to the checking point. Will mark the result and exit the test" )
492 resultFile = open( "/tmp/findPatchResult.txt", "w" )
493 resultFile.write( "0" )
494 resultFile.close()
495 self.cleanAndExit()
496
Jon Hall714eeba2015-09-29 17:53:10 -0700497 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000498 '''
Jon Hall5b586732015-06-11 11:39:39 -0700499 Print a summary of the current test's results then attempt to release
500 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700501
Jon Hall5b586732015-06-11 11:39:39 -0700502 This function shouldbe threadsafe such that cleanup will only be
503 executed once per test.
504
505 This will return TRUE if all the component handles and log handles
506 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000507 '''
adminbae64d82013-08-01 10:50:15 -0700508 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700509 lock = self.cleanupLock
510 if lock.acquire( False ):
511 try:
512 if self.cleanupFlag is False: # First thread to run this
513 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700514 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700515 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700516 components = self.componentDictionary
517 for component in sorted( components,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700518 key=lambda item: components[ item ][ 'connect_order' ],
Jon Hall892818c2015-10-20 17:58:34 -0700519 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700520 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700521 tempObject = vars( self )[ component ]
522 print "Disconnecting from " + str( tempObject.name ) + \
523 ": " + str( tempObject.__class__ )
Jon Hall5b586732015-06-11 11:39:39 -0700524 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700525 except KeyboardInterrupt:
526 pass
527 except KeyError:
528 # Component not created yet
529 self.log.warn( "Could not find the component " +
530 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000531 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700532 self.log.exception( "Exception while disconnecting from " +
533 str( component ) )
534 result = self.FALSE
535 # Closing all the driver's session files
536 for driver in self.componentDictionary.keys():
537 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700538 vars( self )[ driver ].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700539 except KeyboardInterrupt:
540 pass
541 except KeyError:
542 # Component not created yet
543 self.log.warn( "Could not find the component " +
544 str( driver ) + " while trying to" +
545 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000546 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700547 self.log.exception( "Exception while closing log files for " +
548 str( driver ) )
549 result = self.FALSE
550 else:
551 pass # Someone else already ran through this function
552 finally:
553 lock.release()
554 else: # Someone already has a lock
555 # NOTE: This could cause problems if we don't release the lock
556 # correctly
557 lock.acquire() # Wait for the other thread to finish
558 # NOTE: If we don't wait, exit could be called while the thread
559 # with the lock is still cleaning up
560 lock.release()
adminbae64d82013-08-01 10:50:15 -0700561 return result
Jon Halld61331b2015-02-17 16:35:47 -0800562
Jon Hall714eeba2015-09-29 17:53:10 -0700563 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000564 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700565 This function will pause the test's execution, and will continue after
566 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000567 '''
adminbae64d82013-08-01 10:50:15 -0700568 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700569
Jon Hall714eeba2015-09-29 17:53:10 -0700570 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000571 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700572 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000573 '''
adminbae64d82013-08-01 10:50:15 -0700574 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700575 try:
adminbae64d82013-08-01 10:50:15 -0700576 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700577 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700578 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000579 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700580 print str( e )
adminbae64d82013-08-01 10:50:15 -0700581 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700582 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700583 try:
adminbae64d82013-08-01 10:50:15 -0700584 for component in components:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700585 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700586 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000587 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700588 print str( e )
adminbae64d82013-08-01 10:50:15 -0700589 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700590
Jon Hall714eeba2015-09-29 17:53:10 -0700591 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000592 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700593 Based on the component 'type' specified in the params , this method
594 will find the absolute path, by recursively searching the name of
595 the component.
596
597 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000598 '''
adminbae64d82013-08-01 10:50:15 -0700599 import commands
600
Jon Hall714eeba2015-09-29 17:53:10 -0700601 cmd = "find " + drivers_path + " -name " + driverName + ".py"
602 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700603
Jon Hall714eeba2015-09-29 17:53:10 -0700604 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700605 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700606
adminbae64d82013-08-01 10:50:15 -0700607 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700608 result_count = result_count + 1
609 if result_count > 1:
610 print "Found " + driverName + " " + str( result_count ) + " times:"
611 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700612 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700613
Jon Hall714eeba2015-09-29 17:53:10 -0700614 result = re.sub( "(.*)drivers", "", result )
615 result = re.sub( "\/\/", "/", result )
616 result = re.sub( "\.py", "", result )
617 result = re.sub( "\.pyc", "", result )
618 result = re.sub( "\/", ".", result )
619 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700620 return result
adminbae64d82013-08-01 10:50:15 -0700621
Jon Hall714eeba2015-09-29 17:53:10 -0700622 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000623 '''
adminbae64d82013-08-01 10:50:15 -0700624 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000625 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700626 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700627 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700628 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700629 self.stepNumber += 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700630 self.stepResults[ 0 ].append( self.stepNumber )
631 self.stepResults[ 1 ].append( stepDesc )
632 self.stepResults[ 2 ].append( self.NORESULT )
633 self.stepResults[ 3 ].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700634
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700635 stepName = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700636 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700637 self.log.step( stepName )
adminbae64d82013-08-01 10:50:15 -0700638 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700639 line = "\n" + "-" * 45 + "\n"
640 if self.stepNumber > 1:
641 stepHeader = line + "End of Step " + previousStep + line
642 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700643 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700644 vars( self )[ driver + 'log' ].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700645
Jon Hall714eeba2015-09-29 17:53:10 -0700646 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000647 '''
adminbae64d82013-08-01 10:50:15 -0700648 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000649 '''
Jon Halld61331b2015-02-17 16:35:47 -0800650 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700651 testCaseName = " " + str( testCaseName )
652 self.log.case( testCaseName )
653 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700654 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700655 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700656
Jon Hall714eeba2015-09-29 17:53:10 -0700657 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000658 '''
adminbae64d82013-08-01 10:50:15 -0700659 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000660 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700661 description = "Test Description : " + str( description )
662 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700663
Jon Hall714eeba2015-09-29 17:53:10 -0700664 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000665 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700666 This method will parse the test script to find required test
667 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000668 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700669 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700670 testFileList = testFileHandler.readlines()
671 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700672 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700673 for index in range( len( testFileList ) ):
674 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700675 testFileList[ index ],
Jon Hall714eeba2015-09-29 17:53:10 -0700676 0 )
adminbae64d82013-08-01 10:50:15 -0700677 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700678 counter = counter + 1
679 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700680
Jon Hall714eeba2015-09-29 17:53:10 -0700681 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000682 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700683 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700684 response_dict = self.response_to_dict( response, return_format )
685 return_format_string = self.dict_to_return_format( response,
686 return_format,
687 response_dict )
adminbae64d82013-08-01 10:50:15 -0700688 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700689
Jon Hall714eeba2015-09-29 17:53:10 -0700690 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700691 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700692 json_match = re.search( '^\s*{', response )
693 xml_match = re.search( '^\s*\<', response )
694 ini_match = re.search( '^\s*\[', response )
695 if json_match:
696 self.log.info( "Response is in 'JSON' format, converting to '" +
697 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800698 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000699 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700700 response = re.sub( r",\s*'?(\w)", r',"\1', response )
701 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
702 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
703 try:
adminbae64d82013-08-01 10:50:15 -0700704 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700705 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000706 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700707 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700708 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700709 elif ini_match:
710 self.log.info( "Response is in 'INI' format, converting to '" +
711 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700712 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700713 response_file = open( "respnse_file.temp", 'w' )
714 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800715 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700716 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700717 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700718 elif xml_match:
719 self.log.info( "Response is in 'XML' format, converting to '" +
720 return_format + "' format" )
721 try:
722 response_dict = xmldict.xml_to_dict( "<response> " +
723 str( response ) +
724 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000725 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700726 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700727 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700728
Jon Hall714eeba2015-09-29 17:53:10 -0700729 def dict_to_return_format( self, response, return_format, response_dict ):
730 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000731 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700732 to_do = "Call the table output formatter"
733 global response_table
734 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700735 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700736
Jon Hall714eeba2015-09-29 17:53:10 -0700737 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000738 ''' This will parse the dictionary recusrsively and print as
739 table format'''
adminbae64d82013-08-01 10:50:15 -0700740 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700741 if isinstance( value_to_convert, dict ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700742 table_data = table_data + '\t'.join( value_to_convert ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700743 "\n"
744 for temp_val in value_to_convert.values():
745 table_data = table_data + get_table( temp_val )
746 else:
747 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800748 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700749
Jon Hall714eeba2015-09-29 17:53:10 -0700750 for value in response_dict.values():
751 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700752 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700753
Jon Hall714eeba2015-09-29 17:53:10 -0700754 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000755 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700756 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700757 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700758 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700759 response_config = re.sub( ",", "\n\t", response_string )
760 response_config = re.sub( "u\'", "\'", response_config )
761 response_config = re.sub( "{", "", response_config )
762 response_config = re.sub( "}", "\n", response_config )
763 response_config = re.sub( ":", " =", response_config )
764 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700765 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000766 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700767 response_xml = xmldict.dict_to_xml( response_dict )
768 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
769 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700770 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000771 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700772 to_do = 'Call dict to xml coverter'
773 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700774 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700775 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700776
Jon Hall714eeba2015-09-29 17:53:10 -0700777 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700778 self.random_order = self.random_order + 1
779 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700780
Jon Hall714eeba2015-09-29 17:53:10 -0700781 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700782 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700783 for thread in threading.enumerate():
784 if thread.isAlive():
785 try:
786 thread._Thread__stop()
787 except:
Jon Hall1306a562015-09-04 11:21:24 -0700788 # NOTE: We should catch any exceptions while trying to
789 # close the thread so that we can try to close the other
790 # threads as well
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700791 print str( thread.getName() ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700792 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700793 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700794 sys.exit()
795
Devin Lim44075962017-08-11 10:56:37 -0700796 def cleanAndExit( self ):
797 """
798 It will set the testcase result to be FAILED and update it
799 before cleaning up and exitting the test.
800 :return:
801 """
802 if self.CurrentTestCaseNumber:
803 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700804 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700805 self.logger.updateCaseResults( self )
806 self.cleanup()
807 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700808
Jon Hallcd3d2a32015-10-01 11:07:28 -0700809 def stop( self, email=False ):
810 """
811 Stop the test until Ctrl-D is entered.
812 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700813
814 Optional arguments:
815 email can either be a bool, or you can specify the email address
816 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700817 """
818 try:
819 if email:
Jon Hall25079782015-10-13 13:54:39 -0700820 if '@' in email:
821 main.mail = email
822 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700823 self.log.debug( "Test execution suspended. \n"
824 "- Type 'c' to resume the test.\n"
825 "- Type Ctrl-C to exit the test.\n"
826 "- Enter interactive python interpreter commands.\n"
827 "\t- ie: main.Mininet1.pingall()\n"
828 "- Type 'help' for help with pdb." )
829 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700830 except EOFError:
831 return
832 # Pass all other exceptions up to caller
833
834
Jon Hall714eeba2015-09-29 17:53:10 -0700835def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000836 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700837 This will verify the command line options and set to default values,
838 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000839 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700840 verifyTest( options )
841 verifyExample( options )
842 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700843 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700844 verifyLogdir( options )
845 verifyMail( options )
846 verifyTestCases( options )
847 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700848
Jon Hall714eeba2015-09-29 17:53:10 -0700849def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700850 try:
851 if options.testname:
852 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700853 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700854 main.tests_path = tests_path
855 elif options.example:
856 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700857 main.tests_path = path + "/examples/"
858 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700859 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700860 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700861 main.exit()
adminbae64d82013-08-01 10:50:15 -0700862
Jon Hall714eeba2015-09-29 17:53:10 -0700863def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700864 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700865 main.testDir = path + '/examples/'
866 main.tests_path = path + "/examples/"
867 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700868
Jon Hall714eeba2015-09-29 17:53:10 -0700869def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800870 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700871 if options.logdir:
872 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700873 else:
Jon Halld61331b2015-02-17 16:35:47 -0800874 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700875
Jon Hall714eeba2015-09-29 17:53:10 -0700876def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700877 # Mail-To: field
878 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700879 main.mail = options.mail
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700880 elif main.params.get( 'mail' ): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700881 main.mail = main.params.get( 'mail' )
882 else: # TestON specific
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700883 main.mail = main.config[ 'config' ].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700884 # Mail-From: field
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700885 main.sender = main.config[ 'config' ].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700886 # Mail smtp server
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700887 main.smtp = main.config[ 'config' ].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700888 # Mail-From account password
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700889 main.senderPwd = main.config[ 'config' ].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700890
Devin Lim2df68a12017-06-30 15:39:05 -0700891def evalTestCase( tempList ):
892 tList = []
893 for tcase in tempList:
894 if isinstance( tcase, list ):
895 tList.extend( evalTestCase( tcase ) )
896 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700897 tList.extend( [ tcase ] )
Devin Lim2df68a12017-06-30 15:39:05 -0700898 return tList
adminbae64d82013-08-01 10:50:15 -0700899
Jon Hall714eeba2015-09-29 17:53:10 -0700900def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800901 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700902 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800903 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800904 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700905 testcases_list = re.sub( "(\[|\])", "", options.testcases )
906 main.testcases_list = eval( testcases_list + "," )
907 else:
adminbae64d82013-08-01 10:50:15 -0700908 if 'testcases' in main.params.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700909 temp = eval( main.params[ 'testcases' ] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700910 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700911 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700912 print "Testcases not specifed in params, please provide in " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700913 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800914 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700915
Jon Hall714eeba2015-09-29 17:53:10 -0700916def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700917 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700918 if options.onoscell:
919 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700920 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700921 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700922 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700923 output = subprocess.check_output( [ "bash", '-c', cellCMD ] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700924 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700925 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700926 for i in range( len( splitOutput ) ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700927 if re.match( "OCN", splitOutput[ i ] ):
928 mnNode = splitOutput[ i ].split( "=" )
929 main.mnIP = mnNode[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700930 # cell already sorts OC variables in bash, so no need to
931 # sort in TestON
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700932 elif re.match( "OC[1-9]", splitOutput[ i ] ):
933 onosNodes = splitOutput[ i ].split( "=" )
934 main.ONOSip.append( onosNodes[ 1 ] )
935 elif re.match( "ONOS_APPS", splitOutput[ i ] ):
936 main.apps = ( splitOutput[ i ].split( "=" ) )[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700937 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700938 main.onoscell = main.FALSE
939
Jon Hall714eeba2015-09-29 17:53:10 -0700940def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000941 '''
adminbae64d82013-08-01 10:50:15 -0700942 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000943 '''
Jon Halld61331b2015-02-17 16:35:47 -0800944 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700945 directory = main.testDir + "/" + main.TEST
946 if os.path.exists( directory ):
947 pass
948 else:
949 directory = ""
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700950 for root, dirs, files in os.walk( main.testDir, topdown=True ):
Jon Hall53c5e662016-04-13 16:06:56 -0700951 if not directory:
952 for name in dirs:
953 if name == main.TEST:
954 directory = ( os.path.join( root, name ) )
955 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700956 main.classPath = directory[ index: ].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700957 break
958 openspeakfile = directory + "/" + main.TEST + ".ospk"
Jon Halld74d2952018-03-01 13:26:39 -0800959 main.testDir = directory
Jon Hall53c5e662016-04-13 16:06:56 -0700960 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700961 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700962 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700963 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700964 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700965 # No openspeak found, using python file instead
966 pass
adminbae64d82013-08-01 10:50:15 -0700967 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700968 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " + \
969 "Python or OpenSpeak test script in the tests folder: " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700970 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700971 __builtin__.testthread = None
972 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700973 try:
974 testModule = __import__( main.classPath,
975 globals(),
976 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700977 [ main.TEST ],
Jon Hall714eeba2015-09-29 17:53:10 -0700978 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700979 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700980 print "There was an import error, it might mean that there is " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700981 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800982 main.exit()
adminbae64d82013-08-01 10:50:15 -0700983
Jon Hall714eeba2015-09-29 17:53:10 -0700984 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700985 main.testObject = testClass()
986 load_parser()
Jon Halld74d2952018-03-01 13:26:39 -0800987 main.paramsFile = main.TEST + ".params" if options.paramsFile is None else options.paramsFile
988 main.topoFile = main.TEST + ".topo" if options.topoFile is None else options.topoFile
989 main.params = main.parser.parseFile( main.testDir + "/" + main.paramsFile )
990 main.topology = main.parser.parseFile( main.testDir + "/" + main.topoFile )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700991
YPZhang1c89e762016-06-29 10:43:58 -0700992def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -0700993 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700994 main.params = main.params[ 'PARAMS' ]
Jon Hall1306a562015-09-04 11:21:24 -0700995 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700996 print "Error with the params file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700997 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800998 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700999 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001000 main.topology = main.topology[ 'TOPOLOGY' ]
Jon Hall1306a562015-09-04 11:21:24 -07001001 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001002 print "Error with the Topology file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -07001003 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -07001004 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -07001005 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001006 if len( options.params ) > 0:
YPZhang1c89e762016-06-29 10:43:58 -07001007 # Some params variables are specified from command line
1008 for param in options.params:
1009 if not re.search( ".=.", param ):
1010 print( "Error when parsing params: params should follow key=value format" )
1011 continue
Jon Hall7c4f4302016-07-15 14:39:02 -07001012 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -07001013 [ keys, value ] = param.split( "=" )
1014 # Split the nested keys according to its hierarchy
1015 keyList = keys.split( "/" )
1016 # Get the outermost dictionary
1017 paramDict = main.params
1018 # Get the innermost dictionary
1019 try:
1020 while len( keyList ) > 1:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001021 key = keyList.pop( 0 )
YPZhang1c89e762016-06-29 10:43:58 -07001022 assert isinstance( paramDict[ key ], dict )
1023 paramDict = paramDict[ key ]
1024 except KeyError:
1025 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1026 main.exit()
1027 except AssertionError:
1028 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1029 main.exit()
1030 # Change the value
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001031 if keyList[ 0 ] not in paramDict:
1032 print( "Error when parsing params: key \"" + keyList[ 0 ] + "\" not found in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001033 main.exit()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001034 elif isinstance( paramDict[ keyList[ 0 ] ], dict ):
1035 print( "Error when parsing params: more levels under key \"" + keyList[ 0 ] + "\" in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001036 main.exit()
1037 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001038 paramDict[ keyList[ 0 ] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001039
Jon Hall714eeba2015-09-29 17:53:10 -07001040def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001041 '''
adminbae64d82013-08-01 10:50:15 -07001042 It facilitates the loading customised parser for topology and params file.
1043 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001044 It also loads default xmlparser if no parser have specified in teston.cfg
1045 file.
adminbae64d82013-08-01 10:50:15 -07001046
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001047 '''
adminbae64d82013-08-01 10:50:15 -07001048 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001049 if 'file' in confighash[ 'config' ][ 'parser' ] and\
1050 'class' in confighash[ 'config' ][ 'parser' ]:
1051 path = confighash[ 'config' ][ 'parser' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001052 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001053 confighash[ 'config' ][ 'parser' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001054 try:
1055 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001056 moduleList = module.split( "/" )
1057 newModule = ".".join( moduleList[ -2: ] )
1058 parsingClass = confighash[ 'config' ][ 'parser' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001059 parsingModule = __import__( newModule,
1060 globals(),
1061 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001062 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001063 -1 )
1064 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001065 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001066 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001067 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -07001068 pass
1069 else:
1070 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -07001071 main.exit()
Jon Hall44506242015-07-29 17:40:26 -07001072 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001073 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001074 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001075 load_defaultParser()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001076 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1077 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001078 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -07001079 else:
1080 load_defaultParser()
1081
1082def load_defaultParser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001083 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001084 It will load the default parser which is xml parser to parse the params and
1085 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001086 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001087 moduleList = main.parserPath.split( "/" )
1088 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001089 try:
Jon Halld61331b2015-02-17 16:35:47 -08001090 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -07001091 parsingModule = __import__( newModule,
1092 globals(),
1093 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001094 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001095 -1 )
1096 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -07001097 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001098 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001099 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001100 pass
1101 else:
1102 main.exit()
adminbae64d82013-08-01 10:50:15 -07001103 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001104 print sys.exc_info()[ 1 ]
adminbae64d82013-08-01 10:50:15 -07001105
Jon Hall714eeba2015-09-29 17:53:10 -07001106def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001107 '''
adminbae64d82013-08-01 10:50:15 -07001108 It facilitates the loading customised parser for topology and params file.
1109 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001110 It also loads default xmlparser if no parser have specified in teston.cfg
1111 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001112 '''
adminbae64d82013-08-01 10:50:15 -07001113 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001114 if 'file' in confighash[ 'config' ][ 'logger' ] and\
1115 'class' in confighash[ 'config' ][ 'logger' ]:
1116 path = confighash[ 'config' ][ 'logger' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001117 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001118 confighash[ 'config' ][ 'logger' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001119 try:
1120 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001121 moduleList = module.split( "/" )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001122 newModule = ".".join( moduleList[ -2: ] )
1123 loggerClass = confighash[ 'config' ][ 'logger' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001124 loggerModule = __import__( newModule,
1125 globals(),
1126 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001127 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001128 -1 )
1129 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001130 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001131 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001132 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001133 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001134 load_defaultlogger()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001135 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1136 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001137 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001138 else:
1139 load_defaultlogger()
1140
1141def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001142 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001143 It will load the default parser which is xml parser to parse the params and
1144 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001145 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001146 moduleList = main.loggerPath.split( "/" )
1147 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001148 try:
Jon Halld61331b2015-02-17 16:35:47 -08001149 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001150 loggerModule = __import__( newModule,
1151 globals(),
1152 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001153 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001154 -1 )
1155 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001156 main.logger = loggerClass()
1157
1158 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001159 print sys.exc_info()[ 1 ]
Jon Halld61331b2015-02-17 16:35:47 -08001160 main.exit()
adminbae64d82013-08-01 10:50:15 -07001161
Jon Hall714eeba2015-09-29 17:53:10 -07001162def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001163 print "THIS IS ECHO"