blob: 89315dcaeb9e19d28fb9b76873c1d0f49a417618 [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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000113 self.componentDictionary = self.topology['COMPONENT']
Jon Hall714eeba2015-09-29 17:53:10 -0700114 self.driversList = []
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000115 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000119 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000125 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000139 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000144 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000172 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 Ronquillo4d5f1d02017-10-13 20:23:57 +0000183 if "OCN" in self.componentDictionary[component]['host'] and\
Jon Hall714eeba2015-09-29 17:53:10 -0700184 main.onoscell:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000185 self.componentDictionary[component]['host'] = main.mnIP
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700186
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000187 user_name = self.componentDictionary[component].get( 'user',
188 getpass.getuser() )
189 ip_address = self.componentDictionary[component].get( 'host',
190 'localhost' )
191 pwd = self.componentDictionary[component].get( 'password',
192 'changeme' )
193 port = self.componentDictionary[component].get( 'port' )
Jon Hall714eeba2015-09-29 17:53:10 -0700194 connect_result = driverObject.connect( user_name=user_name,
195 ip_address=ip_address,
196 pwd=pwd,
197 port=port,
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000198 options=driver_options)
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700199
adminbae64d82013-08-01 10:50:15 -0700200 if not connect_result:
Jon Hall714eeba2015-09-29 17:53:10 -0700201 self.log.error( "Exiting from the test execution because connecting to the " +
202 component + " component failed." )
Jon Halld61331b2015-02-17 16:35:47 -0800203 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700204
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000205 vars( self )[component] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700206 self.initiated = True
Jon Hallca319892017-06-15 15:25:22 -0700207 return driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700208
Jon Hall714eeba2015-09-29 17:53:10 -0700209 def run( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000210 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700211 The Execution of the test script's cases listed in the Test params
212 file will be done here then update each test case result.
213 This method will return main.TRUE if it executed all the test cases
214 successfully, else will retun main.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000215 '''
adminbae64d82013-08-01 10:50:15 -0700216 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700217 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700218 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800219 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700220 self.TOTAL_TC_NORESULT = 0
221 self.TOTAL_TC_FAIL = 0
222 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700223 self.TEST_ITERATION = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700224
225 # NOTE: number of main.step statements in the
226 # outer most level of the test case. used to
227 # execute code in smaller steps
228 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700229 self.CASERESULT = self.NORESULT
230
Jon Halld61331b2015-02-17 16:35:47 -0800231 import testparser
Jon Hall53c5e662016-04-13 16:06:56 -0700232 test = testparser.TestParser( main.testFile )
adminbae64d82013-08-01 10:50:15 -0700233 self.testscript = test.testscript
234 self.code = test.getStepCode()
Jon Hall714eeba2015-09-29 17:53:10 -0700235 repeat = int( self.params.get( 'repeat', 1 ) )
236 self.TOTAL_TC_PLANNED = len( self.testcases_list ) * repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700237
adminbae64d82013-08-01 10:50:15 -0700238 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700239 while repeat:
Devin Limec989792017-08-15 15:57:55 -0700240 self.leftCase.extend( self.testcases_list )
Jon Halla1185982014-09-15 14:55:10 -0700241 for self.CurrentTestCaseNumber in self.testcases_list:
Devin Limec989792017-08-15 15:57:55 -0700242 self.executedCase.append( self.leftCase.pop( 0 ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700243 result = self.runCase( self.CurrentTestCaseNumber )
244 repeat -= 1
adminbae64d82013-08-01 10:50:15 -0700245 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700246
Jon Halle234cc42015-08-31 15:26:47 -0700247 def runCase( self, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700248 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700249 self.CurrentTestCase = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700250
251 # List of step results in a case. ANDed together to get the result
252 self.stepResultsList = []
kelvin-onlabf70fd542015-05-07 18:41:40 -0700253 self.stepName = ""
Jon Hall783bbf92015-07-23 14:33:19 -0700254 self.caseExplanation = ""
adminbae64d82013-08-01 10:50:15 -0700255 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700256
257 # NOTE: number of main.step statements in the
258 # outer most level of the test case. used to
259 # execute code in smaller steps
260 self.stepCount = 0
261
262 # NOTE: This is the current number of main.step()'s executed
263 # in a case. Used for logging.
264 self.stepNumber = 0
adminbae64d82013-08-01 10:50:15 -0700265 self.EXPERIMENTAL_MODE = self.FALSE
266 self.addCaseHeader()
Devin Limec989792017-08-15 15:57:55 -0700267 self.log.debug( "Case Executed : " + str( self.executedCase ) )
268 self.log.debug( "Case to be executed : " + str( self.leftCase ) )
Jon Halle234cc42015-08-31 15:26:47 -0700269 self.testCaseNumber = str( testCaseNumber )
270 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700271 stopped = False
Jon Hall5a72b712015-09-28 12:20:59 -0700272 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000273 self.code[self.testCaseNumber]
Jon Halld61331b2015-02-17 16:35:47 -0800274 except KeyError:
Jon Halle234cc42015-08-31 15:26:47 -0700275 self.log.error( "There is no Test-Case " + self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800276 return self.FALSE
adminbae64d82013-08-01 10:50:15 -0700277 self.stepCount = 0
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000278 while self.stepCount < len( self.code[self.testCaseNumber].keys() ):
Jon Hall714eeba2015-09-29 17:53:10 -0700279 result = self.runStep( self.code, self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800280 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700281 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800282 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700283 continue
Jon Hall5a72b712015-09-28 12:20:59 -0700284 # stepResults format: ( stepNo[], stepName[], stepResult[], onFail[] )
285 stepResults = self.stepResultsList
Jon Halle234cc42015-08-31 15:26:47 -0700286 if not stopped:
287 if self.CASERESULT == self.TRUE or self.CASERESULT == self.FALSE:
Jon Hall714eeba2015-09-29 17:53:10 -0700288 # Result was already explitily set somewhere else like
289 # in skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700290 pass
Jon Hall5a72b712015-09-28 12:20:59 -0700291 elif all( self.TRUE == i for i in stepResults ):
kelvin-onlabf70fd542015-05-07 18:41:40 -0700292 # ALL PASSED
293 self.CASERESULT = self.TRUE
Jon Hall5a72b712015-09-28 12:20:59 -0700294 elif self.FALSE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700295 # AT LEAST ONE FAILED
296 self.CASERESULT = self.FALSE
Jon Hall5a72b712015-09-28 12:20:59 -0700297 elif self.TRUE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700298 # AT LEAST ONE PASSED
299 self.CASERESULT = self.TRUE
300 else:
301 self.CASERESULT = self.NORESULT
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000302 self.testCaseResult[str( self.CurrentTestCaseNumber )] = self.CASERESULT
Devin Limec989792017-08-15 15:57:55 -0700303 self.organizeResult( self.CurrentTestCaseNumber, self.CASERESULT )
Jon Hall714eeba2015-09-29 17:53:10 -0700304 self.logger.updateCaseResults( self )
Jon Hall783bbf92015-07-23 14:33:19 -0700305 self.log.wiki( "<p>" + self.caseExplanation + "</p>" )
306 self.log.summary( self.caseExplanation )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700307 self.log.wiki( "<ul>" )
acsmarse2d1ed12015-10-05 13:51:17 -0700308 subcaseMessage = False
kelvin-onlabf70fd542015-05-07 18:41:40 -0700309 for line in self.stepCache.splitlines():
acsmarse2d1ed12015-10-05 13:51:17 -0700310 if re.search( "[0-9]\.[0-9]", line ): # Step
311 if subcaseMessage: # End of Failure Message Printout
312 self.log.wiki( "</ul>\n" )
313 subcaseMessage = False
314 if re.search( " - PASS$", line ):
315 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
316 elif re.search( " - FAIL$", line ):
317 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
318 elif re.search( " - No Result$", line ):
319 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
320 else: # Substep
321 if not subcaseMessage: # Open Failure Message Printout
322 self.log.wiki( "<ul><li>" + line + "</li>\n" )
323 subcaseMessage = True
324 else: # Add to Failure Message Printout
325 self.log.wiki( "<li>" + line + "</li>\n" )
acsmars27e62dd2015-10-06 11:35:47 -0700326 if subcaseMessage: # End of Failure Message Printout for last item
327 self.log.wiki( "</ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700328 self.log.wiki( "</ul>" )
329 self.log.summary( self.stepCache )
330 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700331 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700332
Devin Limec989792017-08-15 15:57:55 -0700333 def organizeResult( self, caseNum, result ):
334 """
335 Organize the result and put the current number into either
336 failed/noResult lists.
337 * caseNum - number of the case
338 * result - result of the case
339 """
340 if result == main.FALSE:
341 self.failedCase.append( caseNum )
342 elif result == self.NORESULT:
343 self.noResultCase.append( caseNum )
344
Jon Hall714eeba2015-09-29 17:53:10 -0700345 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700346 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700347 try:
348 step = self.stepCount
349 # stepResults format: ( stepNo, stepName, stepResult, onFail )
350 # NOTE: This is needed to catch results of main.step()'s
351 # called inside functions or loops
352 self.stepResults = ( [], [], [], [] )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000353 exec code[testCaseNumber][step] in module.__dict__
adminbae64d82013-08-01 10:50:15 -0700354 self.stepCount = self.stepCount + 1
Jon Hall96b816f2015-11-03 12:00:56 -0800355 self.parseStepResults( testCaseNumber )
Jon Hallca319892017-06-15 15:25:22 -0700356 except SkipCase: # Raised in self.skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700357 self.log.warn( "Skipping the rest of CASE" +
358 str( testCaseNumber ) )
Jon Hall96b816f2015-11-03 12:00:56 -0800359 self.parseStepResults( testCaseNumber )
Jon Hall714eeba2015-09-29 17:53:10 -0700360 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700361 self.stepCache += "\t\t" + self.onFailMsg + "\n"
362 self.stepCount = self.stepCount + 1
363 return self.FALSE
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000364 except StandardError as e:
Jon Hallc1606352015-10-06 14:51:36 -0700365 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000366 stepNo = self.stepResults[0][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700367 except IndexError:
368 stepNo = "<IndexError>"
369 main.log.warn( "Error trying to get step number. " +
370 "It is likely between step " +
Jon Hall6e709752016-02-01 13:38:46 -0800371 str( self.stepNumber ) + " and step " +
Jon Hallc1606352015-10-06 14:51:36 -0700372 str( self.stepNumber + 1 ) )
373 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000374 stepName = self.stepResults[1][ self.stepNumber - 1 ]
Jon Hallc1606352015-10-06 14:51:36 -0700375 except IndexError:
376 stepName = "<IndexError>"
377 self.log.error( "\nException in the following section of" +
378 " code: " + str( testCaseNumber ) + "." +
379 str( stepNo ) + ": " + stepName )
Jeremyd9e4eb12016-04-13 12:09:06 -0700380 self.log.error( str( e.__class__ ) + str( e.message ) )
adminbae64d82013-08-01 10:50:15 -0700381 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700382 self.logger.updateCaseResults( self )
383 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700384 self.log.wiki( "<ul>" )
385 for line in self.stepCache.splitlines():
386 if re.search( " - PASS$", line ):
387 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
388 elif re.search( " - FAIL$", line ):
389 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
390 elif re.search( " - No Result$", line ):
391 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700392 else: # Should only be on fail message
393 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700394 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700395 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700396 self.log.summary( self.stepCache )
397 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700398 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700399 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700400 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700401 if cli.stop:
402 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700403 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000404 self.testCaseResult[str( self.CurrentTestCaseNumber )] = "Stopped"
Jon Hall714eeba2015-09-29 17:53:10 -0700405 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700406 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700407 return self.FALSE
408
Jon Hall96b816f2015-11-03 12:00:56 -0800409 def parseStepResults( self, testCaseNumber ):
410 """
411 Parse throught the step results for the wiki
412 """
413 try:
414 # Iterate through each of the steps and print them
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000415 for index in range( len( self.stepResults[0] ) ):
Jon Hall96b816f2015-11-03 12:00:56 -0800416 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000417 stepNo = self.stepResults[0][ index ]
418 stepName = self.stepResults[1][ index ]
419 stepResult = self.stepResults[2][ index ]
420 onFail = self.stepResults[3][ index ]
Jon Hall96b816f2015-11-03 12:00:56 -0800421 self.stepCache += "\t" + str( testCaseNumber ) + "."
422 self.stepCache += str( stepNo ) + " "
423 self.stepCache += stepName + " - "
424 if stepResult == self.TRUE:
425 self.stepCache += "PASS\n"
426 elif stepResult == self.FALSE:
427 self.stepCache += "FAIL\n"
428 self.stepCache += "\t\t" + onFail + "\n"
429 else:
430 self.stepCache += "No Result\n"
431 self.stepResultsList.append( stepResult )
432 except Exception:
433 self.log.exception( "Error parsing step results" )
434
Jon Halle234cc42015-08-31 15:26:47 -0700435 def skipCase( self, result="DEFAULT", msg=None ):
436 """
437 Will skip the rest of the code in a test case. The case results will be
438 determined as normal based on completed assertions unless the result
439 argument is given.
440
441 Optional Arguments:
Jon Hall7c4f4302016-07-15 14:39:02 -0700442 result: Case insensitive string. Can be 'PASS' or 'FAIL' and will set
Jon Halle234cc42015-08-31 15:26:47 -0700443 the case result accordingly.
444 msg: Message to be printed when the case is skipped in the reports.
445 """
446 result = result.upper().strip()
447 if result == "PASS":
448 self.CASERESULT = self.TRUE
449 elif result == "FAIL":
450 self.CASERESULT = self.FALSE
451 self.onFailMsg = "Skipping the rest of this case. "
452 if msg:
453 self.onFailMsg += str( msg )
Jon Hallca319892017-06-15 15:25:22 -0700454 raise SkipCase
kelvin-onlabf70fd542015-05-07 18:41:40 -0700455
Jon Hall714eeba2015-09-29 17:53:10 -0700456 def addCaseHeader( self ):
457 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" +\
458 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
459 self.log.exact( caseHeader )
460 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" +\
461 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700462 for driver in self.componentDictionary.keys():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000463 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700464
Jon Hall714eeba2015-09-29 17:53:10 -0700465 def addCaseFooter( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000466 stepNo = self.stepResults[0][-2]
Jon Hall714eeba2015-09-29 17:53:10 -0700467 if stepNo > 0:
468 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
469 str( stepNo ) + ": " + str( self.stepName )
470 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep +\
471 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700472
Jon Hall714eeba2015-09-29 17:53:10 -0700473 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " +\
474 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700475
adminbae64d82013-08-01 10:50:15 -0700476 for driver in self.driversList:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000477 vars( self )[driver].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700478
Jon Hall714eeba2015-09-29 17:53:10 -0700479 def cleanup( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000480 '''
Jon Hall5b586732015-06-11 11:39:39 -0700481 Print a summary of the current test's results then attempt to release
482 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700483
Jon Hall5b586732015-06-11 11:39:39 -0700484 This function shouldbe threadsafe such that cleanup will only be
485 executed once per test.
486
487 This will return TRUE if all the component handles and log handles
488 closed properly, else return FALSE.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000489 '''
adminbae64d82013-08-01 10:50:15 -0700490 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700491 lock = self.cleanupLock
492 if lock.acquire( False ):
493 try:
494 if self.cleanupFlag is False: # First thread to run this
495 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700496 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700497 self.logger.testSummary( self )
Jon Hall892818c2015-10-20 17:58:34 -0700498 components = self.componentDictionary
499 for component in sorted( components,
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000500 key=lambda item: components[item]['connect_order'],
Jon Hall892818c2015-10-20 17:58:34 -0700501 reverse=True ):
Jon Hall714eeba2015-09-29 17:53:10 -0700502 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000503 tempObject = vars( self )[component]
Jon Hall714eeba2015-09-29 17:53:10 -0700504 print "Disconnecting from " + str( tempObject.name ) +\
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000505 ": " + str( tempObject.__class__)
Jon Hall5b586732015-06-11 11:39:39 -0700506 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700507 except KeyboardInterrupt:
508 pass
509 except KeyError:
510 # Component not created yet
511 self.log.warn( "Could not find the component " +
512 str( component ) )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000513 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700514 self.log.exception( "Exception while disconnecting from " +
515 str( component ) )
516 result = self.FALSE
517 # Closing all the driver's session files
518 for driver in self.componentDictionary.keys():
519 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000520 vars( self )[driver].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700521 except KeyboardInterrupt:
522 pass
523 except KeyError:
524 # Component not created yet
525 self.log.warn( "Could not find the component " +
526 str( driver ) + " while trying to" +
527 " close log file" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000528 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700529 self.log.exception( "Exception while closing log files for " +
530 str( driver ) )
531 result = self.FALSE
532 else:
533 pass # Someone else already ran through this function
534 finally:
535 lock.release()
536 else: # Someone already has a lock
537 # NOTE: This could cause problems if we don't release the lock
538 # correctly
539 lock.acquire() # Wait for the other thread to finish
540 # NOTE: If we don't wait, exit could be called while the thread
541 # with the lock is still cleaning up
542 lock.release()
adminbae64d82013-08-01 10:50:15 -0700543 return result
Jon Halld61331b2015-02-17 16:35:47 -0800544
Jon Hall714eeba2015-09-29 17:53:10 -0700545 def pause( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000546 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700547 This function will pause the test's execution, and will continue after
548 user provide 'resume' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000549 '''
adminbae64d82013-08-01 10:50:15 -0700550 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700551
Jon Hall714eeba2015-09-29 17:53:10 -0700552 def onfail( self, *components ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000553 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700554 When test step failed, calling all the components onfail.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000555 '''
adminbae64d82013-08-01 10:50:15 -0700556 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700557 try:
adminbae64d82013-08-01 10:50:15 -0700558 for component in self.componentDictionary.keys():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000559 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700560 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000561 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700562 print str( e )
adminbae64d82013-08-01 10:50:15 -0700563 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700564 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700565 try:
adminbae64d82013-08-01 10:50:15 -0700566 for component in components:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000567 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700568 result = tempObject.onfail()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000569 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700570 print str( e )
adminbae64d82013-08-01 10:50:15 -0700571 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700572
Jon Hall714eeba2015-09-29 17:53:10 -0700573 def getDriverPath( self, driverName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000574 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700575 Based on the component 'type' specified in the params , this method
576 will find the absolute path, by recursively searching the name of
577 the component.
578
579 NOTE: This function requires the linux 'find' command.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000580 '''
adminbae64d82013-08-01 10:50:15 -0700581 import commands
582
Jon Hall714eeba2015-09-29 17:53:10 -0700583 cmd = "find " + drivers_path + " -name " + driverName + ".py"
584 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700585
Jon Hall714eeba2015-09-29 17:53:10 -0700586 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700587 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700588
adminbae64d82013-08-01 10:50:15 -0700589 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700590 result_count = result_count + 1
591 if result_count > 1:
592 print "Found " + driverName + " " + str( result_count ) + " times:"
593 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700594 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700595
Jon Hall714eeba2015-09-29 17:53:10 -0700596 result = re.sub( "(.*)drivers", "", result )
597 result = re.sub( "\/\/", "/", result )
598 result = re.sub( "\.py", "", result )
599 result = re.sub( "\.pyc", "", result )
600 result = re.sub( "\/", ".", result )
601 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700602 return result
adminbae64d82013-08-01 10:50:15 -0700603
Jon Hall714eeba2015-09-29 17:53:10 -0700604 def step( self, stepDesc ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000605 '''
adminbae64d82013-08-01 10:50:15 -0700606 The step information of the test-case will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000607 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700608 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
609 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700610 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700611 self.stepNumber += 1
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000612 self.stepResults[0].append( self.stepNumber )
613 self.stepResults[1].append( stepDesc )
614 self.stepResults[2].append( self.NORESULT )
615 self.stepResults[3].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700616
Jon Hall714eeba2015-09-29 17:53:10 -0700617 stepName = " " + str( self.CurrentTestCaseNumber ) + "." +\
618 str( self.stepNumber ) + ": " + str( stepDesc )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000619 self.log.step(stepName)
adminbae64d82013-08-01 10:50:15 -0700620 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700621 line = "\n" + "-" * 45 + "\n"
622 if self.stepNumber > 1:
623 stepHeader = line + "End of Step " + previousStep + line
624 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700625 for driver in self.componentDictionary.keys():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000626 vars( self )[driver + 'log'].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700627
Jon Hall714eeba2015-09-29 17:53:10 -0700628 def case( self, testCaseName ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000629 '''
adminbae64d82013-08-01 10:50:15 -0700630 Test's each test-case information will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000631 '''
Jon Halld61331b2015-02-17 16:35:47 -0800632 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700633 testCaseName = " " + str( testCaseName )
634 self.log.case( testCaseName )
635 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700636 for driver in self.componentDictionary.keys():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000637 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700638
Jon Hall714eeba2015-09-29 17:53:10 -0700639 def testDesc( self, description ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000640 '''
adminbae64d82013-08-01 10:50:15 -0700641 Test description will append to the logs.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000642 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700643 description = "Test Description : " + str( description )
644 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700645
Jon Hall714eeba2015-09-29 17:53:10 -0700646 def _getTest( self ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000647 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700648 This method will parse the test script to find required test
649 information.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000650 '''
Jon Hall53c5e662016-04-13 16:06:56 -0700651 testFileHandler = open( main.testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700652 testFileList = testFileHandler.readlines()
653 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700654 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700655 for index in range( len( testFileList ) ):
656 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000657 testFileList[index],
Jon Hall714eeba2015-09-29 17:53:10 -0700658 0 )
adminbae64d82013-08-01 10:50:15 -0700659 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700660 counter = counter + 1
661 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700662
Jon Hall714eeba2015-09-29 17:53:10 -0700663 def response_parser( self, response, return_format ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000664 ''' It will load the default response parser '''
adminbae64d82013-08-01 10:50:15 -0700665 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700666 response_dict = self.response_to_dict( response, return_format )
667 return_format_string = self.dict_to_return_format( response,
668 return_format,
669 response_dict )
adminbae64d82013-08-01 10:50:15 -0700670 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700671
Jon Hall714eeba2015-09-29 17:53:10 -0700672 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700673 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700674 json_match = re.search( '^\s*{', response )
675 xml_match = re.search( '^\s*\<', response )
676 ini_match = re.search( '^\s*\[', response )
677 if json_match:
678 self.log.info( "Response is in 'JSON' format, converting to '" +
679 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800680 # Formatting the json string
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000681 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
Jon Hall714eeba2015-09-29 17:53:10 -0700682 response = re.sub( r",\s*'?(\w)", r',"\1', response )
683 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
684 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
685 try:
adminbae64d82013-08-01 10:50:15 -0700686 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700687 response_dict = json.loads( response )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000688 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700689 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700690 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700691 elif ini_match:
692 self.log.info( "Response is in 'INI' format, converting to '" +
693 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700694 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700695 response_file = open( "respnse_file.temp", 'w' )
696 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800697 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700698 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700699 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700700 elif xml_match:
701 self.log.info( "Response is in 'XML' format, converting to '" +
702 return_format + "' format" )
703 try:
704 response_dict = xmldict.xml_to_dict( "<response> " +
705 str( response ) +
706 " </response>" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000707 except StandardError:
Jon Hall1306a562015-09-04 11:21:24 -0700708 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700709 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700710
Jon Hall714eeba2015-09-29 17:53:10 -0700711 def dict_to_return_format( self, response, return_format, response_dict ):
712 if return_format == 'table':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000713 ''' Will return in table format'''
adminbae64d82013-08-01 10:50:15 -0700714 to_do = "Call the table output formatter"
715 global response_table
716 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700717 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700718
Jon Hall714eeba2015-09-29 17:53:10 -0700719 def get_table( value_to_convert ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000720 ''' This will parse the dictionary recusrsively and print as
721 table format'''
adminbae64d82013-08-01 10:50:15 -0700722 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700723 if isinstance( value_to_convert, dict ):
724 table_data = table_data + '\t'.join( value_to_convert ) +\
725 "\n"
726 for temp_val in value_to_convert.values():
727 table_data = table_data + get_table( temp_val )
728 else:
729 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800730 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700731
Jon Hall714eeba2015-09-29 17:53:10 -0700732 for value in response_dict.values():
733 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700734 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700735
Jon Hall714eeba2015-09-29 17:53:10 -0700736 elif return_format == 'config':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000737 ''' Will return in config format'''
adminbae64d82013-08-01 10:50:15 -0700738 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700739 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700740 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700741 response_config = re.sub( ",", "\n\t", response_string )
742 response_config = re.sub( "u\'", "\'", response_config )
743 response_config = re.sub( "{", "", response_config )
744 response_config = re.sub( "}", "\n", response_config )
745 response_config = re.sub( ":", " =", response_config )
746 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700747 elif return_format == 'xml':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000748 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700749 response_xml = xmldict.dict_to_xml( response_dict )
750 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
751 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700752 elif return_format == 'json':
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000753 ''' Will return in json format'''
adminbae64d82013-08-01 10:50:15 -0700754 to_do = 'Call dict to xml coverter'
755 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700756 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700757 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700758
Jon Hall714eeba2015-09-29 17:53:10 -0700759 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700760 self.random_order = self.random_order + 1
761 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700762
Jon Hall714eeba2015-09-29 17:53:10 -0700763 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700764 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700765 for thread in threading.enumerate():
766 if thread.isAlive():
767 try:
768 thread._Thread__stop()
769 except:
Jon Hall1306a562015-09-04 11:21:24 -0700770 # NOTE: We should catch any exceptions while trying to
771 # close the thread so that we can try to close the other
772 # threads as well
Jon Hall714eeba2015-09-29 17:53:10 -0700773 print str( thread.getName() ) +\
774 ' could not be terminated'
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700775 os.system( "stty sane" ) # fix format if necessary
adminbae64d82013-08-01 10:50:15 -0700776 sys.exit()
777
Devin Lim44075962017-08-11 10:56:37 -0700778 def cleanAndExit( self ):
779 """
780 It will set the testcase result to be FAILED and update it
781 before cleaning up and exitting the test.
782 :return:
783 """
784 if self.CurrentTestCaseNumber:
785 self.testCaseResult[ str( self.CurrentTestCaseNumber ) ] = self.FALSE
Devin Limec989792017-08-15 15:57:55 -0700786 self.organizeResult( self.CurrentTestCaseNumber, self.FALSE )
Devin Lim44075962017-08-11 10:56:37 -0700787 self.logger.updateCaseResults( self )
788 self.cleanup()
789 self.exit()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700790
Jon Hallcd3d2a32015-10-01 11:07:28 -0700791 def stop( self, email=False ):
792 """
793 Stop the test until Ctrl-D is entered.
794 Ctrl-C will kill the test
Jon Hall25079782015-10-13 13:54:39 -0700795
796 Optional arguments:
797 email can either be a bool, or you can specify the email address
798 to send the email to
Jon Hallcd3d2a32015-10-01 11:07:28 -0700799 """
800 try:
801 if email:
Jon Hall25079782015-10-13 13:54:39 -0700802 if '@' in email:
803 main.mail = email
804 utilities.send_warning_email()
Jeremy Ronquillo15ff1072017-07-17 10:55:46 -0700805 self.log.debug( "Test execution suspended. \n"
806 "- Type 'c' to resume the test.\n"
807 "- Type Ctrl-C to exit the test.\n"
808 "- Enter interactive python interpreter commands.\n"
809 "\t- ie: main.Mininet1.pingall()\n"
810 "- Type 'help' for help with pdb." )
811 pdb.set_trace()
Jon Hallcd3d2a32015-10-01 11:07:28 -0700812 except EOFError:
813 return
814 # Pass all other exceptions up to caller
815
816
Jon Hall714eeba2015-09-29 17:53:10 -0700817def verifyOptions( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000818 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700819 This will verify the command line options and set to default values,
820 if any option not given in command line.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000821 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700822 verifyTest( options )
823 verifyExample( options )
824 verifyTestScript( options )
YPZhang1c89e762016-06-29 10:43:58 -0700825 verifyParams( options )
Jon Hall714eeba2015-09-29 17:53:10 -0700826 verifyLogdir( options )
827 verifyMail( options )
828 verifyTestCases( options )
829 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700830
Jon Hall714eeba2015-09-29 17:53:10 -0700831def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700832 try:
833 if options.testname:
834 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700835 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700836 main.tests_path = tests_path
837 elif options.example:
838 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700839 main.tests_path = path + "/examples/"
840 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700841 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700842 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700843 main.exit()
adminbae64d82013-08-01 10:50:15 -0700844
Jon Hall714eeba2015-09-29 17:53:10 -0700845def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700846 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700847 main.testDir = path + '/examples/'
848 main.tests_path = path + "/examples/"
849 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700850
Jon Hall714eeba2015-09-29 17:53:10 -0700851def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800852 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700853 if options.logdir:
854 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700855 else:
Jon Halld61331b2015-02-17 16:35:47 -0800856 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700857
Jon Hall714eeba2015-09-29 17:53:10 -0700858def verifyMail( options ):
Jon Hall25079782015-10-13 13:54:39 -0700859 # Mail-To: field
860 if options.mail: # Test run specific
adminbae64d82013-08-01 10:50:15 -0700861 main.mail = options.mail
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000862 elif main.params.get('mail'): # Test suite specific
Jon Hall25079782015-10-13 13:54:39 -0700863 main.mail = main.params.get( 'mail' )
864 else: # TestON specific
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000865 main.mail = main.config['config'].get( 'mail_to' )
Jon Hall25079782015-10-13 13:54:39 -0700866 # Mail-From: field
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000867 main.sender = main.config['config'].get( 'mail_from' )
Jon Hall25079782015-10-13 13:54:39 -0700868 # Mail smtp server
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000869 main.smtp = main.config['config'].get( 'mail_server' )
Jon Hall25079782015-10-13 13:54:39 -0700870 # Mail-From account password
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000871 main.senderPwd = main.config['config'].get( 'mail_pass' )
Jon Hall25079782015-10-13 13:54:39 -0700872
Devin Lim2df68a12017-06-30 15:39:05 -0700873def evalTestCase( tempList ):
874 tList = []
875 for tcase in tempList:
876 if isinstance( tcase, list ):
877 tList.extend( evalTestCase( tcase ) )
878 else:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000879 tList.extend( [tcase] )
Devin Lim2df68a12017-06-30 15:39:05 -0700880 return tList
adminbae64d82013-08-01 10:50:15 -0700881
Jon Hall714eeba2015-09-29 17:53:10 -0700882def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800883 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700884 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800885 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800886 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700887 testcases_list = re.sub( "(\[|\])", "", options.testcases )
888 main.testcases_list = eval( testcases_list + "," )
889 else:
adminbae64d82013-08-01 10:50:15 -0700890 if 'testcases' in main.params.keys():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000891 temp = eval( main.params['testcases'] + "," )
Devin Lim2df68a12017-06-30 15:39:05 -0700892 main.testcases_list = evalTestCase( list( temp ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700893 else:
894 print "Testcases not specifed in params, please provide in " +\
895 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800896 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700897
Jon Hall714eeba2015-09-29 17:53:10 -0700898def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700899 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700900 if options.onoscell:
901 main.onoscell = options.onoscell
Devin Lim58046fa2017-07-05 16:55:00 -0700902 main.ONOSip = []
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700903 main.mnIP = ""
Devin Lim58046fa2017-07-05 16:55:00 -0700904 cellCMD = ". ~/onos/tools/dev/bash_profile; cell " + main.onoscell
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000905 output = subprocess.check_output( ["bash", '-c', cellCMD] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700906 splitOutput = output.splitlines()
Devin Lim58046fa2017-07-05 16:55:00 -0700907 main.apps = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700908 for i in range( len( splitOutput ) ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000909 if re.match( "OCN", splitOutput[i] ):
910 mnNode = splitOutput[i].split( "=" )
911 main.mnIP = mnNode[1]
Jon Hall714eeba2015-09-29 17:53:10 -0700912 # cell already sorts OC variables in bash, so no need to
913 # sort in TestON
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000914 elif re.match( "OC[1-9]", splitOutput[i] ):
915 onosNodes = splitOutput[i].split( "=" )
916 main.ONOSip.append( onosNodes[1] )
917 elif re.match( "ONOS_APPS", splitOutput[i] ):
918 main.apps = ( splitOutput[i].split( "=" ) )[1]
Jon Hall714eeba2015-09-29 17:53:10 -0700919 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700920 main.onoscell = main.FALSE
921
Jon Hall714eeba2015-09-29 17:53:10 -0700922def verifyTestScript( options ):
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000923 '''
adminbae64d82013-08-01 10:50:15 -0700924 Verifyies test script.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000925 '''
Jon Halld61331b2015-02-17 16:35:47 -0800926 main.openspeak = openspeak.OpenSpeak()
Jon Hall53c5e662016-04-13 16:06:56 -0700927 directory = main.testDir + "/" + main.TEST
928 if os.path.exists( directory ):
929 pass
930 else:
931 directory = ""
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000932 for root, dirs, files in os.walk( main.testDir, topdown=True):
Jon Hall53c5e662016-04-13 16:06:56 -0700933 if not directory:
934 for name in dirs:
935 if name == main.TEST:
936 directory = ( os.path.join( root, name ) )
937 index = directory.find( "/tests/" ) + 1
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000938 main.classPath = directory[index:].replace( '/', '.' ) + "." + main.TEST
Jon Hall53c5e662016-04-13 16:06:56 -0700939 break
940 openspeakfile = directory + "/" + main.TEST + ".ospk"
941 main.testFile = directory + "/" + main.TEST + ".py"
Jon Hall714eeba2015-09-29 17:53:10 -0700942 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700943 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700944 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
Jon Hall53c5e662016-04-13 16:06:56 -0700945 elif os.path.exists( main.testFile ):
Jon Hall44506242015-07-29 17:40:26 -0700946 # No openspeak found, using python file instead
947 pass
adminbae64d82013-08-01 10:50:15 -0700948 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700949 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " +\
Jon Hall44506242015-07-29 17:40:26 -0700950 "Python or OpenSpeak test script in the tests folder: " +\
Jon Hall714eeba2015-09-29 17:53:10 -0700951 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700952 __builtin__.testthread = None
953 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700954 try:
955 testModule = __import__( main.classPath,
956 globals(),
957 locals(),
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000958 [main.TEST],
Jon Hall714eeba2015-09-29 17:53:10 -0700959 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700960 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700961 print "There was an import error, it might mean that there is " +\
962 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800963 main.exit()
adminbae64d82013-08-01 10:50:15 -0700964
Jon Hall714eeba2015-09-29 17:53:10 -0700965 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700966 main.testObject = testClass()
967 load_parser()
Jon Hall714eeba2015-09-29 17:53:10 -0700968 main.params = main.parser.parseParams( main.classPath )
969 main.topology = main.parser.parseTopology( main.classPath )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700970
YPZhang1c89e762016-06-29 10:43:58 -0700971def verifyParams( options ):
Jon Hall714eeba2015-09-29 17:53:10 -0700972 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000973 main.params = main.params['PARAMS']
Jon Hall1306a562015-09-04 11:21:24 -0700974 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700975 print "Error with the params file: Either the file not specified " +\
976 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800977 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700978 try:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000979 main.topology = main.topology['TOPOLOGY']
Jon Hall1306a562015-09-04 11:21:24 -0700980 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700981 print "Error with the Topology file: Either the file not specified " +\
982 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700983 main.exit()
YPZhang1c89e762016-06-29 10:43:58 -0700984 # Overwrite existing params variables if they are specified from command line
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +0000985 if len(options.params) > 0:
YPZhang1c89e762016-06-29 10:43:58 -0700986 # Some params variables are specified from command line
987 for param in options.params:
988 if not re.search( ".=.", param ):
989 print( "Error when parsing params: params should follow key=value format" )
990 continue
Jon Hall7c4f4302016-07-15 14:39:02 -0700991 # Split the param string to catch nested keys and the value
YPZhang1c89e762016-06-29 10:43:58 -0700992 [ keys, value ] = param.split( "=" )
993 # Split the nested keys according to its hierarchy
994 keyList = keys.split( "/" )
995 # Get the outermost dictionary
996 paramDict = main.params
997 # Get the innermost dictionary
998 try:
999 while len( keyList ) > 1:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001000 key = keyList.pop(0)
YPZhang1c89e762016-06-29 10:43:58 -07001001 assert isinstance( paramDict[ key ], dict )
1002 paramDict = paramDict[ key ]
1003 except KeyError:
1004 print( "Error when parsing params: key \"" + key + "\" not found in main.params" )
1005 main.exit()
1006 except AssertionError:
1007 print( "Error when parsing params: \"" + key + "\" is already the innermost level in main.params" )
1008 main.exit()
1009 # Change the value
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001010 if not paramDict.has_key( keyList[0] ):
YPZhang1c89e762016-06-29 10:43:58 -07001011 print( "Error when parsing params: key \"" + keyList[0] + "\" not found in main.params" )
1012 main.exit()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001013 elif isinstance( paramDict[ keyList[0] ], dict ):
YPZhang1c89e762016-06-29 10:43:58 -07001014 print( "Error when parsing params: more levels under key \"" + keyList[0] + "\" in main.params" )
1015 main.exit()
1016 else:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001017 paramDict[ keyList[0] ] = value
kelvin-onlabf70fd542015-05-07 18:41:40 -07001018
Jon Hall714eeba2015-09-29 17:53:10 -07001019def load_parser():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001020 '''
adminbae64d82013-08-01 10:50:15 -07001021 It facilitates the loading customised parser for topology and params file.
1022 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001023 It also loads default xmlparser if no parser have specified in teston.cfg
1024 file.
adminbae64d82013-08-01 10:50:15 -07001025
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001026 '''
adminbae64d82013-08-01 10:50:15 -07001027 confighash = main.configDict
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001028 if 'file' in confighash['config']['parser'] and\
1029 'class' in confighash['config']['parser']:
1030 path = confighash['config']['parser']['file']
Jon Hall714eeba2015-09-29 17:53:10 -07001031 if path is not None or\
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001032 confighash['config']['parser']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001033 try:
1034 module = re.sub( r".py\s*$", "", path )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001035 moduleList = module.split("/")
1036 newModule = ".".join( moduleList[-2:] )
1037 parsingClass = confighash['config']['parser']['class']
Jon Hall714eeba2015-09-29 17:53:10 -07001038 parsingModule = __import__( newModule,
1039 globals(),
1040 locals(),
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001041 [parsingClass],
Jon Hall714eeba2015-09-29 17:53:10 -07001042 -1 )
1043 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -07001044 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -07001045 if hasattr( main.parser, "parseParams" ) and\
1046 hasattr( main.parser, "parseTopology" ) and\
1047 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:
Jon Hall714eeba2015-09-29 17:53:10 -07001053 print "Could not find the file " + path +\
1054 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -08001055 load_defaultParser()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001056 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 '''
1067 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 Ronquillo4d5f1d02017-10-13 20:23:57 +00001074 [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 Hall714eeba2015-09-29 17:53:10 -07001078 if hasattr( main.parser, "parseParams" ) and\
1079 hasattr( main.parser, "parseTopology" ) and\
1080 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -07001081 pass
1082 else:
1083 main.exit()
adminbae64d82013-08-01 10:50:15 -07001084 except ImportError:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001085 print sys.exc_info()[1]
adminbae64d82013-08-01 10:50:15 -07001086
Jon Hall714eeba2015-09-29 17:53:10 -07001087def load_logger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001088 '''
adminbae64d82013-08-01 10:50:15 -07001089 It facilitates the loading customised parser for topology and params file.
1090 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -07001091 It also loads default xmlparser if no parser have specified in teston.cfg
1092 file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001093 '''
adminbae64d82013-08-01 10:50:15 -07001094 confighash = main.configDict
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001095 if 'file' in confighash['config']['logger'] and\
1096 'class' in confighash['config']['logger']:
1097 path = confighash['config']['logger']['file']
Jon Hall714eeba2015-09-29 17:53:10 -07001098 if path is not None or\
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001099 confighash['config']['logger']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -07001100 try:
1101 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -07001102 moduleList = module.split( "/" )
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001103 newModule = ".".join( moduleList[-2:] )
1104 loggerClass = confighash['config']['logger']['class']
Jon Hall714eeba2015-09-29 17:53:10 -07001105 loggerModule = __import__( newModule,
1106 globals(),
1107 locals(),
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001108 [loggerClass],
Jon Hall714eeba2015-09-29 17:53:10 -07001109 -1 )
1110 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -07001111 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -07001112 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -07001113 print "Could not find the file " + path +\
1114 " using default logger."
adminbae64d82013-08-01 10:50:15 -07001115 load_defaultlogger()
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001116 elif confighash['config']['parser']['file'] is None or\
1117 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -08001118 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -07001119 else:
1120 load_defaultlogger()
1121
1122def load_defaultlogger():
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001123 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001124 It will load the default parser which is xml parser to parse the params and
1125 topology file.
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001126 '''
1127 moduleList = main.loggerPath.split("/")
1128 newModule = ".".join( moduleList[-2:] )
Jon Hall714eeba2015-09-29 17:53:10 -07001129 try:
Jon Halld61331b2015-02-17 16:35:47 -08001130 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001131 loggerModule = __import__( newModule,
1132 globals(),
1133 locals(),
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001134 [loggerClass],
Jon Hall714eeba2015-09-29 17:53:10 -07001135 -1 )
1136 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001137 main.logger = loggerClass()
1138
1139 except ImportError:
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00001140 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -08001141 main.exit()
adminbae64d82013-08-01 10:50:15 -07001142
Jon Hall714eeba2015-09-29 17:53:10 -07001143def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001144 print "THIS IS ECHO"