blob: bd65010e16560786ac8599a74ff14eec0e621299 [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>" )
295 for line in self.stepCache.splitlines():
296 if re.search( " - PASS$", line ):
297 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
298 elif re.search( " - FAIL$", line ):
299 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
300 elif re.search( " - No Result$", line ):
301 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700302 else: # Should only be on fail message
303 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700304 self.log.wiki( "</ul>" )
305 self.log.summary( self.stepCache )
306 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700307 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700308
Jon Hall714eeba2015-09-29 17:53:10 -0700309 def runStep( self, code, testCaseNumber ):
adminbae64d82013-08-01 10:50:15 -0700310 if not cli.pause:
Jon Hall5a72b712015-09-28 12:20:59 -0700311 try:
312 step = self.stepCount
313 # stepResults format: ( stepNo, stepName, stepResult, onFail )
314 # NOTE: This is needed to catch results of main.step()'s
315 # called inside functions or loops
316 self.stepResults = ( [], [], [], [] )
adminbae64d82013-08-01 10:50:15 -0700317 exec code[testCaseNumber][step] in module.__dict__
318 self.stepCount = self.stepCount + 1
Jon Hall5a72b712015-09-28 12:20:59 -0700319
320 # Iterate through each of the steps and print them
321 for index in range( len( self.stepResults[0] ) ):
Jon Hall714eeba2015-09-29 17:53:10 -0700322 # stepResults = ( stepNo, stepName, stepResult, onFail )
Jon Hall5a72b712015-09-28 12:20:59 -0700323 stepNo = self.stepResults[0][ index ]
324 stepName = self.stepResults[1][ index ]
325 stepResult = self.stepResults[2][ index ]
326 onFail = self.stepResults[3][ index ]
327 self.stepCache += "\t" + str( testCaseNumber ) + "."
328 self.stepCache += str( stepNo ) + " "
329 self.stepCache += stepName + " - "
330 if stepResult == self.TRUE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700331 self.stepCache += "PASS\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700332 elif stepResult == self.FALSE:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700333 self.stepCache += "FAIL\n"
Jon Hall5a72b712015-09-28 12:20:59 -0700334 self.stepCache += "\t\t" + onFail + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700335 else:
336 self.stepCache += "No Result\n"
Jon Hall714eeba2015-09-29 17:53:10 -0700337 self.stepResultsList.append( stepResult )
Jon Halle234cc42015-08-31 15:26:47 -0700338 except StopIteration: # Raised in self.skipCase()
339 self.log.warn( "Skipping the rest of CASE" +
340 str( testCaseNumber ) )
Jon Hall714eeba2015-09-29 17:53:10 -0700341 self.stepResultsList.append( self.STEPRESULT )
Jon Halle234cc42015-08-31 15:26:47 -0700342 self.stepCache += "\t\t" + self.onFailMsg + "\n"
343 self.stepCount = self.stepCount + 1
344 return self.FALSE
Jon Hall5b586732015-06-11 11:39:39 -0700345 except StandardError:
Jon Hall5a72b712015-09-28 12:20:59 -0700346 stepNo = self.stepResults[0][ self.stepNumber - 1]
347 stepName = self.stepResults[1][ self.stepNumber - 1 ]
Jon Hall40d2cbd2015-06-03 16:24:29 -0700348 self.log.exception( "\nException in the following section of" +
Jon Halle234cc42015-08-31 15:26:47 -0700349 " code: " + str( testCaseNumber ) + "." +
Jon Hall5a72b712015-09-28 12:20:59 -0700350 str( stepNo ) + ": " + stepName )
adminbae64d82013-08-01 10:50:15 -0700351 self.stepCount = self.stepCount + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700352 self.logger.updateCaseResults( self )
353 # WIKI results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700354 self.log.wiki( "<ul>" )
355 for line in self.stepCache.splitlines():
356 if re.search( " - PASS$", line ):
357 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
358 elif re.search( " - FAIL$", line ):
359 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
360 elif re.search( " - No Result$", line ):
361 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700362 else: # Should only be on fail message
363 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700364 self.log.wiki( "</ul>" )
Jon Hall714eeba2015-09-29 17:53:10 -0700365 # summary results
kelvin-onlabf70fd542015-05-07 18:41:40 -0700366 self.log.summary( self.stepCache )
367 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700368 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700369 self.exit()
Jon Halle234cc42015-08-31 15:26:47 -0700370 return self.TRUE
adminbae64d82013-08-01 10:50:15 -0700371 if cli.stop:
372 cli.stop = False
adminbae64d82013-08-01 10:50:15 -0700373 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
Jon Hall714eeba2015-09-29 17:53:10 -0700374 self.testCaseResult[str( self.CurrentTestCaseNumber )] = "Stopped"
375 self.logger.updateCaseResults( self )
adminbae64d82013-08-01 10:50:15 -0700376 result = self.cleanup()
Jon Halle234cc42015-08-31 15:26:47 -0700377 return self.FALSE
378
379 def skipCase( self, result="DEFAULT", msg=None ):
380 """
381 Will skip the rest of the code in a test case. The case results will be
382 determined as normal based on completed assertions unless the result
383 argument is given.
384
385 Optional Arguments:
386 result: Case insensite string. Can be 'PASS' or 'FAIL' and will set
387 the case result accordingly.
388 msg: Message to be printed when the case is skipped in the reports.
389 """
390 result = result.upper().strip()
391 if result == "PASS":
392 self.CASERESULT = self.TRUE
393 elif result == "FAIL":
394 self.CASERESULT = self.FALSE
395 self.onFailMsg = "Skipping the rest of this case. "
396 if msg:
397 self.onFailMsg += str( msg )
398 raise StopIteration
kelvin-onlabf70fd542015-05-07 18:41:40 -0700399
Jon Hall714eeba2015-09-29 17:53:10 -0700400 def addCaseHeader( self ):
401 caseHeader = "\n" + "*" * 30 + "\n Result summary for Testcase" +\
402 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 30 + "\n"
403 self.log.exact( caseHeader )
404 caseHeader = "\n" + "*" * 40 + "\nStart of Test Case" +\
405 str( self.CurrentTestCaseNumber ) + " : "
adminbae64d82013-08-01 10:50:15 -0700406 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700407 vars( self )[driver + 'log'].info( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700408
Jon Hall714eeba2015-09-29 17:53:10 -0700409 def addCaseFooter( self ):
Jon Hall5a72b712015-09-28 12:20:59 -0700410 stepNo = self.stepResults[0][-2]
Jon Hall714eeba2015-09-29 17:53:10 -0700411 if stepNo > 0:
412 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
413 str( stepNo ) + ": " + str( self.stepName )
414 stepHeader = "\n" + "*" * 40 + "\nEnd of Step " + previousStep +\
415 "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700416
Jon Hall714eeba2015-09-29 17:53:10 -0700417 caseFooter = "\n" + "*" * 40 + "\nEnd of Test case " +\
418 str( self.CurrentTestCaseNumber ) + "\n" + "*" * 40 + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700419
adminbae64d82013-08-01 10:50:15 -0700420 for driver in self.driversList:
Jon Hall714eeba2015-09-29 17:53:10 -0700421 vars( self )[driver].write( stepHeader + "\n" + caseFooter )
adminbae64d82013-08-01 10:50:15 -0700422
Jon Hall714eeba2015-09-29 17:53:10 -0700423 def cleanup( self ):
adminbae64d82013-08-01 10:50:15 -0700424 '''
Jon Hall5b586732015-06-11 11:39:39 -0700425 Print a summary of the current test's results then attempt to release
426 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700427
Jon Hall5b586732015-06-11 11:39:39 -0700428 This function shouldbe threadsafe such that cleanup will only be
429 executed once per test.
430
431 This will return TRUE if all the component handles and log handles
432 closed properly, else return FALSE.
adminbae64d82013-08-01 10:50:15 -0700433 '''
434 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700435 lock = self.cleanupLock
436 if lock.acquire( False ):
437 try:
438 if self.cleanupFlag is False: # First thread to run this
439 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700440 if self.initiated:
Jon Hall714eeba2015-09-29 17:53:10 -0700441 self.logger.testSummary( self )
Jon Hall5b586732015-06-11 11:39:39 -0700442 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700443 try:
444 tempObject = vars( self )[component]
445 print "Disconnecting from " + str( tempObject.name ) +\
446 ": " + str( tempObject.__class__)
Jon Hall5b586732015-06-11 11:39:39 -0700447 tempObject.disconnect()
Jon Hall1306a562015-09-04 11:21:24 -0700448 except KeyboardInterrupt:
449 pass
450 except KeyError:
451 # Component not created yet
452 self.log.warn( "Could not find the component " +
453 str( component ) )
454 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700455 self.log.exception( "Exception while disconnecting from " +
456 str( component ) )
457 result = self.FALSE
458 # Closing all the driver's session files
459 for driver in self.componentDictionary.keys():
460 try:
Jon Hall714eeba2015-09-29 17:53:10 -0700461 vars( self )[driver].close_log_handles()
Jon Hall1306a562015-09-04 11:21:24 -0700462 except KeyboardInterrupt:
463 pass
464 except KeyError:
465 # Component not created yet
466 self.log.warn( "Could not find the component " +
467 str( driver ) + " while trying to" +
468 " close log file" )
469 except StandardError:
Jon Hall5b586732015-06-11 11:39:39 -0700470 self.log.exception( "Exception while closing log files for " +
471 str( driver ) )
472 result = self.FALSE
473 else:
474 pass # Someone else already ran through this function
475 finally:
476 lock.release()
477 else: # Someone already has a lock
478 # NOTE: This could cause problems if we don't release the lock
479 # correctly
480 lock.acquire() # Wait for the other thread to finish
481 # NOTE: If we don't wait, exit could be called while the thread
482 # with the lock is still cleaning up
483 lock.release()
adminbae64d82013-08-01 10:50:15 -0700484 return result
Jon Halld61331b2015-02-17 16:35:47 -0800485
Jon Hall714eeba2015-09-29 17:53:10 -0700486 def pause( self ):
adminbae64d82013-08-01 10:50:15 -0700487 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700488 This function will pause the test's execution, and will continue after
489 user provide 'resume' command.
adminbae64d82013-08-01 10:50:15 -0700490 '''
491 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700492
Jon Hall714eeba2015-09-29 17:53:10 -0700493 def onfail( self, *components ):
adminbae64d82013-08-01 10:50:15 -0700494 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700495 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700496 '''
adminbae64d82013-08-01 10:50:15 -0700497 if not components:
Jon Hall714eeba2015-09-29 17:53:10 -0700498 try:
adminbae64d82013-08-01 10:50:15 -0700499 for component in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700500 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700501 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700502 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700503 print str( e )
adminbae64d82013-08-01 10:50:15 -0700504 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700505 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700506 try:
adminbae64d82013-08-01 10:50:15 -0700507 for component in components:
Jon Hall714eeba2015-09-29 17:53:10 -0700508 tempObject = vars( self )[component]
adminbae64d82013-08-01 10:50:15 -0700509 result = tempObject.onfail()
Jon Hall1306a562015-09-04 11:21:24 -0700510 except StandardError as e:
Jon Hall714eeba2015-09-29 17:53:10 -0700511 print str( e )
adminbae64d82013-08-01 10:50:15 -0700512 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700513
Jon Hall714eeba2015-09-29 17:53:10 -0700514 def getDriverPath( self, driverName ):
adminbae64d82013-08-01 10:50:15 -0700515 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700516 Based on the component 'type' specified in the params , this method
517 will find the absolute path, by recursively searching the name of
518 the component.
519
520 NOTE: This function requires the linux 'find' command.
adminbae64d82013-08-01 10:50:15 -0700521 '''
522 import commands
523
Jon Hall714eeba2015-09-29 17:53:10 -0700524 cmd = "find " + drivers_path + " -name " + driverName + ".py"
525 result = commands.getoutput( cmd )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700526
Jon Hall714eeba2015-09-29 17:53:10 -0700527 result_array = str( result ).split( '\n' )
adminbae64d82013-08-01 10:50:15 -0700528 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700529
adminbae64d82013-08-01 10:50:15 -0700530 for drivers_list in result_array:
Jon Hall714eeba2015-09-29 17:53:10 -0700531 result_count = result_count + 1
532 if result_count > 1:
533 print "Found " + driverName + " " + str( result_count ) + " times:"
534 print str( result_array )
adminbae64d82013-08-01 10:50:15 -0700535 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700536
Jon Hall714eeba2015-09-29 17:53:10 -0700537 result = re.sub( "(.*)drivers", "", result )
538 result = re.sub( "\/\/", "/", result )
539 result = re.sub( "\.py", "", result )
540 result = re.sub( "\.pyc", "", result )
541 result = re.sub( "\/", ".", result )
542 result = "drivers" + result
adminbae64d82013-08-01 10:50:15 -0700543 return result
adminbae64d82013-08-01 10:50:15 -0700544
Jon Hall714eeba2015-09-29 17:53:10 -0700545 def step( self, stepDesc ):
adminbae64d82013-08-01 10:50:15 -0700546 '''
547 The step information of the test-case will append to the logs.
548 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700549 previousStep = " " + str( self.CurrentTestCaseNumber ) + "." +\
550 str( self.stepNumber ) + ": " + str( self.stepName )
adminbae64d82013-08-01 10:50:15 -0700551 self.stepName = stepDesc
Jon Hall5a72b712015-09-28 12:20:59 -0700552 self.stepNumber += 1
553 self.stepResults[0].append( self.stepNumber )
554 self.stepResults[1].append( stepDesc )
555 self.stepResults[2].append( self.NORESULT )
556 self.stepResults[3].append( "No on fail message given" )
adminbae64d82013-08-01 10:50:15 -0700557
Jon Hall714eeba2015-09-29 17:53:10 -0700558 stepName = " " + str( self.CurrentTestCaseNumber ) + "." +\
559 str( self.stepNumber ) + ": " + str( stepDesc )
adminbae64d82013-08-01 10:50:15 -0700560 self.log.step(stepName)
561 stepHeader = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700562 line = "\n" + "-" * 45 + "\n"
563 if self.stepNumber > 1:
564 stepHeader = line + "End of Step " + previousStep + line
565 stepHeader += line + "Start of Step" + stepName + line
adminbae64d82013-08-01 10:50:15 -0700566 for driver in self.componentDictionary.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700567 vars( self )[driver + 'log'].info( stepHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700568
Jon Hall714eeba2015-09-29 17:53:10 -0700569 def case( self, testCaseName ):
adminbae64d82013-08-01 10:50:15 -0700570 '''
571 Test's each test-case information will append to the logs.
572 '''
Jon Halld61331b2015-02-17 16:35:47 -0800573 self.CurrentTestCase = testCaseName
Jon Hall714eeba2015-09-29 17:53:10 -0700574 testCaseName = " " + str( testCaseName )
575 self.log.case( testCaseName )
576 caseHeader = testCaseName + "\n" + "*" * 40 + "\n"
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( caseHeader )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700579
Jon Hall714eeba2015-09-29 17:53:10 -0700580 def testDesc( self, description ):
adminbae64d82013-08-01 10:50:15 -0700581 '''
582 Test description will append to the logs.
583 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700584 description = "Test Description : " + str( description )
585 self.log.info( description )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700586
Jon Hall714eeba2015-09-29 17:53:10 -0700587 def _getTest( self ):
adminbae64d82013-08-01 10:50:15 -0700588 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700589 This method will parse the test script to find required test
590 information.
adminbae64d82013-08-01 10:50:15 -0700591 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700592 testFile = self.tests_path + "/" + self.TEST + "/" + self.TEST + ".py"
593 testFileHandler = open( testFile, 'r' )
adminbae64d82013-08-01 10:50:15 -0700594 testFileList = testFileHandler.readlines()
595 testFileHandler.close()
adminbae64d82013-08-01 10:50:15 -0700596 counter = 0
Jon Hall714eeba2015-09-29 17:53:10 -0700597 for index in range( len( testFileList ) ):
598 lineMatch = re.match( '\s+def CASE(\d+)(.*):',
599 testFileList[index],
600 0 )
adminbae64d82013-08-01 10:50:15 -0700601 if lineMatch:
Jon Hall714eeba2015-09-29 17:53:10 -0700602 counter = counter + 1
603 self.TC_PLANNED = len( self.testcases_list )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700604
Jon Hall714eeba2015-09-29 17:53:10 -0700605 def response_parser( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700606 ''' It will load the default response parser '''
607 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700608 response_dict = self.response_to_dict( response, return_format )
609 return_format_string = self.dict_to_return_format( response,
610 return_format,
611 response_dict )
adminbae64d82013-08-01 10:50:15 -0700612 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700613
Jon Hall714eeba2015-09-29 17:53:10 -0700614 def response_to_dict( self, response, return_format ):
adminbae64d82013-08-01 10:50:15 -0700615 response_dict = {}
Jon Hall714eeba2015-09-29 17:53:10 -0700616 json_match = re.search( '^\s*{', response )
617 xml_match = re.search( '^\s*\<', response )
618 ini_match = re.search( '^\s*\[', response )
619 if json_match:
620 self.log.info( "Response is in 'JSON' format, converting to '" +
621 return_format + "' format" )
Jon Halld61331b2015-02-17 16:35:47 -0800622 # Formatting the json string
Jon Hall714eeba2015-09-29 17:53:10 -0700623 response = re.sub( r"{\s*'?(\w)", r'{"\1', response )
624 response = re.sub( r",\s*'?(\w)", r',"\1', response )
625 response = re.sub( r"(\w)'?\s*:", r'\1":', response )
626 response = re.sub( r":\s*'(\w)'\s*([,}])", r':"\1"\2', response )
627 try:
adminbae64d82013-08-01 10:50:15 -0700628 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700629 response_dict = json.loads( response )
Jon Hall1306a562015-09-04 11:21:24 -0700630 except StandardError:
Jon Hall2a5002c2015-08-21 16:49:11 -0700631 self.log.exception( "Json Parser is unable to parse the string" )
adminbae64d82013-08-01 10:50:15 -0700632 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700633 elif ini_match:
634 self.log.info( "Response is in 'INI' format, converting to '" +
635 return_format + "' format" )
adminbae64d82013-08-01 10:50:15 -0700636 from configobj import ConfigObj
Jon Hall714eeba2015-09-29 17:53:10 -0700637 response_file = open( "respnse_file.temp", 'w' )
638 response_file.write( response )
Jon Halld61331b2015-02-17 16:35:47 -0800639 response_file.close()
Jon Hall714eeba2015-09-29 17:53:10 -0700640 response_dict = ConfigObj( "respnse_file.temp" )
adminbae64d82013-08-01 10:50:15 -0700641 return response_dict
Jon Hall714eeba2015-09-29 17:53:10 -0700642 elif xml_match:
643 self.log.info( "Response is in 'XML' format, converting to '" +
644 return_format + "' format" )
645 try:
646 response_dict = xmldict.xml_to_dict( "<response> " +
647 str( response ) +
648 " </response>" )
Jon Hall1306a562015-09-04 11:21:24 -0700649 except StandardError:
650 self.log.exception()
adminbae64d82013-08-01 10:50:15 -0700651 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700652
Jon Hall714eeba2015-09-29 17:53:10 -0700653 def dict_to_return_format( self, response, return_format, response_dict ):
654 if return_format == 'table':
adminbae64d82013-08-01 10:50:15 -0700655 ''' Will return in table format'''
656 to_do = "Call the table output formatter"
657 global response_table
658 response_table = '\n'
Jon Hall714eeba2015-09-29 17:53:10 -0700659 response_table = response_table + '\t'.join( response_dict ) + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700660
Jon Hall714eeba2015-09-29 17:53:10 -0700661 def get_table( value_to_convert ):
662 ''' This will parse the dictionary recusrsively and print as
663 table format'''
adminbae64d82013-08-01 10:50:15 -0700664 table_data = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700665 if isinstance( value_to_convert, dict ):
666 table_data = table_data + '\t'.join( value_to_convert ) +\
667 "\n"
668 for temp_val in value_to_convert.values():
669 table_data = table_data + get_table( temp_val )
670 else:
671 table_data = table_data + str( value_to_convert ) + "\t"
Jon Halld61331b2015-02-17 16:35:47 -0800672 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700673
Jon Hall714eeba2015-09-29 17:53:10 -0700674 for value in response_dict.values():
675 response_table = response_table + get_table( value )
adminbae64d82013-08-01 10:50:15 -0700676 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700677
Jon Hall714eeba2015-09-29 17:53:10 -0700678 elif return_format == 'config':
adminbae64d82013-08-01 10:50:15 -0700679 ''' Will return in config format'''
680 to_do = 'Call dict to config coverter'
Jon Hall714eeba2015-09-29 17:53:10 -0700681 response_string = str( response_dict )
adminbae64d82013-08-01 10:50:15 -0700682 print response_string
Jon Hall714eeba2015-09-29 17:53:10 -0700683 response_config = re.sub( ",", "\n\t", response_string )
684 response_config = re.sub( "u\'", "\'", response_config )
685 response_config = re.sub( "{", "", response_config )
686 response_config = re.sub( "}", "\n", response_config )
687 response_config = re.sub( ":", " =", response_config )
688 return "[response]\n\t " + response_config
adminbae64d82013-08-01 10:50:15 -0700689 elif return_format == 'xml':
690 ''' Will return in xml format'''
Jon Hall714eeba2015-09-29 17:53:10 -0700691 response_xml = xmldict.dict_to_xml( response_dict )
692 response_xml = re.sub( ">\s*<", ">\n<", response_xml )
693 return "\n" + response_xml
adminbae64d82013-08-01 10:50:15 -0700694 elif return_format == 'json':
695 ''' Will return in json format'''
696 to_do = 'Call dict to xml coverter'
697 import json
Jon Hall714eeba2015-09-29 17:53:10 -0700698 response_json = json.dumps( response_dict )
adminbae64d82013-08-01 10:50:15 -0700699 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700700
Jon Hall714eeba2015-09-29 17:53:10 -0700701 def get_random( self ):
adminbae64d82013-08-01 10:50:15 -0700702 self.random_order = self.random_order + 1
703 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700704
Jon Hall714eeba2015-09-29 17:53:10 -0700705 def exit( self ):
adminbae64d82013-08-01 10:50:15 -0700706 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700707 for thread in threading.enumerate():
708 if thread.isAlive():
709 try:
710 thread._Thread__stop()
711 except:
Jon Hall1306a562015-09-04 11:21:24 -0700712 # NOTE: We should catch any exceptions while trying to
713 # close the thread so that we can try to close the other
714 # threads as well
Jon Hall714eeba2015-09-29 17:53:10 -0700715 print str( thread.getName() ) +\
716 ' could not be terminated'
adminbae64d82013-08-01 10:50:15 -0700717 sys.exit()
718
Jon Hall714eeba2015-09-29 17:53:10 -0700719def verifyOptions( options ):
adminbae64d82013-08-01 10:50:15 -0700720 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700721 This will verify the command line options and set to default values,
722 if any option not given in command line.
adminbae64d82013-08-01 10:50:15 -0700723 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700724 verifyTest( options )
725 verifyExample( options )
726 verifyTestScript( options )
adminbae64d82013-08-01 10:50:15 -0700727 verifyParams()
Jon Hall714eeba2015-09-29 17:53:10 -0700728 verifyLogdir( options )
729 verifyMail( options )
730 verifyTestCases( options )
731 verifyOnosCell( options )
adminbae64d82013-08-01 10:50:15 -0700732
Jon Hall714eeba2015-09-29 17:53:10 -0700733def verifyTest( options ):
Jon Hall44506242015-07-29 17:40:26 -0700734 try:
735 if options.testname:
736 main.TEST = options.testname
Jon Hall714eeba2015-09-29 17:53:10 -0700737 main.classPath = "tests." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700738 main.tests_path = tests_path
739 elif options.example:
740 main.TEST = options.example
Jon Hall714eeba2015-09-29 17:53:10 -0700741 main.tests_path = path + "/examples/"
742 main.classPath = "examples." + main.TEST + "." + main.TEST
Jon Hall44506242015-07-29 17:40:26 -0700743 except AttributeError:
adminbae64d82013-08-01 10:50:15 -0700744 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700745 main.exit()
adminbae64d82013-08-01 10:50:15 -0700746
Jon Hall714eeba2015-09-29 17:53:10 -0700747def verifyExample( options ):
adminbae64d82013-08-01 10:50:15 -0700748 if options.example:
Jon Hall714eeba2015-09-29 17:53:10 -0700749 main.testDir = path + '/examples/'
750 main.tests_path = path + "/examples/"
751 main.classPath = "examples." + main.TEST + "." + main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700752
Jon Hall714eeba2015-09-29 17:53:10 -0700753def verifyLogdir( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800754 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700755 if options.logdir:
756 main.logdir = options.logdir
Jon Hall714eeba2015-09-29 17:53:10 -0700757 else:
Jon Halld61331b2015-02-17 16:35:47 -0800758 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700759
Jon Hall714eeba2015-09-29 17:53:10 -0700760def verifyMail( options ):
Jon Halld61331b2015-02-17 16:35:47 -0800761 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700762 if options.mail:
763 main.mail = options.mail
Jon Hall714eeba2015-09-29 17:53:10 -0700764 else:
765 main.mail = main.params.get( 'mail', 'paxweb@paxterrasolutions.com' )
adminbae64d82013-08-01 10:50:15 -0700766
Jon Hall714eeba2015-09-29 17:53:10 -0700767def verifyTestCases( options ):
Jon Hall88e498c2015-03-06 09:54:35 -0800768 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700769 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800770 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800771 # sys.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700772 testcases_list = re.sub( "(\[|\])", "", options.testcases )
773 main.testcases_list = eval( testcases_list + "," )
774 else:
adminbae64d82013-08-01 10:50:15 -0700775 if 'testcases' in main.params.keys():
Jon Hall714eeba2015-09-29 17:53:10 -0700776 temp = eval( main.params['testcases'] + "," )
777 list1 = []
778 if isinstance( temp[0], list ):
Jon Hallfebb1c72015-03-05 13:30:09 -0800779 for test in temp:
780 for testcase in test:
Jon Hall714eeba2015-09-29 17:53:10 -0700781 if isinstance( testcase, int ):
782 testcase = [testcase]
783 list1.extend( testcase )
784 else:
785 temp = list( temp )
Jon Hallfebb1c72015-03-05 13:30:09 -0800786 for testcase in temp:
Jon Hall714eeba2015-09-29 17:53:10 -0700787 if isinstance( testcase, int ):
788 testcase = [testcase]
789 list1.extend( testcase )
790 main.testcases_list = list1
791 else:
792 print "Testcases not specifed in params, please provide in " +\
793 "params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800794 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700795
Jon Hall714eeba2015-09-29 17:53:10 -0700796def verifyOnosCell( options ):
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700797 # Verifying onoscell option
Hari Krishna03f530e2015-07-10 17:28:27 -0700798 if options.onoscell:
799 main.onoscell = options.onoscell
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700800 main.onosIPs = []
801 main.mnIP = ""
Jon Hall714eeba2015-09-29 17:53:10 -0700802 cellCMD = ". ~/.profile; cell " + main.onoscell
803 output = subprocess.check_output( ["bash", '-c', cellCMD] )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700804 splitOutput = output.splitlines()
Jon Hall714eeba2015-09-29 17:53:10 -0700805 for i in range( len( splitOutput ) ):
806 if re.match( "OCN", splitOutput[i] ):
807 mnNode = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700808 main.mnIP = mnNode[1]
Jon Hall714eeba2015-09-29 17:53:10 -0700809 # cell already sorts OC variables in bash, so no need to
810 # sort in TestON
811 if re.match( "OC[1-9]", splitOutput[i] ):
812 onosNodes = splitOutput[i].split( "=" )
Hari Krishnabe4b97b2015-07-15 12:19:43 -0700813 main.onosIPs.append( onosNodes[1] )
Jon Hall714eeba2015-09-29 17:53:10 -0700814 else:
Hari Krishna03f530e2015-07-10 17:28:27 -0700815 main.onoscell = main.FALSE
816
Jon Hall714eeba2015-09-29 17:53:10 -0700817def verifyTestScript( options ):
adminbae64d82013-08-01 10:50:15 -0700818 '''
819 Verifyies test script.
820 '''
Jon Halld61331b2015-02-17 16:35:47 -0800821 main.openspeak = openspeak.OpenSpeak()
Jon Hall714eeba2015-09-29 17:53:10 -0700822 openspeakfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".ospk"
823 testfile = main.testDir + "/" + main.TEST + "/" + main.TEST + ".py"
824 if os.path.exists( openspeakfile ):
Jon Hall44506242015-07-29 17:40:26 -0700825 # Openspeak file found, compiling to python
Jon Hall714eeba2015-09-29 17:53:10 -0700826 main.openspeak.compiler( openspeakfile=openspeakfile, writetofile=1 )
827 elif os.path.exists( testfile ):
Jon Hall44506242015-07-29 17:40:26 -0700828 # No openspeak found, using python file instead
829 pass
adminbae64d82013-08-01 10:50:15 -0700830 else:
Jon Hall714eeba2015-09-29 17:53:10 -0700831 print "\nThere is no \"" + main.TEST + "\" test script.\nPlease provide a " +\
Jon Hall44506242015-07-29 17:40:26 -0700832 "Python or OpenSpeak test script in the tests folder: " +\
Jon Hall714eeba2015-09-29 17:53:10 -0700833 main.testDir + "/" + main.TEST + "/"
adminbae64d82013-08-01 10:50:15 -0700834 __builtin__.testthread = None
835 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700836 try:
837 testModule = __import__( main.classPath,
838 globals(),
839 locals(),
840 [main.TEST],
841 -1 )
Jon Hall1306a562015-09-04 11:21:24 -0700842 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700843 print "There was an import error, it might mean that there is " +\
844 "no test named " + main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800845 main.exit()
adminbae64d82013-08-01 10:50:15 -0700846
Jon Hall714eeba2015-09-29 17:53:10 -0700847 testClass = getattr( testModule, main.TEST )
adminbae64d82013-08-01 10:50:15 -0700848 main.testObject = testClass()
849 load_parser()
Jon Hall714eeba2015-09-29 17:53:10 -0700850 main.params = main.parser.parseParams( main.classPath )
851 main.topology = main.parser.parseTopology( main.classPath )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700852
adminbae64d82013-08-01 10:50:15 -0700853def verifyParams():
Jon Hall714eeba2015-09-29 17:53:10 -0700854 try:
adminbae64d82013-08-01 10:50:15 -0700855 main.params = main.params['PARAMS']
Jon Hall1306a562015-09-04 11:21:24 -0700856 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700857 print "Error with the params file: Either the file not specified " +\
858 "or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800859 main.exit()
Jon Hall714eeba2015-09-29 17:53:10 -0700860 try:
adminbae64d82013-08-01 10:50:15 -0700861 main.topology = main.topology['TOPOLOGY']
Jon Hall1306a562015-09-04 11:21:24 -0700862 except KeyError:
Jon Hall714eeba2015-09-29 17:53:10 -0700863 print "Error with the Topology file: Either the file not specified " +\
864 "or the format is not correct"
adminbae64d82013-08-01 10:50:15 -0700865 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700866
Jon Hall714eeba2015-09-29 17:53:10 -0700867def load_parser():
adminbae64d82013-08-01 10:50:15 -0700868 '''
869 It facilitates the loading customised parser for topology and params file.
870 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700871 It also loads default xmlparser if no parser have specified in teston.cfg
872 file.
adminbae64d82013-08-01 10:50:15 -0700873
874 '''
875 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700876 if 'file' in confighash['config']['parser'] and\
877 'class' in confighash['config']['parser']:
Jon Hall44506242015-07-29 17:40:26 -0700878 path = confighash['config']['parser']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700879 if path is not None or\
880 confighash['config']['parser']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700881 try:
882 module = re.sub( r".py\s*$", "", path )
adminbae64d82013-08-01 10:50:15 -0700883 moduleList = module.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700884 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700885 parsingClass = confighash['config']['parser']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700886 parsingModule = __import__( newModule,
887 globals(),
888 locals(),
889 [parsingClass],
890 -1 )
891 parsingClass = getattr( parsingModule, parsingClass )
Jon Hall44506242015-07-29 17:40:26 -0700892 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700893 if hasattr( main.parser, "parseParams" ) and\
894 hasattr( main.parser, "parseTopology" ) and\
895 hasattr( main.parser, "parse" ):
Jon Hall44506242015-07-29 17:40:26 -0700896 pass
897 else:
898 print "Invalid parser format"
adminbae64d82013-08-01 10:50:15 -0700899 main.exit()
Jon Hall44506242015-07-29 17:40:26 -0700900 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700901 print "Could not find the file " + path +\
902 " using default parser."
Jon Halld61331b2015-02-17 16:35:47 -0800903 load_defaultParser()
Jon Hall714eeba2015-09-29 17:53:10 -0700904 elif confighash['config']['parser']['file'] is None or\
905 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800906 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700907 else:
908 load_defaultParser()
909
910def load_defaultParser():
911 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700912 It will load the default parser which is xml parser to parse the params and
913 topology file.
adminbae64d82013-08-01 10:50:15 -0700914 '''
915 moduleList = main.parserPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700916 newModule = ".".join( moduleList[-2:] )
917 try:
Jon Halld61331b2015-02-17 16:35:47 -0800918 parsingClass = main.parsingClass
Jon Hall714eeba2015-09-29 17:53:10 -0700919 parsingModule = __import__( newModule,
920 globals(),
921 locals(),
922 [parsingClass],
923 -1 )
924 parsingClass = getattr( parsingModule, parsingClass )
adminbae64d82013-08-01 10:50:15 -0700925 main.parser = parsingClass()
Jon Hall714eeba2015-09-29 17:53:10 -0700926 if hasattr( main.parser, "parseParams" ) and\
927 hasattr( main.parser, "parseTopology" ) and\
928 hasattr( main.parser, "parse" ):
adminbae64d82013-08-01 10:50:15 -0700929 pass
930 else:
931 main.exit()
adminbae64d82013-08-01 10:50:15 -0700932 except ImportError:
933 print sys.exc_info()[1]
934
Jon Hall714eeba2015-09-29 17:53:10 -0700935def load_logger():
adminbae64d82013-08-01 10:50:15 -0700936 '''
937 It facilitates the loading customised parser for topology and params file.
938 It loads parser mentioned in tab named parser of teston.cfg file.
Jon Hall714eeba2015-09-29 17:53:10 -0700939 It also loads default xmlparser if no parser have specified in teston.cfg
940 file.
adminbae64d82013-08-01 10:50:15 -0700941 '''
942 confighash = main.configDict
Jon Hall714eeba2015-09-29 17:53:10 -0700943 if 'file' in confighash['config']['logger'] and\
944 'class' in confighash['config']['logger']:
Jon Hall44506242015-07-29 17:40:26 -0700945 path = confighash['config']['logger']['file']
Jon Hall714eeba2015-09-29 17:53:10 -0700946 if path is not None or\
947 confighash['config']['logger']['class'] is not None:
Jon Hall44506242015-07-29 17:40:26 -0700948 try:
949 module = re.sub( r".py\s*$", "", path )
Jon Hall714eeba2015-09-29 17:53:10 -0700950 moduleList = module.split( "/" )
951 newModule = ".".join( moduleList[-2:] )
Jon Hall44506242015-07-29 17:40:26 -0700952 loggerClass = confighash['config']['logger']['class']
Jon Hall714eeba2015-09-29 17:53:10 -0700953 loggerModule = __import__( newModule,
954 globals(),
955 locals(),
956 [loggerClass],
957 -1 )
958 loggerClass = getattr( loggerModule, loggerClass )
Jon Hall44506242015-07-29 17:40:26 -0700959 main.logger = loggerClass()
Jon Hall44506242015-07-29 17:40:26 -0700960 except ImportError:
Jon Hall714eeba2015-09-29 17:53:10 -0700961 print "Could not find the file " + path +\
962 " using default logger."
adminbae64d82013-08-01 10:50:15 -0700963 load_defaultlogger()
Jon Hall714eeba2015-09-29 17:53:10 -0700964 elif confighash['config']['parser']['file'] is None or\
965 confighash['config']['parser']['class'] is None:
Jon Halld61331b2015-02-17 16:35:47 -0800966 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700967 else:
968 load_defaultlogger()
969
970def load_defaultlogger():
971 '''
Jon Hall714eeba2015-09-29 17:53:10 -0700972 It will load the default parser which is xml parser to parse the params and
973 topology file.
adminbae64d82013-08-01 10:50:15 -0700974 '''
975 moduleList = main.loggerPath.split("/")
Jon Hall714eeba2015-09-29 17:53:10 -0700976 newModule = ".".join( moduleList[-2:] )
977 try:
Jon Halld61331b2015-02-17 16:35:47 -0800978 loggerClass = main.loggerClass
Jon Hall714eeba2015-09-29 17:53:10 -0700979 loggerModule = __import__( newModule,
980 globals(),
981 locals(),
982 [loggerClass],
983 -1 )
984 loggerClass = getattr( loggerModule, loggerClass )
adminbae64d82013-08-01 10:50:15 -0700985 main.logger = loggerClass()
986
987 except ImportError:
988 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800989 main.exit()
adminbae64d82013-08-01 10:50:15 -0700990
Jon Hall714eeba2015-09-29 17:53:10 -0700991def _echo( self ):
adminbae64d82013-08-01 10:50:15 -0700992 print "THIS IS ECHO"