blob: f296c698439ba89e7812687e47c79552e3b712ac [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 ) )
adminbae64d82013-08-01 10:50:15 -0700382 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700383 self.logger.updateCaseResults( self )
384 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700385 self.log.wiki( "<ul>" )
386 for line in self.stepCache.splitlines():
387 if re.search( " - PASS$", line ):
388 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
389 elif re.search( " - FAIL$", line ):
390 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
391 elif re.search( " - No Result$", line ):
392 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700393 else: # Should only be on fail message
394 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700395 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700396 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700397 self.log.summary( self.stepCache )
398 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700399 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700400 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700401 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700402 if cli.stop:
403 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700404 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700405 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = "Stopped"
Jon Hall714eeba2015-09-29 17:53:10 -0700406 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700407 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700408 return self.FALSE
409
Jon Hall96b816f2015-11-03 12:00:56 -0800410 def parseStepResults( self, testCaseNumber ):
411 """
412 Parse throught the step results for the wiki
413 """
414 try:
415 # Iterate through each of the steps and print them
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700416 for index in range( len( self.stepResults[ 0 ] ) ):
Jon Hall96b816f2015-11-03 12:00:56 -0800417 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700418 stepNo = self.stepResults[ 0 ][ index ]
419 stepName = self.stepResults[ 1 ][ index ]
420 stepResult = self.stepResults[ 2 ][ index ]
421 onFail = self.stepResults[ 3 ][ index ]
Jon Hall96b816f2015-11-03 12:00:56 -0800422 self.stepCache += "\t" + str( testCaseNumber ) + "."
423 self.stepCache += str( stepNo ) + " "
424 self.stepCache += stepName + " - "
425 if stepResult == self.TRUE:
426 self.stepCache += "PASS\n"
427 elif stepResult == self.FALSE:
428 self.stepCache += "FAIL\n"
429 self.stepCache += "\t\t" + onFail + "\n"
430 else:
431 self.stepCache += "No Result\n"
432 self.stepResultsList.append( stepResult )
433 except Exception:
434 self.log.exception( "Error parsing step results" )
435
Jon Halle234cc42015-08-31 15:26:47 -0700436 def skipCase( self, result="DEFAULT", msg=None ):
437 """
438 Will skip the rest of the code in a test case. The case results will be
439 determined as normal based on completed assertions unless the result
440 argument is given.
441
442 Optional Arguments:
Jon Hall7c4f4302016-07-15 14:39:02 -0700443 result: Case insensitive string. Can be 'PASS' or 'FAIL' and will set
Jon Halle234cc42015-08-31 15:26:47 -0700444 the case result accordingly.
445 msg: Message to be printed when the case is skipped in the reports.
446 """
447 result = result.upper().strip()
448 if result == "PASS":
449 self.CASERESULT = self.TRUE
450 elif result == "FAIL":
451 self.CASERESULT = self.FALSE
452 self.onFailMsg = "Skipping the rest of this case. "
453 if msg:
454 self.onFailMsg += str( msg )
Jon Hallca319892017-06-15 15:25:22 -0700455 raise SkipCase
kelvin-onlabf70fd542015-05-07 18:41:40 -0700456
Jon Hall714eeba2015-09-29 17:53:10 -0700457 def addCaseHeader( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700458 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700459 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
460 self.log.exact( caseHeader )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700461 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700462 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700463 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700464 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700465
Jon Hall714eeba2015-09-29 17:53:10 -0700466 def addCaseFooter( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700467 stepNo = self.stepResults[ 0 ][ -2 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700468 if stepNo > 0:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700469 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700470 str( stepNo ) + ": " + str( self.stepName )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700471 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep + \
Jon Hall714eeba2015-09-29 17:53:10 -0700472 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700473
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700474 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700475 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700476
adminbae64d82013-08-01 10:50:15 -0700477 for driver in self.driversList:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700478 vars( self )[ driver ].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700479
Devin Limba37cdd2018-05-07 11:41:05 -0700480 def setCheckingPoint( self ):
481 '''
482 Using when running findPatchScript.sh. This function needs to be placed
483 on the point that has the problem.
484
485 For example, if you see unusual behavior or from the portion of the code,
486 this is where you need to put with the conditional statement.
487 If some of the latency result is much greater than usual, have if statement
488 that checks if the result is greater than some point and include this function.
489
490 This will mark the 0 to findPatchResult.txt in /tmp/ and exit the test.
491 Then from findPatchScript, it will move onto the next commit and re-run the
492 test.
493 '''
494 self.log.error( "Reached to the checking point. Will mark the result and exit the test" )
495 resultFile = open( "/tmp/findPatchResult.txt", "w" )
496 resultFile.write( "0" )
497 resultFile.close()
498 self.cleanAndExit()
499
Jon Hall714eeba2015-09-29 17:53:10 -0700500 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000501 '''
Jon Hall5b586732015-06-11 11:39:39 -0700502 Print a summary of the current test's results then attempt to release
503 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700504
Jon Hall5b586732015-06-11 11:39:39 -0700505 This function shouldbe threadsafe such that cleanup will only be
506 executed once per test.
507
508 This will return TRUE if all the component handles and log handles
509 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000510 '''
adminbae64d82013-08-01 10:50:15 -0700511 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700512 lock = self.cleanupLock
513 if lock.acquire( False ):
514 try:
515 if self.cleanupFlag is False: # First thread to run this
516 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700517 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700518 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700519 components = self.componentDictionary
520 for component in sorted( components,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700521 key=lambda item: components[ item ][ 'connect_order' ],
Jon Hall892818c2015-10-20 17:58:34 -0700522 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700523 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700524 tempObject = vars( self )[ component ]
525 print "Disconnecting from " + str( tempObject.name ) + \
526 ": " + str( tempObject.__class__ )
Jon Hall5b586732015-06-11 11:39:39 -0700527 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700528 except KeyboardInterrupt:
529 pass
530 except KeyError:
531 # Component not created yet
532 self.log.warn( "Could not find the component " +
533 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000534 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700535 self.log.exception( "Exception while disconnecting from " +
536 str( component ) )
537 result = self.FALSE
538 # Closing all the driver's session files
539 for driver in self.componentDictionary.keys():
540 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700541 vars( self )[ driver ].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700542 except KeyboardInterrupt:
543 pass
544 except KeyError:
545 # Component not created yet
546 self.log.warn( "Could not find the component " +
547 str( driver ) + " while trying to" +
548 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000549 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700550 self.log.exception( "Exception while closing log files for " +
551 str( driver ) )
552 result = self.FALSE
553 else:
554 pass # Someone else already ran through this function
555 finally:
556 lock.release()
557 else: # Someone already has a lock
558 # NOTE: This could cause problems if we don't release the lock
559 # correctly
560 lock.acquire() # Wait for the other thread to finish
561 # NOTE: If we don't wait, exit could be called while the thread
562 # with the lock is still cleaning up
563 lock.release()
adminbae64d82013-08-01 10:50:15 -0700564 return result
Jon Halld61331b2015-02-17 16:35:47 -0800565
Jon Hall714eeba2015-09-29 17:53:10 -0700566 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000567 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700568 This function will pause the test's execution, and will continue after
569 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000570 '''
adminbae64d82013-08-01 10:50:15 -0700571 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700572
Jon Hall714eeba2015-09-29 17:53:10 -0700573 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000574 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700575 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000576 '''
adminbae64d82013-08-01 10:50:15 -0700577 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700578 try:
adminbae64d82013-08-01 10:50:15 -0700579 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700580 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700581 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000582 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700583 print str( e )
adminbae64d82013-08-01 10:50:15 -0700584 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700585 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700586 try:
adminbae64d82013-08-01 10:50:15 -0700587 for component in components:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700588 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700589 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000590 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700591 print str( e )
adminbae64d82013-08-01 10:50:15 -0700592 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700593
Jon Hall714eeba2015-09-29 17:53:10 -0700594 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000595 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700596 Based on the component 'type' specified in the params , this method
597 will find the absolute path, by recursively searching the name of
598 the component.
599
600 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000601 '''
adminbae64d82013-08-01 10:50:15 -0700602 import commands
603
Jon Hall714eeba2015-09-29 17:53:10 -0700604 cmd = "find " + drivers_path + " -name " + driverName + ".py"
605 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700606
Jon Hall714eeba2015-09-29 17:53:10 -0700607 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700608 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700609
adminbae64d82013-08-01 10:50:15 -0700610 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700611 result_count = result_count + 1
612 if result_count > 1:
613 print "Found " + driverName + " " + str( result_count ) + " times:"
614 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700615 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700616
Jon Hall714eeba2015-09-29 17:53:10 -0700617 result = re.sub( "(.*)drivers", "", result )
618 result = re.sub( "\/\/", "/", result )
619 result = re.sub( "\.py", "", result )
620 result = re.sub( "\.pyc", "", result )
621 result = re.sub( "\/", ".", result )
622 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700623 return result
adminbae64d82013-08-01 10:50:15 -0700624
Jon Hall714eeba2015-09-29 17:53:10 -0700625 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000626 '''
adminbae64d82013-08-01 10:50:15 -0700627 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000628 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700629 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700630 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700631 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700632 self.stepNumber += 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700633 self.stepResults[ 0 ].append( self.stepNumber )
634 self.stepResults[ 1 ].append( stepDesc )
635 self.stepResults[ 2 ].append( self.NORESULT )
636 self.stepResults[ 3 ].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700637
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700638 stepName = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700639 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700640 self.log.step( stepName )
adminbae64d82013-08-01 10:50:15 -0700641 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700642 line = "\n" + "-" * 45 + "\n"
643 if self.stepNumber > 1:
644 stepHeader = line + "End of Step " + previousStep + line
645 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700646 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700647 vars( self )[ driver + 'log' ].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700648
Jon Hall714eeba2015-09-29 17:53:10 -0700649 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000650 '''
adminbae64d82013-08-01 10:50:15 -0700651 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000652 '''
Jon Halld61331b2015-02-17 16:35:47 -0800653 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700654 testCaseName = " " + str( testCaseName )
655 self.log.case( testCaseName )
656 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700657 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700658 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700659
Jon Hall714eeba2015-09-29 17:53:10 -0700660 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000661 '''
adminbae64d82013-08-01 10:50:15 -0700662 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000663 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700664 description = "Test Description : " + str( description )
665 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700666
Jon Hall714eeba2015-09-29 17:53:10 -0700667 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000668 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700669 This method will parse the test script to find required test
670 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000671 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700672 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700673 testFileList = testFileHandler.readlines()
674 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700675 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700676 for index in range( len( testFileList ) ):
677 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700678 testFileList[ index ],
Jon Hall714eeba2015-09-29 17:53:10 -0700679 0 )
adminbae64d82013-08-01 10:50:15 -0700680 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700681 counter = counter + 1
682 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700683
Jon Hall714eeba2015-09-29 17:53:10 -0700684 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000685 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700686 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700687 response_dict = self.response_to_dict( response, return_format )
688 return_format_string = self.dict_to_return_format( response,
689 return_format,
690 response_dict )
adminbae64d82013-08-01 10:50:15 -0700691 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700692
Jon Hall714eeba2015-09-29 17:53:10 -0700693 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700694 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700695 json_match = re.search( '^\s*{', response )
696 xml_match = re.search( '^\s*\<', response )
697 ini_match = re.search( '^\s*\[', response )
698 if json_match:
699 self.log.info( "Response is in 'JSON' format, converting to '" +
700 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800701 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000702 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700703 response = re.sub( r",\s*'?(\w)", r',"\1', response )
704 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
705 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
706 try:
adminbae64d82013-08-01 10:50:15 -0700707 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700708 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000709 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700710 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700711 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700712 elif ini_match:
713 self.log.info( "Response is in 'INI' format, converting to '" +
714 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700715 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700716 response_file = open( "respnse_file.temp", 'w' )
717 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800718 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700719 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700720 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700721 elif xml_match:
722 self.log.info( "Response is in 'XML' format, converting to '" +
723 return_format + "' format" )
724 try:
725 response_dict = xmldict.xml_to_dict( "<response> " +
726 str( response ) +
727 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000728 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700729 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700730 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700731
Jon Hall714eeba2015-09-29 17:53:10 -0700732 def dict_to_return_format( self, response, return_format, response_dict ):
733 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000734 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700735 to_do = "Call the table output formatter"
736 global response_table
737 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700738 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700739
Jon Hall714eeba2015-09-29 17:53:10 -0700740 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000741 ''' This will parse the dictionary recusrsively and print as
742 table format'''
adminbae64d82013-08-01 10:50:15 -0700743 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700744 if isinstance( value_to_convert, dict ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700745 table_data = table_data + '\t'.join( value_to_convert ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700746 "\n"
747 for temp_val in value_to_convert.values():
748 table_data = table_data + get_table( temp_val )
749 else:
750 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800751 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700752
Jon Hall714eeba2015-09-29 17:53:10 -0700753 for value in response_dict.values():
754 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700755 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700756
Jon Hall714eeba2015-09-29 17:53:10 -0700757 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000758 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700759 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700760 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700761 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700762 response_config = re.sub( ",", "\n\t", response_string )
763 response_config = re.sub( "u\'", "\'", response_config )
764 response_config = re.sub( "{", "", response_config )
765 response_config = re.sub( "}", "\n", response_config )
766 response_config = re.sub( ":", " =", response_config )
767 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700768 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000769 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700770 response_xml = xmldict.dict_to_xml( response_dict )
771 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
772 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700773 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000774 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700775 to_do = 'Call dict to xml coverter'
776 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700777 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700778 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700779
Jon Hall714eeba2015-09-29 17:53:10 -0700780 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700781 self.random_order = self.random_order + 1
782 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700783
Jon Hall714eeba2015-09-29 17:53:10 -0700784 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700785 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700786 for thread in threading.enumerate():
787 if thread.isAlive():
788 try:
789 thread._Thread__stop()
790 except:
Jon Hall1306a562015-09-04 11:21:24 -0700791 # NOTE: We should catch any exceptions while trying to
792 # close the thread so that we can try to close the other
793 # threads as well
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700794 print str( thread.getName() ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700795 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700796 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700797 sys.exit()
798
You Wang7880b372019-02-27 16:50:47 -0800799 def cleanAndExit( self, alarm=True, msg="" ):
Devin Lim44075962017-08-11 10:56:37 -0700800 """
801 It will set the testcase result to be FAILED and update it
802 before cleaning up and exitting the test.
You Wang7880b372019-02-27 16:50:47 -0800803 alarm: when set to True, it will write to the alarm log before
804 cleaning up and exitting; otherwise it will write to error log.
805 msg: message that will be written to the log if specified;
806 otherwise a default message will be written.
Devin Lim44075962017-08-11 10:56:37 -0700807 :return:
808 """
809 if self.CurrentTestCaseNumber:
810 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700811 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700812 self.logger.updateCaseResults( self )
You Wang7880b372019-02-27 16:50:47 -0800813 if alarm:
814 if msg:
815 self.log.alarm( "Test exited unexpectedly: {}".format( msg ) )
816 else:
817 self.log.alarm( "Test exited unexpectedly" )
818 else:
819 if msg:
820 self.log.error( "Test exited unexpectedly: {}".format( msg ) )
821 else:
822 self.log.error( "Test exited unexpectedly" )
Devin Lim44075962017-08-11 10:56:37 -0700823 self.cleanup()
824 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700825
Jon Hallcd3d2a32015-10-01 11:07:28 -0700826 def stop( self, email=False ):
827 """
828 Stop the test until Ctrl-D is entered.
829 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700830
831 Optional arguments:
832 email can either be a bool, or you can specify the email address
833 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700834 """
835 try:
836 if email:
Jon Hall25079782015-10-13 13:54:39 -0700837 if '@' in email:
838 main.mail = email
839 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700840 self.log.debug( "Test execution suspended. \n"
841 "- Type 'c' to resume the test.\n"
842 "- Type Ctrl-C to exit the test.\n"
843 "- Enter interactive python interpreter commands.\n"
844 "\t- ie: main.Mininet1.pingall()\n"
845 "- Type 'help' for help with pdb." )
846 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700847 except EOFError:
848 return
849 # Pass all other exceptions up to caller
850
851
Jon Hall714eeba2015-09-29 17:53:10 -0700852def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000853 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700854 This will verify the command line options and set to default values,
855 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000856 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700857 verifyTest( options )
858 verifyExample( options )
859 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700860 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700861 verifyLogdir( options )
862 verifyMail( options )
863 verifyTestCases( options )
864 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700865
Jon Hall714eeba2015-09-29 17:53:10 -0700866def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700867 try:
868 if options.testname:
869 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700870 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700871 main.tests_path = tests_path
872 elif options.example:
873 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700874 main.tests_path = path + "/examples/"
875 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700876 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700877 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700878 main.exit()
adminbae64d82013-08-01 10:50:15 -0700879
Jon Hall714eeba2015-09-29 17:53:10 -0700880def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700881 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700882 main.testDir = path + '/examples/'
883 main.tests_path = path + "/examples/"
884 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700885
Jon Hall714eeba2015-09-29 17:53:10 -0700886def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800887 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700888 if options.logdir:
889 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700890 else:
Jon Halld61331b2015-02-17 16:35:47 -0800891 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700892
Jon Hall714eeba2015-09-29 17:53:10 -0700893def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700894 # Mail-To: field
895 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700896 main.mail = options.mail
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700897 elif main.params.get( 'mail' ): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700898 main.mail = main.params.get( 'mail' )
899 else: # TestON specific
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700900 main.mail = main.config[ 'config' ].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700901 # Mail-From: field
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700902 main.sender = main.config[ 'config' ].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700903 # Mail smtp server
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700904 main.smtp = main.config[ 'config' ].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700905 # Mail-From account password
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700906 main.senderPwd = main.config[ 'config' ].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700907
Devin Lim2df68a12017-06-30 15:39:05 -0700908def evalTestCase( tempList ):
909 tList = []
910 for tcase in tempList:
911 if isinstance( tcase, list ):
912 tList.extend( evalTestCase( tcase ) )
913 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700914 tList.extend( [ tcase ] )
Devin Lim2df68a12017-06-30 15:39:05 -0700915 return tList
adminbae64d82013-08-01 10:50:15 -0700916
Jon Hall714eeba2015-09-29 17:53:10 -0700917def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800918 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700919 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800920 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800921 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700922 testcases_list = re.sub( "(\[|\])", "", options.testcases )
923 main.testcases_list = eval( testcases_list + "," )
924 else:
adminbae64d82013-08-01 10:50:15 -0700925 if 'testcases' in main.params.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700926 temp = eval( main.params[ 'testcases' ] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700927 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700928 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700929 print "Testcases not specifed in params, please provide in " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700930 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800931 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700932
Jon Hall714eeba2015-09-29 17:53:10 -0700933def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700934 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700935 if options.onoscell:
936 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700937 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700938 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700939 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700940 output = subprocess.check_output( [ "bash", '-c', cellCMD ] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700941 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700942 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700943 for i in range( len( splitOutput ) ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700944 if re.match( "OCN", splitOutput[ i ] ):
945 mnNode = splitOutput[ i ].split( "=" )
946 main.mnIP = mnNode[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700947 # cell already sorts OC variables in bash, so no need to
948 # sort in TestON
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700949 elif re.match( "OC[1-9]", splitOutput[ i ] ):
950 onosNodes = splitOutput[ i ].split( "=" )
951 main.ONOSip.append( onosNodes[ 1 ] )
952 elif re.match( "ONOS_APPS", splitOutput[ i ] ):
953 main.apps = ( splitOutput[ i ].split( "=" ) )[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700954 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700955 main.onoscell = main.FALSE
956
Jon Hall714eeba2015-09-29 17:53:10 -0700957def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000958 '''
adminbae64d82013-08-01 10:50:15 -0700959 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000960 '''
Jon Halld61331b2015-02-17 16:35:47 -0800961 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700962 directory = main.testDir + "/" + main.TEST
963 if os.path.exists( directory ):
964 pass
965 else:
966 directory = ""
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700967 for root, dirs, files in os.walk( main.testDir, topdown=True ):
Jon Hall53c5e662016-04-13 16:06:56 -0700968 if not directory:
969 for name in dirs:
970 if name == main.TEST:
971 directory = ( os.path.join( root, name ) )
972 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700973 main.classPath = directory[ index: ].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700974 break
975 openspeakfile = directory + "/" + main.TEST + ".ospk"
Jon Halld74d2952018-03-01 13:26:39 -0800976 main.testDir = directory
Jon Hall53c5e662016-04-13 16:06:56 -0700977 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700978 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700979 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700980 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700981 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700982 # No openspeak found, using python file instead
983 pass
adminbae64d82013-08-01 10:50:15 -0700984 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700985 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " + \
986 "Python or OpenSpeak test script in the tests folder: " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700987 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700988 __builtin__.testthread = None
989 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700990 try:
991 testModule = __import__( main.classPath,
992 globals(),
993 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700994 [ main.TEST ],
Jon Hall714eeba2015-09-29 17:53:10 -0700995 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700996 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700997 print "There was an import error, it might mean that there is " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700998 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800999 main.exit()
adminbae64d82013-08-01 10:50:15 -07001000
Jon Hall714eeba2015-09-29 17:53:10 -07001001 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -07001002 main.testObject = testClass()
1003 load_parser()
Jon Halld74d2952018-03-01 13:26:39 -08001004 main.paramsFile = main.TEST + ".params" if options.paramsFile is None else options.paramsFile
1005 main.topoFile = main.TEST + ".topo" if options.topoFile is None else options.topoFile
1006 main.params = main.parser.parseFile( main.testDir + "/" + main.paramsFile )
1007 main.topology = main.parser.parseFile( main.testDir + "/" + main.topoFile )
kelvin-onlabf70fd542015-05-07 18:41:40 -07001008
YPZhang1c89e762016-06-29 10:43:58 -07001009def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -07001010 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001011 main.params = main.params[ 'PARAMS' ]
Jon Hall1306a562015-09-04 11:21:24 -07001012 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001013 print "Error with the params file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -07001014 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -08001015 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -07001016 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001017 main.topology = main.topology[ 'TOPOLOGY' ]
Jon Hall1306a562015-09-04 11:21:24 -07001018 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001019 print "Error with the Topology file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -07001020 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -07001021 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -07001022 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001023 if len( options.params ) > 0:
YPZhang1c89e762016-06-29 10:43:58 -07001024 # Some params variables are specified from command line
1025 for param in options.params:
1026 if not re.search( ".=.", param ):
1027 print( "Error when parsing params: params should follow key=value format" )
1028 continue
Jon Hall7c4f4302016-07-15 14:39:02 -07001029 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -07001030 [ keys, value ] = param.split( "=" )
1031 # Split the nested keys according to its hierarchy
1032 keyList = keys.split( "/" )
1033 # Get the outermost dictionary
1034 paramDict = main.params
1035 # Get the innermost dictionary
1036 try:
1037 while len( keyList ) > 1:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001038 key = keyList.pop( 0 )
YPZhang1c89e762016-06-29 10:43:58 -07001039 assert isinstance( paramDict[ key ], dict )
1040 paramDict = paramDict[ key ]
1041 except KeyError:
1042 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1043 main.exit()
1044 except AssertionError:
1045 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1046 main.exit()
1047 # Change the value
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001048 if keyList[ 0 ] not in paramDict:
1049 print( "Error when parsing params: key \"" + keyList[ 0 ] + "\" not found in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001050 main.exit()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001051 elif isinstance( paramDict[ keyList[ 0 ] ], dict ):
1052 print( "Error when parsing params: more levels under key \"" + keyList[ 0 ] + "\" in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001053 main.exit()
1054 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001055 paramDict[ keyList[ 0 ] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001056
Jon Hall714eeba2015-09-29 17:53:10 -07001057def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001058 '''
adminbae64d82013-08-01 10:50:15 -07001059 It facilitates the loading customised parser for topology and params file.
1060 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001061 It also loads default xmlparser if no parser have specified in teston.cfg
1062 file.
adminbae64d82013-08-01 10:50:15 -07001063
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001064 '''
adminbae64d82013-08-01 10:50:15 -07001065 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001066 if 'file' in confighash[ 'config' ][ 'parser' ] and\
1067 'class' in confighash[ 'config' ][ 'parser' ]:
1068 path = confighash[ 'config' ][ 'parser' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001069 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001070 confighash[ 'config' ][ 'parser' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001071 try:
1072 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001073 moduleList = module.split( "/" )
1074 newModule = ".".join( moduleList[ -2: ] )
1075 parsingClass = confighash[ 'config' ][ 'parser' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001076 parsingModule = __import__( newModule,
1077 globals(),
1078 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001079 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001080 -1 )
1081 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001082 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001083 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001084 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -07001085 pass
1086 else:
1087 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -07001088 main.exit()
Jon Hall44506242015-07-29 17:40:26 -07001089 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001090 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001091 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001092 load_defaultParser()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001093 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1094 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001095 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -07001096 else:
1097 load_defaultParser()
1098
1099def load_defaultParser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001100 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001101 It will load the default parser which is xml parser to parse the params and
1102 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001103 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001104 moduleList = main.parserPath.split( "/" )
1105 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001106 try:
Jon Halld61331b2015-02-17 16:35:47 -08001107 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -07001108 parsingModule = __import__( newModule,
1109 globals(),
1110 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001111 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001112 -1 )
1113 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -07001114 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001115 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001116 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001117 pass
1118 else:
1119 main.exit()
adminbae64d82013-08-01 10:50:15 -07001120 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001121 print sys.exc_info()[ 1 ]
adminbae64d82013-08-01 10:50:15 -07001122
Jon Hall714eeba2015-09-29 17:53:10 -07001123def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001124 '''
adminbae64d82013-08-01 10:50:15 -07001125 It facilitates the loading customised parser for topology and params file.
1126 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001127 It also loads default xmlparser if no parser have specified in teston.cfg
1128 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001129 '''
adminbae64d82013-08-01 10:50:15 -07001130 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001131 if 'file' in confighash[ 'config' ][ 'logger' ] and\
1132 'class' in confighash[ 'config' ][ 'logger' ]:
1133 path = confighash[ 'config' ][ 'logger' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001134 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001135 confighash[ 'config' ][ 'logger' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001136 try:
1137 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001138 moduleList = module.split( "/" )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001139 newModule = ".".join( moduleList[ -2: ] )
1140 loggerClass = confighash[ 'config' ][ 'logger' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001141 loggerModule = __import__( newModule,
1142 globals(),
1143 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001144 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001145 -1 )
1146 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001147 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001148 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001149 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001150 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001151 load_defaultlogger()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001152 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1153 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001154 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001155 else:
1156 load_defaultlogger()
1157
1158def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001159 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001160 It will load the default parser which is xml parser to parse the params and
1161 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001162 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001163 moduleList = main.loggerPath.split( "/" )
1164 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001165 try:
Jon Halld61331b2015-02-17 16:35:47 -08001166 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001167 loggerModule = __import__( newModule,
1168 globals(),
1169 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001170 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001171 -1 )
1172 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001173 main.logger = loggerClass()
1174
1175 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001176 print sys.exc_info()[ 1 ]
Jon Halld61331b2015-02-17 16:35:47 -08001177 main.exit()
adminbae64d82013-08-01 10:50:15 -07001178
Jon Hall714eeba2015-09-29 17:53:10 -07001179def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001180 print "THIS IS ECHO"