blob: 667f99cc5296f1e4c396c0b1d21a3423e89ff8f0 [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
adminbae64d82013-08-01 10:50:15 -070035module = new.module("test")
36import openspeak
37global path, drivers_path, core_path, tests_path,logs_path
38path = re.sub("(core|bin)$", "", os.getcwd())
39drivers_path = path+"drivers/"
40core_path = path+"core"
41tests_path = path+"tests"
42logs_path = path+"logs/"
43config_path = path + "config/"
44sys.path.append(path)
45sys.path.append( drivers_path)
46sys.path.append(core_path )
47sys.path.append(tests_path)
48
49from core.utilities import Utilities
kelvin-onlabfb521662015-02-27 09:52:40 -080050from core.Thread import Thread
adminbae64d82013-08-01 10:50:15 -070051
adminbae64d82013-08-01 10:50:15 -070052
53class TestON:
54 '''
Jon Hall81d3d392015-04-24 14:40:35 -070055 TestON will initiate the specified test.
56 The main tasks are :
57 * Initiate the required Component handles for the test.
adminbae64d82013-08-01 10:50:15 -070058 * Create Log file Handles.
adminbae64d82013-08-01 10:50:15 -070059 '''
60 def __init__(self,options):
61 '''
62 Initialise the component handles specified in the topology file of the specified test.
adminbae64d82013-08-01 10:50:15 -070063 '''
64 # Initialization of the variables.
65 __builtin__.main = self
adminbae64d82013-08-01 10:50:15 -070066 __builtin__.path = path
67 __builtin__.utilities = Utilities()
68 self.TRUE = 1
69 self.FALSE = 0
70 self.ERROR = -1
Jon Hall79bec222015-04-30 16:23:30 -070071 self.NORESULT = 2
adminbae64d82013-08-01 10:50:15 -070072 self.FAIL = False
73 self.PASS = True
Jon Hall79bec222015-04-30 16:23:30 -070074 self.CASERESULT = self.ERROR
75 self.STEPRESULT = self.NORESULT
76 self.stepResults = []
adminbae64d82013-08-01 10:50:15 -070077 self.init_result = self.TRUE
78 self.testResult = "Summary"
Jon Hall81d3d392015-04-24 14:40:35 -070079 self.stepName = ""
Jon Hall79bec222015-04-30 16:23:30 -070080 self.stepCache = ""
Jon Hall81d3d392015-04-24 14:40:35 -070081 # make this into two lists? one for step names, one for results?
82 # this way, the case result could be a true AND of these results
Jon Halld61331b2015-02-17 16:35:47 -080083 self.EXPERIMENTAL_MODE = False
adminbae64d82013-08-01 10:50:15 -070084 self.test_target = None
85 self.lastcommand = None
Jon Halld61331b2015-02-17 16:35:47 -080086 self.testDir = tests_path
87 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070088 self.parsingClass = "xmlparser"
89 self.parserPath = core_path + "/xmlparser"
90 self.loggerPath = core_path + "/logger"
91 self.loggerClass = "Logger"
92 self.logs_path = logs_path
93 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -080094 self.Thread = Thread
Jon Hall65844a32015-03-09 19:09:37 -070095
adminbae64d82013-08-01 10:50:15 -070096 self.configparser()
97 verifyOptions(options)
98 load_logger()
99 self.componentDictionary = {}
100 self.componentDictionary = self.topology ['COMPONENT']
101 self.driversList=[]
102 if type(self.componentDictionary) == str :
103 self.componentDictionary = dict(self.componentDictionary)
Jon Hall65844a32015-03-09 19:09:37 -0700104
adminbae64d82013-08-01 10:50:15 -0700105 for component in self.componentDictionary :
106 self.driversList.append(self.componentDictionary[component]['type'])
Jon Hall65844a32015-03-09 19:09:37 -0700107
adminbae64d82013-08-01 10:50:15 -0700108 self.driversList = list(set(self.driversList)) # Removing duplicates.
109 # Checking the test_target option set for the component or not
110 if type(self.componentDictionary) == dict:
111 for component in self.componentDictionary.keys():
112 if 'test_target' in self.componentDictionary[component].keys():
113 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700114
Jon Halld61331b2015-02-17 16:35:47 -0800115 # Checking for the openspeak file and test script
adminbae64d82013-08-01 10:50:15 -0700116 self.logger.initlog(self)
117
118 # Creating Drivers Handles
119 initString = "\n"+"*" * 30+"\n CASE INIT \n"+"*" * 30+"\n"
120 self.log.exact(initString)
121 self.driverObject = {}
122 self.random_order = 111 # Random order id to connect the components
123 components_connect_order = {}
124 #component_list.append()
125 if type(self.componentDictionary) == dict:
126 for component in self.componentDictionary.keys():
127 self.componentDictionary[component]['connect_order'] = self.componentDictionary[component]['connect_order'] if ('connect_order' in self.componentDictionary[component].keys()) else str(self.get_random())
128 components_connect_order[component] = eval(self.componentDictionary[component]['connect_order'])
129 #Ordering components based on the connect order.
130 ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
131 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700132 for component in ordered_component_list:
133 self.componentInit(component)
134
135 def configparser(self):
136 '''
137 It will parse the config file (teston.cfg) and return as dictionary
138 '''
139 matchFileName = re.match(r'(.*)\.cfg', self.configFile, re.M | re.I)
140 if matchFileName:
141 xml = open(self.configFile).read()
142 try :
143 self.configDict = xmldict.xml_to_dict(xml)
144 return self.configDict
Jon Hallfebb1c72015-03-05 13:30:09 -0800145 except Exception:
adminbae64d82013-08-01 10:50:15 -0700146 print "There is no such file to parse " + self.configFile
Jon Hall81d3d392015-04-24 14:40:35 -0700147
adminbae64d82013-08-01 10:50:15 -0700148 def componentInit(self,component):
149 '''
150 This method will initialize specified component
151 '''
152 global driver_options
153 self.log.info("Creating component Handle: "+component)
Jon Halld61331b2015-02-17 16:35:47 -0800154 driver_options = {}
adminbae64d82013-08-01 10:50:15 -0700155 if 'COMPONENTS' in self.componentDictionary[component].keys():
156 driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
157
158 driver_options['name']=component
159 driverName = self.componentDictionary[component]['type']
160 driver_options ['type'] = driverName
Jon Hall81d3d392015-04-24 14:40:35 -0700161
adminbae64d82013-08-01 10:50:15 -0700162 classPath = self.getDriverPath(driverName.lower())
Jon Hall30b82fa2015-03-04 17:15:43 -0800163 driverModule = importlib.import_module(classPath)
adminbae64d82013-08-01 10:50:15 -0700164 driverClass = getattr(driverModule, driverName)
165 driverObject = driverClass()
Jon Hall81d3d392015-04-24 14:40:35 -0700166
adminbae64d82013-08-01 10:50:15 -0700167 connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
168 ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
169 pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
170 port = self.componentDictionary[component]['port'] if ('port' in self.componentDictionary[component].keys()) else None,
171 options = driver_options)
172 if not connect_result:
173 self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
Jon Halld61331b2015-02-17 16:35:47 -0800174 self.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700175
adminbae64d82013-08-01 10:50:15 -0700176 vars(self)[component] = driverObject
Jon Hall81d3d392015-04-24 14:40:35 -0700177
adminbae64d82013-08-01 10:50:15 -0700178 def run(self):
179 '''
Jon Hall81d3d392015-04-24 14:40:35 -0700180 The Execution of the test script's cases listed in the Test params file will be done here.
181 And Update each test case result.
182 This method will return TRUE if it executed all the test cases successfully,
adminbae64d82013-08-01 10:50:15 -0700183 else will retun FALSE
184 '''
adminbae64d82013-08-01 10:50:15 -0700185 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700186 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700187 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800188 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700189 self.TOTAL_TC_NORESULT = 0
190 self.TOTAL_TC_FAIL = 0
191 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700192 self.TEST_ITERATION = 0
adminbae64d82013-08-01 10:50:15 -0700193 self.stepCount = 0
Jon Hall79bec222015-04-30 16:23:30 -0700194 self.CASERESULT = self.NORESULT
Jon Hall81d3d392015-04-24 14:40:35 -0700195
Jon Halld61331b2015-02-17 16:35:47 -0800196 import testparser
adminbae64d82013-08-01 10:50:15 -0700197 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
198 test = testparser.TestParser(testFile)
199 self.testscript = test.testscript
200 self.code = test.getStepCode()
Jon Hallfebb1c72015-03-05 13:30:09 -0800201 repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
202 self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
Jon Hall81d3d392015-04-24 14:40:35 -0700203
adminbae64d82013-08-01 10:50:15 -0700204 result = self.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800205 while(repeat):
Jon Halla1185982014-09-15 14:55:10 -0700206 for self.CurrentTestCaseNumber in self.testcases_list:
Jon Halld61331b2015-02-17 16:35:47 -0800207 result = self.runCase(self.CurrentTestCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800208 repeat-=1
adminbae64d82013-08-01 10:50:15 -0700209 return result
Jon Hall81d3d392015-04-24 14:40:35 -0700210
adminbae64d82013-08-01 10:50:15 -0700211 def runCase(self,testCaseNumber):
212 self.CurrentTestCaseNumber = testCaseNumber
Jon Hall81d3d392015-04-24 14:40:35 -0700213 self.CurrentTestCase = ""
Jon Hall79bec222015-04-30 16:23:30 -0700214 self.stepResults = []
Jon Hall81d3d392015-04-24 14:40:35 -0700215 self.stepName = ""
Jon Hall79bec222015-04-30 16:23:30 -0700216 self.caseExplaination = ""
adminbae64d82013-08-01 10:50:15 -0700217 result = self.TRUE
218 self.stepCount = 0
219 self.EXPERIMENTAL_MODE = self.FALSE
220 self.addCaseHeader()
221 self.testCaseNumber = str(testCaseNumber)
222 stopped = False
223 try :
224 self.stepList = self.code[self.testCaseNumber].keys()
Jon Halld61331b2015-02-17 16:35:47 -0800225 except KeyError:
Jon Hallfebb1c72015-03-05 13:30:09 -0800226 self.log.error("There is no Test-Case "+ self.testCaseNumber)
227 return self.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700228
adminbae64d82013-08-01 10:50:15 -0700229 self.stepCount = 0
230 while self.stepCount < len(self.code[self.testCaseNumber].keys()):
231 result = self.runStep(self.stepList,self.code,self.testCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800232 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700233 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800234 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700235 continue
adminbae64d82013-08-01 10:50:15 -0700236 if not stopped :
Jon Hall79bec222015-04-30 16:23:30 -0700237 if all( self.TRUE == i for i in self.stepResults ):
238 # ALL PASSED
239 self.CASERESULT = self.TRUE
240 elif self.FALSE in self.stepResults:
241 # AT LEAST ONE FAILED
242 self.CASERESULT = self.FALSE
243 elif self.TRUE in self.stepResults:
244 # AT LEAST ONE PASSED
245 self.CASERESULT = self.TRUE
246 else:
247 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700248 self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
249 self.logger.updateCaseResults(self)
Jon Hall79bec222015-04-30 16:23:30 -0700250 self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
251 self.log.summary( self.caseExplaination )
252 self.log.wiki( "<ul>" )
253 for line in self.stepCache.splitlines():
254 self.log.error( repr(line) )
255 if re.search( " - PASS$", line ):
256 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
257 elif re.search( " - FAIL$", line ):
258 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
259 elif re.search( " - No Result$", line ):
260 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
261 self.log.wiki( "</ul>" )
262 self.log.summary( self.stepCache )
263 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700264 return result
Jon Hall81d3d392015-04-24 14:40:35 -0700265
adminbae64d82013-08-01 10:50:15 -0700266 def runStep(self,stepList,code,testCaseNumber):
267 if not cli.pause:
268 try :
269 step = stepList[self.stepCount]
Jon Hall79bec222015-04-30 16:23:30 -0700270 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700271 exec code[testCaseNumber][step] in module.__dict__
272 self.stepCount = self.stepCount + 1
Jon Hall79bec222015-04-30 16:23:30 -0700273 if step > 0:
274 self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
275 if self.STEPRESULT == self.TRUE:
276 self.stepCache += "PASS\n"
277 #self.stepCache += "PASS <ac:emoticon ac:name=\"tick\" /></li>\n"
278 elif self.STEPRESULT == self.FALSE:
279 self.stepCache += "FAIL\n"
280 #self.stepCache += "FAIL <ac:emoticon ac:name=\"cross\" /></li>\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700281 else:
Jon Hall79bec222015-04-30 16:23:30 -0700282 self.stepCache += "No Result\n"
283 #self.stepCache += "No Result <ac:emoticon ac:name=\"warning\" /></li>\n"
284 self.stepResults.append(self.STEPRESULT)
adminbae64d82013-08-01 10:50:15 -0700285 except TypeError,e:
Jon Hall79bec222015-04-30 16:23:30 -0700286 print "\nException in the following section of code: " +\
287 str(testCaseNumber) + "." + str(step) + ": " +\
288 self.stepName
Jon Hall63604932015-02-26 17:09:50 -0800289 #print code[testCaseNumber][step]
adminbae64d82013-08-01 10:50:15 -0700290 self.stepCount = self.stepCount + 1
Jon Hall30b82fa2015-03-04 17:15:43 -0800291 self.log.exception(e)
Jon Hall79bec222015-04-30 16:23:30 -0700292 self.logger.updateCaseResults(self)
293 #WIKI results
294 self.log.wiki( "<ul>" )
295 for line in self.stepCachesplitlines():
296 self.log.error( repr(line) )
297 if re.search( " - PASS$", line ):
298 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
299 elif re.search( " - FAIL$", line ):
300 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
301 elif re.search( " - No Result$", line ):
302 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
303 self.log.wiki( "</ul>" )
304 #summary results
305 self.log.summary( self.stepCache )
306 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700307 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700308 self.exit()
adminbae64d82013-08-01 10:50:15 -0700309 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700310 if cli.stop:
311 cli.stop = False
312 stopped = True
313 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
314 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
315 self.logger.updateCaseResults(self)
316 result = self.cleanup()
317 return main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700318
adminbae64d82013-08-01 10:50:15 -0700319 def addCaseHeader(self):
320 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800321 self.log.exact(caseHeader)
322 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700323 for driver in self.componentDictionary.keys():
324 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700325
adminbae64d82013-08-01 10:50:15 -0700326 def addCaseFooter(self):
327 if self.stepCount-1 > 0 :
328 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
329 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700330
adminbae64d82013-08-01 10:50:15 -0700331 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700332
adminbae64d82013-08-01 10:50:15 -0700333 for driver in self.driversList:
334 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
335
336 def cleanup(self):
337 '''
338 Release all the component handles and the close opened file handles.
339 This will return TRUE if all the component handles and log handles closed properly,
340 else return FALSE
341
342 '''
343 result = self.TRUE
344 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800345
adminbae64d82013-08-01 10:50:15 -0700346 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800347
admin2c7034f2013-08-02 15:09:17 -0700348 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700349 for component in self.componentDictionary.keys():
350 try :
Jon Halld61331b2015-02-17 16:35:47 -0800351 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700352 print "Disconnecting from " + str(tempObject.name) + ": " + \
353 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700354 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800355 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700356
Jon Hall00539b12015-04-03 13:55:46 -0700357 except (Exception):
358 self.log.exception( "Exception while disconnecting from " +
359 str( component ) )
360 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700361 # Closing all the driver's session files
362 for driver in self.componentDictionary.keys():
363 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800364
adminbae64d82013-08-01 10:50:15 -0700365 return result
Jon Halld61331b2015-02-17 16:35:47 -0800366
adminbae64d82013-08-01 10:50:15 -0700367 def pause(self):
368 '''
369 This function will pause the test's execution, and will continue after user provide 'resume' command.
370 '''
371 __builtin__.testthread.pause()
Jon Hall81d3d392015-04-24 14:40:35 -0700372
adminbae64d82013-08-01 10:50:15 -0700373 def onfail(self,*components):
374 '''
Jon Hall81d3d392015-04-24 14:40:35 -0700375 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700376 '''
adminbae64d82013-08-01 10:50:15 -0700377 if not components:
378 try :
379 for component in self.componentDictionary.keys():
380 tempObject = vars(self)[component]
381 result = tempObject.onfail()
382 except(Exception),e:
383 print str(e)
384 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700385 else:
386 try :
387 for component in components:
388 tempObject = vars(self)[component]
389 result = tempObject.onfail()
390 except(Exception),e:
391 print str(e)
392 result = self.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700393
adminbae64d82013-08-01 10:50:15 -0700394 def getDriverPath(self,driverName):
395 '''
396 Based on the component 'type' specified in the params , this method will find the absolute path ,
397 by recursively searching the name of the component.
398 '''
399 import commands
400
401 cmd = "find "+drivers_path+" -name "+driverName+".py"
402 result = commands.getoutput(cmd)
Jon Hall81d3d392015-04-24 14:40:35 -0700403
adminbae64d82013-08-01 10:50:15 -0700404 result_array = str(result).split('\n')
405 result_count = 0
Jon Hall81d3d392015-04-24 14:40:35 -0700406
adminbae64d82013-08-01 10:50:15 -0700407 for drivers_list in result_array:
408 result_count = result_count+1
409 if result_count > 1 :
410 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
411 self.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700412
adminbae64d82013-08-01 10:50:15 -0700413 result = re.sub("(.*)drivers","",result)
414 result = re.sub("\.py","",result)
415 result = re.sub("\.pyc","",result)
416 result = re.sub("\/",".",result)
417 result = "drivers"+result
418 return result
adminbae64d82013-08-01 10:50:15 -0700419
420 def step(self,stepDesc):
421 '''
422 The step information of the test-case will append to the logs.
423 '''
424 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
425 self.stepName = stepDesc
426
427 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
428 try :
429 if self.stepCount == 0:
430 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
431 except AttributeError:
432 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
Jon Hall81d3d392015-04-24 14:40:35 -0700433
adminbae64d82013-08-01 10:50:15 -0700434 self.log.step(stepName)
435 stepHeader = ""
436 if self.stepCount > 1 :
437 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700438
Jon Halld61331b2015-02-17 16:35:47 -0800439 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700440 for driver in self.componentDictionary.keys():
441 vars(self)[driver+'log'].info(stepHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700442
adminbae64d82013-08-01 10:50:15 -0700443 def case(self,testCaseName):
444 '''
445 Test's each test-case information will append to the logs.
446 '''
Jon Halld61331b2015-02-17 16:35:47 -0800447 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700448 testCaseName = " " + str(testCaseName) + ""
449 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800450 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700451 for driver in self.componentDictionary.keys():
452 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700453
adminbae64d82013-08-01 10:50:15 -0700454 def testDesc(self,description):
455 '''
456 Test description will append to the logs.
457 '''
458 description = "Test Description : " + str (description) + ""
459 self.log.info(description)
Jon Hall81d3d392015-04-24 14:40:35 -0700460
adminbae64d82013-08-01 10:50:15 -0700461 def _getTest(self):
462 '''
463 This method will parse the test script to find required test information.
464 '''
465 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
466 testFileHandler = open(testFile, 'r')
467 testFileList = testFileHandler.readlines()
468 testFileHandler.close()
469 #self.TOTAL_TC_PLANNED = 0
470 counter = 0
471 for index in range(len(testFileList)):
472 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
473 if lineMatch:
474 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700475 self.TC_PLANNED = len(self.testcases_list)
Jon Hall81d3d392015-04-24 14:40:35 -0700476
adminbae64d82013-08-01 10:50:15 -0700477 def response_parser(self,response, return_format):
478 ''' It will load the default response parser '''
479 response_dict = {}
480 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800481 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700482 return return_format_string
Jon Hall81d3d392015-04-24 14:40:35 -0700483
adminbae64d82013-08-01 10:50:15 -0700484 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700485 response_dict = {}
486 json_match = re.search('^\s*{', response)
487 xml_match = re.search('^\s*\<', response)
488 ini_match = re.search('^\s*\[', response)
489 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800490 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800491 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700492 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
493 response = re.sub(r",\s*'?(\w)", r',"\1', response)
494 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
495 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700496 try :
497 import json
498 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800499 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800500 self.log.exception( e )
501 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700502 return response_dict
adminbae64d82013-08-01 10:50:15 -0700503 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800504 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700505 from configobj import ConfigObj
506 response_file = open("respnse_file.temp",'w')
507 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800508 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700509 response_dict = ConfigObj("respnse_file.temp")
510 return response_dict
adminbae64d82013-08-01 10:50:15 -0700511 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800512 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700513 try :
adminbae64d82013-08-01 10:50:15 -0700514 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
515 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800516 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700517 return response_dict
Jon Hall81d3d392015-04-24 14:40:35 -0700518
adminbae64d82013-08-01 10:50:15 -0700519 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700520 if return_format =='table' :
521 ''' Will return in table format'''
522 to_do = "Call the table output formatter"
523 global response_table
524 response_table = '\n'
525 response_table = response_table +'\t'.join(response_dict)+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700526
adminbae64d82013-08-01 10:50:15 -0700527 def get_table(value_to_convert):
528 ''' This will parse the dictionary recusrsively and print as table format'''
529 table_data = ""
530 if type(value_to_convert) == dict :
531 table_data = table_data +'\t'.join(value_to_convert)+"\n"
532 for temp_val in value_to_convert.values() :
533 table_data = table_data + get_table(temp_val)
534 else :
535 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800536 return table_data
Jon Hall81d3d392015-04-24 14:40:35 -0700537
adminbae64d82013-08-01 10:50:15 -0700538 for value in response_dict.values() :
539 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800540 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700541 return response_table
Jon Hall81d3d392015-04-24 14:40:35 -0700542
adminbae64d82013-08-01 10:50:15 -0700543 elif return_format =='config':
544 ''' Will return in config format'''
545 to_do = 'Call dict to config coverter'
546 response_string = str(response_dict)
547 print response_string
548 response_config = re.sub(",", "\n\t", response_string)
549 response_config = re.sub("u\'", "\'", response_config)
550 response_config = re.sub("{", "", response_config)
551 response_config = re.sub("}", "\n", response_config)
552 response_config = re.sub(":", " =", response_config)
553 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700554 elif return_format == 'xml':
555 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700556 response_xml = xmldict.dict_to_xml(response_dict)
557 response_xml = re.sub(">\s*<", ">\n<", response_xml)
558 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700559 elif return_format == 'json':
560 ''' Will return in json format'''
561 to_do = 'Call dict to xml coverter'
562 import json
563 response_json = json.dumps(response_dict)
564 return response_json
Jon Hall81d3d392015-04-24 14:40:35 -0700565
adminbae64d82013-08-01 10:50:15 -0700566 def get_random(self):
567 self.random_order = self.random_order + 1
568 return self.random_order
Jon Hall81d3d392015-04-24 14:40:35 -0700569
adminbae64d82013-08-01 10:50:15 -0700570 def exit(self):
571 __builtin__.testthread = None
572 sys.exit()
573
574def verifyOptions(options):
575 '''
576 This will verify the command line options and set to default values, if any option not given in command line.
577 '''
578 import pprint
579 pp = pprint.PrettyPrinter(indent=4)
580
Jon Hall88e498c2015-03-06 09:54:35 -0800581 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700582 verifyTest(options)
583 verifyExample(options)
584 verifyTestScript(options)
585 verifyParams()
586 verifyLogdir(options)
587 verifyMail(options)
588 verifyTestCases(options)
589
590def verifyTest(options):
591 if options.testname:
592 main.TEST = options.testname
593 main.classPath = "tests."+main.TEST+"."+main.TEST
594 main.tests_path = tests_path
595 elif options.example :
596 main.TEST = options.example
597 main.tests_path = path+"/examples/"
598 main.classPath = "examples."+main.TEST+"."+main.TEST
599 else :
600 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
601 self.exit()
602
603def verifyExample(options):
604 if options.example:
605 main.testDir = path+'/examples/'
606 main.tests_path = path+"/examples/"
607 main.classPath = "examples."+main.TEST+"."+main.TEST
Jon Hall81d3d392015-04-24 14:40:35 -0700608
adminbae64d82013-08-01 10:50:15 -0700609def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800610 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700611 if options.logdir:
612 main.logdir = options.logdir
613 else :
Jon Halld61331b2015-02-17 16:35:47 -0800614 main.logdir = main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700615
adminbae64d82013-08-01 10:50:15 -0700616def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800617 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700618 if options.mail:
619 main.mail = options.mail
620 elif main.params.has_key('mail'):
621 main.mail = main.params['mail']
622 else :
623 main.mail = 'paxweb@paxterrasolutions.com'
624
625def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800626 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700627 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800628 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800629 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700630 testcases_list = re.sub("(\[|\])", "", options.testcases)
631 main.testcases_list = eval(testcases_list+",")
632 else :
633 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700634 temp = eval(main.params['testcases']+",")
635 list1=[]
636 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800637 for test in temp:
638 for testcase in test:
639 if type(testcase)==int:
640 testcase=[testcase]
641 list1.extend(testcase)
642 else :
643 temp=list(temp)
644 for testcase in temp:
645 if type(testcase)==int:
646 testcase=[testcase]
647 list1.extend(testcase)
648 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700649 else :
650 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800651 sys.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700652
adminbae64d82013-08-01 10:50:15 -0700653def verifyTestScript(options):
654 '''
655 Verifyies test script.
656 '''
Jon Halld61331b2015-02-17 16:35:47 -0800657 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700658 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
659 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
660 if os.path.exists(openspeakfile) :
661 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
662 elif os.path.exists(testfile):
663 print ''
664 else:
665 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
666 __builtin__.testthread = None
667 main.exit()
adminbae64d82013-08-01 10:50:15 -0700668 try :
adminbae64d82013-08-01 10:50:15 -0700669 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
670 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500671 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800672 main.exit()
adminbae64d82013-08-01 10:50:15 -0700673
674 testClass = getattr(testModule, main.TEST)
675 main.testObject = testClass()
676 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800677 main.params = main.parser.parseParams(main.classPath)
678 main.topology = main.parser.parseTopology(main.classPath)
Jon Hall81d3d392015-04-24 14:40:35 -0700679
adminbae64d82013-08-01 10:50:15 -0700680def verifyParams():
681 try :
682 main.params = main.params['PARAMS']
683 except(KeyError):
684 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800685 main.exit()
adminbae64d82013-08-01 10:50:15 -0700686 try :
687 main.topology = main.topology['TOPOLOGY']
688 except(KeyError):
689 print "Error with the Topology file: Either the file not specified or the format is not correct"
690 main.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700691
adminbae64d82013-08-01 10:50:15 -0700692def load_parser() :
693 '''
694 It facilitates the loading customised parser for topology and params file.
695 It loads parser mentioned in tab named parser of teston.cfg file.
696 It also loads default xmlparser if no parser have specified in teston.cfg file.
697
698 '''
699 confighash = main.configDict
700 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
701 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
702 if os.path.exists(confighash['config']['parser']['file']) :
703 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
704 moduleList = module.split("/")
705 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
706 try :
707 parsingClass = confighash['config']['parser']['class']
708 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
709 parsingClass = getattr(parsingModule, parsingClass)
710 main.parser = parsingClass()
711 #hashobj = main.parser.parseParams(main.classPath)
712 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700713 pass
714 else:
715 main.exit()
adminbae64d82013-08-01 10:50:15 -0700716 except ImportError:
717 print sys.exc_info()[1]
718 main.exit()
719 else :
720 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800721 load_defaultParser()
722 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
723 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700724 else:
725 load_defaultParser()
726
727def load_defaultParser():
728 '''
729 It will load the default parser which is xml parser to parse the params and topology file.
730 '''
731 moduleList = main.parserPath.split("/")
732 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
733 try :
Jon Halld61331b2015-02-17 16:35:47 -0800734 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700735 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
736 parsingClass = getattr(parsingModule, parsingClass)
737 main.parser = parsingClass()
738 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
739 pass
740 else:
741 main.exit()
742
743 except ImportError:
744 print sys.exc_info()[1]
745
adminbae64d82013-08-01 10:50:15 -0700746def load_logger() :
747 '''
748 It facilitates the loading customised parser for topology and params file.
749 It loads parser mentioned in tab named parser of teston.cfg file.
750 It also loads default xmlparser if no parser have specified in teston.cfg file.
751
752 '''
753 confighash = main.configDict
754 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
755 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
756 if os.path.exists(confighash['config']['logger']['file']) :
757 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
758 moduleList = module.split("/")
759 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
760 try :
761 loggerClass = confighash['config']['logger']['class']
762 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
763 loggerClass = getattr(loggerModule, loggerClass)
764 main.logger = loggerClass()
765 #hashobj = main.parser.parseParams(main.classPath)
766
767 except ImportError:
768 print sys.exc_info()[1]
769 else :
770 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
771 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800772 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
773 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700774 else:
775 load_defaultlogger()
776
777def load_defaultlogger():
778 '''
779 It will load the default parser which is xml parser to parse the params and topology file.
780 '''
781 moduleList = main.loggerPath.split("/")
782 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
783 try :
Jon Halld61331b2015-02-17 16:35:47 -0800784 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700785 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
786 loggerClass = getattr(loggerModule, loggerClass)
787 main.logger = loggerClass()
788
789 except ImportError:
790 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800791 main.exit()
adminbae64d82013-08-01 10:50:15 -0700792
793def load_defaultlogger():
794 '''
795 It will load the default parser which is xml parser to parse the params and topology file.
796 '''
797 moduleList = main.loggerPath.split("/")
798 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
799 try :
Jon Halld61331b2015-02-17 16:35:47 -0800800 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700801 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
802 loggerClass = getattr(loggerModule, loggerClass)
803 main.logger = loggerClass()
804
805 except ImportError:
806 print sys.exc_info()[1]
807 main.exit()
808
adminbae64d82013-08-01 10:50:15 -0700809def _echo(self):
810 print "THIS IS ECHO"