blob: 19449f4f5e8acacf6a6926fb386c8bb2d381999a [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
Jon Hall714eeba2015-09-29 17:53:10 -0700477 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000478 '''
Jon Hall5b586732015-06-11 11:39:39 -0700479 Print a summary of the current test's results then attempt to release
480 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700481
Jon Hall5b586732015-06-11 11:39:39 -0700482 This function shouldbe threadsafe such that cleanup will only be
483 executed once per test.
484
485 This will return TRUE if all the component handles and log handles
486 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000487 '''
adminbae64d82013-08-01 10:50:15 -0700488 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700489 lock = self.cleanupLock
490 if lock.acquire( False ):
491 try:
492 if self.cleanupFlag is False: # First thread to run this
493 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700494 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700495 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700496 components = self.componentDictionary
497 for component in sorted( components,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700498 key=lambda item: components[ item ][ 'connect_order' ],
Jon Hall892818c2015-10-20 17:58:34 -0700499 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700500 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700501 tempObject = vars( self )[ component ]
502 print "Disconnecting from " + str( tempObject.name ) + \
503 ": " + str( tempObject.__class__ )
Jon Hall5b586732015-06-11 11:39:39 -0700504 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700505 except KeyboardInterrupt:
506 pass
507 except KeyError:
508 # Component not created yet
509 self.log.warn( "Could not find the component " +
510 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000511 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700512 self.log.exception( "Exception while disconnecting from " +
513 str( component ) )
514 result = self.FALSE
515 # Closing all the driver's session files
516 for driver in self.componentDictionary.keys():
517 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700518 vars( self )[ driver ].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700519 except KeyboardInterrupt:
520 pass
521 except KeyError:
522 # Component not created yet
523 self.log.warn( "Could not find the component " +
524 str( driver ) + " while trying to" +
525 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000526 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700527 self.log.exception( "Exception while closing log files for " +
528 str( driver ) )
529 result = self.FALSE
530 else:
531 pass # Someone else already ran through this function
532 finally:
533 lock.release()
534 else: # Someone already has a lock
535 # NOTE: This could cause problems if we don't release the lock
536 # correctly
537 lock.acquire() # Wait for the other thread to finish
538 # NOTE: If we don't wait, exit could be called while the thread
539 # with the lock is still cleaning up
540 lock.release()
adminbae64d82013-08-01 10:50:15 -0700541 return result
Jon Halld61331b2015-02-17 16:35:47 -0800542
Jon Hall714eeba2015-09-29 17:53:10 -0700543 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000544 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700545 This function will pause the test's execution, and will continue after
546 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000547 '''
adminbae64d82013-08-01 10:50:15 -0700548 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700549
Jon Hall714eeba2015-09-29 17:53:10 -0700550 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000551 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700552 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000553 '''
adminbae64d82013-08-01 10:50:15 -0700554 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700555 try:
adminbae64d82013-08-01 10:50:15 -0700556 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700557 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700558 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000559 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700560 print str( e )
adminbae64d82013-08-01 10:50:15 -0700561 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700562 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700563 try:
adminbae64d82013-08-01 10:50:15 -0700564 for component in components:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700565 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700566 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000567 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700568 print str( e )
adminbae64d82013-08-01 10:50:15 -0700569 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700570
Jon Hall714eeba2015-09-29 17:53:10 -0700571 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000572 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700573 Based on the component 'type' specified in the params , this method
574 will find the absolute path, by recursively searching the name of
575 the component.
576
577 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000578 '''
adminbae64d82013-08-01 10:50:15 -0700579 import commands
580
Jon Hall714eeba2015-09-29 17:53:10 -0700581 cmd = "find " + drivers_path + " -name " + driverName + ".py"
582 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700583
Jon Hall714eeba2015-09-29 17:53:10 -0700584 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700585 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700586
adminbae64d82013-08-01 10:50:15 -0700587 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700588 result_count = result_count + 1
589 if result_count > 1:
590 print "Found " + driverName + " " + str( result_count ) + " times:"
591 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700592 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700593
Jon Hall714eeba2015-09-29 17:53:10 -0700594 result = re.sub( "(.*)drivers", "", result )
595 result = re.sub( "\/\/", "/", result )
596 result = re.sub( "\.py", "", result )
597 result = re.sub( "\.pyc", "", result )
598 result = re.sub( "\/", ".", result )
599 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700600 return result
adminbae64d82013-08-01 10:50:15 -0700601
Jon Hall714eeba2015-09-29 17:53:10 -0700602 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000603 '''
adminbae64d82013-08-01 10:50:15 -0700604 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000605 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700606 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700607 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700608 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700609 self.stepNumber += 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700610 self.stepResults[ 0 ].append( self.stepNumber )
611 self.stepResults[ 1 ].append( stepDesc )
612 self.stepResults[ 2 ].append( self.NORESULT )
613 self.stepResults[ 3 ].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700614
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700615 stepName = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700616 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700617 self.log.step( stepName )
adminbae64d82013-08-01 10:50:15 -0700618 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700619 line = "\n" + "-" * 45 + "\n"
620 if self.stepNumber > 1:
621 stepHeader = line + "End of Step " + previousStep + line
622 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700623 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700624 vars( self )[ driver + 'log' ].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700625
Jon Hall714eeba2015-09-29 17:53:10 -0700626 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000627 '''
adminbae64d82013-08-01 10:50:15 -0700628 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000629 '''
Jon Halld61331b2015-02-17 16:35:47 -0800630 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700631 testCaseName = " " + str( testCaseName )
632 self.log.case( testCaseName )
633 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700634 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700635 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700636
Jon Hall714eeba2015-09-29 17:53:10 -0700637 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000638 '''
adminbae64d82013-08-01 10:50:15 -0700639 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000640 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700641 description = "Test Description : " + str( description )
642 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700643
Jon Hall714eeba2015-09-29 17:53:10 -0700644 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000645 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700646 This method will parse the test script to find required test
647 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000648 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700649 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700650 testFileList = testFileHandler.readlines()
651 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700652 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700653 for index in range( len( testFileList ) ):
654 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700655 testFileList[ index ],
Jon Hall714eeba2015-09-29 17:53:10 -0700656 0 )
adminbae64d82013-08-01 10:50:15 -0700657 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700658 counter = counter + 1
659 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700660
Jon Hall714eeba2015-09-29 17:53:10 -0700661 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000662 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700663 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700664 response_dict = self.response_to_dict( response, return_format )
665 return_format_string = self.dict_to_return_format( response,
666 return_format,
667 response_dict )
adminbae64d82013-08-01 10:50:15 -0700668 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700669
Jon Hall714eeba2015-09-29 17:53:10 -0700670 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700671 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700672 json_match = re.search( '^\s*{', response )
673 xml_match = re.search( '^\s*\<', response )
674 ini_match = re.search( '^\s*\[', response )
675 if json_match:
676 self.log.info( "Response is in 'JSON' format, converting to '" +
677 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800678 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000679 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700680 response = re.sub( r",\s*'?(\w)", r',"\1', response )
681 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
682 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
683 try:
adminbae64d82013-08-01 10:50:15 -0700684 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700685 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000686 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700687 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700688 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700689 elif ini_match:
690 self.log.info( "Response is in 'INI' format, converting to '" +
691 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700692 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700693 response_file = open( "respnse_file.temp", 'w' )
694 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800695 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700696 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700697 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700698 elif xml_match:
699 self.log.info( "Response is in 'XML' format, converting to '" +
700 return_format + "' format" )
701 try:
702 response_dict = xmldict.xml_to_dict( "<response> " +
703 str( response ) +
704 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000705 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700706 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700707 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700708
Jon Hall714eeba2015-09-29 17:53:10 -0700709 def dict_to_return_format( self, response, return_format, response_dict ):
710 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000711 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700712 to_do = "Call the table output formatter"
713 global response_table
714 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700715 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700716
Jon Hall714eeba2015-09-29 17:53:10 -0700717 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000718 ''' This will parse the dictionary recusrsively and print as
719 table format'''
adminbae64d82013-08-01 10:50:15 -0700720 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700721 if isinstance( value_to_convert, dict ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700722 table_data = table_data + '\t'.join( value_to_convert ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700723 "\n"
724 for temp_val in value_to_convert.values():
725 table_data = table_data + get_table( temp_val )
726 else:
727 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800728 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700729
Jon Hall714eeba2015-09-29 17:53:10 -0700730 for value in response_dict.values():
731 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700732 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700733
Jon Hall714eeba2015-09-29 17:53:10 -0700734 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000735 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700736 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700737 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700738 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700739 response_config = re.sub( ",", "\n\t", response_string )
740 response_config = re.sub( "u\'", "\'", response_config )
741 response_config = re.sub( "{", "", response_config )
742 response_config = re.sub( "}", "\n", response_config )
743 response_config = re.sub( ":", " =", response_config )
744 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700745 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000746 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700747 response_xml = xmldict.dict_to_xml( response_dict )
748 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
749 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700750 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000751 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700752 to_do = 'Call dict to xml coverter'
753 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700754 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700755 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700756
Jon Hall714eeba2015-09-29 17:53:10 -0700757 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700758 self.random_order = self.random_order + 1
759 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700760
Jon Hall714eeba2015-09-29 17:53:10 -0700761 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700762 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700763 for thread in threading.enumerate():
764 if thread.isAlive():
765 try:
766 thread._Thread__stop()
767 except:
Jon Hall1306a562015-09-04 11:21:24 -0700768 # NOTE: We should catch any exceptions while trying to
769 # close the thread so that we can try to close the other
770 # threads as well
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700771 print str( thread.getName() ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700772 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700773 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700774 sys.exit()
775
Devin Lim44075962017-08-11 10:56:37 -0700776 def cleanAndExit( self ):
777 """
778 It will set the testcase result to be FAILED and update it
779 before cleaning up and exitting the test.
780 :return:
781 """
782 if self.CurrentTestCaseNumber:
783 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700784 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700785 self.logger.updateCaseResults( self )
786 self.cleanup()
787 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700788
Jon Hallcd3d2a32015-10-01 11:07:28 -0700789 def stop( self, email=False ):
790 """
791 Stop the test until Ctrl-D is entered.
792 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700793
794 Optional arguments:
795 email can either be a bool, or you can specify the email address
796 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700797 """
798 try:
799 if email:
Jon Hall25079782015-10-13 13:54:39 -0700800 if '@' in email:
801 main.mail = email
802 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700803 self.log.debug( "Test execution suspended. \n"
804 "- Type 'c' to resume the test.\n"
805 "- Type Ctrl-C to exit the test.\n"
806 "- Enter interactive python interpreter commands.\n"
807 "\t- ie: main.Mininet1.pingall()\n"
808 "- Type 'help' for help with pdb." )
809 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700810 except EOFError:
811 return
812 # Pass all other exceptions up to caller
813
814
Jon Hall714eeba2015-09-29 17:53:10 -0700815def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000816 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700817 This will verify the command line options and set to default values,
818 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000819 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700820 verifyTest( options )
821 verifyExample( options )
822 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700823 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700824 verifyLogdir( options )
825 verifyMail( options )
826 verifyTestCases( options )
827 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700828
Jon Hall714eeba2015-09-29 17:53:10 -0700829def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700830 try:
831 if options.testname:
832 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700833 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700834 main.tests_path = tests_path
835 elif options.example:
836 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700837 main.tests_path = path + "/examples/"
838 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700839 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700840 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700841 main.exit()
adminbae64d82013-08-01 10:50:15 -0700842
Jon Hall714eeba2015-09-29 17:53:10 -0700843def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700844 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700845 main.testDir = path + '/examples/'
846 main.tests_path = path + "/examples/"
847 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700848
Jon Hall714eeba2015-09-29 17:53:10 -0700849def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800850 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700851 if options.logdir:
852 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700853 else:
Jon Halld61331b2015-02-17 16:35:47 -0800854 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700855
Jon Hall714eeba2015-09-29 17:53:10 -0700856def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700857 # Mail-To: field
858 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700859 main.mail = options.mail
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700860 elif main.params.get( 'mail' ): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700861 main.mail = main.params.get( 'mail' )
862 else: # TestON specific
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700863 main.mail = main.config[ 'config' ].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700864 # Mail-From: field
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700865 main.sender = main.config[ 'config' ].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700866 # Mail smtp server
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700867 main.smtp = main.config[ 'config' ].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700868 # Mail-From account password
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700869 main.senderPwd = main.config[ 'config' ].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700870
Devin Lim2df68a12017-06-30 15:39:05 -0700871def evalTestCase( tempList ):
872 tList = []
873 for tcase in tempList:
874 if isinstance( tcase, list ):
875 tList.extend( evalTestCase( tcase ) )
876 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700877 tList.extend( [ tcase ] )
Devin Lim2df68a12017-06-30 15:39:05 -0700878 return tList
adminbae64d82013-08-01 10:50:15 -0700879
Jon Hall714eeba2015-09-29 17:53:10 -0700880def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800881 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700882 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800883 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800884 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700885 testcases_list = re.sub( "(\[|\])", "", options.testcases )
886 main.testcases_list = eval( testcases_list + "," )
887 else:
adminbae64d82013-08-01 10:50:15 -0700888 if 'testcases' in main.params.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700889 temp = eval( main.params[ 'testcases' ] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700890 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700891 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700892 print "Testcases not specifed in params, please provide in " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700893 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800894 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700895
Jon Hall714eeba2015-09-29 17:53:10 -0700896def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700897 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700898 if options.onoscell:
899 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700900 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700901 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700902 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700903 output = subprocess.check_output( [ "bash", '-c', cellCMD ] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700904 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700905 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700906 for i in range( len( splitOutput ) ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700907 if re.match( "OCN", splitOutput[ i ] ):
908 mnNode = splitOutput[ i ].split( "=" )
909 main.mnIP = mnNode[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700910 # cell already sorts OC variables in bash, so no need to
911 # sort in TestON
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700912 elif re.match( "OC[1-9]", splitOutput[ i ] ):
913 onosNodes = splitOutput[ i ].split( "=" )
914 main.ONOSip.append( onosNodes[ 1 ] )
915 elif re.match( "ONOS_APPS", splitOutput[ i ] ):
916 main.apps = ( splitOutput[ i ].split( "=" ) )[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700917 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700918 main.onoscell = main.FALSE
919
Jon Hall714eeba2015-09-29 17:53:10 -0700920def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000921 '''
adminbae64d82013-08-01 10:50:15 -0700922 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000923 '''
Jon Halld61331b2015-02-17 16:35:47 -0800924 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700925 directory = main.testDir + "/" + main.TEST
926 if os.path.exists( directory ):
927 pass
928 else:
929 directory = ""
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700930 for root, dirs, files in os.walk( main.testDir, topdown=True ):
Jon Hall53c5e662016-04-13 16:06:56 -0700931 if not directory:
932 for name in dirs:
933 if name == main.TEST:
934 directory = ( os.path.join( root, name ) )
935 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700936 main.classPath = directory[ index: ].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700937 break
938 openspeakfile = directory + "/" + main.TEST + ".ospk"
Jon Halld74d2952018-03-01 13:26:39 -0800939 main.testDir = directory
Jon Hall53c5e662016-04-13 16:06:56 -0700940 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700941 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700942 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700943 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700944 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700945 # No openspeak found, using python file instead
946 pass
adminbae64d82013-08-01 10:50:15 -0700947 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700948 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " + \
949 "Python or OpenSpeak test script in the tests folder: " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700950 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700951 __builtin__.testthread = None
952 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700953 try:
954 testModule = __import__( main.classPath,
955 globals(),
956 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700957 [ main.TEST ],
Jon Hall714eeba2015-09-29 17:53:10 -0700958 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700959 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700960 print "There was an import error, it might mean that there is " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700961 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800962 main.exit()
adminbae64d82013-08-01 10:50:15 -0700963
Jon Hall714eeba2015-09-29 17:53:10 -0700964 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700965 main.testObject = testClass()
966 load_parser()
Jon Halld74d2952018-03-01 13:26:39 -0800967 main.paramsFile = main.TEST + ".params" if options.paramsFile is None else options.paramsFile
968 main.topoFile = main.TEST + ".topo" if options.topoFile is None else options.topoFile
969 main.params = main.parser.parseFile( main.testDir + "/" + main.paramsFile )
970 main.topology = main.parser.parseFile( main.testDir + "/" + main.topoFile )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700971
YPZhang1c89e762016-06-29 10:43:58 -0700972def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -0700973 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700974 main.params = main.params[ 'PARAMS' ]
Jon Hall1306a562015-09-04 11:21:24 -0700975 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700976 print "Error with the params file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700977 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800978 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700979 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700980 main.topology = main.topology[ 'TOPOLOGY' ]
Jon Hall1306a562015-09-04 11:21:24 -0700981 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700982 print "Error with the Topology file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700983 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700984 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -0700985 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700986 if len( options.params ) > 0:
YPZhang1c89e762016-06-29 10:43:58 -0700987 # Some params variables are specified from command line
988 for param in options.params:
989 if not re.search( ".=.", param ):
990 print( "Error when parsing params: params should follow key=value format" )
991 continue
Jon Hall7c4f4302016-07-15 14:39:02 -0700992 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -0700993 [ keys, value ] = param.split( "=" )
994 # Split the nested keys according to its hierarchy
995 keyList = keys.split( "/" )
996 # Get the outermost dictionary
997 paramDict = main.params
998 # Get the innermost dictionary
999 try:
1000 while len( keyList ) > 1:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001001 key = keyList.pop( 0 )
YPZhang1c89e762016-06-29 10:43:58 -07001002 assert isinstance( paramDict[ key ], dict )
1003 paramDict = paramDict[ key ]
1004 except KeyError:
1005 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1006 main.exit()
1007 except AssertionError:
1008 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1009 main.exit()
1010 # Change the value
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001011 if keyList[ 0 ] not in paramDict:
1012 print( "Error when parsing params: key \"" + keyList[ 0 ] + "\" not found in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001013 main.exit()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001014 elif isinstance( paramDict[ keyList[ 0 ] ], dict ):
1015 print( "Error when parsing params: more levels under key \"" + keyList[ 0 ] + "\" in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001016 main.exit()
1017 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001018 paramDict[ keyList[ 0 ] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001019
Jon Hall714eeba2015-09-29 17:53:10 -07001020def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001021 '''
adminbae64d82013-08-01 10:50:15 -07001022 It facilitates the loading customised parser for topology and params file.
1023 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001024 It also loads default xmlparser if no parser have specified in teston.cfg
1025 file.
adminbae64d82013-08-01 10:50:15 -07001026
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001027 '''
adminbae64d82013-08-01 10:50:15 -07001028 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001029 if 'file' in confighash[ 'config' ][ 'parser' ] and\
1030 'class' in confighash[ 'config' ][ 'parser' ]:
1031 path = confighash[ 'config' ][ 'parser' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001032 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001033 confighash[ 'config' ][ 'parser' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001034 try:
1035 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001036 moduleList = module.split( "/" )
1037 newModule = ".".join( moduleList[ -2: ] )
1038 parsingClass = confighash[ 'config' ][ 'parser' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001039 parsingModule = __import__( newModule,
1040 globals(),
1041 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001042 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001043 -1 )
1044 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001045 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001046 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001047 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -07001048 pass
1049 else:
1050 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -07001051 main.exit()
Jon Hall44506242015-07-29 17:40:26 -07001052 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001053 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001054 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001055 load_defaultParser()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001056 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1057 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001058 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -07001059 else:
1060 load_defaultParser()
1061
1062def load_defaultParser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001063 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001064 It will load the default parser which is xml parser to parse the params and
1065 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001066 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001067 moduleList = main.parserPath.split( "/" )
1068 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001069 try:
Jon Halld61331b2015-02-17 16:35:47 -08001070 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -07001071 parsingModule = __import__( newModule,
1072 globals(),
1073 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001074 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001075 -1 )
1076 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -07001077 main.parser = parsingClass()
Jon Halld74d2952018-03-01 13:26:39 -08001078 if hasattr( main.parser, "parseFile" ) and\
Jon Hall714eeba2015-09-29 17:53:10 -07001079 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001080 pass
1081 else:
1082 main.exit()
adminbae64d82013-08-01 10:50:15 -07001083 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001084 print sys.exc_info()[ 1 ]
adminbae64d82013-08-01 10:50:15 -07001085
Jon Hall714eeba2015-09-29 17:53:10 -07001086def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001087 '''
adminbae64d82013-08-01 10:50:15 -07001088 It facilitates the loading customised parser for topology and params file.
1089 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001090 It also loads default xmlparser if no parser have specified in teston.cfg
1091 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001092 '''
adminbae64d82013-08-01 10:50:15 -07001093 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001094 if 'file' in confighash[ 'config' ][ 'logger' ] and\
1095 'class' in confighash[ 'config' ][ 'logger' ]:
1096 path = confighash[ 'config' ][ 'logger' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001097 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001098 confighash[ 'config' ][ 'logger' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001099 try:
1100 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001101 moduleList = module.split( "/" )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001102 newModule = ".".join( moduleList[ -2: ] )
1103 loggerClass = confighash[ 'config' ][ 'logger' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001104 loggerModule = __import__( newModule,
1105 globals(),
1106 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001107 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001108 -1 )
1109 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001110 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001111 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001112 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001113 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001114 load_defaultlogger()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001115 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1116 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001117 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001118 else:
1119 load_defaultlogger()
1120
1121def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001122 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001123 It will load the default parser which is xml parser to parse the params and
1124 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001125 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001126 moduleList = main.loggerPath.split( "/" )
1127 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001128 try:
Jon Halld61331b2015-02-17 16:35:47 -08001129 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001130 loggerModule = __import__( newModule,
1131 globals(),
1132 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001133 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001134 -1 )
1135 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001136 main.logger = loggerClass()
1137
1138 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001139 print sys.exc_info()[ 1 ]
Jon Halld61331b2015-02-17 16:35:47 -08001140 main.exit()
adminbae64d82013-08-01 10:50:15 -07001141
Jon Hall714eeba2015-09-29 17:53:10 -07001142def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001143 print "THIS IS ECHO"