blob: e15b9e1380fdb9f3569e511c0eb9fd9221eae32c [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 22-Oct-2012
Jon Hall65844a32015-03-09 19:09:37 -07004
adminbae64d82013-08-01 10:50:15 -07005@author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
6
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
Jon Hall65844a32015-03-09 19:09:37 -070019 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070020
21
22
23teston is the main module.
24
25'''
26
27import sys
28import getpass
29import os
30import re
31import __builtin__
32import new
33import xmldict
Jon Hall30b82fa2015-03-04 17:15:43 -080034import importlib
Jon Hall5b586732015-06-11 11:39:39 -070035import threading
Jon Hall714eeba2015-09-29 17:53:10 -070036module = new.module( "test" )
adminbae64d82013-08-01 10:50:15 -070037import openspeak
Hari Krishnabe4b97b2015-07-15 12:19:43 -070038import subprocess
Jon Hall714eeba2015-09-29 17:53:10 -070039global path, drivers_path, core_path, tests_path, logs_path
Jon Hall44506242015-07-29 17:40:26 -070040location = os.path.abspath( os.path.dirname( __file__ ) )
41path = re.sub( "(core|bin)$", "", location )
Jon Hall714eeba2015-09-29 17:53:10 -070042drivers_path = path + "drivers"
43core_path = path + "core"
44tests_path = path + "tests"
45logs_path = path + "logs/"
adminbae64d82013-08-01 10:50:15 -070046config_path = path + "config/"
Jon Hall44506242015-07-29 17:40:26 -070047sys.path.append( path )
48sys.path.append( drivers_path )
49sys.path.append( core_path )
50sys.path.append( tests_path )
adminbae64d82013-08-01 10:50:15 -070051
52from core.utilities import Utilities
kelvin-onlabfb521662015-02-27 09:52:40 -080053from core.Thread import Thread
adminbae64d82013-08-01 10:50:15 -070054
adminbae64d82013-08-01 10:50:15 -070055
56class TestON:
57 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -070058 TestON will initiate the specified test.
Jon Hall714eeba2015-09-29 17:53:10 -070059 The main tasks are:
kelvin-onlabf70fd542015-05-07 18:41:40 -070060 * Initiate the required Component handles for the test.
adminbae64d82013-08-01 10:50:15 -070061 * Create Log file Handles.
adminbae64d82013-08-01 10:50:15 -070062 '''
Jon Hall714eeba2015-09-29 17:53:10 -070063 def __init__( self, options ):
adminbae64d82013-08-01 10:50:15 -070064 '''
Jon Hall714eeba2015-09-29 17:53:10 -070065 Initialise the component handles specified in the topology file of
66 the specified test.
adminbae64d82013-08-01 10:50:15 -070067 '''
68 # Initialization of the variables.
69 __builtin__.main = self
adminbae64d82013-08-01 10:50:15 -070070 __builtin__.path = path
71 __builtin__.utilities = Utilities()
72 self.TRUE = 1
73 self.FALSE = 0
74 self.ERROR = -1
kelvin-onlabf70fd542015-05-07 18:41:40 -070075 self.NORESULT = 2
adminbae64d82013-08-01 10:50:15 -070076 self.FAIL = False
77 self.PASS = True
kelvin-onlabf70fd542015-05-07 18:41:40 -070078 self.CASERESULT = self.ERROR
79 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -070080 self.init_result = self.TRUE
81 self.testResult = "Summary"
kelvin-onlabf70fd542015-05-07 18:41:40 -070082 self.stepName = ""
83 self.stepCache = ""
Jon Halld61331b2015-02-17 16:35:47 -080084 self.EXPERIMENTAL_MODE = False
adminbae64d82013-08-01 10:50:15 -070085 self.test_target = None
86 self.lastcommand = None
Jon Halld61331b2015-02-17 16:35:47 -080087 self.testDir = tests_path
88 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070089 self.parsingClass = "xmlparser"
90 self.parserPath = core_path + "/xmlparser"
91 self.loggerPath = core_path + "/logger"
92 self.loggerClass = "Logger"
93 self.logs_path = logs_path
94 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -080095 self.Thread = Thread
Jon Hall5b586732015-06-11 11:39:39 -070096 self.cleanupFlag = False
97 self.cleanupLock = threading.Lock()
Jon Hall0fc0d452015-07-14 09:49:58 -070098 self.initiated = False
Jon Hall65844a32015-03-09 19:09:37 -070099
adminbae64d82013-08-01 10:50:15 -0700100 self.configparser()
Jon Hall714eeba2015-09-29 17:53:10 -0700101 verifyOptions( options )
adminbae64d82013-08-01 10:50:15 -0700102 load_logger()
103 self.componentDictionary = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700104 self.componentDictionary = self.topology['COMPONENT']
105 self.driversList = []
106 if isinstance( self.componentDictionary, str):
107 self.componentDictionary = dict( self.componentDictionary )
Jon Hall65844a32015-03-09 19:09:37 -0700108
Jon Hall714eeba2015-09-29 17:53:10 -0700109 for component in self.componentDictionary:
110 self.driversList.append( self.componentDictionary[component]['type'] )
Jon Hall65844a32015-03-09 19:09:37 -0700111
Jon Hall714eeba2015-09-29 17:53:10 -0700112 self.driversList = list( set( self.driversList ) ) # Removing duplicates.
adminbae64d82013-08-01 10:50:15 -0700113 # Checking the test_target option set for the component or not
Jon Hall714eeba2015-09-29 17:53:10 -0700114 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700115 for component in self.componentDictionary.keys():
116 if 'test_target' in self.componentDictionary[component].keys():
117 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700118
Jon Halld61331b2015-02-17 16:35:47 -0800119 # Checking for the openspeak file and test script
Jon Hall714eeba2015-09-29 17:53:10 -0700120 self.logger.initlog( self )
adminbae64d82013-08-01 10:50:15 -0700121
122 # Creating Drivers Handles
Jon Hall714eeba2015-09-29 17:53:10 -0700123 initString = "\n" + "*" * 30 + "\n CASE INIT \n" + "*" * 30 + "\n"
124 self.log.exact( initString )
adminbae64d82013-08-01 10:50:15 -0700125 self.driverObject = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700126 self.random_order = 111 # Random order id to connect the components
adminbae64d82013-08-01 10:50:15 -0700127 components_connect_order = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700128 if isinstance( self.componentDictionary, dict ):
adminbae64d82013-08-01 10:50:15 -0700129 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700130 if 'connect_order' not in self.componentDictionary[component].keys():
131 self.componentDictionary[component]['connect_order'] = str( self.get_random() )
132 components_connect_order[component] = eval( self.componentDictionary[component]['connect_order'] )
133 # Ordering components based on the connect order.
134 ordered_component_list = sorted( components_connect_order,
135 key=lambda key: components_connect_order[key] )
adminbae64d82013-08-01 10:50:15 -0700136 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700137 for component in ordered_component_list:
Jon Hall714eeba2015-09-29 17:53:10 -0700138 self.componentInit( component )
adminbae64d82013-08-01 10:50:15 -0700139
Jon Hall714eeba2015-09-29 17:53:10 -0700140 def configparser( self ):
adminbae64d82013-08-01 10:50:15 -0700141 '''
142 It will parse the config file (teston.cfg) and return as dictionary
143 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700144 matchFileName = re.match( r'(.*)\.cfg', self.configFile, re.M | re.I )
adminbae64d82013-08-01 10:50:15 -0700145 if matchFileName:
Jon Hall714eeba2015-09-29 17:53:10 -0700146 xml = open( self.configFile ).read()
147 try:
148 self.configDict = xmldict.xml_to_dict( xml )
adminbae64d82013-08-01 10:50:15 -0700149 return self.configDict
Jon Hall1306a562015-09-04 11:21:24 -0700150 except IOError:
adminbae64d82013-08-01 10:50:15 -0700151 print "There is no such file to parse " + self.configFile
Jon Hall1306a562015-09-04 11:21:24 -0700152 else:
153 print "There is no such file to parse " + self.configFile
kelvin-onlabf70fd542015-05-07 18:41:40 -0700154
Jon Hall714eeba2015-09-29 17:53:10 -0700155 def componentInit( self, component ):
adminbae64d82013-08-01 10:50:15 -0700156 '''
157 This method will initialize specified component
158 '''
159 global driver_options
Jon Hall0fc0d452015-07-14 09:49:58 -0700160 self.initiated = False
Jon Hall714eeba2015-09-29 17:53:10 -0700161 self.log.info( "Creating component Handle: " + component )
Jon Halld61331b2015-02-17 16:35:47 -0800162 driver_options = {}
adminbae64d82013-08-01 10:50:15 -0700163 if 'COMPONENTS' in self.componentDictionary[component].keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700164 driver_options = dict( self.componentDictionary[component]['COMPONENTS'] )
adminbae64d82013-08-01 10:50:15 -0700165
Jon Hall714eeba2015-09-29 17:53:10 -0700166 driver_options['name'] = component
adminbae64d82013-08-01 10:50:15 -0700167 driverName = self.componentDictionary[component]['type']
Jon Hall714eeba2015-09-29 17:53:10 -0700168 driver_options['type'] = driverName
kelvin-onlabf70fd542015-05-07 18:41:40 -0700169
Jon Hall714eeba2015-09-29 17:53:10 -0700170 classPath = self.getDriverPath( driverName.lower() )
171 driverModule = importlib.import_module( classPath )
172 driverClass = getattr( driverModule, driverName )
adminbae64d82013-08-01 10:50:15 -0700173 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700174
Jon Hall714eeba2015-09-29 17:53:10 -0700175 if "OCN" in self.componentDictionary[component]['host'] and\
176 main.onoscell:
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700177 self.componentDictionary[component]['host'] = main.mnIP
178
Jon Hall714eeba2015-09-29 17:53:10 -0700179 user_name = self.componentDictionary[component].get( 'user',
180 getpass.getuser() )
181 ip_address = self.componentDictionary[component].get( 'host',
182 'localhost' )
183 pwd = self.componentDictionary[component].get( 'password',
184 'changeme' )
185 port = self.componentDictionary[component].get( 'port' )
186 connect_result = driverObject.connect( user_name=user_name,
187 ip_address=ip_address,
188 pwd=pwd,
189 port=port,
190 options=driver_options)
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700191
adminbae64d82013-08-01 10:50:15 -0700192 if not connect_result:
Jon Hall714eeba2015-09-29 17:53:10 -0700193 self.log.error( "Exiting from the test execution because connecting to the " +
194 component + " component failed." )
Jon Halld61331b2015-02-17 16:35:47 -0800195 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700196
Jon Hall714eeba2015-09-29 17:53:10 -0700197 vars( self )[component] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700198 self.initiated = True
kelvin-onlabf70fd542015-05-07 18:41:40 -0700199
Jon Hall714eeba2015-09-29 17:53:10 -0700200 def run( self ):
adminbae64d82013-08-01 10:50:15 -0700201 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700202 The Execution of the test script's cases listed in the Test params
203 file will be done here then update each test case result.
204 This method will return main.TRUE if it executed all the test cases
205 successfully, else will retun main.FALSE
adminbae64d82013-08-01 10:50:15 -0700206 '''
adminbae64d82013-08-01 10:50:15 -0700207 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700208 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700209 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800210 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700211 self.TOTAL_TC_NORESULT = 0
212 self.TOTAL_TC_FAIL = 0
213 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700214 self.TEST_ITERATION = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700215
216 # NOTE: number of main.step statements in the
217 # outer most level of the test case. used to
218 # execute code in smaller steps
219 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700220 self.CASERESULT = self.NORESULT
221
Jon Halld61331b2015-02-17 16:35:47 -0800222 import testparser
Jon Hall714eeba2015-09-29 17:53:10 -0700223 testFile = self.tests_path + "/" + self.TEST + "/" + self.TEST + ".py"
224 test = testparser.TestParser( testFile )
adminbae64d82013-08-01 10:50:15 -0700225 self.testscript = test.testscript
226 self.code = test.getStepCode()
Jon Hall714eeba2015-09-29 17:53:10 -0700227 repeat = int( self.params.get( 'repeat', 1 ) )
228 self.TOTAL_TC_PLANNED = len( self.testcases_list ) * repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700229
adminbae64d82013-08-01 10:50:15 -0700230 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700231 while repeat:
Jon Halla1185982014-09-15 14:55:10 -0700232 for self.CurrentTestCaseNumber in self.testcases_list:
Jon Hall714eeba2015-09-29 17:53:10 -0700233 result = self.runCase( self.CurrentTestCaseNumber )
234 repeat -= 1
adminbae64d82013-08-01 10:50:15 -0700235 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700236
Jon Halle234cc42015-08-31 15:26:47 -0700237 def runCase( self, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700238 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700239 self.CurrentTestCase = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700240
241 # List of step results in a case. ANDed together to get the result
242 self.stepResultsList = []
kelvin-onlabf70fd542015-05-07 18:41:40 -0700243 self.stepName = ""
Jon Hall783bbf92015-07-23 14:33:19 -0700244 self.caseExplanation = ""
adminbae64d82013-08-01 10:50:15 -0700245 result = self.TRUE
Jon Hall714eeba2015-09-29 17:53:10 -0700246
247 # NOTE: number of main.step statements in the
248 # outer most level of the test case. used to
249 # execute code in smaller steps
250 self.stepCount = 0
251
252 # NOTE: This is the current number of main.step()'s executed
253 # in a case. Used for logging.
254 self.stepNumber = 0
adminbae64d82013-08-01 10:50:15 -0700255 self.EXPERIMENTAL_MODE = self.FALSE
256 self.addCaseHeader()
Jon Halle234cc42015-08-31 15:26:47 -0700257 self.testCaseNumber = str( testCaseNumber )
258 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700259 stopped = False
Jon Hall5a72b712015-09-28 12:20:59 -0700260 try:
261 self.code[self.testCaseNumber]
Jon Halld61331b2015-02-17 16:35:47 -0800262 except KeyError:
Jon Halle234cc42015-08-31 15:26:47 -0700263 self.log.error( "There is no Test-Case " + self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800264 return self.FALSE
adminbae64d82013-08-01 10:50:15 -0700265 self.stepCount = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700266 while self.stepCount < len( self.code[self.testCaseNumber].keys() ):
267 result = self.runStep( self.code, self.testCaseNumber )
Jon Hallfebb1c72015-03-05 13:30:09 -0800268 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700269 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800270 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700271 continue
Jon Hall5a72b712015-09-28 12:20:59 -0700272 # stepResults format: ( stepNo[], stepName[], stepResult[], onFail[] )
273 stepResults = self.stepResultsList
Jon Halle234cc42015-08-31 15:26:47 -0700274 if not stopped:
275 if self.CASERESULT == self.TRUE or self.CASERESULT == self.FALSE:
Jon Hall714eeba2015-09-29 17:53:10 -0700276 # Result was already explitily set somewhere else like
277 # in skipCase()
Jon Halle234cc42015-08-31 15:26:47 -0700278 pass
Jon Hall5a72b712015-09-28 12:20:59 -0700279 elif all( self.TRUE == i for i in stepResults ):
kelvin-onlabf70fd542015-05-07 18:41:40 -0700280 # ALL PASSED
281 self.CASERESULT = self.TRUE
Jon Hall5a72b712015-09-28 12:20:59 -0700282 elif self.FALSE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700283 # AT LEAST ONE FAILED
284 self.CASERESULT = self.FALSE
Jon Hall5a72b712015-09-28 12:20:59 -0700285 elif self.TRUE in stepResults:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700286 # AT LEAST ONE PASSED
287 self.CASERESULT = self.TRUE
288 else:
289 self.CASERESULT = self.NORESULT
Jon Hall714eeba2015-09-29 17:53:10 -0700290 self.testCaseResult[str( self.CurrentTestCaseNumber )] = self.CASERESULT
291 self.logger.updateCaseResults( self )
Jon Hall783bbf92015-07-23 14:33:19 -0700292 self.log.wiki( "<p>" + self.caseExplanation + "</p>" )
293 self.log.summary( self.caseExplanation )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700294 self.log.wiki( "<ul>" )
acsmarse2d1ed12015-10-05 13:51:17 -0700295 subcaseMessage = False
kelvin-onlabf70fd542015-05-07 18:41:40 -0700296 for line in self.stepCache.splitlines():
acsmarse2d1ed12015-10-05 13:51:17 -0700297 if re.search( "[0-9]\.[0-9]", line ): # Step
298 if subcaseMessage: # End of Failure Message Printout
299 self.log.wiki( "</ul>\n" )
300 subcaseMessage = False
301 if re.search( " - PASS$", line ):
302 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
303 elif re.search( " - FAIL$", line ):
304 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
305 elif re.search( " - No Result$", line ):
306 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
307 else: # Substep
308 if not subcaseMessage: # Open Failure Message Printout
309 self.log.wiki( "<ul><li>" + line + "</li>\n" )
310 subcaseMessage = True
311 else: # Add to Failure Message Printout
312 self.log.wiki( "<li>" + line + "</li>\n" )
acsmars27e62dd2015-10-06 11:35:47 -0700313 if subcaseMessage: # End of Failure Message Printout for last item
314 self.log.wiki( "</ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700315 self.log.wiki( "</ul>" )
316 self.log.summary( self.stepCache )
317 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700318 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700319
Jon Hall714eeba2015-09-29 17:53:10 -0700320 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700321 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700322 try:
323 step = self.stepCount
324 # stepResults format: ( stepNo, stepName, stepResult, onFail )
325 # NOTE: This is needed to catch results of main.step()'s
326 # called inside functions or loops
327 self.stepResults = ( [], [], [], [] )
adminbae64d82013-08-01 10:50:15 -0700328 exec code[testCaseNumber][step] in module.__dict__
329 self.stepCount = self.stepCount + 1
Jon Hall5a72b712015-09-28 12:20:59 -0700330
331 # Iterate through each of the steps and print them
332 for index in range( len( self.stepResults[0] ) ):
Jon Hall714eeba2015-09-29 17:53:10 -0700333 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jon Hall5a72b712015-09-28 12:20:59 -0700334 stepNo = self.stepResults[0][ index ]
335 stepName = self.stepResults[1][ index ]
336 stepResult = self.stepResults[2][ index ]
337 onFail = self.stepResults[3][ index ]
338 self.stepCache += "\t" + str( testCaseNumber ) + "."
339 self.stepCache += str( stepNo ) + " "
340 self.stepCache += stepName + " - "
341 if stepResult == self.TRUE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700342 self.stepCache += "PASS\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700343 elif stepResult == self.FALSE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700344 self.stepCache += "FAIL\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700345 self.stepCache += "\t\t" + onFail + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700346 else:
347 self.stepCache += "No Result\n"
Jon Hall714eeba2015-09-29 17:53:10 -0700348 self.stepResultsList.append( stepResult )
Jon Halle234cc42015-08-31 15:26:47 -0700349 except StopIteration: # Raised in self.skipCase()
350 self.log.warn( "Skipping the rest of CASE" +
351 str( testCaseNumber ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700352 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700353 self.stepCache += "\t\t" + self.onFailMsg + "\n"
354 self.stepCount = self.stepCount + 1
355 return self.FALSE
Jon Hall5b586732015-06-11 11:39:39 -0700356 except StandardError:
Jon Hall5a72b712015-09-28 12:20:59 -0700357 stepNo = self.stepResults[0][ self.stepNumber - 1]
358 stepName = self.stepResults[1][ self.stepNumber - 1 ]
Jon Hall40d2cbd2015-06-03 16:24:29 -0700359 self.log.exception( "\nException in the following section of" +
Jon Halle234cc42015-08-31 15:26:47 -0700360 " code: " + str( testCaseNumber ) + "." +
Jon Hall5a72b712015-09-28 12:20:59 -0700361 str( stepNo ) + ": " + stepName )
adminbae64d82013-08-01 10:50:15 -0700362 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700363 self.logger.updateCaseResults( self )
364 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700365 self.log.wiki( "<ul>" )
366 for line in self.stepCache.splitlines():
367 if re.search( " - PASS$", line ):
368 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
369 elif re.search( " - FAIL$", line ):
370 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
371 elif re.search( " - No Result$", line ):
372 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700373 else: # Should only be on fail message
374 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700375 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700376 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700377 self.log.summary( self.stepCache )
378 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700379 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700380 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700381 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700382 if cli.stop:
383 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700384 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700385 self.testCaseResult[str( self.CurrentTestCaseNumber )] = "Stopped"
386 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700387 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700388 return self.FALSE
389
390 def skipCase( self, result="DEFAULT", msg=None ):
391 """
392 Will skip the rest of the code in a test case. The case results will be
393 determined as normal based on completed assertions unless the result
394 argument is given.
395
396 Optional Arguments:
397 result: Case insensite string. Can be 'PASS' or 'FAIL' and will set
398 the case result accordingly.
399 msg: Message to be printed when the case is skipped in the reports.
400 """
401 result = result.upper().strip()
402 if result == "PASS":
403 self.CASERESULT = self.TRUE
404 elif result == "FAIL":
405 self.CASERESULT = self.FALSE
406 self.onFailMsg = "Skipping the rest of this case. "
407 if msg:
408 self.onFailMsg += str( msg )
409 raise StopIteration
kelvin-onlabf70fd542015-05-07 18:41:40 -0700410
Jon Hall714eeba2015-09-29 17:53:10 -0700411 def addCaseHeader( self ):
412 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" +\
413 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
414 self.log.exact( caseHeader )
415 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" +\
416 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700417 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700418 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700419
Jon Hall714eeba2015-09-29 17:53:10 -0700420 def addCaseFooter( self ):
Jon Hall5a72b712015-09-28 12:20:59 -0700421 stepNo = self.stepResults[0][-2]
Jon Hall714eeba2015-09-29 17:53:10 -0700422 if stepNo > 0:
423 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
424 str( stepNo ) + ": " + str( self.stepName )
425 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep +\
426 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700427
Jon Hall714eeba2015-09-29 17:53:10 -0700428 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " +\
429 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700430
adminbae64d82013-08-01 10:50:15 -0700431 for driver in self.driversList:
Jon Hall714eeba2015-09-29 17:53:10 -0700432 vars( self )[driver].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700433
Jon Hall714eeba2015-09-29 17:53:10 -0700434 def cleanup( self ):
adminbae64d82013-08-01 10:50:15 -0700435 '''
Jon Hall5b586732015-06-11 11:39:39 -0700436 Print a summary of the current test's results then attempt to release
437 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700438
Jon Hall5b586732015-06-11 11:39:39 -0700439 This function shouldbe threadsafe such that cleanup will only be
440 executed once per test.
441
442 This will return TRUE if all the component handles and log handles
443 closed properly, else return FALSE.
adminbae64d82013-08-01 10:50:15 -0700444 '''
445 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700446 lock = self.cleanupLock
447 if lock.acquire( False ):
448 try:
449 if self.cleanupFlag is False: # First thread to run this
450 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700451 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700452 self.logger.testSummary( self )
Jon Hall5b586732015-06-11 11:39:39 -0700453 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700454 try:
455 tempObject = vars( self )[component]
456 print "Disconnecting from " + str( tempObject.name ) +\
457 ": " + str( tempObject.__class__)
Jon Hall5b586732015-06-11 11:39:39 -0700458 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700459 except KeyboardInterrupt:
460 pass
461 except KeyError:
462 # Component not created yet
463 self.log.warn( "Could not find the component " +
464 str( component ) )
465 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700466 self.log.exception( "Exception while disconnecting from " +
467 str( component ) )
468 result = self.FALSE
469 # Closing all the driver's session files
470 for driver in self.componentDictionary.keys():
471 try:
Jon Hall714eeba2015-09-29 17:53:10 -0700472 vars( self )[driver].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700473 except KeyboardInterrupt:
474 pass
475 except KeyError:
476 # Component not created yet
477 self.log.warn( "Could not find the component " +
478 str( driver ) + " while trying to" +
479 " close log file" )
480 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700481 self.log.exception( "Exception while closing log files for " +
482 str( driver ) )
483 result = self.FALSE
484 else:
485 pass # Someone else already ran through this function
486 finally:
487 lock.release()
488 else: # Someone already has a lock
489 # NOTE: This could cause problems if we don't release the lock
490 # correctly
491 lock.acquire() # Wait for the other thread to finish
492 # NOTE: If we don't wait, exit could be called while the thread
493 # with the lock is still cleaning up
494 lock.release()
adminbae64d82013-08-01 10:50:15 -0700495 return result
Jon Halld61331b2015-02-17 16:35:47 -0800496
Jon Hall714eeba2015-09-29 17:53:10 -0700497 def pause( self ):
adminbae64d82013-08-01 10:50:15 -0700498 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700499 This function will pause the test's execution, and will continue after
500 user provide 'resume' command.
adminbae64d82013-08-01 10:50:15 -0700501 '''
502 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700503
Jon Hall714eeba2015-09-29 17:53:10 -0700504 def onfail( self, *components ):
adminbae64d82013-08-01 10:50:15 -0700505 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700506 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700507 '''
adminbae64d82013-08-01 10:50:15 -0700508 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700509 try:
adminbae64d82013-08-01 10:50:15 -0700510 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700511 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700512 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700513 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700514 print str( e )
adminbae64d82013-08-01 10:50:15 -0700515 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700516 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700517 try:
adminbae64d82013-08-01 10:50:15 -0700518 for component in components:
Jon Hall714eeba2015-09-29 17:53:10 -0700519 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700520 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700521 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700522 print str( e )
adminbae64d82013-08-01 10:50:15 -0700523 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700524
Jon Hall714eeba2015-09-29 17:53:10 -0700525 def getDriverPath( self, driverName ):
adminbae64d82013-08-01 10:50:15 -0700526 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700527 Based on the component 'type' specified in the params , this method
528 will find the absolute path, by recursively searching the name of
529 the component.
530
531 NOTE: This function requires the linux 'find' command.
adminbae64d82013-08-01 10:50:15 -0700532 '''
533 import commands
534
Jon Hall714eeba2015-09-29 17:53:10 -0700535 cmd = "find " + drivers_path + " -name " + driverName + ".py"
536 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700537
Jon Hall714eeba2015-09-29 17:53:10 -0700538 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700539 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700540
adminbae64d82013-08-01 10:50:15 -0700541 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700542 result_count = result_count + 1
543 if result_count > 1:
544 print "Found " + driverName + " " + str( result_count ) + " times:"
545 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700546 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700547
Jon Hall714eeba2015-09-29 17:53:10 -0700548 result = re.sub( "(.*)drivers", "", result )
549 result = re.sub( "\/\/", "/", result )
550 result = re.sub( "\.py", "", result )
551 result = re.sub( "\.pyc", "", result )
552 result = re.sub( "\/", ".", result )
553 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700554 return result
adminbae64d82013-08-01 10:50:15 -0700555
Jon Hall714eeba2015-09-29 17:53:10 -0700556 def step( self, stepDesc ):
adminbae64d82013-08-01 10:50:15 -0700557 '''
558 The step information of the test-case will append to the logs.
559 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700560 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
561 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700562 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700563 self.stepNumber += 1
564 self.stepResults[0].append( self.stepNumber )
565 self.stepResults[1].append( stepDesc )
566 self.stepResults[2].append( self.NORESULT )
567 self.stepResults[3].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700568
Jon Hall714eeba2015-09-29 17:53:10 -0700569 stepName = " " + str( self.CurrentTestCaseNumber ) + "." +\
570 str( self.stepNumber ) + ": " + str( stepDesc )
adminbae64d82013-08-01 10:50:15 -0700571 self.log.step(stepName)
572 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700573 line = "\n" + "-" * 45 + "\n"
574 if self.stepNumber > 1:
575 stepHeader = line + "End of Step " + previousStep + line
576 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700577 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700578 vars( self )[driver + 'log'].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700579
Jon Hall714eeba2015-09-29 17:53:10 -0700580 def case( self, testCaseName ):
adminbae64d82013-08-01 10:50:15 -0700581 '''
582 Test's each test-case information will append to the logs.
583 '''
Jon Halld61331b2015-02-17 16:35:47 -0800584 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700585 testCaseName = " " + str( testCaseName )
586 self.log.case( testCaseName )
587 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700588 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700589 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700590
Jon Hall714eeba2015-09-29 17:53:10 -0700591 def testDesc( self, description ):
adminbae64d82013-08-01 10:50:15 -0700592 '''
593 Test description will append to the logs.
594 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700595 description = "Test Description : " + str( description )
596 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700597
Jon Hall714eeba2015-09-29 17:53:10 -0700598 def _getTest( self ):
adminbae64d82013-08-01 10:50:15 -0700599 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700600 This method will parse the test script to find required test
601 information.
adminbae64d82013-08-01 10:50:15 -0700602 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700603 testFile = self.tests_path + "/" + self.TEST + "/" + self.TEST + ".py"
604 testFileHandler = open( testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700605 testFileList = testFileHandler.readlines()
606 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700607 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700608 for index in range( len( testFileList ) ):
609 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
610 testFileList[index],
611 0 )
adminbae64d82013-08-01 10:50:15 -0700612 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700613 counter = counter + 1
614 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700615
Jon Hall714eeba2015-09-29 17:53:10 -0700616 def response_parser( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700617 ''' It will load the default response parser '''
618 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700619 response_dict = self.response_to_dict( response, return_format )
620 return_format_string = self.dict_to_return_format( response,
621 return_format,
622 response_dict )
adminbae64d82013-08-01 10:50:15 -0700623 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700624
Jon Hall714eeba2015-09-29 17:53:10 -0700625 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700626 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700627 json_match = re.search( '^\s*{', response )
628 xml_match = re.search( '^\s*\<', response )
629 ini_match = re.search( '^\s*\[', response )
630 if json_match:
631 self.log.info( "Response is in 'JSON' format, converting to '" +
632 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800633 # Formatting the json string
Jon Hall714eeba2015-09-29 17:53:10 -0700634 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
635 response = re.sub( r",\s*'?(\w)", r',"\1', response )
636 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
637 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
638 try:
adminbae64d82013-08-01 10:50:15 -0700639 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700640 response_dict = json.loads( response )
Jon Hall1306a562015-09-04 11:21:24 -0700641 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700642 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700643 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700644 elif ini_match:
645 self.log.info( "Response is in 'INI' format, converting to '" +
646 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700647 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700648 response_file = open( "respnse_file.temp", 'w' )
649 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800650 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700651 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700652 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700653 elif xml_match:
654 self.log.info( "Response is in 'XML' format, converting to '" +
655 return_format + "' format" )
656 try:
657 response_dict = xmldict.xml_to_dict( "<response> " +
658 str( response ) +
659 " </response>" )
Jon Hall1306a562015-09-04 11:21:24 -0700660 except StandardError:
661 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700662 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700663
Jon Hall714eeba2015-09-29 17:53:10 -0700664 def dict_to_return_format( self, response, return_format, response_dict ):
665 if return_format == 'table':
adminbae64d82013-08-01 10:50:15 -0700666 ''' Will return in table format'''
667 to_do = "Call the table output formatter"
668 global response_table
669 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700670 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700671
Jon Hall714eeba2015-09-29 17:53:10 -0700672 def get_table( value_to_convert ):
673 ''' This will parse the dictionary recusrsively and print as
674 table format'''
adminbae64d82013-08-01 10:50:15 -0700675 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700676 if isinstance( value_to_convert, dict ):
677 table_data = table_data + '\t'.join( value_to_convert ) +\
678 "\n"
679 for temp_val in value_to_convert.values():
680 table_data = table_data + get_table( temp_val )
681 else:
682 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800683 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700684
Jon Hall714eeba2015-09-29 17:53:10 -0700685 for value in response_dict.values():
686 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700687 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700688
Jon Hall714eeba2015-09-29 17:53:10 -0700689 elif return_format == 'config':
adminbae64d82013-08-01 10:50:15 -0700690 ''' Will return in config format'''
691 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700692 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700693 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700694 response_config = re.sub( ",", "\n\t", response_string )
695 response_config = re.sub( "u\'", "\'", response_config )
696 response_config = re.sub( "{", "", response_config )
697 response_config = re.sub( "}", "\n", response_config )
698 response_config = re.sub( ":", " =", response_config )
699 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700700 elif return_format == 'xml':
701 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700702 response_xml = xmldict.dict_to_xml( response_dict )
703 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
704 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700705 elif return_format == 'json':
706 ''' Will return in json format'''
707 to_do = 'Call dict to xml coverter'
708 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700709 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700710 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700711
Jon Hall714eeba2015-09-29 17:53:10 -0700712 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700713 self.random_order = self.random_order + 1
714 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700715
Jon Hall714eeba2015-09-29 17:53:10 -0700716 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700717 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700718 for thread in threading.enumerate():
719 if thread.isAlive():
720 try:
721 thread._Thread__stop()
722 except:
Jon Hall1306a562015-09-04 11:21:24 -0700723 # NOTE: We should catch any exceptions while trying to
724 # close the thread so that we can try to close the other
725 # threads as well
Jon Hall714eeba2015-09-29 17:53:10 -0700726 print str( thread.getName() ) +\
727 ' could not be terminated'
adminbae64d82013-08-01 10:50:15 -0700728 sys.exit()
729
Jon Hallcd3d2a32015-10-01 11:07:28 -0700730 def stop( self, email=False ):
731 """
732 Stop the test until Ctrl-D is entered.
733 Ctrl-C will kill the test
734 """
735 try:
736 if email:
737 # FIXME: implement this
738 raise NotImplementedError
739 self.log.error( "Test execution suspended. Press Ctrl-D to "
740 "resume or Ctrl-C to exit the test" )
741 # NOTE: Ctrl-D needs to be entered on a new line
742 while True:
743 # TODO: we could give the user an interactive prompt where
744 # they could call functions
745 raw_input()
746 except EOFError:
747 return
748 # Pass all other exceptions up to caller
749
750
Jon Hall714eeba2015-09-29 17:53:10 -0700751def verifyOptions( options ):
adminbae64d82013-08-01 10:50:15 -0700752 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700753 This will verify the command line options and set to default values,
754 if any option not given in command line.
adminbae64d82013-08-01 10:50:15 -0700755 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700756 verifyTest( options )
757 verifyExample( options )
758 verifyTestScript( options )
adminbae64d82013-08-01 10:50:15 -0700759 verifyParams()
Jon Hall714eeba2015-09-29 17:53:10 -0700760 verifyLogdir( options )
761 verifyMail( options )
762 verifyTestCases( options )
763 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700764
Jon Hall714eeba2015-09-29 17:53:10 -0700765def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700766 try:
767 if options.testname:
768 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700769 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700770 main.tests_path = tests_path
771 elif options.example:
772 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700773 main.tests_path = path + "/examples/"
774 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700775 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700776 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700777 main.exit()
adminbae64d82013-08-01 10:50:15 -0700778
Jon Hall714eeba2015-09-29 17:53:10 -0700779def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700780 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700781 main.testDir = path + '/examples/'
782 main.tests_path = path + "/examples/"
783 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700784
Jon Hall714eeba2015-09-29 17:53:10 -0700785def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800786 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700787 if options.logdir:
788 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700789 else:
Jon Halld61331b2015-02-17 16:35:47 -0800790 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700791
Jon Hall714eeba2015-09-29 17:53:10 -0700792def verifyMail( options ):
Jon Halld61331b2015-02-17 16:35:47 -0800793 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700794 if options.mail:
795 main.mail = options.mail
Jon Hall714eeba2015-09-29 17:53:10 -0700796 else:
797 main.mail = main.params.get( 'mail', 'paxweb@paxterrasolutions.com' )
adminbae64d82013-08-01 10:50:15 -0700798
Jon Hall714eeba2015-09-29 17:53:10 -0700799def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800800 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700801 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800802 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800803 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700804 testcases_list = re.sub( "(\[|\])", "", options.testcases )
805 main.testcases_list = eval( testcases_list + "," )
806 else:
adminbae64d82013-08-01 10:50:15 -0700807 if 'testcases' in main.params.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700808 temp = eval( main.params['testcases'] + "," )
809 list1 = []
810 if isinstance( temp[0], list ):
Jon Hallfebb1c72015-03-05 13:30:09 -0800811 for test in temp:
812 for testcase in test:
Jon Hall714eeba2015-09-29 17:53:10 -0700813 if isinstance( testcase, int ):
814 testcase = [testcase]
815 list1.extend( testcase )
816 else:
817 temp = list( temp )
Jon Hallfebb1c72015-03-05 13:30:09 -0800818 for testcase in temp:
Jon Hall714eeba2015-09-29 17:53:10 -0700819 if isinstance( testcase, int ):
820 testcase = [testcase]
821 list1.extend( testcase )
822 main.testcases_list = list1
823 else:
824 print "Testcases not specifed in params, please provide in " +\
825 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800826 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700827
Jon Hall714eeba2015-09-29 17:53:10 -0700828def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700829 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700830 if options.onoscell:
831 main.onoscell = options.onoscell
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700832 main.onosIPs = []
833 main.mnIP = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700834 cellCMD = ". ~/.profile; cell " + main.onoscell
835 output = subprocess.check_output( ["bash", '-c', cellCMD] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700836 splitOutput = output.splitlines()
Jon Hall714eeba2015-09-29 17:53:10 -0700837 for i in range( len( splitOutput ) ):
838 if re.match( "OCN", splitOutput[i] ):
839 mnNode = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700840 main.mnIP = mnNode[1]
Jon Hall714eeba2015-09-29 17:53:10 -0700841 # cell already sorts OC variables in bash, so no need to
842 # sort in TestON
843 if re.match( "OC[1-9]", splitOutput[i] ):
844 onosNodes = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700845 main.onosIPs.append( onosNodes[1] )
Jon Hall714eeba2015-09-29 17:53:10 -0700846 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700847 main.onoscell = main.FALSE
848
Jon Hall714eeba2015-09-29 17:53:10 -0700849def verifyTestScript( options ):
adminbae64d82013-08-01 10:50:15 -0700850 '''
851 Verifyies test script.
852 '''
Jon Halld61331b2015-02-17 16:35:47 -0800853 main.openspeak = openspeak.OpenSpeak()
Jon Hall714eeba2015-09-29 17:53:10 -0700854 openspeakfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".ospk"
855 testfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".py"
856 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700857 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700858 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
859 elif os.path.exists( testfile ):
Jon Hall44506242015-07-29 17:40:26 -0700860 # No openspeak found, using python file instead
861 pass
adminbae64d82013-08-01 10:50:15 -0700862 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700863 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " +\
Jon Hall44506242015-07-29 17:40:26 -0700864 "Python or OpenSpeak test script in the tests folder: " +\
Jon Hall714eeba2015-09-29 17:53:10 -0700865 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700866 __builtin__.testthread = None
867 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700868 try:
869 testModule = __import__( main.classPath,
870 globals(),
871 locals(),
872 [main.TEST],
873 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700874 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700875 print "There was an import error, it might mean that there is " +\
876 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800877 main.exit()
adminbae64d82013-08-01 10:50:15 -0700878
Jon Hall714eeba2015-09-29 17:53:10 -0700879 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700880 main.testObject = testClass()
881 load_parser()
Jon Hall714eeba2015-09-29 17:53:10 -0700882 main.params = main.parser.parseParams( main.classPath )
883 main.topology = main.parser.parseTopology( main.classPath )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700884
adminbae64d82013-08-01 10:50:15 -0700885def verifyParams():
Jon Hall714eeba2015-09-29 17:53:10 -0700886 try:
adminbae64d82013-08-01 10:50:15 -0700887 main.params = main.params['PARAMS']
Jon Hall1306a562015-09-04 11:21:24 -0700888 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700889 print "Error with the params file: Either the file not specified " +\
890 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800891 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700892 try:
adminbae64d82013-08-01 10:50:15 -0700893 main.topology = main.topology['TOPOLOGY']
Jon Hall1306a562015-09-04 11:21:24 -0700894 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700895 print "Error with the Topology file: Either the file not specified " +\
896 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700897 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700898
Jon Hall714eeba2015-09-29 17:53:10 -0700899def load_parser():
adminbae64d82013-08-01 10:50:15 -0700900 '''
901 It facilitates the loading customised parser for topology and params file.
902 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700903 It also loads default xmlparser if no parser have specified in teston.cfg
904 file.
adminbae64d82013-08-01 10:50:15 -0700905
906 '''
907 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700908 if 'file' in confighash['config']['parser'] and\
909 'class' in confighash['config']['parser']:
Jon Hall44506242015-07-29 17:40:26 -0700910 path = confighash['config']['parser']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700911 if path is not None or\
912 confighash['config']['parser']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700913 try:
914 module = re.sub( r".py\s*$", "", path )
adminbae64d82013-08-01 10:50:15 -0700915 moduleList = module.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700916 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700917 parsingClass = confighash['config']['parser']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700918 parsingModule = __import__( newModule,
919 globals(),
920 locals(),
921 [parsingClass],
922 -1 )
923 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -0700924 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700925 if hasattr( main.parser, "parseParams" ) and\
926 hasattr( main.parser, "parseTopology" ) and\
927 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -0700928 pass
929 else:
930 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -0700931 main.exit()
Jon Hall44506242015-07-29 17:40:26 -0700932 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700933 print "Could not find the file " + path +\
934 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -0800935 load_defaultParser()
Jon Hall714eeba2015-09-29 17:53:10 -0700936 elif confighash['config']['parser']['file'] is None or\
937 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800938 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700939 else:
940 load_defaultParser()
941
942def load_defaultParser():
943 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700944 It will load the default parser which is xml parser to parse the params and
945 topology file.
adminbae64d82013-08-01 10:50:15 -0700946 '''
947 moduleList = main.parserPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700948 newModule = ".".join( moduleList[-2:] )
949 try:
Jon Halld61331b2015-02-17 16:35:47 -0800950 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -0700951 parsingModule = __import__( newModule,
952 globals(),
953 locals(),
954 [parsingClass],
955 -1 )
956 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -0700957 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700958 if hasattr( main.parser, "parseParams" ) and\
959 hasattr( main.parser, "parseTopology" ) and\
960 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -0700961 pass
962 else:
963 main.exit()
adminbae64d82013-08-01 10:50:15 -0700964 except ImportError:
965 print sys.exc_info()[1]
966
Jon Hall714eeba2015-09-29 17:53:10 -0700967def load_logger():
adminbae64d82013-08-01 10:50:15 -0700968 '''
969 It facilitates the loading customised parser for topology and params file.
970 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700971 It also loads default xmlparser if no parser have specified in teston.cfg
972 file.
adminbae64d82013-08-01 10:50:15 -0700973 '''
974 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700975 if 'file' in confighash['config']['logger'] and\
976 'class' in confighash['config']['logger']:
Jon Hall44506242015-07-29 17:40:26 -0700977 path = confighash['config']['logger']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700978 if path is not None or\
979 confighash['config']['logger']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700980 try:
981 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -0700982 moduleList = module.split( "/" )
983 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700984 loggerClass = confighash['config']['logger']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700985 loggerModule = __import__( newModule,
986 globals(),
987 locals(),
988 [loggerClass],
989 -1 )
990 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -0700991 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -0700992 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700993 print "Could not find the file " + path +\
994 " using default logger."
adminbae64d82013-08-01 10:50:15 -0700995 load_defaultlogger()
Jon Hall714eeba2015-09-29 17:53:10 -0700996 elif confighash['config']['parser']['file'] is None or\
997 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800998 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700999 else:
1000 load_defaultlogger()
1001
1002def load_defaultlogger():
1003 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001004 It will load the default parser which is xml parser to parse the params and
1005 topology file.
adminbae64d82013-08-01 10:50:15 -07001006 '''
1007 moduleList = main.loggerPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -07001008 newModule = ".".join( moduleList[-2:] )
1009 try:
Jon Halld61331b2015-02-17 16:35:47 -08001010 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001011 loggerModule = __import__( newModule,
1012 globals(),
1013 locals(),
1014 [loggerClass],
1015 -1 )
1016 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001017 main.logger = loggerClass()
1018
1019 except ImportError:
1020 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -08001021 main.exit()
adminbae64d82013-08-01 10:50:15 -07001022
Jon Hall714eeba2015-09-29 17:53:10 -07001023def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001024 print "THIS IS ECHO"