blob: 632c56c6362b3ff6136237db6dcc320e1d92b9bd [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 Hall3a03cad2021-04-07 11:21:55 -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
Jon Hall06fd0df2021-01-25 15:50:06 -0800178 driver_home = self.componentDictionary[ component ].get( 'home' )
179 if driver_home:
180 driver_options[ 'home' ] = driver_home
kelvin-onlabf70fd542015-05-07 18:41:40 -0700181
Jon Hall714eeba2015-09-29 17:53:10 -0700182 classPath = self.getDriverPath( driverName.lower() )
183 driverModule = importlib.import_module( classPath )
184 driverClass = getattr( driverModule, driverName )
adminbae64d82013-08-01 10:50:15 -0700185 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700186
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700187 if "OCN" in self.componentDictionary[ component ][ 'host' ] and\
Jon Hall714eeba2015-09-29 17:53:10 -0700188 main.onoscell:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700189 self.componentDictionary[ component ][ 'host' ] = main.mnIP
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700190
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700191 user_name = self.componentDictionary[ component ].get( 'user', getpass.getuser() )
192 ip_address = self.componentDictionary[ component ].get( 'host', 'localhost' )
193 pwd = self.componentDictionary[ component ].get( 'password', 'changeme' )
194 port = self.componentDictionary[ component ].get( 'port' )
Jon Hall714eeba2015-09-29 17:53:10 -0700195 connect_result = driverObject.connect( user_name=user_name,
196 ip_address=ip_address,
197 pwd=pwd,
198 port=port,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700199 options=driver_options )
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700200
adminbae64d82013-08-01 10:50:15 -0700201 if not connect_result:
Jon Hall714eeba2015-09-29 17:53:10 -0700202 self.log.error( "Exiting from the test execution because connecting to the " +
203 component + " component failed." )
Jon Halld61331b2015-02-17 16:35:47 -0800204 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700205
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700206 vars( self )[ component ] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700207 self.initiated = True
Jon Hallca319892017-06-15 15:25:22 -0700208 return driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700209
Jon Hall714eeba2015-09-29 17:53:10 -0700210 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000211 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700212 The Execution of the test script's cases listed in the Test params
213 file will be done here then update each test case result.
214 This method will return main.TRUE if it executed all the test cases
215 successfully, else will retun main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000216 '''
adminbae64d82013-08-01 10:50:15 -0700217 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700218 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700219 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800220 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700221 self.TOTAL_TC_NORESULT = 0
222 self.TOTAL_TC_FAIL = 0
223 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700224 self.TEST_ITERATION = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700225
226 # NOTE: number of main.step statements in the
227 # outer most level of the test case. used to
228 # execute code in smaller steps
229 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700230 self.CASERESULT = self.NORESULT
231
Jon Halld61331b2015-02-17 16:35:47 -0800232 import testparser
Jon Hall53c5e662016-04-13 16:06:56 -0700233 test = testparser.TestParser( main.testFile )
adminbae64d82013-08-01 10:50:15 -0700234 self.testscript = test.testscript
235 self.code = test.getStepCode()
Jon Hall714eeba2015-09-29 17:53:10 -0700236 repeat = int( self.params.get( 'repeat', 1 ) )
237 self.TOTAL_TC_PLANNED = len( self.testcases_list ) * repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700238
adminbae64d82013-08-01 10:50:15 -0700239 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700240 while repeat:
Devin Limec989792017-08-15 15:57:55 -0700241 self.leftCase.extend( self.testcases_list )
Jon Halla1185982014-09-15 14:55:10 -0700242 for self.CurrentTestCaseNumber in self.testcases_list:
Devin Limec989792017-08-15 15:57:55 -0700243 self.executedCase.append( self.leftCase.pop( 0 ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700244 result = self.runCase( self.CurrentTestCaseNumber )
245 repeat -= 1
adminbae64d82013-08-01 10:50:15 -0700246 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700247
Jon Halle234cc42015-08-31 15:26:47 -0700248 def runCase( self, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700249 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700250 self.CurrentTestCase = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700251
252 # List of step results in a case. ANDed together to get the result
253 self.stepResultsList = []
kelvin-onlabf70fd542015-05-07 18:41:40 -0700254 self.stepName = ""
Jon Hall783bbf92015-07-23 14:33:19 -0700255 self.caseExplanation = ""
adminbae64d82013-08-01 10:50:15 -0700256 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700257
258 # NOTE: number of main.step statements in the
259 # outer most level of the test case. used to
260 # execute code in smaller steps
261 self.stepCount = 0
262
263 # NOTE: This is the current number of main.step()'s executed
264 # in a case. Used for logging.
265 self.stepNumber = 0
adminbae64d82013-08-01 10:50:15 -0700266 self.EXPERIMENTAL_MODE = self.FALSE
267 self.addCaseHeader()
Devin Limec989792017-08-15 15:57:55 -0700268 self.log.debug( "Case Executed : " + str( self.executedCase ) )
269 self.log.debug( "Case to be executed : " + str( self.leftCase ) )
Jon Halle234cc42015-08-31 15:26:47 -0700270 self.testCaseNumber = str( testCaseNumber )
271 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700272 stopped = False
Jon Hall5a72b712015-09-28 12:20:59 -0700273 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700274 self.code[ self.testCaseNumber ]
Jon Halld61331b2015-02-17 16:35:47 -0800275 except KeyError:
Jon Halle234cc42015-08-31 15:26:47 -0700276 self.log.error( "There is no Test-Case " + self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800277 return self.FALSE
adminbae64d82013-08-01 10:50:15 -0700278 self.stepCount = 0
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700279 while self.stepCount < len( self.code[ self.testCaseNumber ].keys() ):
Jon Hall714eeba2015-09-29 17:53:10 -0700280 result = self.runStep( self.code, self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800281 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700282 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800283 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700284 continue
Jon Hall5a72b712015-09-28 12:20:59 -0700285 # stepResults format: ( stepNo[], stepName[], stepResult[], onFail[] )
286 stepResults = self.stepResultsList
Jon Halle234cc42015-08-31 15:26:47 -0700287 if not stopped:
288 if self.CASERESULT == self.TRUE or self.CASERESULT == self.FALSE:
Jon Hall714eeba2015-09-29 17:53:10 -0700289 # Result was already explitily set somewhere else like
290 # in skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700291 pass
Jon Hall5a72b712015-09-28 12:20:59 -0700292 elif all( self.TRUE == i for i in stepResults ):
kelvin-onlabf70fd542015-05-07 18:41:40 -0700293 # ALL PASSED
294 self.CASERESULT = self.TRUE
Jon Hall5a72b712015-09-28 12:20:59 -0700295 elif self.FALSE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700296 # AT LEAST ONE FAILED
297 self.CASERESULT = self.FALSE
Jon Hall5a72b712015-09-28 12:20:59 -0700298 elif self.TRUE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700299 # AT LEAST ONE PASSED
300 self.CASERESULT = self.TRUE
301 else:
302 self.CASERESULT = self.NORESULT
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700303 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.CASERESULT
Devin Limec989792017-08-15 15:57:55 -0700304 self.organizeResult( self.CurrentTestCaseNumber, self.CASERESULT )
Jon Hall714eeba2015-09-29 17:53:10 -0700305 self.logger.updateCaseResults( self )
Jon Hall783bbf92015-07-23 14:33:19 -0700306 self.log.wiki( "<p>" + self.caseExplanation + "</p>" )
307 self.log.summary( self.caseExplanation )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700308 self.log.wiki( "<ul>" )
acsmarse2d1ed12015-10-05 13:51:17 -0700309 subcaseMessage = False
kelvin-onlabf70fd542015-05-07 18:41:40 -0700310 for line in self.stepCache.splitlines():
acsmarse2d1ed12015-10-05 13:51:17 -0700311 if re.search( "[0-9]\.[0-9]", line ): # Step
312 if subcaseMessage: # End of Failure Message Printout
313 self.log.wiki( "</ul>\n" )
314 subcaseMessage = False
315 if re.search( " - PASS$", line ):
316 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
317 elif re.search( " - FAIL$", line ):
318 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
319 elif re.search( " - No Result$", line ):
320 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
321 else: # Substep
322 if not subcaseMessage: # Open Failure Message Printout
323 self.log.wiki( "<ul><li>" + line + "</li>\n" )
324 subcaseMessage = True
325 else: # Add to Failure Message Printout
326 self.log.wiki( "<li>" + line + "</li>\n" )
acsmars27e62dd2015-10-06 11:35:47 -0700327 if subcaseMessage: # End of Failure Message Printout for last item
328 self.log.wiki( "</ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700329 self.log.wiki( "</ul>" )
330 self.log.summary( self.stepCache )
331 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700332 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700333
Devin Limec989792017-08-15 15:57:55 -0700334 def organizeResult( self, caseNum, result ):
335 """
336 Organize the result and put the current number into either
337 failed/noResult lists.
338 * caseNum - number of the case
339 * result - result of the case
340 """
341 if result == main.FALSE:
342 self.failedCase.append( caseNum )
343 elif result == self.NORESULT:
344 self.noResultCase.append( caseNum )
345
Jon Hall714eeba2015-09-29 17:53:10 -0700346 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700347 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700348 try:
349 step = self.stepCount
350 # stepResults format: ( stepNo, stepName, stepResult, onFail )
351 # NOTE: This is needed to catch results of main.step()'s
352 # called inside functions or loops
353 self.stepResults = ( [], [], [], [] )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700354 exec code[ testCaseNumber ][ step ] in module.__dict__
adminbae64d82013-08-01 10:50:15 -0700355 self.stepCount = self.stepCount + 1
Jon Hall96b816f2015-11-03 12:00:56 -0800356 self.parseStepResults( testCaseNumber )
Jon Hallca319892017-06-15 15:25:22 -0700357 except SkipCase: # Raised in self.skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700358 self.log.warn( "Skipping the rest of CASE" +
359 str( testCaseNumber ) )
Jon Hall96b816f2015-11-03 12:00:56 -0800360 self.parseStepResults( testCaseNumber )
Jon Hall714eeba2015-09-29 17:53:10 -0700361 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700362 self.stepCache += "\t\t" + self.onFailMsg + "\n"
363 self.stepCount = self.stepCount + 1
364 return self.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000365 except StandardError as e:
Jon Hallc1606352015-10-06 14:51:36 -0700366 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700367 stepNo = self.stepResults[ 0 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700368 except IndexError:
369 stepNo = "<IndexError>"
370 main.log.warn( "Error trying to get step number. " +
371 "It is likely between step " +
Jon Hall6e709752016-02-01 13:38:46 -0800372 str( self.stepNumber ) + " and step " +
Jon Hallc1606352015-10-06 14:51:36 -0700373 str( self.stepNumber + 1 ) )
374 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700375 stepName = self.stepResults[ 1 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700376 except IndexError:
377 stepName = "<IndexError>"
378 self.log.error( "\nException in the following section of" +
379 " code: " + str( testCaseNumber ) + "." +
380 str( stepNo ) + ": " + stepName )
Jeremyd9e4eb12016-04-13 12:09:06 -0700381 self.log.error( str( e.__class__ ) + str( e.message ) )
Jon Halld14a5002021-03-30 16:45:30 -0700382 self.log.exception( "" )
adminbae64d82013-08-01 10:50:15 -0700383 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700384 self.logger.updateCaseResults( self )
385 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700386 self.log.wiki( "<ul>" )
387 for line in self.stepCache.splitlines():
388 if re.search( " - PASS$", line ):
389 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
390 elif re.search( " - FAIL$", line ):
391 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
392 elif re.search( " - No Result$", line ):
393 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700394 else: # Should only be on fail message
395 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700396 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700397 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700398 self.log.summary( self.stepCache )
399 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700400 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700401 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700402 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700403 if cli.stop:
404 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700405 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700406 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = "Stopped"
Jon Hall714eeba2015-09-29 17:53:10 -0700407 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700408 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700409 return self.FALSE
410
Jon Hall96b816f2015-11-03 12:00:56 -0800411 def parseStepResults( self, testCaseNumber ):
412 """
413 Parse throught the step results for the wiki
414 """
415 try:
416 # Iterate through each of the steps and print them
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700417 for index in range( len( self.stepResults[ 0 ] ) ):
Jon Hall96b816f2015-11-03 12:00:56 -0800418 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700419 stepNo = self.stepResults[ 0 ][ index ]
420 stepName = self.stepResults[ 1 ][ index ]
421 stepResult = self.stepResults[ 2 ][ index ]
422 onFail = self.stepResults[ 3 ][ index ]
Jon Hall96b816f2015-11-03 12:00:56 -0800423 self.stepCache += "\t" + str( testCaseNumber ) + "."
424 self.stepCache += str( stepNo ) + " "
425 self.stepCache += stepName + " - "
426 if stepResult == self.TRUE:
427 self.stepCache += "PASS\n"
428 elif stepResult == self.FALSE:
429 self.stepCache += "FAIL\n"
430 self.stepCache += "\t\t" + onFail + "\n"
431 else:
432 self.stepCache += "No Result\n"
433 self.stepResultsList.append( stepResult )
434 except Exception:
435 self.log.exception( "Error parsing step results" )
436
Jon Halle234cc42015-08-31 15:26:47 -0700437 def skipCase( self, result="DEFAULT", msg=None ):
438 """
439 Will skip the rest of the code in a test case. The case results will be
440 determined as normal based on completed assertions unless the result
441 argument is given.
442
443 Optional Arguments:
Jon Hall7c4f4302016-07-15 14:39:02 -0700444 result: Case insensitive string. Can be 'PASS' or 'FAIL' and will set
Jon Halle234cc42015-08-31 15:26:47 -0700445 the case result accordingly.
446 msg: Message to be printed when the case is skipped in the reports.
447 """
448 result = result.upper().strip()
449 if result == "PASS":
450 self.CASERESULT = self.TRUE
451 elif result == "FAIL":
452 self.CASERESULT = self.FALSE
453 self.onFailMsg = "Skipping the rest of this case. "
454 if msg:
455 self.onFailMsg += str( msg )
Jon Hallca319892017-06-15 15:25:22 -0700456 raise SkipCase
kelvin-onlabf70fd542015-05-07 18:41:40 -0700457
Jon Hall714eeba2015-09-29 17:53:10 -0700458 def addCaseHeader( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700459 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700460 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
461 self.log.exact( caseHeader )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700462 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700463 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700464 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700465 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700466
Jon Hall714eeba2015-09-29 17:53:10 -0700467 def addCaseFooter( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700468 stepNo = self.stepResults[ 0 ][ -2 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700469 if stepNo > 0:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700470 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700471 str( stepNo ) + ": " + str( self.stepName )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700472 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep + \
Jon Hall714eeba2015-09-29 17:53:10 -0700473 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700474
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700475 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700476 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700477
adminbae64d82013-08-01 10:50:15 -0700478 for driver in self.driversList:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700479 vars( self )[ driver ].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700480
Devin Limba37cdd2018-05-07 11:41:05 -0700481 def setCheckingPoint( self ):
482 '''
483 Using when running findPatchScript.sh. This function needs to be placed
484 on the point that has the problem.
485
486 For example, if you see unusual behavior or from the portion of the code,
487 this is where you need to put with the conditional statement.
488 If some of the latency result is much greater than usual, have if statement
489 that checks if the result is greater than some point and include this function.
490
491 This will mark the 0 to findPatchResult.txt in /tmp/ and exit the test.
492 Then from findPatchScript, it will move onto the next commit and re-run the
493 test.
494 '''
495 self.log.error( "Reached to the checking point. Will mark the result and exit the test" )
496 resultFile = open( "/tmp/findPatchResult.txt", "w" )
497 resultFile.write( "0" )
498 resultFile.close()
499 self.cleanAndExit()
500
Jon Hall714eeba2015-09-29 17:53:10 -0700501 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000502 '''
Jon Hall5b586732015-06-11 11:39:39 -0700503 Print a summary of the current test's results then attempt to release
504 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700505
Jon Hall5b586732015-06-11 11:39:39 -0700506 This function shouldbe threadsafe such that cleanup will only be
507 executed once per test.
508
509 This will return TRUE if all the component handles and log handles
510 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000511 '''
adminbae64d82013-08-01 10:50:15 -0700512 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700513 lock = self.cleanupLock
514 if lock.acquire( False ):
515 try:
516 if self.cleanupFlag is False: # First thread to run this
517 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700518 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700519 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700520 components = self.componentDictionary
521 for component in sorted( components,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700522 key=lambda item: components[ item ][ 'connect_order' ],
Jon Hall892818c2015-10-20 17:58:34 -0700523 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700524 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700525 tempObject = vars( self )[ component ]
526 print "Disconnecting from " + str( tempObject.name ) + \
527 ": " + str( tempObject.__class__ )
Jon Hall5b586732015-06-11 11:39:39 -0700528 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700529 except KeyboardInterrupt:
530 pass
531 except KeyError:
532 # Component not created yet
533 self.log.warn( "Could not find the component " +
534 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000535 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700536 self.log.exception( "Exception while disconnecting from " +
537 str( component ) )
538 result = self.FALSE
539 # Closing all the driver's session files
540 for driver in self.componentDictionary.keys():
541 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700542 vars( self )[ driver ].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700543 except KeyboardInterrupt:
544 pass
545 except KeyError:
546 # Component not created yet
547 self.log.warn( "Could not find the component " +
548 str( driver ) + " while trying to" +
549 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000550 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700551 self.log.exception( "Exception while closing log files for " +
552 str( driver ) )
553 result = self.FALSE
554 else:
555 pass # Someone else already ran through this function
556 finally:
557 lock.release()
558 else: # Someone already has a lock
559 # NOTE: This could cause problems if we don't release the lock
560 # correctly
561 lock.acquire() # Wait for the other thread to finish
562 # NOTE: If we don't wait, exit could be called while the thread
563 # with the lock is still cleaning up
564 lock.release()
adminbae64d82013-08-01 10:50:15 -0700565 return result
Jon Halld61331b2015-02-17 16:35:47 -0800566
Jon Hall714eeba2015-09-29 17:53:10 -0700567 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000568 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700569 This function will pause the test's execution, and will continue after
570 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000571 '''
adminbae64d82013-08-01 10:50:15 -0700572 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700573
Jon Hall714eeba2015-09-29 17:53:10 -0700574 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000575 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700576 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000577 '''
adminbae64d82013-08-01 10:50:15 -0700578 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700579 try:
adminbae64d82013-08-01 10:50:15 -0700580 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700581 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700582 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000583 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700584 print str( e )
adminbae64d82013-08-01 10:50:15 -0700585 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700586 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700587 try:
adminbae64d82013-08-01 10:50:15 -0700588 for component in components:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700589 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700590 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000591 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700592 print str( e )
adminbae64d82013-08-01 10:50:15 -0700593 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700594
Jon Hall714eeba2015-09-29 17:53:10 -0700595 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000596 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700597 Based on the component 'type' specified in the params , this method
598 will find the absolute path, by recursively searching the name of
599 the component.
600
601 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000602 '''
adminbae64d82013-08-01 10:50:15 -0700603 import commands
604
Jon Hall714eeba2015-09-29 17:53:10 -0700605 cmd = "find " + drivers_path + " -name " + driverName + ".py"
606 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700607
Jon Hall714eeba2015-09-29 17:53:10 -0700608 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700609 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700610
adminbae64d82013-08-01 10:50:15 -0700611 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700612 result_count = result_count + 1
613 if result_count > 1:
614 print "Found " + driverName + " " + str( result_count ) + " times:"
615 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700616 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700617
Jon Hall714eeba2015-09-29 17:53:10 -0700618 result = re.sub( "(.*)drivers", "", result )
619 result = re.sub( "\/\/", "/", result )
620 result = re.sub( "\.py", "", result )
621 result = re.sub( "\.pyc", "", result )
622 result = re.sub( "\/", ".", result )
623 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700624 return result
adminbae64d82013-08-01 10:50:15 -0700625
Jon Hall714eeba2015-09-29 17:53:10 -0700626 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000627 '''
adminbae64d82013-08-01 10:50:15 -0700628 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000629 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700630 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700631 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700632 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700633 self.stepNumber += 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700634 self.stepResults[ 0 ].append( self.stepNumber )
635 self.stepResults[ 1 ].append( stepDesc )
636 self.stepResults[ 2 ].append( self.NORESULT )
637 self.stepResults[ 3 ].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700638
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700639 stepName = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700640 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700641 self.log.step( stepName )
adminbae64d82013-08-01 10:50:15 -0700642 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700643 line = "\n" + "-" * 45 + "\n"
644 if self.stepNumber > 1:
645 stepHeader = line + "End of Step " + previousStep + line
646 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700647 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700648 vars( self )[ driver + 'log' ].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700649
Jon Hall714eeba2015-09-29 17:53:10 -0700650 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000651 '''
adminbae64d82013-08-01 10:50:15 -0700652 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000653 '''
Jon Halld61331b2015-02-17 16:35:47 -0800654 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700655 testCaseName = " " + str( testCaseName )
656 self.log.case( testCaseName )
657 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700658 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700659 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700660
Jon Hall714eeba2015-09-29 17:53:10 -0700661 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000662 '''
adminbae64d82013-08-01 10:50:15 -0700663 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000664 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700665 description = "Test Description : " + str( description )
666 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700667
Jon Hall714eeba2015-09-29 17:53:10 -0700668 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000669 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700670 This method will parse the test script to find required test
671 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000672 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700673 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700674 testFileList = testFileHandler.readlines()
675 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700676 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700677 for index in range( len( testFileList ) ):
678 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700679 testFileList[ index ],
Jon Hall714eeba2015-09-29 17:53:10 -0700680 0 )
adminbae64d82013-08-01 10:50:15 -0700681 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700682 counter = counter + 1
683 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700684
Jon Hall714eeba2015-09-29 17:53:10 -0700685 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000686 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700687 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700688 response_dict = self.response_to_dict( response, return_format )
689 return_format_string = self.dict_to_return_format( response,
690 return_format,
691 response_dict )
adminbae64d82013-08-01 10:50:15 -0700692 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700693
Jon Hall714eeba2015-09-29 17:53:10 -0700694 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700695 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700696 json_match = re.search( '^\s*{', response )
697 xml_match = re.search( '^\s*\<', response )
698 ini_match = re.search( '^\s*\[', response )
699 if json_match:
700 self.log.info( "Response is in 'JSON' format, converting to '" +
701 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800702 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000703 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700704 response = re.sub( r",\s*'?(\w)", r',"\1', response )
705 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
706 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
707 try:
adminbae64d82013-08-01 10:50:15 -0700708 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700709 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000710 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700711 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700712 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700713 elif ini_match:
714 self.log.info( "Response is in 'INI' format, converting to '" +
715 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700716 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700717 response_file = open( "respnse_file.temp", 'w' )
718 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800719 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700720 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700721 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700722 elif xml_match:
723 self.log.info( "Response is in 'XML' format, converting to '" +
724 return_format + "' format" )
725 try:
726 response_dict = xmldict.xml_to_dict( "<response> " +
727 str( response ) +
728 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000729 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700730 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700731 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700732
Jon Hall714eeba2015-09-29 17:53:10 -0700733 def dict_to_return_format( self, response, return_format, response_dict ):
734 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000735 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700736 to_do = "Call the table output formatter"
737 global response_table
738 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700739 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700740
Jon Hall714eeba2015-09-29 17:53:10 -0700741 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000742 ''' This will parse the dictionary recusrsively and print as
743 table format'''
adminbae64d82013-08-01 10:50:15 -0700744 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700745 if isinstance( value_to_convert, dict ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700746 table_data = table_data + '\t'.join( value_to_convert ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700747 "\n"
748 for temp_val in value_to_convert.values():
749 table_data = table_data + get_table( temp_val )
750 else:
751 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800752 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700753
Jon Hall714eeba2015-09-29 17:53:10 -0700754 for value in response_dict.values():
755 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700756 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700757
Jon Hall714eeba2015-09-29 17:53:10 -0700758 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000759 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700760 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700761 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700762 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700763 response_config = re.sub( ",", "\n\t", response_string )
764 response_config = re.sub( "u\'", "\'", response_config )
765 response_config = re.sub( "{", "", response_config )
766 response_config = re.sub( "}", "\n", response_config )
767 response_config = re.sub( ":", " =", response_config )
768 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700769 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000770 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700771 response_xml = xmldict.dict_to_xml( response_dict )
772 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
773 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700774 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000775 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700776 to_do = 'Call dict to xml coverter'
777 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700778 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700779 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700780
Jon Hall714eeba2015-09-29 17:53:10 -0700781 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700782 self.random_order = self.random_order + 1
783 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700784
Jon Hall714eeba2015-09-29 17:53:10 -0700785 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700786 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700787 for thread in threading.enumerate():
788 if thread.isAlive():
789 try:
790 thread._Thread__stop()
791 except:
Jon Hall1306a562015-09-04 11:21:24 -0700792 # NOTE: We should catch any exceptions while trying to
793 # close the thread so that we can try to close the other
794 # threads as well
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700795 print str( thread.getName() ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700796 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700797 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700798 sys.exit()
799
You Wang7880b372019-02-27 16:50:47 -0800800 def cleanAndExit( self, alarm=True, msg="" ):
Devin Lim44075962017-08-11 10:56:37 -0700801 """
802 It will set the testcase result to be FAILED and update it
803 before cleaning up and exitting the test.
You Wang7880b372019-02-27 16:50:47 -0800804 alarm: when set to True, it will write to the alarm log before
805 cleaning up and exitting; otherwise it will write to error log.
806 msg: message that will be written to the log if specified;
807 otherwise a default message will be written.
Devin Lim44075962017-08-11 10:56:37 -0700808 :return:
809 """
810 if self.CurrentTestCaseNumber:
811 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700812 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700813 self.logger.updateCaseResults( self )
You Wang7880b372019-02-27 16:50:47 -0800814 if alarm:
815 if msg:
816 self.log.alarm( "Test exited unexpectedly: {}".format( msg ) )
817 else:
818 self.log.alarm( "Test exited unexpectedly" )
819 else:
820 if msg:
821 self.log.error( "Test exited unexpectedly: {}".format( msg ) )
822 else:
823 self.log.error( "Test exited unexpectedly" )
Devin Lim44075962017-08-11 10:56:37 -0700824 self.cleanup()
825 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700826
Jon Hallcd3d2a32015-10-01 11:07:28 -0700827 def stop( self, email=False ):
828 """
829 Stop the test until Ctrl-D is entered.
830 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700831
832 Optional arguments:
833 email can either be a bool, or you can specify the email address
834 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700835 """
836 try:
837 if email:
Jon Hall25079782015-10-13 13:54:39 -0700838 if '@' in email:
839 main.mail = email
840 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700841 self.log.debug( "Test execution suspended. \n"
842 "- Type 'c' to resume the test.\n"
843 "- Type Ctrl-C to exit the test.\n"
844 "- Enter interactive python interpreter commands.\n"
845 "\t- ie: main.Mininet1.pingall()\n"
846 "- Type 'help' for help with pdb." )
847 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700848 except EOFError:
849 return
850 # Pass all other exceptions up to caller
851
852
Jon Hall714eeba2015-09-29 17:53:10 -0700853def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000854 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700855 This will verify the command line options and set to default values,
856 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000857 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700858 verifyTest( options )
859 verifyExample( options )
860 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700861 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700862 verifyLogdir( options )
863 verifyMail( options )
864 verifyTestCases( options )
865 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700866
Jon Hall714eeba2015-09-29 17:53:10 -0700867def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700868 try:
869 if options.testname:
870 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700871 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700872 main.tests_path = tests_path
873 elif options.example:
874 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700875 main.tests_path = path + "/examples/"
876 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700877 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700878 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700879 main.exit()
adminbae64d82013-08-01 10:50:15 -0700880
Jon Hall714eeba2015-09-29 17:53:10 -0700881def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700882 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700883 main.testDir = path + '/examples/'
884 main.tests_path = path + "/examples/"
885 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700886
Jon Hall714eeba2015-09-29 17:53:10 -0700887def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800888 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700889 if options.logdir:
890 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700891 else:
Jon Halld61331b2015-02-17 16:35:47 -0800892 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700893
Jon Hall714eeba2015-09-29 17:53:10 -0700894def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700895 # Mail-To: field
896 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700897 main.mail = options.mail
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700898 elif main.params.get( 'mail' ): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700899 main.mail = main.params.get( 'mail' )
900 else: # TestON specific
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700901 main.mail = main.config[ 'config' ].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700902 # Mail-From: field
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700903 main.sender = main.config[ 'config' ].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700904 # Mail smtp server
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700905 main.smtp = main.config[ 'config' ].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700906 # Mail-From account password
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700907 main.senderPwd = main.config[ 'config' ].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700908
Devin Lim2df68a12017-06-30 15:39:05 -0700909def evalTestCase( tempList ):
910 tList = []
911 for tcase in tempList:
912 if isinstance( tcase, list ):
913 tList.extend( evalTestCase( tcase ) )
914 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700915 tList.extend( [ tcase ] )
Devin Lim2df68a12017-06-30 15:39:05 -0700916 return tList
adminbae64d82013-08-01 10:50:15 -0700917
Jon Hall714eeba2015-09-29 17:53:10 -0700918def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800919 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700920 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800921 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800922 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700923 testcases_list = re.sub( "(\[|\])", "", options.testcases )
924 main.testcases_list = eval( testcases_list + "," )
925 else:
adminbae64d82013-08-01 10:50:15 -0700926 if 'testcases' in main.params.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700927 temp = eval( main.params[ 'testcases' ] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700928 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700929 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700930 print "Testcases not specifed in params, please provide in " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700931 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800932 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700933
Jon Hall714eeba2015-09-29 17:53:10 -0700934def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700935 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700936 if options.onoscell:
937 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700938 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700939 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700940 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700941 output = subprocess.check_output( [ "bash", '-c', cellCMD ] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700942 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700943 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700944 for i in range( len( splitOutput ) ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700945 if re.match( "OCN", splitOutput[ i ] ):
946 mnNode = splitOutput[ i ].split( "=" )
947 main.mnIP = mnNode[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700948 # cell already sorts OC variables in bash, so no need to
949 # sort in TestON
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700950 elif re.match( "OC[1-9]", splitOutput[ i ] ):
951 onosNodes = splitOutput[ i ].split( "=" )
952 main.ONOSip.append( onosNodes[ 1 ] )
953 elif re.match( "ONOS_APPS", splitOutput[ i ] ):
954 main.apps = ( splitOutput[ i ].split( "=" ) )[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700955 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700956 main.onoscell = main.FALSE
957
Jon Hall714eeba2015-09-29 17:53:10 -0700958def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000959 '''
adminbae64d82013-08-01 10:50:15 -0700960 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000961 '''
Jon Halld61331b2015-02-17 16:35:47 -0800962 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700963 directory = main.testDir + "/" + main.TEST
964 if os.path.exists( directory ):
965 pass
966 else:
967 directory = ""
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700968 for root, dirs, files in os.walk( main.testDir, topdown=True ):
Jon Hall53c5e662016-04-13 16:06:56 -0700969 if not directory:
970 for name in dirs:
971 if name == main.TEST:
972 directory = ( os.path.join( root, name ) )
973 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700974 main.classPath = directory[ index: ].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700975 break
976 openspeakfile = directory + "/" + main.TEST + ".ospk"
Jon Halld74d2952018-03-01 13:26:39 -0800977 main.testDir = directory
Jon Hall53c5e662016-04-13 16:06:56 -0700978 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700979 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700980 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700981 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700982 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700983 # No openspeak found, using python file instead
984 pass
adminbae64d82013-08-01 10:50:15 -0700985 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700986 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " + \
987 "Python or OpenSpeak test script in the tests folder: " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700988 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700989 __builtin__.testthread = None
990 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700991 try:
992 testModule = __import__( main.classPath,
993 globals(),
994 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700995 [ main.TEST ],
Jon Hall714eeba2015-09-29 17:53:10 -0700996 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700997 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700998 print "There was an import error, it might mean that there is " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700999 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -08001000 main.exit()
adminbae64d82013-08-01 10:50:15 -07001001
Jon Hall714eeba2015-09-29 17:53:10 -07001002 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -07001003 main.testObject = testClass()
1004 load_parser()
Jon Halld74d2952018-03-01 13:26:39 -08001005 main.paramsFile = main.TEST + ".params" if options.paramsFile is None else options.paramsFile
1006 main.topoFile = main.TEST + ".topo" if options.topoFile is None else options.topoFile
1007 main.params = main.parser.parseFile( main.testDir + "/" + main.paramsFile )
1008 main.topology = main.parser.parseFile( main.testDir + "/" + main.topoFile )
kelvin-onlabf70fd542015-05-07 18:41:40 -07001009
YPZhang1c89e762016-06-29 10:43:58 -07001010def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -07001011 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001012 main.params = main.params[ 'PARAMS' ]
Jon Hall1306a562015-09-04 11:21:24 -07001013 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001014 print "Error with the params file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -07001015 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -08001016 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -07001017 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001018 main.topology = main.topology[ 'TOPOLOGY' ]
Jon Hall1306a562015-09-04 11:21:24 -07001019 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001020 print "Error with the Topology file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -07001021 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -07001022 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -07001023 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001024 if len( options.params ) > 0:
YPZhang1c89e762016-06-29 10:43:58 -07001025 # Some params variables are specified from command line
1026 for param in options.params:
1027 if not re.search( ".=.", param ):
1028 print( "Error when parsing params: params should follow key=value format" )
1029 continue
Jon Hall7c4f4302016-07-15 14:39:02 -07001030 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -07001031 [ keys, value ] = param.split( "=" )
1032 # Split the nested keys according to its hierarchy
1033 keyList = keys.split( "/" )
1034 # Get the outermost dictionary
1035 paramDict = main.params
1036 # Get the innermost dictionary
1037 try:
1038 while len( keyList ) > 1:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001039 key = keyList.pop( 0 )
YPZhang1c89e762016-06-29 10:43:58 -07001040 assert isinstance( paramDict[ key ], dict )
1041 paramDict = paramDict[ key ]
1042 except KeyError:
1043 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1044 main.exit()
1045 except AssertionError:
1046 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1047 main.exit()
1048 # Change the value
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001049 if keyList[ 0 ] not in paramDict:
1050 print( "Error when parsing params: key \"" + keyList[ 0 ] + "\" not found in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001051 main.exit()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001052 elif isinstance( paramDict[ keyList[ 0 ] ], dict ):
1053 print( "Error when parsing params: more levels under key \"" + keyList[ 0 ] + "\" in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001054 main.exit()
1055 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001056 paramDict[ keyList[ 0 ] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001057
Jon Hall714eeba2015-09-29 17:53:10 -07001058def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001059 '''
adminbae64d82013-08-01 10:50:15 -07001060 It facilitates the loading customised parser for topology and params file.
1061 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001062 It also loads default xmlparser if no parser have specified in teston.cfg
1063 file.
adminbae64d82013-08-01 10:50:15 -07001064
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001065 '''
adminbae64d82013-08-01 10:50:15 -07001066 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001067 if 'file' in confighash[ 'config' ][ 'parser' ] and\
1068 'class' in confighash[ 'config' ][ 'parser' ]:
1069 path = confighash[ 'config' ][ 'parser' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001070 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001071 confighash[ 'config' ][ 'parser' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001072 try:
1073 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001074 moduleList = module.split( "/" )
1075 newModule = ".".join( moduleList[ -2: ] )
1076 parsingClass = confighash[ 'config' ][ 'parser' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001077 parsingModule = __import__( newModule,
1078 globals(),
1079 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001080 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001081 -1 )
1082 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001083 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001084 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001085 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -07001086 pass
1087 else:
1088 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -07001089 main.exit()
Jon Hall44506242015-07-29 17:40:26 -07001090 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001091 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001092 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001093 load_defaultParser()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001094 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1095 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001096 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -07001097 else:
1098 load_defaultParser()
1099
1100def load_defaultParser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001101 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001102 It will load the default parser which is xml parser to parse the params and
1103 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001104 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001105 moduleList = main.parserPath.split( "/" )
1106 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001107 try:
Jon Halld61331b2015-02-17 16:35:47 -08001108 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -07001109 parsingModule = __import__( newModule,
1110 globals(),
1111 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001112 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001113 -1 )
1114 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -07001115 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001116 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001117 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001118 pass
1119 else:
1120 main.exit()
adminbae64d82013-08-01 10:50:15 -07001121 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001122 print sys.exc_info()[ 1 ]
adminbae64d82013-08-01 10:50:15 -07001123
Jon Hall714eeba2015-09-29 17:53:10 -07001124def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001125 '''
adminbae64d82013-08-01 10:50:15 -07001126 It facilitates the loading customised parser for topology and params file.
1127 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001128 It also loads default xmlparser if no parser have specified in teston.cfg
1129 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001130 '''
adminbae64d82013-08-01 10:50:15 -07001131 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001132 if 'file' in confighash[ 'config' ][ 'logger' ] and\
1133 'class' in confighash[ 'config' ][ 'logger' ]:
1134 path = confighash[ 'config' ][ 'logger' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001135 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001136 confighash[ 'config' ][ 'logger' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001137 try:
1138 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001139 moduleList = module.split( "/" )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001140 newModule = ".".join( moduleList[ -2: ] )
1141 loggerClass = confighash[ 'config' ][ 'logger' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001142 loggerModule = __import__( newModule,
1143 globals(),
1144 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001145 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001146 -1 )
1147 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001148 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001149 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001150 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001151 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001152 load_defaultlogger()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001153 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1154 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001155 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001156 else:
1157 load_defaultlogger()
1158
1159def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001160 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001161 It will load the default parser which is xml parser to parse the params and
1162 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001163 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001164 moduleList = main.loggerPath.split( "/" )
1165 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001166 try:
Jon Halld61331b2015-02-17 16:35:47 -08001167 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001168 loggerModule = __import__( newModule,
1169 globals(),
1170 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001171 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001172 -1 )
1173 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001174 main.logger = loggerClass()
1175
1176 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001177 print sys.exc_info()[ 1 ]
Jon Halld61331b2015-02-17 16:35:47 -08001178 main.exit()
adminbae64d82013-08-01 10:50:15 -07001179
Jon Hall714eeba2015-09-29 17:53:10 -07001180def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001181 print "THIS IS ECHO"