blob: 6eb70e8e1c82e38097879e6975ce6dc81e1ad341 [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" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700313 self.log.wiki( "</ul>" )
314 self.log.summary( self.stepCache )
315 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700316 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700317
Jon Hall714eeba2015-09-29 17:53:10 -0700318 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700319 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700320 try:
321 step = self.stepCount
322 # stepResults format: ( stepNo, stepName, stepResult, onFail )
323 # NOTE: This is needed to catch results of main.step()'s
324 # called inside functions or loops
325 self.stepResults = ( [], [], [], [] )
adminbae64d82013-08-01 10:50:15 -0700326 exec code[testCaseNumber][step] in module.__dict__
327 self.stepCount = self.stepCount + 1
Jon Hall5a72b712015-09-28 12:20:59 -0700328
329 # Iterate through each of the steps and print them
330 for index in range( len( self.stepResults[0] ) ):
Jon Hall714eeba2015-09-29 17:53:10 -0700331 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jon Hall5a72b712015-09-28 12:20:59 -0700332 stepNo = self.stepResults[0][ index ]
333 stepName = self.stepResults[1][ index ]
334 stepResult = self.stepResults[2][ index ]
335 onFail = self.stepResults[3][ index ]
336 self.stepCache += "\t" + str( testCaseNumber ) + "."
337 self.stepCache += str( stepNo ) + " "
338 self.stepCache += stepName + " - "
339 if stepResult == self.TRUE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700340 self.stepCache += "PASS\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700341 elif stepResult == self.FALSE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700342 self.stepCache += "FAIL\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700343 self.stepCache += "\t\t" + onFail + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700344 else:
345 self.stepCache += "No Result\n"
Jon Hall714eeba2015-09-29 17:53:10 -0700346 self.stepResultsList.append( stepResult )
Jon Halle234cc42015-08-31 15:26:47 -0700347 except StopIteration: # Raised in self.skipCase()
348 self.log.warn( "Skipping the rest of CASE" +
349 str( testCaseNumber ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700350 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700351 self.stepCache += "\t\t" + self.onFailMsg + "\n"
352 self.stepCount = self.stepCount + 1
353 return self.FALSE
Jon Hall5b586732015-06-11 11:39:39 -0700354 except StandardError:
Jon Hall5a72b712015-09-28 12:20:59 -0700355 stepNo = self.stepResults[0][ self.stepNumber - 1]
356 stepName = self.stepResults[1][ self.stepNumber - 1 ]
Jon Hall40d2cbd2015-06-03 16:24:29 -0700357 self.log.exception( "\nException in the following section of" +
Jon Halle234cc42015-08-31 15:26:47 -0700358 " code: " + str( testCaseNumber ) + "." +
Jon Hall5a72b712015-09-28 12:20:59 -0700359 str( stepNo ) + ": " + stepName )
adminbae64d82013-08-01 10:50:15 -0700360 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700361 self.logger.updateCaseResults( self )
362 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700363 self.log.wiki( "<ul>" )
364 for line in self.stepCache.splitlines():
365 if re.search( " - PASS$", line ):
366 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
367 elif re.search( " - FAIL$", line ):
368 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
369 elif re.search( " - No Result$", line ):
370 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700371 else: # Should only be on fail message
372 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700373 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700374 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700375 self.log.summary( self.stepCache )
376 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700377 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700378 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700379 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700380 if cli.stop:
381 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700382 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700383 self.testCaseResult[str( self.CurrentTestCaseNumber )] = "Stopped"
384 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700385 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700386 return self.FALSE
387
388 def skipCase( self, result="DEFAULT", msg=None ):
389 """
390 Will skip the rest of the code in a test case. The case results will be
391 determined as normal based on completed assertions unless the result
392 argument is given.
393
394 Optional Arguments:
395 result: Case insensite string. Can be 'PASS' or 'FAIL' and will set
396 the case result accordingly.
397 msg: Message to be printed when the case is skipped in the reports.
398 """
399 result = result.upper().strip()
400 if result == "PASS":
401 self.CASERESULT = self.TRUE
402 elif result == "FAIL":
403 self.CASERESULT = self.FALSE
404 self.onFailMsg = "Skipping the rest of this case. "
405 if msg:
406 self.onFailMsg += str( msg )
407 raise StopIteration
kelvin-onlabf70fd542015-05-07 18:41:40 -0700408
Jon Hall714eeba2015-09-29 17:53:10 -0700409 def addCaseHeader( self ):
410 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" +\
411 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
412 self.log.exact( caseHeader )
413 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" +\
414 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700415 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700416 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700417
Jon Hall714eeba2015-09-29 17:53:10 -0700418 def addCaseFooter( self ):
Jon Hall5a72b712015-09-28 12:20:59 -0700419 stepNo = self.stepResults[0][-2]
Jon Hall714eeba2015-09-29 17:53:10 -0700420 if stepNo > 0:
421 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
422 str( stepNo ) + ": " + str( self.stepName )
423 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep +\
424 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700425
Jon Hall714eeba2015-09-29 17:53:10 -0700426 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " +\
427 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700428
adminbae64d82013-08-01 10:50:15 -0700429 for driver in self.driversList:
Jon Hall714eeba2015-09-29 17:53:10 -0700430 vars( self )[driver].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700431
Jon Hall714eeba2015-09-29 17:53:10 -0700432 def cleanup( self ):
adminbae64d82013-08-01 10:50:15 -0700433 '''
Jon Hall5b586732015-06-11 11:39:39 -0700434 Print a summary of the current test's results then attempt to release
435 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700436
Jon Hall5b586732015-06-11 11:39:39 -0700437 This function shouldbe threadsafe such that cleanup will only be
438 executed once per test.
439
440 This will return TRUE if all the component handles and log handles
441 closed properly, else return FALSE.
adminbae64d82013-08-01 10:50:15 -0700442 '''
443 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700444 lock = self.cleanupLock
445 if lock.acquire( False ):
446 try:
447 if self.cleanupFlag is False: # First thread to run this
448 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700449 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700450 self.logger.testSummary( self )
Jon Hall5b586732015-06-11 11:39:39 -0700451 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700452 try:
453 tempObject = vars( self )[component]
454 print "Disconnecting from " + str( tempObject.name ) +\
455 ": " + str( tempObject.__class__)
Jon Hall5b586732015-06-11 11:39:39 -0700456 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700457 except KeyboardInterrupt:
458 pass
459 except KeyError:
460 # Component not created yet
461 self.log.warn( "Could not find the component " +
462 str( component ) )
463 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700464 self.log.exception( "Exception while disconnecting from " +
465 str( component ) )
466 result = self.FALSE
467 # Closing all the driver's session files
468 for driver in self.componentDictionary.keys():
469 try:
Jon Hall714eeba2015-09-29 17:53:10 -0700470 vars( self )[driver].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700471 except KeyboardInterrupt:
472 pass
473 except KeyError:
474 # Component not created yet
475 self.log.warn( "Could not find the component " +
476 str( driver ) + " while trying to" +
477 " close log file" )
478 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700479 self.log.exception( "Exception while closing log files for " +
480 str( driver ) )
481 result = self.FALSE
482 else:
483 pass # Someone else already ran through this function
484 finally:
485 lock.release()
486 else: # Someone already has a lock
487 # NOTE: This could cause problems if we don't release the lock
488 # correctly
489 lock.acquire() # Wait for the other thread to finish
490 # NOTE: If we don't wait, exit could be called while the thread
491 # with the lock is still cleaning up
492 lock.release()
adminbae64d82013-08-01 10:50:15 -0700493 return result
Jon Halld61331b2015-02-17 16:35:47 -0800494
Jon Hall714eeba2015-09-29 17:53:10 -0700495 def pause( self ):
adminbae64d82013-08-01 10:50:15 -0700496 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700497 This function will pause the test's execution, and will continue after
498 user provide 'resume' command.
adminbae64d82013-08-01 10:50:15 -0700499 '''
500 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700501
Jon Hall714eeba2015-09-29 17:53:10 -0700502 def onfail( self, *components ):
adminbae64d82013-08-01 10:50:15 -0700503 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700504 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700505 '''
adminbae64d82013-08-01 10:50:15 -0700506 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700507 try:
adminbae64d82013-08-01 10:50:15 -0700508 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700509 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700510 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700511 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700512 print str( e )
adminbae64d82013-08-01 10:50:15 -0700513 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700514 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700515 try:
adminbae64d82013-08-01 10:50:15 -0700516 for component in components:
Jon Hall714eeba2015-09-29 17:53:10 -0700517 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700518 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700519 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700520 print str( e )
adminbae64d82013-08-01 10:50:15 -0700521 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700522
Jon Hall714eeba2015-09-29 17:53:10 -0700523 def getDriverPath( self, driverName ):
adminbae64d82013-08-01 10:50:15 -0700524 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700525 Based on the component 'type' specified in the params , this method
526 will find the absolute path, by recursively searching the name of
527 the component.
528
529 NOTE: This function requires the linux 'find' command.
adminbae64d82013-08-01 10:50:15 -0700530 '''
531 import commands
532
Jon Hall714eeba2015-09-29 17:53:10 -0700533 cmd = "find " + drivers_path + " -name " + driverName + ".py"
534 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700535
Jon Hall714eeba2015-09-29 17:53:10 -0700536 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700537 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700538
adminbae64d82013-08-01 10:50:15 -0700539 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700540 result_count = result_count + 1
541 if result_count > 1:
542 print "Found " + driverName + " " + str( result_count ) + " times:"
543 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700544 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700545
Jon Hall714eeba2015-09-29 17:53:10 -0700546 result = re.sub( "(.*)drivers", "", result )
547 result = re.sub( "\/\/", "/", result )
548 result = re.sub( "\.py", "", result )
549 result = re.sub( "\.pyc", "", result )
550 result = re.sub( "\/", ".", result )
551 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700552 return result
adminbae64d82013-08-01 10:50:15 -0700553
Jon Hall714eeba2015-09-29 17:53:10 -0700554 def step( self, stepDesc ):
adminbae64d82013-08-01 10:50:15 -0700555 '''
556 The step information of the test-case will append to the logs.
557 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700558 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
559 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700560 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700561 self.stepNumber += 1
562 self.stepResults[0].append( self.stepNumber )
563 self.stepResults[1].append( stepDesc )
564 self.stepResults[2].append( self.NORESULT )
565 self.stepResults[3].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700566
Jon Hall714eeba2015-09-29 17:53:10 -0700567 stepName = " " + str( self.CurrentTestCaseNumber ) + "." +\
568 str( self.stepNumber ) + ": " + str( stepDesc )
adminbae64d82013-08-01 10:50:15 -0700569 self.log.step(stepName)
570 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700571 line = "\n" + "-" * 45 + "\n"
572 if self.stepNumber > 1:
573 stepHeader = line + "End of Step " + previousStep + line
574 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700575 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700576 vars( self )[driver + 'log'].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700577
Jon Hall714eeba2015-09-29 17:53:10 -0700578 def case( self, testCaseName ):
adminbae64d82013-08-01 10:50:15 -0700579 '''
580 Test's each test-case information will append to the logs.
581 '''
Jon Halld61331b2015-02-17 16:35:47 -0800582 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700583 testCaseName = " " + str( testCaseName )
584 self.log.case( testCaseName )
585 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
adminbae64d82013-08-01 10:50:15 -0700586 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700587 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700588
Jon Hall714eeba2015-09-29 17:53:10 -0700589 def testDesc( self, description ):
adminbae64d82013-08-01 10:50:15 -0700590 '''
591 Test description will append to the logs.
592 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700593 description = "Test Description : " + str( description )
594 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700595
Jon Hall714eeba2015-09-29 17:53:10 -0700596 def _getTest( self ):
adminbae64d82013-08-01 10:50:15 -0700597 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700598 This method will parse the test script to find required test
599 information.
adminbae64d82013-08-01 10:50:15 -0700600 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700601 testFile = self.tests_path + "/" + self.TEST + "/" + self.TEST + ".py"
602 testFileHandler = open( testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700603 testFileList = testFileHandler.readlines()
604 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700605 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700606 for index in range( len( testFileList ) ):
607 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
608 testFileList[index],
609 0 )
adminbae64d82013-08-01 10:50:15 -0700610 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700611 counter = counter + 1
612 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700613
Jon Hall714eeba2015-09-29 17:53:10 -0700614 def response_parser( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700615 ''' It will load the default response parser '''
616 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700617 response_dict = self.response_to_dict( response, return_format )
618 return_format_string = self.dict_to_return_format( response,
619 return_format,
620 response_dict )
adminbae64d82013-08-01 10:50:15 -0700621 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700622
Jon Hall714eeba2015-09-29 17:53:10 -0700623 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700624 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700625 json_match = re.search( '^\s*{', response )
626 xml_match = re.search( '^\s*\<', response )
627 ini_match = re.search( '^\s*\[', response )
628 if json_match:
629 self.log.info( "Response is in 'JSON' format, converting to '" +
630 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800631 # Formatting the json string
Jon Hall714eeba2015-09-29 17:53:10 -0700632 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
633 response = re.sub( r",\s*'?(\w)", r',"\1', response )
634 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
635 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
636 try:
adminbae64d82013-08-01 10:50:15 -0700637 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700638 response_dict = json.loads( response )
Jon Hall1306a562015-09-04 11:21:24 -0700639 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700640 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700641 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700642 elif ini_match:
643 self.log.info( "Response is in 'INI' format, converting to '" +
644 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700645 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700646 response_file = open( "respnse_file.temp", 'w' )
647 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800648 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700649 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700650 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700651 elif xml_match:
652 self.log.info( "Response is in 'XML' format, converting to '" +
653 return_format + "' format" )
654 try:
655 response_dict = xmldict.xml_to_dict( "<response> " +
656 str( response ) +
657 " </response>" )
Jon Hall1306a562015-09-04 11:21:24 -0700658 except StandardError:
659 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700660 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700661
Jon Hall714eeba2015-09-29 17:53:10 -0700662 def dict_to_return_format( self, response, return_format, response_dict ):
663 if return_format == 'table':
adminbae64d82013-08-01 10:50:15 -0700664 ''' Will return in table format'''
665 to_do = "Call the table output formatter"
666 global response_table
667 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700668 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700669
Jon Hall714eeba2015-09-29 17:53:10 -0700670 def get_table( value_to_convert ):
671 ''' This will parse the dictionary recusrsively and print as
672 table format'''
adminbae64d82013-08-01 10:50:15 -0700673 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700674 if isinstance( value_to_convert, dict ):
675 table_data = table_data + '\t'.join( value_to_convert ) +\
676 "\n"
677 for temp_val in value_to_convert.values():
678 table_data = table_data + get_table( temp_val )
679 else:
680 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800681 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700682
Jon Hall714eeba2015-09-29 17:53:10 -0700683 for value in response_dict.values():
684 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700685 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700686
Jon Hall714eeba2015-09-29 17:53:10 -0700687 elif return_format == 'config':
adminbae64d82013-08-01 10:50:15 -0700688 ''' Will return in config format'''
689 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700690 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700691 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700692 response_config = re.sub( ",", "\n\t", response_string )
693 response_config = re.sub( "u\'", "\'", response_config )
694 response_config = re.sub( "{", "", response_config )
695 response_config = re.sub( "}", "\n", response_config )
696 response_config = re.sub( ":", " =", response_config )
697 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700698 elif return_format == 'xml':
699 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700700 response_xml = xmldict.dict_to_xml( response_dict )
701 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
702 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700703 elif return_format == 'json':
704 ''' Will return in json format'''
705 to_do = 'Call dict to xml coverter'
706 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700707 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700708 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700709
Jon Hall714eeba2015-09-29 17:53:10 -0700710 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700711 self.random_order = self.random_order + 1
712 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700713
Jon Hall714eeba2015-09-29 17:53:10 -0700714 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700715 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700716 for thread in threading.enumerate():
717 if thread.isAlive():
718 try:
719 thread._Thread__stop()
720 except:
Jon Hall1306a562015-09-04 11:21:24 -0700721 # NOTE: We should catch any exceptions while trying to
722 # close the thread so that we can try to close the other
723 # threads as well
Jon Hall714eeba2015-09-29 17:53:10 -0700724 print str( thread.getName() ) +\
725 ' could not be terminated'
adminbae64d82013-08-01 10:50:15 -0700726 sys.exit()
727
Jon Hallcd3d2a32015-10-01 11:07:28 -0700728 def stop( self, email=False ):
729 """
730 Stop the test until Ctrl-D is entered.
731 Ctrl-C will kill the test
732 """
733 try:
734 if email:
735 # FIXME: implement this
736 raise NotImplementedError
737 self.log.error( "Test execution suspended. Press Ctrl-D to "
738 "resume or Ctrl-C to exit the test" )
739 # NOTE: Ctrl-D needs to be entered on a new line
740 while True:
741 # TODO: we could give the user an interactive prompt where
742 # they could call functions
743 raw_input()
744 except EOFError:
745 return
746 # Pass all other exceptions up to caller
747
748
Jon Hall714eeba2015-09-29 17:53:10 -0700749def verifyOptions( options ):
adminbae64d82013-08-01 10:50:15 -0700750 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700751 This will verify the command line options and set to default values,
752 if any option not given in command line.
adminbae64d82013-08-01 10:50:15 -0700753 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700754 verifyTest( options )
755 verifyExample( options )
756 verifyTestScript( options )
adminbae64d82013-08-01 10:50:15 -0700757 verifyParams()
Jon Hall714eeba2015-09-29 17:53:10 -0700758 verifyLogdir( options )
759 verifyMail( options )
760 verifyTestCases( options )
761 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700762
Jon Hall714eeba2015-09-29 17:53:10 -0700763def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700764 try:
765 if options.testname:
766 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700767 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700768 main.tests_path = tests_path
769 elif options.example:
770 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700771 main.tests_path = path + "/examples/"
772 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700773 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700774 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700775 main.exit()
adminbae64d82013-08-01 10:50:15 -0700776
Jon Hall714eeba2015-09-29 17:53:10 -0700777def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700778 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700779 main.testDir = path + '/examples/'
780 main.tests_path = path + "/examples/"
781 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700782
Jon Hall714eeba2015-09-29 17:53:10 -0700783def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800784 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700785 if options.logdir:
786 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700787 else:
Jon Halld61331b2015-02-17 16:35:47 -0800788 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700789
Jon Hall714eeba2015-09-29 17:53:10 -0700790def verifyMail( options ):
Jon Halld61331b2015-02-17 16:35:47 -0800791 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700792 if options.mail:
793 main.mail = options.mail
Jon Hall714eeba2015-09-29 17:53:10 -0700794 else:
795 main.mail = main.params.get( 'mail', 'paxweb@paxterrasolutions.com' )
adminbae64d82013-08-01 10:50:15 -0700796
Jon Hall714eeba2015-09-29 17:53:10 -0700797def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800798 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700799 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800800 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800801 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700802 testcases_list = re.sub( "(\[|\])", "", options.testcases )
803 main.testcases_list = eval( testcases_list + "," )
804 else:
adminbae64d82013-08-01 10:50:15 -0700805 if 'testcases' in main.params.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700806 temp = eval( main.params['testcases'] + "," )
807 list1 = []
808 if isinstance( temp[0], list ):
Jon Hallfebb1c72015-03-05 13:30:09 -0800809 for test in temp:
810 for testcase in test:
Jon Hall714eeba2015-09-29 17:53:10 -0700811 if isinstance( testcase, int ):
812 testcase = [testcase]
813 list1.extend( testcase )
814 else:
815 temp = list( temp )
Jon Hallfebb1c72015-03-05 13:30:09 -0800816 for testcase in temp:
Jon Hall714eeba2015-09-29 17:53:10 -0700817 if isinstance( testcase, int ):
818 testcase = [testcase]
819 list1.extend( testcase )
820 main.testcases_list = list1
821 else:
822 print "Testcases not specifed in params, please provide in " +\
823 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800824 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700825
Jon Hall714eeba2015-09-29 17:53:10 -0700826def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700827 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700828 if options.onoscell:
829 main.onoscell = options.onoscell
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700830 main.onosIPs = []
831 main.mnIP = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700832 cellCMD = ". ~/.profile; cell " + main.onoscell
833 output = subprocess.check_output( ["bash", '-c', cellCMD] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700834 splitOutput = output.splitlines()
Jon Hall714eeba2015-09-29 17:53:10 -0700835 for i in range( len( splitOutput ) ):
836 if re.match( "OCN", splitOutput[i] ):
837 mnNode = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700838 main.mnIP = mnNode[1]
Jon Hall714eeba2015-09-29 17:53:10 -0700839 # cell already sorts OC variables in bash, so no need to
840 # sort in TestON
841 if re.match( "OC[1-9]", splitOutput[i] ):
842 onosNodes = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700843 main.onosIPs.append( onosNodes[1] )
Jon Hall714eeba2015-09-29 17:53:10 -0700844 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700845 main.onoscell = main.FALSE
846
Jon Hall714eeba2015-09-29 17:53:10 -0700847def verifyTestScript( options ):
adminbae64d82013-08-01 10:50:15 -0700848 '''
849 Verifyies test script.
850 '''
Jon Halld61331b2015-02-17 16:35:47 -0800851 main.openspeak = openspeak.OpenSpeak()
Jon Hall714eeba2015-09-29 17:53:10 -0700852 openspeakfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".ospk"
853 testfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".py"
854 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700855 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700856 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
857 elif os.path.exists( testfile ):
Jon Hall44506242015-07-29 17:40:26 -0700858 # No openspeak found, using python file instead
859 pass
adminbae64d82013-08-01 10:50:15 -0700860 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700861 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " +\
Jon Hall44506242015-07-29 17:40:26 -0700862 "Python or OpenSpeak test script in the tests folder: " +\
Jon Hall714eeba2015-09-29 17:53:10 -0700863 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700864 __builtin__.testthread = None
865 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700866 try:
867 testModule = __import__( main.classPath,
868 globals(),
869 locals(),
870 [main.TEST],
871 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700872 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700873 print "There was an import error, it might mean that there is " +\
874 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800875 main.exit()
adminbae64d82013-08-01 10:50:15 -0700876
Jon Hall714eeba2015-09-29 17:53:10 -0700877 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700878 main.testObject = testClass()
879 load_parser()
Jon Hall714eeba2015-09-29 17:53:10 -0700880 main.params = main.parser.parseParams( main.classPath )
881 main.topology = main.parser.parseTopology( main.classPath )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700882
adminbae64d82013-08-01 10:50:15 -0700883def verifyParams():
Jon Hall714eeba2015-09-29 17:53:10 -0700884 try:
adminbae64d82013-08-01 10:50:15 -0700885 main.params = main.params['PARAMS']
Jon Hall1306a562015-09-04 11:21:24 -0700886 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700887 print "Error with the params file: Either the file not specified " +\
888 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800889 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700890 try:
adminbae64d82013-08-01 10:50:15 -0700891 main.topology = main.topology['TOPOLOGY']
Jon Hall1306a562015-09-04 11:21:24 -0700892 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700893 print "Error with the Topology file: Either the file not specified " +\
894 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700895 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700896
Jon Hall714eeba2015-09-29 17:53:10 -0700897def load_parser():
adminbae64d82013-08-01 10:50:15 -0700898 '''
899 It facilitates the loading customised parser for topology and params file.
900 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700901 It also loads default xmlparser if no parser have specified in teston.cfg
902 file.
adminbae64d82013-08-01 10:50:15 -0700903
904 '''
905 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700906 if 'file' in confighash['config']['parser'] and\
907 'class' in confighash['config']['parser']:
Jon Hall44506242015-07-29 17:40:26 -0700908 path = confighash['config']['parser']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700909 if path is not None or\
910 confighash['config']['parser']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700911 try:
912 module = re.sub( r".py\s*$", "", path )
adminbae64d82013-08-01 10:50:15 -0700913 moduleList = module.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700914 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700915 parsingClass = confighash['config']['parser']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700916 parsingModule = __import__( newModule,
917 globals(),
918 locals(),
919 [parsingClass],
920 -1 )
921 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -0700922 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700923 if hasattr( main.parser, "parseParams" ) and\
924 hasattr( main.parser, "parseTopology" ) and\
925 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -0700926 pass
927 else:
928 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -0700929 main.exit()
Jon Hall44506242015-07-29 17:40:26 -0700930 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700931 print "Could not find the file " + path +\
932 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -0800933 load_defaultParser()
Jon Hall714eeba2015-09-29 17:53:10 -0700934 elif confighash['config']['parser']['file'] is None or\
935 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800936 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700937 else:
938 load_defaultParser()
939
940def load_defaultParser():
941 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700942 It will load the default parser which is xml parser to parse the params and
943 topology file.
adminbae64d82013-08-01 10:50:15 -0700944 '''
945 moduleList = main.parserPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700946 newModule = ".".join( moduleList[-2:] )
947 try:
Jon Halld61331b2015-02-17 16:35:47 -0800948 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -0700949 parsingModule = __import__( newModule,
950 globals(),
951 locals(),
952 [parsingClass],
953 -1 )
954 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -0700955 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700956 if hasattr( main.parser, "parseParams" ) and\
957 hasattr( main.parser, "parseTopology" ) and\
958 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -0700959 pass
960 else:
961 main.exit()
adminbae64d82013-08-01 10:50:15 -0700962 except ImportError:
963 print sys.exc_info()[1]
964
Jon Hall714eeba2015-09-29 17:53:10 -0700965def load_logger():
adminbae64d82013-08-01 10:50:15 -0700966 '''
967 It facilitates the loading customised parser for topology and params file.
968 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700969 It also loads default xmlparser if no parser have specified in teston.cfg
970 file.
adminbae64d82013-08-01 10:50:15 -0700971 '''
972 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700973 if 'file' in confighash['config']['logger'] and\
974 'class' in confighash['config']['logger']:
Jon Hall44506242015-07-29 17:40:26 -0700975 path = confighash['config']['logger']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700976 if path is not None or\
977 confighash['config']['logger']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700978 try:
979 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -0700980 moduleList = module.split( "/" )
981 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700982 loggerClass = confighash['config']['logger']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700983 loggerModule = __import__( newModule,
984 globals(),
985 locals(),
986 [loggerClass],
987 -1 )
988 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -0700989 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -0700990 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700991 print "Could not find the file " + path +\
992 " using default logger."
adminbae64d82013-08-01 10:50:15 -0700993 load_defaultlogger()
Jon Hall714eeba2015-09-29 17:53:10 -0700994 elif confighash['config']['parser']['file'] is None or\
995 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800996 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700997 else:
998 load_defaultlogger()
999
1000def load_defaultlogger():
1001 '''
Jon Hall714eeba2015-09-29 17:53:10 -07001002 It will load the default parser which is xml parser to parse the params and
1003 topology file.
adminbae64d82013-08-01 10:50:15 -07001004 '''
1005 moduleList = main.loggerPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -07001006 newModule = ".".join( moduleList[-2:] )
1007 try:
Jon Halld61331b2015-02-17 16:35:47 -08001008 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -07001009 loggerModule = __import__( newModule,
1010 globals(),
1011 locals(),
1012 [loggerClass],
1013 -1 )
1014 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -07001015 main.logger = loggerClass()
1016
1017 except ImportError:
1018 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -08001019 main.exit()
adminbae64d82013-08-01 10:50:15 -07001020
Jon Hall714eeba2015-09-29 17:53:10 -07001021def _echo( self ):
adminbae64d82013-08-01 10:50:15 -07001022 print "THIS IS ECHO"