blob: ed25ccaa4d3035415ff432b30221f696794f989f [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 Halld61331b2015-02-17 16:35:47 -080081 self.EXPERIMENTAL_MODE = False
adminbae64d82013-08-01 10:50:15 -070082 self.test_target = None
83 self.lastcommand = None
Jon Halld61331b2015-02-17 16:35:47 -080084 self.testDir = tests_path
85 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070086 self.parsingClass = "xmlparser"
87 self.parserPath = core_path + "/xmlparser"
88 self.loggerPath = core_path + "/logger"
89 self.loggerClass = "Logger"
90 self.logs_path = logs_path
91 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -080092 self.Thread = Thread
Jon Hall65844a32015-03-09 19:09:37 -070093
adminbae64d82013-08-01 10:50:15 -070094 self.configparser()
95 verifyOptions(options)
96 load_logger()
97 self.componentDictionary = {}
98 self.componentDictionary = self.topology ['COMPONENT']
99 self.driversList=[]
100 if type(self.componentDictionary) == str :
101 self.componentDictionary = dict(self.componentDictionary)
Jon Hall65844a32015-03-09 19:09:37 -0700102
adminbae64d82013-08-01 10:50:15 -0700103 for component in self.componentDictionary :
104 self.driversList.append(self.componentDictionary[component]['type'])
Jon Hall65844a32015-03-09 19:09:37 -0700105
adminbae64d82013-08-01 10:50:15 -0700106 self.driversList = list(set(self.driversList)) # Removing duplicates.
107 # Checking the test_target option set for the component or not
108 if type(self.componentDictionary) == dict:
109 for component in self.componentDictionary.keys():
110 if 'test_target' in self.componentDictionary[component].keys():
111 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700112
Jon Halld61331b2015-02-17 16:35:47 -0800113 # Checking for the openspeak file and test script
adminbae64d82013-08-01 10:50:15 -0700114 self.logger.initlog(self)
115
116 # Creating Drivers Handles
117 initString = "\n"+"*" * 30+"\n CASE INIT \n"+"*" * 30+"\n"
118 self.log.exact(initString)
119 self.driverObject = {}
120 self.random_order = 111 # Random order id to connect the components
121 components_connect_order = {}
122 #component_list.append()
123 if type(self.componentDictionary) == dict:
124 for component in self.componentDictionary.keys():
125 self.componentDictionary[component]['connect_order'] = self.componentDictionary[component]['connect_order'] if ('connect_order' in self.componentDictionary[component].keys()) else str(self.get_random())
126 components_connect_order[component] = eval(self.componentDictionary[component]['connect_order'])
127 #Ordering components based on the connect order.
128 ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
129 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700130 for component in ordered_component_list:
131 self.componentInit(component)
132
133 def configparser(self):
134 '''
135 It will parse the config file (teston.cfg) and return as dictionary
136 '''
137 matchFileName = re.match(r'(.*)\.cfg', self.configFile, re.M | re.I)
138 if matchFileName:
139 xml = open(self.configFile).read()
140 try :
141 self.configDict = xmldict.xml_to_dict(xml)
142 return self.configDict
Jon Hallfebb1c72015-03-05 13:30:09 -0800143 except Exception:
adminbae64d82013-08-01 10:50:15 -0700144 print "There is no such file to parse " + self.configFile
Jon Hall81d3d392015-04-24 14:40:35 -0700145
adminbae64d82013-08-01 10:50:15 -0700146 def componentInit(self,component):
147 '''
148 This method will initialize specified component
149 '''
150 global driver_options
151 self.log.info("Creating component Handle: "+component)
Jon Halld61331b2015-02-17 16:35:47 -0800152 driver_options = {}
adminbae64d82013-08-01 10:50:15 -0700153 if 'COMPONENTS' in self.componentDictionary[component].keys():
154 driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
155
156 driver_options['name']=component
157 driverName = self.componentDictionary[component]['type']
158 driver_options ['type'] = driverName
Jon Hall81d3d392015-04-24 14:40:35 -0700159
adminbae64d82013-08-01 10:50:15 -0700160 classPath = self.getDriverPath(driverName.lower())
Jon Hall30b82fa2015-03-04 17:15:43 -0800161 driverModule = importlib.import_module(classPath)
adminbae64d82013-08-01 10:50:15 -0700162 driverClass = getattr(driverModule, driverName)
163 driverObject = driverClass()
Jon Hall81d3d392015-04-24 14:40:35 -0700164
adminbae64d82013-08-01 10:50:15 -0700165 connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
166 ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
167 pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
168 port = self.componentDictionary[component]['port'] if ('port' in self.componentDictionary[component].keys()) else None,
169 options = driver_options)
170 if not connect_result:
171 self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
Jon Halld61331b2015-02-17 16:35:47 -0800172 self.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700173
adminbae64d82013-08-01 10:50:15 -0700174 vars(self)[component] = driverObject
Jon Hall81d3d392015-04-24 14:40:35 -0700175
adminbae64d82013-08-01 10:50:15 -0700176 def run(self):
177 '''
Jon Hall81d3d392015-04-24 14:40:35 -0700178 The Execution of the test script's cases listed in the Test params file will be done here.
179 And Update each test case result.
180 This method will return TRUE if it executed all the test cases successfully,
adminbae64d82013-08-01 10:50:15 -0700181 else will retun FALSE
182 '''
adminbae64d82013-08-01 10:50:15 -0700183 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700184 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700185 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800186 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700187 self.TOTAL_TC_NORESULT = 0
188 self.TOTAL_TC_FAIL = 0
189 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700190 self.TEST_ITERATION = 0
adminbae64d82013-08-01 10:50:15 -0700191 self.stepCount = 0
Jon Hall79bec222015-04-30 16:23:30 -0700192 self.CASERESULT = self.NORESULT
Jon Hall81d3d392015-04-24 14:40:35 -0700193
Jon Halld61331b2015-02-17 16:35:47 -0800194 import testparser
adminbae64d82013-08-01 10:50:15 -0700195 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
196 test = testparser.TestParser(testFile)
197 self.testscript = test.testscript
198 self.code = test.getStepCode()
Jon Hallfebb1c72015-03-05 13:30:09 -0800199 repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
200 self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
Jon Hall81d3d392015-04-24 14:40:35 -0700201
adminbae64d82013-08-01 10:50:15 -0700202 result = self.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800203 while(repeat):
Jon Halla1185982014-09-15 14:55:10 -0700204 for self.CurrentTestCaseNumber in self.testcases_list:
Jon Halld61331b2015-02-17 16:35:47 -0800205 result = self.runCase(self.CurrentTestCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800206 repeat-=1
adminbae64d82013-08-01 10:50:15 -0700207 return result
Jon Hall81d3d392015-04-24 14:40:35 -0700208
adminbae64d82013-08-01 10:50:15 -0700209 def runCase(self,testCaseNumber):
210 self.CurrentTestCaseNumber = testCaseNumber
Jon Hall81d3d392015-04-24 14:40:35 -0700211 self.CurrentTestCase = ""
Jon Hall79bec222015-04-30 16:23:30 -0700212 self.stepResults = []
Jon Hall81d3d392015-04-24 14:40:35 -0700213 self.stepName = ""
Jon Hall79bec222015-04-30 16:23:30 -0700214 self.caseExplaination = ""
adminbae64d82013-08-01 10:50:15 -0700215 result = self.TRUE
216 self.stepCount = 0
217 self.EXPERIMENTAL_MODE = self.FALSE
218 self.addCaseHeader()
219 self.testCaseNumber = str(testCaseNumber)
220 stopped = False
221 try :
222 self.stepList = self.code[self.testCaseNumber].keys()
Jon Halld61331b2015-02-17 16:35:47 -0800223 except KeyError:
Jon Hallfebb1c72015-03-05 13:30:09 -0800224 self.log.error("There is no Test-Case "+ self.testCaseNumber)
225 return self.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700226
adminbae64d82013-08-01 10:50:15 -0700227 self.stepCount = 0
228 while self.stepCount < len(self.code[self.testCaseNumber].keys()):
229 result = self.runStep(self.stepList,self.code,self.testCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800230 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700231 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800232 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700233 continue
adminbae64d82013-08-01 10:50:15 -0700234 if not stopped :
Jon Hall79bec222015-04-30 16:23:30 -0700235 if all( self.TRUE == i for i in self.stepResults ):
236 # ALL PASSED
237 self.CASERESULT = self.TRUE
238 elif self.FALSE in self.stepResults:
239 # AT LEAST ONE FAILED
240 self.CASERESULT = self.FALSE
241 elif self.TRUE in self.stepResults:
242 # AT LEAST ONE PASSED
243 self.CASERESULT = self.TRUE
244 else:
245 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700246 self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
247 self.logger.updateCaseResults(self)
Jon Hall79bec222015-04-30 16:23:30 -0700248 self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
249 self.log.summary( self.caseExplaination )
250 self.log.wiki( "<ul>" )
251 for line in self.stepCache.splitlines():
Jon Hall79bec222015-04-30 16:23:30 -0700252 if re.search( " - PASS$", line ):
253 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
254 elif re.search( " - FAIL$", line ):
255 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
256 elif re.search( " - No Result$", line ):
257 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
258 self.log.wiki( "</ul>" )
259 self.log.summary( self.stepCache )
260 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700261 return result
Jon Hall81d3d392015-04-24 14:40:35 -0700262
adminbae64d82013-08-01 10:50:15 -0700263 def runStep(self,stepList,code,testCaseNumber):
264 if not cli.pause:
265 try :
266 step = stepList[self.stepCount]
Jon Hall79bec222015-04-30 16:23:30 -0700267 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700268 exec code[testCaseNumber][step] in module.__dict__
269 self.stepCount = self.stepCount + 1
Jon Hall79bec222015-04-30 16:23:30 -0700270 if step > 0:
271 self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
272 if self.STEPRESULT == self.TRUE:
273 self.stepCache += "PASS\n"
274 #self.stepCache += "PASS <ac:emoticon ac:name=\"tick\" /></li>\n"
275 elif self.STEPRESULT == self.FALSE:
276 self.stepCache += "FAIL\n"
277 #self.stepCache += "FAIL <ac:emoticon ac:name=\"cross\" /></li>\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700278 else:
Jon Hall79bec222015-04-30 16:23:30 -0700279 self.stepCache += "No Result\n"
280 #self.stepCache += "No Result <ac:emoticon ac:name=\"warning\" /></li>\n"
281 self.stepResults.append(self.STEPRESULT)
Jon Hall40d2cbd2015-06-03 16:24:29 -0700282 except StandardError as e:
283 self.log.exception( "\nException in the following section of" +
284 " code: " + str(testCaseNumber) + "." +
285 str(step) + ": " + self.stepName )
Jon Hall63604932015-02-26 17:09:50 -0800286 #print code[testCaseNumber][step]
adminbae64d82013-08-01 10:50:15 -0700287 self.stepCount = self.stepCount + 1
Jon Hall79bec222015-04-30 16:23:30 -0700288 self.logger.updateCaseResults(self)
289 #WIKI results
290 self.log.wiki( "<ul>" )
Jon Hall50157552015-05-04 16:20:03 -0700291 for line in self.stepCache.splitlines():
Jon Hall79bec222015-04-30 16:23:30 -0700292 if re.search( " - PASS$", line ):
293 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
294 elif re.search( " - FAIL$", line ):
295 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
296 elif re.search( " - No Result$", line ):
297 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
298 self.log.wiki( "</ul>" )
299 #summary results
300 self.log.summary( self.stepCache )
301 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700302 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700303 self.exit()
adminbae64d82013-08-01 10:50:15 -0700304 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700305 if cli.stop:
306 cli.stop = False
307 stopped = True
308 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
309 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
310 self.logger.updateCaseResults(self)
311 result = self.cleanup()
312 return main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700313
adminbae64d82013-08-01 10:50:15 -0700314 def addCaseHeader(self):
315 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800316 self.log.exact(caseHeader)
317 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700318 for driver in self.componentDictionary.keys():
319 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700320
adminbae64d82013-08-01 10:50:15 -0700321 def addCaseFooter(self):
322 if self.stepCount-1 > 0 :
323 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
324 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700325
adminbae64d82013-08-01 10:50:15 -0700326 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700327
adminbae64d82013-08-01 10:50:15 -0700328 for driver in self.driversList:
329 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
330
331 def cleanup(self):
332 '''
333 Release all the component handles and the close opened file handles.
334 This will return TRUE if all the component handles and log handles closed properly,
335 else return FALSE
336
337 '''
338 result = self.TRUE
339 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800340
adminbae64d82013-08-01 10:50:15 -0700341 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800342
admin2c7034f2013-08-02 15:09:17 -0700343 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700344 for component in self.componentDictionary.keys():
345 try :
Jon Halld61331b2015-02-17 16:35:47 -0800346 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700347 print "Disconnecting from " + str(tempObject.name) + ": " + \
348 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700349 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800350 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700351
Jon Hall00539b12015-04-03 13:55:46 -0700352 except (Exception):
353 self.log.exception( "Exception while disconnecting from " +
354 str( component ) )
355 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700356 # Closing all the driver's session files
357 for driver in self.componentDictionary.keys():
358 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800359
adminbae64d82013-08-01 10:50:15 -0700360 return result
Jon Halld61331b2015-02-17 16:35:47 -0800361
adminbae64d82013-08-01 10:50:15 -0700362 def pause(self):
363 '''
364 This function will pause the test's execution, and will continue after user provide 'resume' command.
365 '''
366 __builtin__.testthread.pause()
Jon Hall81d3d392015-04-24 14:40:35 -0700367
adminbae64d82013-08-01 10:50:15 -0700368 def onfail(self,*components):
369 '''
Jon Hall81d3d392015-04-24 14:40:35 -0700370 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700371 '''
adminbae64d82013-08-01 10:50:15 -0700372 if not components:
373 try :
374 for component in self.componentDictionary.keys():
375 tempObject = vars(self)[component]
376 result = tempObject.onfail()
377 except(Exception),e:
378 print str(e)
379 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700380 else:
381 try :
382 for component in components:
383 tempObject = vars(self)[component]
384 result = tempObject.onfail()
385 except(Exception),e:
386 print str(e)
387 result = self.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700388
adminbae64d82013-08-01 10:50:15 -0700389 def getDriverPath(self,driverName):
390 '''
391 Based on the component 'type' specified in the params , this method will find the absolute path ,
392 by recursively searching the name of the component.
393 '''
394 import commands
395
396 cmd = "find "+drivers_path+" -name "+driverName+".py"
397 result = commands.getoutput(cmd)
Jon Hall81d3d392015-04-24 14:40:35 -0700398
adminbae64d82013-08-01 10:50:15 -0700399 result_array = str(result).split('\n')
400 result_count = 0
Jon Hall81d3d392015-04-24 14:40:35 -0700401
adminbae64d82013-08-01 10:50:15 -0700402 for drivers_list in result_array:
403 result_count = result_count+1
404 if result_count > 1 :
405 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
406 self.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700407
adminbae64d82013-08-01 10:50:15 -0700408 result = re.sub("(.*)drivers","",result)
409 result = re.sub("\.py","",result)
410 result = re.sub("\.pyc","",result)
411 result = re.sub("\/",".",result)
412 result = "drivers"+result
413 return result
adminbae64d82013-08-01 10:50:15 -0700414
415 def step(self,stepDesc):
416 '''
417 The step information of the test-case will append to the logs.
418 '''
419 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
420 self.stepName = stepDesc
421
422 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
423 try :
424 if self.stepCount == 0:
425 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
426 except AttributeError:
427 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
Jon Hall81d3d392015-04-24 14:40:35 -0700428
adminbae64d82013-08-01 10:50:15 -0700429 self.log.step(stepName)
430 stepHeader = ""
431 if self.stepCount > 1 :
432 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700433
Jon Halld61331b2015-02-17 16:35:47 -0800434 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700435 for driver in self.componentDictionary.keys():
436 vars(self)[driver+'log'].info(stepHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700437
adminbae64d82013-08-01 10:50:15 -0700438 def case(self,testCaseName):
439 '''
440 Test's each test-case information will append to the logs.
441 '''
Jon Halld61331b2015-02-17 16:35:47 -0800442 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700443 testCaseName = " " + str(testCaseName) + ""
444 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800445 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700446 for driver in self.componentDictionary.keys():
447 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700448
adminbae64d82013-08-01 10:50:15 -0700449 def testDesc(self,description):
450 '''
451 Test description will append to the logs.
452 '''
453 description = "Test Description : " + str (description) + ""
454 self.log.info(description)
Jon Hall81d3d392015-04-24 14:40:35 -0700455
adminbae64d82013-08-01 10:50:15 -0700456 def _getTest(self):
457 '''
458 This method will parse the test script to find required test information.
459 '''
460 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
461 testFileHandler = open(testFile, 'r')
462 testFileList = testFileHandler.readlines()
463 testFileHandler.close()
464 #self.TOTAL_TC_PLANNED = 0
465 counter = 0
466 for index in range(len(testFileList)):
467 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
468 if lineMatch:
469 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700470 self.TC_PLANNED = len(self.testcases_list)
Jon Hall81d3d392015-04-24 14:40:35 -0700471
adminbae64d82013-08-01 10:50:15 -0700472 def response_parser(self,response, return_format):
473 ''' It will load the default response parser '''
474 response_dict = {}
475 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800476 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700477 return return_format_string
Jon Hall81d3d392015-04-24 14:40:35 -0700478
adminbae64d82013-08-01 10:50:15 -0700479 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700480 response_dict = {}
481 json_match = re.search('^\s*{', response)
482 xml_match = re.search('^\s*\<', response)
483 ini_match = re.search('^\s*\[', response)
484 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800485 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800486 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700487 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
488 response = re.sub(r",\s*'?(\w)", r',"\1', response)
489 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
490 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700491 try :
492 import json
493 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800494 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800495 self.log.exception( e )
496 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700497 return response_dict
adminbae64d82013-08-01 10:50:15 -0700498 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800499 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700500 from configobj import ConfigObj
501 response_file = open("respnse_file.temp",'w')
502 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800503 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700504 response_dict = ConfigObj("respnse_file.temp")
505 return response_dict
adminbae64d82013-08-01 10:50:15 -0700506 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800507 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700508 try :
adminbae64d82013-08-01 10:50:15 -0700509 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
510 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800511 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700512 return response_dict
Jon Hall81d3d392015-04-24 14:40:35 -0700513
adminbae64d82013-08-01 10:50:15 -0700514 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700515 if return_format =='table' :
516 ''' Will return in table format'''
517 to_do = "Call the table output formatter"
518 global response_table
519 response_table = '\n'
520 response_table = response_table +'\t'.join(response_dict)+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700521
adminbae64d82013-08-01 10:50:15 -0700522 def get_table(value_to_convert):
523 ''' This will parse the dictionary recusrsively and print as table format'''
524 table_data = ""
525 if type(value_to_convert) == dict :
526 table_data = table_data +'\t'.join(value_to_convert)+"\n"
527 for temp_val in value_to_convert.values() :
528 table_data = table_data + get_table(temp_val)
529 else :
530 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800531 return table_data
Jon Hall81d3d392015-04-24 14:40:35 -0700532
adminbae64d82013-08-01 10:50:15 -0700533 for value in response_dict.values() :
534 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800535 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700536 return response_table
Jon Hall81d3d392015-04-24 14:40:35 -0700537
adminbae64d82013-08-01 10:50:15 -0700538 elif return_format =='config':
539 ''' Will return in config format'''
540 to_do = 'Call dict to config coverter'
541 response_string = str(response_dict)
542 print response_string
543 response_config = re.sub(",", "\n\t", response_string)
544 response_config = re.sub("u\'", "\'", response_config)
545 response_config = re.sub("{", "", response_config)
546 response_config = re.sub("}", "\n", response_config)
547 response_config = re.sub(":", " =", response_config)
548 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700549 elif return_format == 'xml':
550 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700551 response_xml = xmldict.dict_to_xml(response_dict)
552 response_xml = re.sub(">\s*<", ">\n<", response_xml)
553 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700554 elif return_format == 'json':
555 ''' Will return in json format'''
556 to_do = 'Call dict to xml coverter'
557 import json
558 response_json = json.dumps(response_dict)
559 return response_json
Jon Hall81d3d392015-04-24 14:40:35 -0700560
adminbae64d82013-08-01 10:50:15 -0700561 def get_random(self):
562 self.random_order = self.random_order + 1
563 return self.random_order
Jon Hall81d3d392015-04-24 14:40:35 -0700564
adminbae64d82013-08-01 10:50:15 -0700565 def exit(self):
566 __builtin__.testthread = None
567 sys.exit()
568
569def verifyOptions(options):
570 '''
571 This will verify the command line options and set to default values, if any option not given in command line.
572 '''
573 import pprint
574 pp = pprint.PrettyPrinter(indent=4)
575
Jon Hall88e498c2015-03-06 09:54:35 -0800576 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700577 verifyTest(options)
578 verifyExample(options)
579 verifyTestScript(options)
580 verifyParams()
581 verifyLogdir(options)
582 verifyMail(options)
583 verifyTestCases(options)
584
585def verifyTest(options):
586 if options.testname:
587 main.TEST = options.testname
588 main.classPath = "tests."+main.TEST+"."+main.TEST
589 main.tests_path = tests_path
590 elif options.example :
591 main.TEST = options.example
592 main.tests_path = path+"/examples/"
593 main.classPath = "examples."+main.TEST+"."+main.TEST
594 else :
595 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
596 self.exit()
597
598def verifyExample(options):
599 if options.example:
600 main.testDir = path+'/examples/'
601 main.tests_path = path+"/examples/"
602 main.classPath = "examples."+main.TEST+"."+main.TEST
Jon Hall81d3d392015-04-24 14:40:35 -0700603
adminbae64d82013-08-01 10:50:15 -0700604def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800605 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700606 if options.logdir:
607 main.logdir = options.logdir
608 else :
Jon Halld61331b2015-02-17 16:35:47 -0800609 main.logdir = main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700610
adminbae64d82013-08-01 10:50:15 -0700611def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800612 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700613 if options.mail:
614 main.mail = options.mail
615 elif main.params.has_key('mail'):
616 main.mail = main.params['mail']
617 else :
618 main.mail = 'paxweb@paxterrasolutions.com'
619
620def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800621 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700622 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800623 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800624 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700625 testcases_list = re.sub("(\[|\])", "", options.testcases)
626 main.testcases_list = eval(testcases_list+",")
627 else :
628 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700629 temp = eval(main.params['testcases']+",")
630 list1=[]
631 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800632 for test in temp:
633 for testcase in test:
634 if type(testcase)==int:
635 testcase=[testcase]
636 list1.extend(testcase)
637 else :
638 temp=list(temp)
639 for testcase in temp:
640 if type(testcase)==int:
641 testcase=[testcase]
642 list1.extend(testcase)
643 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700644 else :
645 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800646 sys.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700647
adminbae64d82013-08-01 10:50:15 -0700648def verifyTestScript(options):
649 '''
650 Verifyies test script.
651 '''
Jon Halld61331b2015-02-17 16:35:47 -0800652 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700653 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
654 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
655 if os.path.exists(openspeakfile) :
656 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
657 elif os.path.exists(testfile):
658 print ''
659 else:
660 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
661 __builtin__.testthread = None
662 main.exit()
adminbae64d82013-08-01 10:50:15 -0700663 try :
adminbae64d82013-08-01 10:50:15 -0700664 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
665 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500666 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800667 main.exit()
adminbae64d82013-08-01 10:50:15 -0700668
669 testClass = getattr(testModule, main.TEST)
670 main.testObject = testClass()
671 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800672 main.params = main.parser.parseParams(main.classPath)
673 main.topology = main.parser.parseTopology(main.classPath)
Jon Hall81d3d392015-04-24 14:40:35 -0700674
adminbae64d82013-08-01 10:50:15 -0700675def verifyParams():
676 try :
677 main.params = main.params['PARAMS']
678 except(KeyError):
679 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800680 main.exit()
adminbae64d82013-08-01 10:50:15 -0700681 try :
682 main.topology = main.topology['TOPOLOGY']
683 except(KeyError):
684 print "Error with the Topology file: Either the file not specified or the format is not correct"
685 main.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700686
adminbae64d82013-08-01 10:50:15 -0700687def load_parser() :
688 '''
689 It facilitates the loading customised parser for topology and params file.
690 It loads parser mentioned in tab named parser of teston.cfg file.
691 It also loads default xmlparser if no parser have specified in teston.cfg file.
692
693 '''
694 confighash = main.configDict
695 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
696 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
697 if os.path.exists(confighash['config']['parser']['file']) :
698 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
699 moduleList = module.split("/")
700 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
701 try :
702 parsingClass = confighash['config']['parser']['class']
703 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
704 parsingClass = getattr(parsingModule, parsingClass)
705 main.parser = parsingClass()
706 #hashobj = main.parser.parseParams(main.classPath)
707 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700708 pass
709 else:
710 main.exit()
adminbae64d82013-08-01 10:50:15 -0700711 except ImportError:
712 print sys.exc_info()[1]
713 main.exit()
714 else :
715 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800716 load_defaultParser()
717 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
718 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700719 else:
720 load_defaultParser()
721
722def load_defaultParser():
723 '''
724 It will load the default parser which is xml parser to parse the params and topology file.
725 '''
726 moduleList = main.parserPath.split("/")
727 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
728 try :
Jon Halld61331b2015-02-17 16:35:47 -0800729 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700730 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
731 parsingClass = getattr(parsingModule, parsingClass)
732 main.parser = parsingClass()
733 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
734 pass
735 else:
736 main.exit()
737
738 except ImportError:
739 print sys.exc_info()[1]
740
adminbae64d82013-08-01 10:50:15 -0700741def load_logger() :
742 '''
743 It facilitates the loading customised parser for topology and params file.
744 It loads parser mentioned in tab named parser of teston.cfg file.
745 It also loads default xmlparser if no parser have specified in teston.cfg file.
746
747 '''
748 confighash = main.configDict
749 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
750 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
751 if os.path.exists(confighash['config']['logger']['file']) :
752 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
753 moduleList = module.split("/")
754 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
755 try :
756 loggerClass = confighash['config']['logger']['class']
757 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
758 loggerClass = getattr(loggerModule, loggerClass)
759 main.logger = loggerClass()
760 #hashobj = main.parser.parseParams(main.classPath)
761
762 except ImportError:
763 print sys.exc_info()[1]
764 else :
765 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
766 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800767 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
768 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700769 else:
770 load_defaultlogger()
771
772def load_defaultlogger():
773 '''
774 It will load the default parser which is xml parser to parse the params and topology file.
775 '''
776 moduleList = main.loggerPath.split("/")
777 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
778 try :
Jon Halld61331b2015-02-17 16:35:47 -0800779 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700780 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
781 loggerClass = getattr(loggerModule, loggerClass)
782 main.logger = loggerClass()
783
784 except ImportError:
785 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800786 main.exit()
adminbae64d82013-08-01 10:50:15 -0700787
788def load_defaultlogger():
789 '''
790 It will load the default parser which is xml parser to parse the params and topology file.
791 '''
792 moduleList = main.loggerPath.split("/")
793 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
794 try :
Jon Halld61331b2015-02-17 16:35:47 -0800795 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700796 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
797 loggerClass = getattr(loggerModule, loggerClass)
798 main.logger = loggerClass()
799
800 except ImportError:
801 print sys.exc_info()[1]
802 main.exit()
803
adminbae64d82013-08-01 10:50:15 -0700804def _echo(self):
805 print "THIS IS ECHO"