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