blob: 67945645bd82f471115af0a9e7a811521b5b9940 [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
93 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070094 self.parsingClass = "xmlparser"
95 self.parserPath = core_path + "/xmlparser"
96 self.loggerPath = core_path + "/logger"
97 self.loggerClass = "Logger"
98 self.logs_path = logs_path
99 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -0800100 self.Thread = Thread
Jon Hall5b586732015-06-11 11:39:39 -0700101 self.cleanupFlag = False
102 self.cleanupLock = threading.Lock()
Jon Hall0fc0d452015-07-14 09:49:58 -0700103 self.initiated = False
Devin Limec989792017-08-15 15:57:55 -0700104 self.executedCase = []
105 self.leftCase = []
106 self.failedCase = []
107 self.noResultCase = []
Jon Hall65844a32015-03-09 19:09:37 -0700108
Jon Hall25079782015-10-13 13:54:39 -0700109 self.config = self.configparser()
Jon Hall714eeba2015-09-29 17:53:10 -0700110 verifyOptions( options )
adminbae64d82013-08-01 10:50:15 -0700111 load_logger()
112 self.componentDictionary = {}
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700113 self.componentDictionary = self.topology[ 'COMPONENT' ]
Jon Hall714eeba2015-09-29 17:53:10 -0700114 self.driversList = []
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700115 if isinstance( self.componentDictionary, str ):
Jon Hall714eeba2015-09-29 17:53:10 -0700116 self.componentDictionary = dict( self.componentDictionary )
Jon Hall65844a32015-03-09 19:09:37 -0700117
Jon Hall714eeba2015-09-29 17:53:10 -0700118 for component in self.componentDictionary:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700119 self.driversList.append( self.componentDictionary[ component ][ 'type' ] )
Jon Hall65844a32015-03-09 19:09:37 -0700120
Jon Hall714eeba2015-09-29 17:53:10 -0700121 self.driversList = list( set( self.driversList ) ) # Removing duplicates.
adminbae64d82013-08-01 10:50:15 -0700122 # Checking the test_target option set for the component or not
Jon Hall714eeba2015-09-29 17:53:10 -0700123 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700124 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700125 if 'test_target' in self.componentDictionary[ component ].keys():
adminbae64d82013-08-01 10:50:15 -0700126 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700127
Jon Halld61331b2015-02-17 16:35:47 -0800128 # Checking for the openspeak file and test script
Jon Hall714eeba2015-09-29 17:53:10 -0700129 self.logger.initlog( self )
adminbae64d82013-08-01 10:50:15 -0700130
131 # Creating Drivers Handles
Jon Hall714eeba2015-09-29 17:53:10 -0700132 initString = "\n" + "*" * 30 + "\n CASE INIT \n" + "*" * 30 + "\n"
133 self.log.exact( initString )
adminbae64d82013-08-01 10:50:15 -0700134 self.driverObject = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700135 self.random_order = 111 # Random order id to connect the components
adminbae64d82013-08-01 10:50:15 -0700136 components_connect_order = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700137 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700138 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700139 if 'connect_order' not in self.componentDictionary[ component ].keys():
140 self.componentDictionary[ component ][ 'connect_order' ] = str( self.get_random() )
141 components_connect_order[ component ] = eval( self.componentDictionary[ component ][ 'connect_order' ] )
Jon Hall714eeba2015-09-29 17:53:10 -0700142 # Ordering components based on the connect order.
143 ordered_component_list = sorted( components_connect_order,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700144 key=lambda key: components_connect_order[ key ] )
adminbae64d82013-08-01 10:50:15 -0700145 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700146 for component in ordered_component_list:
Jon Hall714eeba2015-09-29 17:53:10 -0700147 self.componentInit( component )
adminbae64d82013-08-01 10:50:15 -0700148
Jon Hall714eeba2015-09-29 17:53:10 -0700149 def configparser( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000150 '''
151 It will parse the config file (teston.cfg) and return as dictionary
152 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700153 matchFileName = re.match( r'(.*)\.cfg', self.configFile, re.M | re.I )
adminbae64d82013-08-01 10:50:15 -0700154 if matchFileName:
Jon Hall714eeba2015-09-29 17:53:10 -0700155 xml = open( self.configFile ).read()
156 try:
157 self.configDict = xmldict.xml_to_dict( xml )
adminbae64d82013-08-01 10:50:15 -0700158 return self.configDict
Jon Hall1306a562015-09-04 11:21:24 -0700159 except IOError:
adminbae64d82013-08-01 10:50:15 -0700160 print "There is no such file to parse " + self.configFile
Jon Hall1306a562015-09-04 11:21:24 -0700161 else:
162 print "There is no such file to parse " + self.configFile
kelvin-onlabf70fd542015-05-07 18:41:40 -0700163
Jon Hall714eeba2015-09-29 17:53:10 -0700164 def componentInit( self, component ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000165 '''
adminbae64d82013-08-01 10:50:15 -0700166 This method will initialize specified component
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000167 '''
adminbae64d82013-08-01 10:50:15 -0700168 global driver_options
Jon Hall0fc0d452015-07-14 09:49:58 -0700169 self.initiated = False
Jon Hall714eeba2015-09-29 17:53:10 -0700170 self.log.info( "Creating component Handle: " + component )
Jon Halld61331b2015-02-17 16:35:47 -0800171 driver_options = {}
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700172 if 'COMPONENTS' in self.componentDictionary[ component ].keys():
173 driver_options = dict( self.componentDictionary[ component ][ 'COMPONENTS' ] )
174 driver_options[ 'name' ] = component
175 driverName = self.componentDictionary[ component ][ 'type' ]
176 driver_options[ 'type' ] = driverName
kelvin-onlabf70fd542015-05-07 18:41:40 -0700177
Jon Hall714eeba2015-09-29 17:53:10 -0700178 classPath = self.getDriverPath( driverName.lower() )
179 driverModule = importlib.import_module( classPath )
180 driverClass = getattr( driverModule, driverName )
adminbae64d82013-08-01 10:50:15 -0700181 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700182
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700183 if "OCN" in self.componentDictionary[ component ][ 'host' ] and\
Jon Hall714eeba2015-09-29 17:53:10 -0700184 main.onoscell:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700185 self.componentDictionary[ component ][ 'host' ] = main.mnIP
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700186
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700187 user_name = self.componentDictionary[ component ].get( 'user', getpass.getuser() )
188 ip_address = self.componentDictionary[ component ].get( 'host', 'localhost' )
189 pwd = self.componentDictionary[ component ].get( 'password', 'changeme' )
190 port = self.componentDictionary[ component ].get( 'port' )
Jon Hall714eeba2015-09-29 17:53:10 -0700191 connect_result = driverObject.connect( user_name=user_name,
192 ip_address=ip_address,
193 pwd=pwd,
194 port=port,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700195 options=driver_options )
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700196
adminbae64d82013-08-01 10:50:15 -0700197 if not connect_result:
Jon Hall714eeba2015-09-29 17:53:10 -0700198 self.log.error( "Exiting from the test execution because connecting to the " +
199 component + " component failed." )
Jon Halld61331b2015-02-17 16:35:47 -0800200 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700201
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700202 vars( self )[ component ] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700203 self.initiated = True
Jon Hallca319892017-06-15 15:25:22 -0700204 return driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700205
Jon Hall714eeba2015-09-29 17:53:10 -0700206 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000207 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700208 The Execution of the test script's cases listed in the Test params
209 file will be done here then update each test case result.
210 This method will return main.TRUE if it executed all the test cases
211 successfully, else will retun main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000212 '''
adminbae64d82013-08-01 10:50:15 -0700213 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700214 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700215 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800216 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700217 self.TOTAL_TC_NORESULT = 0
218 self.TOTAL_TC_FAIL = 0
219 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700220 self.TEST_ITERATION = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700221
222 # NOTE: number of main.step statements in the
223 # outer most level of the test case. used to
224 # execute code in smaller steps
225 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700226 self.CASERESULT = self.NORESULT
227
Jon Halld61331b2015-02-17 16:35:47 -0800228 import testparser
Jon Hall53c5e662016-04-13 16:06:56 -0700229 test = testparser.TestParser( main.testFile )
adminbae64d82013-08-01 10:50:15 -0700230 self.testscript = test.testscript
231 self.code = test.getStepCode()
Jon Hall714eeba2015-09-29 17:53:10 -0700232 repeat = int( self.params.get( 'repeat', 1 ) )
233 self.TOTAL_TC_PLANNED = len( self.testcases_list ) * repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700234
adminbae64d82013-08-01 10:50:15 -0700235 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700236 while repeat:
Devin Limec989792017-08-15 15:57:55 -0700237 self.leftCase.extend( self.testcases_list )
Jon Halla1185982014-09-15 14:55:10 -0700238 for self.CurrentTestCaseNumber in self.testcases_list:
Devin Limec989792017-08-15 15:57:55 -0700239 self.executedCase.append( self.leftCase.pop( 0 ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700240 result = self.runCase( self.CurrentTestCaseNumber )
241 repeat -= 1
adminbae64d82013-08-01 10:50:15 -0700242 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700243
Jon Halle234cc42015-08-31 15:26:47 -0700244 def runCase( self, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700245 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700246 self.CurrentTestCase = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700247
248 # List of step results in a case. ANDed together to get the result
249 self.stepResultsList = []
kelvin-onlabf70fd542015-05-07 18:41:40 -0700250 self.stepName = ""
Jon Hall783bbf92015-07-23 14:33:19 -0700251 self.caseExplanation = ""
adminbae64d82013-08-01 10:50:15 -0700252 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700253
254 # NOTE: number of main.step statements in the
255 # outer most level of the test case. used to
256 # execute code in smaller steps
257 self.stepCount = 0
258
259 # NOTE: This is the current number of main.step()'s executed
260 # in a case. Used for logging.
261 self.stepNumber = 0
adminbae64d82013-08-01 10:50:15 -0700262 self.EXPERIMENTAL_MODE = self.FALSE
263 self.addCaseHeader()
Devin Limec989792017-08-15 15:57:55 -0700264 self.log.debug( "Case Executed : " + str( self.executedCase ) )
265 self.log.debug( "Case to be executed : " + str( self.leftCase ) )
Jon Halle234cc42015-08-31 15:26:47 -0700266 self.testCaseNumber = str( testCaseNumber )
267 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700268 stopped = False
Jon Hall5a72b712015-09-28 12:20:59 -0700269 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700270 self.code[ self.testCaseNumber ]
Jon Halld61331b2015-02-17 16:35:47 -0800271 except KeyError:
Jon Halle234cc42015-08-31 15:26:47 -0700272 self.log.error( "There is no Test-Case " + self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800273 return self.FALSE
adminbae64d82013-08-01 10:50:15 -0700274 self.stepCount = 0
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700275 while self.stepCount < len( self.code[ self.testCaseNumber ].keys() ):
Jon Hall714eeba2015-09-29 17:53:10 -0700276 result = self.runStep( self.code, self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800277 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700278 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800279 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700280 continue
Jon Hall5a72b712015-09-28 12:20:59 -0700281 # stepResults format: ( stepNo[], stepName[], stepResult[], onFail[] )
282 stepResults = self.stepResultsList
Jon Halle234cc42015-08-31 15:26:47 -0700283 if not stopped:
284 if self.CASERESULT == self.TRUE or self.CASERESULT == self.FALSE:
Jon Hall714eeba2015-09-29 17:53:10 -0700285 # Result was already explitily set somewhere else like
286 # in skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700287 pass
Jon Hall5a72b712015-09-28 12:20:59 -0700288 elif all( self.TRUE == i for i in stepResults ):
kelvin-onlabf70fd542015-05-07 18:41:40 -0700289 # ALL PASSED
290 self.CASERESULT = self.TRUE
Jon Hall5a72b712015-09-28 12:20:59 -0700291 elif self.FALSE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700292 # AT LEAST ONE FAILED
293 self.CASERESULT = self.FALSE
Jon Hall5a72b712015-09-28 12:20:59 -0700294 elif self.TRUE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700295 # AT LEAST ONE PASSED
296 self.CASERESULT = self.TRUE
297 else:
298 self.CASERESULT = self.NORESULT
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700299 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.CASERESULT
Devin Limec989792017-08-15 15:57:55 -0700300 self.organizeResult( self.CurrentTestCaseNumber, self.CASERESULT )
Jon Hall714eeba2015-09-29 17:53:10 -0700301 self.logger.updateCaseResults( self )
Jon Hall783bbf92015-07-23 14:33:19 -0700302 self.log.wiki( "<p>" + self.caseExplanation + "</p>" )
303 self.log.summary( self.caseExplanation )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700304 self.log.wiki( "<ul>" )
acsmarse2d1ed12015-10-05 13:51:17 -0700305 subcaseMessage = False
kelvin-onlabf70fd542015-05-07 18:41:40 -0700306 for line in self.stepCache.splitlines():
acsmarse2d1ed12015-10-05 13:51:17 -0700307 if re.search( "[0-9]\.[0-9]", line ): # Step
308 if subcaseMessage: # End of Failure Message Printout
309 self.log.wiki( "</ul>\n" )
310 subcaseMessage = False
311 if re.search( " - PASS$", line ):
312 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
313 elif re.search( " - FAIL$", line ):
314 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
315 elif re.search( " - No Result$", line ):
316 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
317 else: # Substep
318 if not subcaseMessage: # Open Failure Message Printout
319 self.log.wiki( "<ul><li>" + line + "</li>\n" )
320 subcaseMessage = True
321 else: # Add to Failure Message Printout
322 self.log.wiki( "<li>" + line + "</li>\n" )
acsmars27e62dd2015-10-06 11:35:47 -0700323 if subcaseMessage: # End of Failure Message Printout for last item
324 self.log.wiki( "</ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700325 self.log.wiki( "</ul>" )
326 self.log.summary( self.stepCache )
327 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700328 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700329
Devin Limec989792017-08-15 15:57:55 -0700330 def organizeResult( self, caseNum, result ):
331 """
332 Organize the result and put the current number into either
333 failed/noResult lists.
334 * caseNum - number of the case
335 * result - result of the case
336 """
337 if result == main.FALSE:
338 self.failedCase.append( caseNum )
339 elif result == self.NORESULT:
340 self.noResultCase.append( caseNum )
341
Jon Hall714eeba2015-09-29 17:53:10 -0700342 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700343 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700344 try:
345 step = self.stepCount
346 # stepResults format: ( stepNo, stepName, stepResult, onFail )
347 # NOTE: This is needed to catch results of main.step()'s
348 # called inside functions or loops
349 self.stepResults = ( [], [], [], [] )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700350 exec code[ testCaseNumber ][ step ] in module.__dict__
adminbae64d82013-08-01 10:50:15 -0700351 self.stepCount = self.stepCount + 1
Jon Hall96b816f2015-11-03 12:00:56 -0800352 self.parseStepResults( testCaseNumber )
Jon Hallca319892017-06-15 15:25:22 -0700353 except SkipCase: # Raised in self.skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700354 self.log.warn( "Skipping the rest of CASE" +
355 str( testCaseNumber ) )
Jon Hall96b816f2015-11-03 12:00:56 -0800356 self.parseStepResults( testCaseNumber )
Jon Hall714eeba2015-09-29 17:53:10 -0700357 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700358 self.stepCache += "\t\t" + self.onFailMsg + "\n"
359 self.stepCount = self.stepCount + 1
360 return self.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000361 except StandardError as e:
Jon Hallc1606352015-10-06 14:51:36 -0700362 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700363 stepNo = self.stepResults[ 0 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700364 except IndexError:
365 stepNo = "<IndexError>"
366 main.log.warn( "Error trying to get step number. " +
367 "It is likely between step " +
Jon Hall6e709752016-02-01 13:38:46 -0800368 str( self.stepNumber ) + " and step " +
Jon Hallc1606352015-10-06 14:51:36 -0700369 str( self.stepNumber + 1 ) )
370 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700371 stepName = self.stepResults[ 1 ][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700372 except IndexError:
373 stepName = "<IndexError>"
374 self.log.error( "\nException in the following section of" +
375 " code: " + str( testCaseNumber ) + "." +
376 str( stepNo ) + ": " + stepName )
Jeremyd9e4eb12016-04-13 12:09:06 -0700377 self.log.error( str( e.__class__ ) + str( e.message ) )
adminbae64d82013-08-01 10:50:15 -0700378 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700379 self.logger.updateCaseResults( self )
380 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700381 self.log.wiki( "<ul>" )
382 for line in self.stepCache.splitlines():
383 if re.search( " - PASS$", line ):
384 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
385 elif re.search( " - FAIL$", line ):
386 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
387 elif re.search( " - No Result$", line ):
388 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700389 else: # Should only be on fail message
390 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700391 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700392 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700393 self.log.summary( self.stepCache )
394 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700395 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700396 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700397 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700398 if cli.stop:
399 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700400 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700401 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = "Stopped"
Jon Hall714eeba2015-09-29 17:53:10 -0700402 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700403 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700404 return self.FALSE
405
Jon Hall96b816f2015-11-03 12:00:56 -0800406 def parseStepResults( self, testCaseNumber ):
407 """
408 Parse throught the step results for the wiki
409 """
410 try:
411 # Iterate through each of the steps and print them
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700412 for index in range( len( self.stepResults[ 0 ] ) ):
Jon Hall96b816f2015-11-03 12:00:56 -0800413 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700414 stepNo = self.stepResults[ 0 ][ index ]
415 stepName = self.stepResults[ 1 ][ index ]
416 stepResult = self.stepResults[ 2 ][ index ]
417 onFail = self.stepResults[ 3 ][ index ]
Jon Hall96b816f2015-11-03 12:00:56 -0800418 self.stepCache += "\t" + str( testCaseNumber ) + "."
419 self.stepCache += str( stepNo ) + " "
420 self.stepCache += stepName + " - "
421 if stepResult == self.TRUE:
422 self.stepCache += "PASS\n"
423 elif stepResult == self.FALSE:
424 self.stepCache += "FAIL\n"
425 self.stepCache += "\t\t" + onFail + "\n"
426 else:
427 self.stepCache += "No Result\n"
428 self.stepResultsList.append( stepResult )
429 except Exception:
430 self.log.exception( "Error parsing step results" )
431
Jon Halle234cc42015-08-31 15:26:47 -0700432 def skipCase( self, result="DEFAULT", msg=None ):
433 """
434 Will skip the rest of the code in a test case. The case results will be
435 determined as normal based on completed assertions unless the result
436 argument is given.
437
438 Optional Arguments:
Jon Hall7c4f4302016-07-15 14:39:02 -0700439 result: Case insensitive string. Can be 'PASS' or 'FAIL' and will set
Jon Halle234cc42015-08-31 15:26:47 -0700440 the case result accordingly.
441 msg: Message to be printed when the case is skipped in the reports.
442 """
443 result = result.upper().strip()
444 if result == "PASS":
445 self.CASERESULT = self.TRUE
446 elif result == "FAIL":
447 self.CASERESULT = self.FALSE
448 self.onFailMsg = "Skipping the rest of this case. "
449 if msg:
450 self.onFailMsg += str( msg )
Jon Hallca319892017-06-15 15:25:22 -0700451 raise SkipCase
kelvin-onlabf70fd542015-05-07 18:41:40 -0700452
Jon Hall714eeba2015-09-29 17:53:10 -0700453 def addCaseHeader( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700454 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700455 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
456 self.log.exact( caseHeader )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700457 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" + \
Jon Hall714eeba2015-09-29 17:53:10 -0700458 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700459 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700460 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700461
Jon Hall714eeba2015-09-29 17:53:10 -0700462 def addCaseFooter( self ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700463 stepNo = self.stepResults[ 0 ][ -2 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700464 if stepNo > 0:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700465 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700466 str( stepNo ) + ": " + str( self.stepName )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700467 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep + \
Jon Hall714eeba2015-09-29 17:53:10 -0700468 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700469
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700470 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700471 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700472
adminbae64d82013-08-01 10:50:15 -0700473 for driver in self.driversList:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700474 vars( self )[ driver ].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700475
Jon Hall714eeba2015-09-29 17:53:10 -0700476 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000477 '''
Jon Hall5b586732015-06-11 11:39:39 -0700478 Print a summary of the current test's results then attempt to release
479 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700480
Jon Hall5b586732015-06-11 11:39:39 -0700481 This function shouldbe threadsafe such that cleanup will only be
482 executed once per test.
483
484 This will return TRUE if all the component handles and log handles
485 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000486 '''
adminbae64d82013-08-01 10:50:15 -0700487 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700488 lock = self.cleanupLock
489 if lock.acquire( False ):
490 try:
491 if self.cleanupFlag is False: # First thread to run this
492 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700493 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700494 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700495 components = self.componentDictionary
496 for component in sorted( components,
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700497 key=lambda item: components[ item ][ 'connect_order' ],
Jon Hall892818c2015-10-20 17:58:34 -0700498 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700499 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700500 tempObject = vars( self )[ component ]
501 print "Disconnecting from " + str( tempObject.name ) + \
502 ": " + str( tempObject.__class__ )
Jon Hall5b586732015-06-11 11:39:39 -0700503 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700504 except KeyboardInterrupt:
505 pass
506 except KeyError:
507 # Component not created yet
508 self.log.warn( "Could not find the component " +
509 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000510 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700511 self.log.exception( "Exception while disconnecting from " +
512 str( component ) )
513 result = self.FALSE
514 # Closing all the driver's session files
515 for driver in self.componentDictionary.keys():
516 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700517 vars( self )[ driver ].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700518 except KeyboardInterrupt:
519 pass
520 except KeyError:
521 # Component not created yet
522 self.log.warn( "Could not find the component " +
523 str( driver ) + " while trying to" +
524 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000525 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700526 self.log.exception( "Exception while closing log files for " +
527 str( driver ) )
528 result = self.FALSE
529 else:
530 pass # Someone else already ran through this function
531 finally:
532 lock.release()
533 else: # Someone already has a lock
534 # NOTE: This could cause problems if we don't release the lock
535 # correctly
536 lock.acquire() # Wait for the other thread to finish
537 # NOTE: If we don't wait, exit could be called while the thread
538 # with the lock is still cleaning up
539 lock.release()
adminbae64d82013-08-01 10:50:15 -0700540 return result
Jon Halld61331b2015-02-17 16:35:47 -0800541
Jon Hall714eeba2015-09-29 17:53:10 -0700542 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000543 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700544 This function will pause the test's execution, and will continue after
545 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000546 '''
adminbae64d82013-08-01 10:50:15 -0700547 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700548
Jon Hall714eeba2015-09-29 17:53:10 -0700549 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000550 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700551 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000552 '''
adminbae64d82013-08-01 10:50:15 -0700553 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700554 try:
adminbae64d82013-08-01 10:50:15 -0700555 for component in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700556 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700557 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000558 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700559 print str( e )
adminbae64d82013-08-01 10:50:15 -0700560 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700561 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700562 try:
adminbae64d82013-08-01 10:50:15 -0700563 for component in components:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700564 tempObject = vars( self )[ component ]
adminbae64d82013-08-01 10:50:15 -0700565 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000566 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700567 print str( e )
adminbae64d82013-08-01 10:50:15 -0700568 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700569
Jon Hall714eeba2015-09-29 17:53:10 -0700570 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000571 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700572 Based on the component 'type' specified in the params , this method
573 will find the absolute path, by recursively searching the name of
574 the component.
575
576 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000577 '''
adminbae64d82013-08-01 10:50:15 -0700578 import commands
579
Jon Hall714eeba2015-09-29 17:53:10 -0700580 cmd = "find " + drivers_path + " -name " + driverName + ".py"
581 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700582
Jon Hall714eeba2015-09-29 17:53:10 -0700583 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700584 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700585
adminbae64d82013-08-01 10:50:15 -0700586 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700587 result_count = result_count + 1
588 if result_count > 1:
589 print "Found " + driverName + " " + str( result_count ) + " times:"
590 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700591 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700592
Jon Hall714eeba2015-09-29 17:53:10 -0700593 result = re.sub( "(.*)drivers", "", result )
594 result = re.sub( "\/\/", "/", result )
595 result = re.sub( "\.py", "", result )
596 result = re.sub( "\.pyc", "", result )
597 result = re.sub( "\/", ".", result )
598 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700599 return result
adminbae64d82013-08-01 10:50:15 -0700600
Jon Hall714eeba2015-09-29 17:53:10 -0700601 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000602 '''
adminbae64d82013-08-01 10:50:15 -0700603 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000604 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700605 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700606 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700607 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700608 self.stepNumber += 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700609 self.stepResults[ 0 ].append( self.stepNumber )
610 self.stepResults[ 1 ].append( stepDesc )
611 self.stepResults[ 2 ].append( self.NORESULT )
612 self.stepResults[ 3 ].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700613
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700614 stepName = " " + str( self.CurrentTestCaseNumber ) + "." + \
Jon Hall714eeba2015-09-29 17:53:10 -0700615 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700616 self.log.step( stepName )
adminbae64d82013-08-01 10:50:15 -0700617 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700618 line = "\n" + "-" * 45 + "\n"
619 if self.stepNumber > 1:
620 stepHeader = line + "End of Step " + previousStep + line
621 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700622 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700623 vars( self )[ driver + 'log' ].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700624
Jon Hall714eeba2015-09-29 17:53:10 -0700625 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000626 '''
adminbae64d82013-08-01 10:50:15 -0700627 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000628 '''
Jon Halld61331b2015-02-17 16:35:47 -0800629 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700630 testCaseName = " " + str( testCaseName )
631 self.log.case( testCaseName )
632 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700633 for driver in self.componentDictionary.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700634 vars( self )[ driver + 'log' ].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700635
Jon Hall714eeba2015-09-29 17:53:10 -0700636 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000637 '''
adminbae64d82013-08-01 10:50:15 -0700638 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000639 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700640 description = "Test Description : " + str( description )
641 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700642
Jon Hall714eeba2015-09-29 17:53:10 -0700643 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000644 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700645 This method will parse the test script to find required test
646 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000647 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700648 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700649 testFileList = testFileHandler.readlines()
650 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700651 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700652 for index in range( len( testFileList ) ):
653 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700654 testFileList[ index ],
Jon Hall714eeba2015-09-29 17:53:10 -0700655 0 )
adminbae64d82013-08-01 10:50:15 -0700656 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700657 counter = counter + 1
658 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700659
Jon Hall714eeba2015-09-29 17:53:10 -0700660 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000661 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700662 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700663 response_dict = self.response_to_dict( response, return_format )
664 return_format_string = self.dict_to_return_format( response,
665 return_format,
666 response_dict )
adminbae64d82013-08-01 10:50:15 -0700667 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700668
Jon Hall714eeba2015-09-29 17:53:10 -0700669 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700670 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700671 json_match = re.search( '^\s*{', response )
672 xml_match = re.search( '^\s*\<', response )
673 ini_match = re.search( '^\s*\[', response )
674 if json_match:
675 self.log.info( "Response is in 'JSON' format, converting to '" +
676 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800677 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000678 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700679 response = re.sub( r",\s*'?(\w)", r',"\1', response )
680 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
681 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
682 try:
adminbae64d82013-08-01 10:50:15 -0700683 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700684 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000685 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700686 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700687 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700688 elif ini_match:
689 self.log.info( "Response is in 'INI' format, converting to '" +
690 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700691 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700692 response_file = open( "respnse_file.temp", 'w' )
693 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800694 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700695 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700696 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700697 elif xml_match:
698 self.log.info( "Response is in 'XML' format, converting to '" +
699 return_format + "' format" )
700 try:
701 response_dict = xmldict.xml_to_dict( "<response> " +
702 str( response ) +
703 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000704 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700705 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700706 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700707
Jon Hall714eeba2015-09-29 17:53:10 -0700708 def dict_to_return_format( self, response, return_format, response_dict ):
709 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000710 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700711 to_do = "Call the table output formatter"
712 global response_table
713 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700714 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700715
Jon Hall714eeba2015-09-29 17:53:10 -0700716 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000717 ''' This will parse the dictionary recusrsively and print as
718 table format'''
adminbae64d82013-08-01 10:50:15 -0700719 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700720 if isinstance( value_to_convert, dict ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700721 table_data = table_data + '\t'.join( value_to_convert ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700722 "\n"
723 for temp_val in value_to_convert.values():
724 table_data = table_data + get_table( temp_val )
725 else:
726 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800727 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700728
Jon Hall714eeba2015-09-29 17:53:10 -0700729 for value in response_dict.values():
730 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700731 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700732
Jon Hall714eeba2015-09-29 17:53:10 -0700733 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000734 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700735 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700736 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700737 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700738 response_config = re.sub( ",", "\n\t", response_string )
739 response_config = re.sub( "u\'", "\'", response_config )
740 response_config = re.sub( "{", "", response_config )
741 response_config = re.sub( "}", "\n", response_config )
742 response_config = re.sub( ":", " =", response_config )
743 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700744 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000745 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700746 response_xml = xmldict.dict_to_xml( response_dict )
747 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
748 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700749 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000750 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700751 to_do = 'Call dict to xml coverter'
752 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700753 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700754 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700755
Jon Hall714eeba2015-09-29 17:53:10 -0700756 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700757 self.random_order = self.random_order + 1
758 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700759
Jon Hall714eeba2015-09-29 17:53:10 -0700760 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700761 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700762 for thread in threading.enumerate():
763 if thread.isAlive():
764 try:
765 thread._Thread__stop()
766 except:
Jon Hall1306a562015-09-04 11:21:24 -0700767 # NOTE: We should catch any exceptions while trying to
768 # close the thread so that we can try to close the other
769 # threads as well
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700770 print str( thread.getName() ) + \
Jon Hall714eeba2015-09-29 17:53:10 -0700771 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700772 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700773 sys.exit()
774
Devin Lim44075962017-08-11 10:56:37 -0700775 def cleanAndExit( self ):
776 """
777 It will set the testcase result to be FAILED and update it
778 before cleaning up and exitting the test.
779 :return:
780 """
781 if self.CurrentTestCaseNumber:
782 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700783 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700784 self.logger.updateCaseResults( self )
785 self.cleanup()
786 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700787
Jon Hallcd3d2a32015-10-01 11:07:28 -0700788 def stop( self, email=False ):
789 """
790 Stop the test until Ctrl-D is entered.
791 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700792
793 Optional arguments:
794 email can either be a bool, or you can specify the email address
795 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700796 """
797 try:
798 if email:
Jon Hall25079782015-10-13 13:54:39 -0700799 if '@' in email:
800 main.mail = email
801 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700802 self.log.debug( "Test execution suspended. \n"
803 "- Type 'c' to resume the test.\n"
804 "- Type Ctrl-C to exit the test.\n"
805 "- Enter interactive python interpreter commands.\n"
806 "\t- ie: main.Mininet1.pingall()\n"
807 "- Type 'help' for help with pdb." )
808 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700809 except EOFError:
810 return
811 # Pass all other exceptions up to caller
812
813
Jon Hall714eeba2015-09-29 17:53:10 -0700814def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000815 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700816 This will verify the command line options and set to default values,
817 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000818 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700819 verifyTest( options )
820 verifyExample( options )
821 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700822 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700823 verifyLogdir( options )
824 verifyMail( options )
825 verifyTestCases( options )
826 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700827
Jon Hall714eeba2015-09-29 17:53:10 -0700828def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700829 try:
830 if options.testname:
831 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700832 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700833 main.tests_path = tests_path
834 elif options.example:
835 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700836 main.tests_path = path + "/examples/"
837 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700838 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700839 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700840 main.exit()
adminbae64d82013-08-01 10:50:15 -0700841
Jon Hall714eeba2015-09-29 17:53:10 -0700842def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700843 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700844 main.testDir = path + '/examples/'
845 main.tests_path = path + "/examples/"
846 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700847
Jon Hall714eeba2015-09-29 17:53:10 -0700848def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800849 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700850 if options.logdir:
851 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700852 else:
Jon Halld61331b2015-02-17 16:35:47 -0800853 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700854
Jon Hall714eeba2015-09-29 17:53:10 -0700855def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700856 # Mail-To: field
857 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700858 main.mail = options.mail
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700859 elif main.params.get( 'mail' ): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700860 main.mail = main.params.get( 'mail' )
861 else: # TestON specific
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700862 main.mail = main.config[ 'config' ].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700863 # Mail-From: field
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700864 main.sender = main.config[ 'config' ].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700865 # Mail smtp server
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700866 main.smtp = main.config[ 'config' ].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700867 # Mail-From account password
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700868 main.senderPwd = main.config[ 'config' ].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700869
Devin Lim2df68a12017-06-30 15:39:05 -0700870def evalTestCase( tempList ):
871 tList = []
872 for tcase in tempList:
873 if isinstance( tcase, list ):
874 tList.extend( evalTestCase( tcase ) )
875 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700876 tList.extend( [ tcase ] )
Devin Lim2df68a12017-06-30 15:39:05 -0700877 return tList
adminbae64d82013-08-01 10:50:15 -0700878
Jon Hall714eeba2015-09-29 17:53:10 -0700879def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800880 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700881 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800882 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800883 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700884 testcases_list = re.sub( "(\[|\])", "", options.testcases )
885 main.testcases_list = eval( testcases_list + "," )
886 else:
adminbae64d82013-08-01 10:50:15 -0700887 if 'testcases' in main.params.keys():
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700888 temp = eval( main.params[ 'testcases' ] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700889 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700890 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700891 print "Testcases not specifed in params, please provide in " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700892 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800893 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700894
Jon Hall714eeba2015-09-29 17:53:10 -0700895def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700896 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700897 if options.onoscell:
898 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700899 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700900 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700901 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700902 output = subprocess.check_output( [ "bash", '-c', cellCMD ] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700903 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700904 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700905 for i in range( len( splitOutput ) ):
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700906 if re.match( "OCN", splitOutput[ i ] ):
907 mnNode = splitOutput[ i ].split( "=" )
908 main.mnIP = mnNode[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700909 # cell already sorts OC variables in bash, so no need to
910 # sort in TestON
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700911 elif re.match( "OC[1-9]", splitOutput[ i ] ):
912 onosNodes = splitOutput[ i ].split( "=" )
913 main.ONOSip.append( onosNodes[ 1 ] )
914 elif re.match( "ONOS_APPS", splitOutput[ i ] ):
915 main.apps = ( splitOutput[ i ].split( "=" ) )[ 1 ]
Jon Hall714eeba2015-09-29 17:53:10 -0700916 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700917 main.onoscell = main.FALSE
918
Jon Hall714eeba2015-09-29 17:53:10 -0700919def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000920 '''
adminbae64d82013-08-01 10:50:15 -0700921 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000922 '''
Jon Halld61331b2015-02-17 16:35:47 -0800923 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700924 directory = main.testDir + "/" + main.TEST
925 if os.path.exists( directory ):
926 pass
927 else:
928 directory = ""
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700929 for root, dirs, files in os.walk( main.testDir, topdown=True ):
Jon Hall53c5e662016-04-13 16:06:56 -0700930 if not directory:
931 for name in dirs:
932 if name == main.TEST:
933 directory = ( os.path.join( root, name ) )
934 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700935 main.classPath = directory[ index: ].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700936 break
937 openspeakfile = directory + "/" + main.TEST + ".ospk"
938 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700939 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700940 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700941 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700942 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700943 # No openspeak found, using python file instead
944 pass
adminbae64d82013-08-01 10:50:15 -0700945 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700946 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " + \
947 "Python or OpenSpeak test script in the tests folder: " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700948 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700949 __builtin__.testthread = None
950 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700951 try:
952 testModule = __import__( main.classPath,
953 globals(),
954 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700955 [ main.TEST ],
Jon Hall714eeba2015-09-29 17:53:10 -0700956 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700957 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700958 print "There was an import error, it might mean that there is " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700959 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800960 main.exit()
adminbae64d82013-08-01 10:50:15 -0700961
Jon Hall714eeba2015-09-29 17:53:10 -0700962 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700963 main.testObject = testClass()
964 load_parser()
Jon Hall714eeba2015-09-29 17:53:10 -0700965 main.params = main.parser.parseParams( main.classPath )
966 main.topology = main.parser.parseTopology( main.classPath )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700967
YPZhang1c89e762016-06-29 10:43:58 -0700968def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -0700969 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700970 main.params = main.params[ 'PARAMS' ]
Jon Hall1306a562015-09-04 11:21:24 -0700971 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700972 print "Error with the params file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700973 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800974 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700975 try:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700976 main.topology = main.topology[ 'TOPOLOGY' ]
Jon Hall1306a562015-09-04 11:21:24 -0700977 except KeyError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700978 print "Error with the Topology file: Either the file not specified " + \
Jon Hall714eeba2015-09-29 17:53:10 -0700979 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700980 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -0700981 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700982 if len( options.params ) > 0:
YPZhang1c89e762016-06-29 10:43:58 -0700983 # Some params variables are specified from command line
984 for param in options.params:
985 if not re.search( ".=.", param ):
986 print( "Error when parsing params: params should follow key=value format" )
987 continue
Jon Hall7c4f4302016-07-15 14:39:02 -0700988 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -0700989 [ keys, value ] = param.split( "=" )
990 # Split the nested keys according to its hierarchy
991 keyList = keys.split( "/" )
992 # Get the outermost dictionary
993 paramDict = main.params
994 # Get the innermost dictionary
995 try:
996 while len( keyList ) > 1:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -0700997 key = keyList.pop( 0 )
YPZhang1c89e762016-06-29 10:43:58 -0700998 assert isinstance( paramDict[ key ], dict )
999 paramDict = paramDict[ key ]
1000 except KeyError:
1001 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1002 main.exit()
1003 except AssertionError:
1004 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1005 main.exit()
1006 # Change the value
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001007 if keyList[ 0 ] not in paramDict:
1008 print( "Error when parsing params: key \"" + keyList[ 0 ] + "\" not found in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001009 main.exit()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001010 elif isinstance( paramDict[ keyList[ 0 ] ], dict ):
1011 print( "Error when parsing params: more levels under key \"" + keyList[ 0 ] + "\" in main.params" )
YPZhang1c89e762016-06-29 10:43:58 -07001012 main.exit()
1013 else:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001014 paramDict[ keyList[ 0 ] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001015
Jon Hall714eeba2015-09-29 17:53:10 -07001016def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001017 '''
adminbae64d82013-08-01 10:50:15 -07001018 It facilitates the loading customised parser for topology and params file.
1019 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001020 It also loads default xmlparser if no parser have specified in teston.cfg
1021 file.
adminbae64d82013-08-01 10:50:15 -07001022
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001023 '''
adminbae64d82013-08-01 10:50:15 -07001024 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001025 if 'file' in confighash[ 'config' ][ 'parser' ] and\
1026 'class' in confighash[ 'config' ][ 'parser' ]:
1027 path = confighash[ 'config' ][ 'parser' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001028 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001029 confighash[ 'config' ][ 'parser' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001030 try:
1031 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001032 moduleList = module.split( "/" )
1033 newModule = ".".join( moduleList[ -2: ] )
1034 parsingClass = confighash[ 'config' ][ 'parser' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001035 parsingModule = __import__( newModule,
1036 globals(),
1037 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001038 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001039 -1 )
1040 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001041 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -07001042 if hasattr( main.parser, "parseParams" ) and\
1043 hasattr( main.parser, "parseTopology" ) and\
1044 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -07001045 pass
1046 else:
1047 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -07001048 main.exit()
Jon Hall44506242015-07-29 17:40:26 -07001049 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001050 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001051 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001052 load_defaultParser()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001053 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1054 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001055 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -07001056 else:
1057 load_defaultParser()
1058
1059def load_defaultParser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001060 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001061 It will load the default parser which is xml parser to parse the params and
1062 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001063 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001064 moduleList = main.parserPath.split( "/" )
1065 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001066 try:
Jon Halld61331b2015-02-17 16:35:47 -08001067 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -07001068 parsingModule = __import__( newModule,
1069 globals(),
1070 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001071 [ parsingClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001072 -1 )
1073 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -07001074 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -07001075 if hasattr( main.parser, "parseParams" ) and\
1076 hasattr( main.parser, "parseTopology" ) and\
1077 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001078 pass
1079 else:
1080 main.exit()
adminbae64d82013-08-01 10:50:15 -07001081 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001082 print sys.exc_info()[ 1 ]
adminbae64d82013-08-01 10:50:15 -07001083
Jon Hall714eeba2015-09-29 17:53:10 -07001084def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001085 '''
adminbae64d82013-08-01 10:50:15 -07001086 It facilitates the loading customised parser for topology and params file.
1087 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001088 It also loads default xmlparser if no parser have specified in teston.cfg
1089 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001090 '''
adminbae64d82013-08-01 10:50:15 -07001091 confighash = main.configDict
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001092 if 'file' in confighash[ 'config' ][ 'logger' ] and\
1093 'class' in confighash[ 'config' ][ 'logger' ]:
1094 path = confighash[ 'config' ][ 'logger' ][ 'file' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001095 if path is not None or\
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001096 confighash[ 'config' ][ 'logger' ][ 'class' ] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001097 try:
1098 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001099 moduleList = module.split( "/" )
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001100 newModule = ".".join( moduleList[ -2: ] )
1101 loggerClass = confighash[ 'config' ][ 'logger' ][ 'class' ]
Jon Hall714eeba2015-09-29 17:53:10 -07001102 loggerModule = __import__( newModule,
1103 globals(),
1104 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001105 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001106 -1 )
1107 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001108 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001109 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001110 print "Could not find the file " + path + \
Jon Hall714eeba2015-09-29 17:53:10 -07001111 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001112 load_defaultlogger()
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001113 elif confighash[ 'config' ][ 'parser' ][ 'file' ] is None or\
1114 confighash[ 'config' ][ 'parser' ][ 'class' ] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001115 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001116 else:
1117 load_defaultlogger()
1118
1119def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001120 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001121 It will load the default parser which is xml parser to parse the params and
1122 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001123 '''
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001124 moduleList = main.loggerPath.split( "/" )
1125 newModule = ".".join( moduleList[ -2: ] )
Jon Hall714eeba2015-09-29 17:53:10 -07001126 try:
Jon Halld61331b2015-02-17 16:35:47 -08001127 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001128 loggerModule = __import__( newModule,
1129 globals(),
1130 locals(),
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001131 [ loggerClass ],
Jon Hall714eeba2015-09-29 17:53:10 -07001132 -1 )
1133 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001134 main.logger = loggerClass()
1135
1136 except ImportError:
Jeremy Ronquillo696f4262017-10-17 10:56:26 -07001137 print sys.exc_info()[ 1 ]
Jon Halld61331b2015-02-17 16:35:47 -08001138 main.exit()
adminbae64d82013-08-01 10:50:15 -07001139
Jon Hall714eeba2015-09-29 17:53:10 -07001140def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001141 print "THIS IS ECHO"