blob: 7199280bbe77fa078def6ebd93aaa3ba94c9c83d [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 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -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
kelvin-onlabf70fd542015-05-07 18:41:40 -070071 self.NORESULT = 2
adminbae64d82013-08-01 10:50:15 -070072 self.FAIL = False
73 self.PASS = True
kelvin-onlabf70fd542015-05-07 18:41:40 -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"
kelvin-onlabf70fd542015-05-07 18:41:40 -070079 self.stepName = ""
80 self.stepCache = ""
81 # 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
kelvin-onlabf70fd542015-05-07 18:41:40 -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
kelvin-onlabf70fd542015-05-07 18:41:40 -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()
kelvin-onlabf70fd542015-05-07 18:41:40 -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()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700175
adminbae64d82013-08-01 10:50:15 -0700176 vars(self)[component] = driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700177
adminbae64d82013-08-01 10:50:15 -0700178 def run(self):
179 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -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
kelvin-onlabf70fd542015-05-07 18:41:40 -0700194 self.CASERESULT = self.NORESULT
195
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
kelvin-onlabf70fd542015-05-07 18:41:40 -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
kelvin-onlabf70fd542015-05-07 18:41:40 -0700210
adminbae64d82013-08-01 10:50:15 -0700211 def runCase(self,testCaseNumber):
212 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700213 self.CurrentTestCase = ""
214 self.stepResults = []
215 self.stepName = ""
216 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
kelvin-onlabf70fd542015-05-07 18:41:40 -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 :
kelvin-onlabf70fd542015-05-07 18:41:40 -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)
kelvin-onlabf70fd542015-05-07 18:41:40 -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 if re.search( " - PASS$", line ):
255 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
256 elif re.search( " - FAIL$", line ):
257 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
258 elif re.search( " - No Result$", line ):
259 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
260 self.log.wiki( "</ul>" )
261 self.log.summary( self.stepCache )
262 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700263 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700264
adminbae64d82013-08-01 10:50:15 -0700265 def runStep(self,stepList,code,testCaseNumber):
266 if not cli.pause:
267 try :
268 step = stepList[self.stepCount]
kelvin-onlabf70fd542015-05-07 18:41:40 -0700269 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700270 exec code[testCaseNumber][step] in module.__dict__
271 self.stepCount = self.stepCount + 1
kelvin-onlabf70fd542015-05-07 18:41:40 -0700272 if step > 0:
273 self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
274 if self.STEPRESULT == self.TRUE:
275 self.stepCache += "PASS\n"
276 #self.stepCache += "PASS <ac:emoticon ac:name=\"tick\" /></li>\n"
277 elif self.STEPRESULT == self.FALSE:
278 self.stepCache += "FAIL\n"
279 #self.stepCache += "FAIL <ac:emoticon ac:name=\"cross\" /></li>\n"
280 else:
281 self.stepCache += "No Result\n"
282 #self.stepCache += "No Result <ac:emoticon ac:name=\"warning\" /></li>\n"
283 self.stepResults.append(self.STEPRESULT)
adminbae64d82013-08-01 10:50:15 -0700284 except TypeError,e:
kelvin-onlabf70fd542015-05-07 18:41:40 -0700285 print "\nException in the following section of code: " +\
286 str(testCaseNumber) + "." + str(step) + ": " +\
287 self.stepName
Jon Hall63604932015-02-26 17:09:50 -0800288 #print code[testCaseNumber][step]
adminbae64d82013-08-01 10:50:15 -0700289 self.stepCount = self.stepCount + 1
Jon Hall30b82fa2015-03-04 17:15:43 -0800290 self.log.exception(e)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700291 self.logger.updateCaseResults(self)
292 #WIKI results
293 self.log.wiki( "<ul>" )
294 for line in self.stepCache.splitlines():
295 if re.search( " - PASS$", line ):
296 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
297 elif re.search( " - FAIL$", line ):
298 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
299 elif re.search( " - No Result$", line ):
300 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
301 self.log.wiki( "</ul>" )
302 #summary results
303 self.log.summary( self.stepCache )
304 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700305 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700306 self.exit()
adminbae64d82013-08-01 10:50:15 -0700307 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700308 if cli.stop:
309 cli.stop = False
310 stopped = True
311 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
312 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
313 self.logger.updateCaseResults(self)
314 result = self.cleanup()
315 return main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700316
adminbae64d82013-08-01 10:50:15 -0700317 def addCaseHeader(self):
318 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800319 self.log.exact(caseHeader)
320 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700321 for driver in self.componentDictionary.keys():
322 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700323
adminbae64d82013-08-01 10:50:15 -0700324 def addCaseFooter(self):
325 if self.stepCount-1 > 0 :
326 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
327 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700328
adminbae64d82013-08-01 10:50:15 -0700329 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700330
adminbae64d82013-08-01 10:50:15 -0700331 for driver in self.driversList:
332 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
333
334 def cleanup(self):
335 '''
336 Release all the component handles and the close opened file handles.
337 This will return TRUE if all the component handles and log handles closed properly,
338 else return FALSE
339
340 '''
341 result = self.TRUE
342 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800343
adminbae64d82013-08-01 10:50:15 -0700344 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800345
admin2c7034f2013-08-02 15:09:17 -0700346 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700347 for component in self.componentDictionary.keys():
348 try :
Jon Halld61331b2015-02-17 16:35:47 -0800349 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700350 print "Disconnecting from " + str(tempObject.name) + ": " + \
351 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700352 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800353 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700354
Jon Hall00539b12015-04-03 13:55:46 -0700355 except (Exception):
356 self.log.exception( "Exception while disconnecting from " +
357 str( component ) )
358 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700359 # Closing all the driver's session files
360 for driver in self.componentDictionary.keys():
361 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800362
adminbae64d82013-08-01 10:50:15 -0700363 return result
Jon Halld61331b2015-02-17 16:35:47 -0800364
adminbae64d82013-08-01 10:50:15 -0700365 def pause(self):
366 '''
367 This function will pause the test's execution, and will continue after user provide 'resume' command.
368 '''
369 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700370
adminbae64d82013-08-01 10:50:15 -0700371 def onfail(self,*components):
372 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700373 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700374 '''
adminbae64d82013-08-01 10:50:15 -0700375 if not components:
376 try :
377 for component in self.componentDictionary.keys():
378 tempObject = vars(self)[component]
379 result = tempObject.onfail()
380 except(Exception),e:
381 print str(e)
382 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700383 else:
384 try :
385 for component in components:
386 tempObject = vars(self)[component]
387 result = tempObject.onfail()
388 except(Exception),e:
389 print str(e)
390 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700391
adminbae64d82013-08-01 10:50:15 -0700392 def getDriverPath(self,driverName):
393 '''
394 Based on the component 'type' specified in the params , this method will find the absolute path ,
395 by recursively searching the name of the component.
396 '''
397 import commands
398
399 cmd = "find "+drivers_path+" -name "+driverName+".py"
400 result = commands.getoutput(cmd)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700401
adminbae64d82013-08-01 10:50:15 -0700402 result_array = str(result).split('\n')
403 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700404
adminbae64d82013-08-01 10:50:15 -0700405 for drivers_list in result_array:
406 result_count = result_count+1
407 if result_count > 1 :
408 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
409 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700410
adminbae64d82013-08-01 10:50:15 -0700411 result = re.sub("(.*)drivers","",result)
412 result = re.sub("\.py","",result)
413 result = re.sub("\.pyc","",result)
414 result = re.sub("\/",".",result)
415 result = "drivers"+result
416 return result
adminbae64d82013-08-01 10:50:15 -0700417
418 def step(self,stepDesc):
419 '''
420 The step information of the test-case will append to the logs.
421 '''
422 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
423 self.stepName = stepDesc
424
425 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
426 try :
427 if self.stepCount == 0:
428 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
429 except AttributeError:
430 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700431
adminbae64d82013-08-01 10:50:15 -0700432 self.log.step(stepName)
433 stepHeader = ""
434 if self.stepCount > 1 :
435 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700436
Jon Halld61331b2015-02-17 16:35:47 -0800437 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700438 for driver in self.componentDictionary.keys():
439 vars(self)[driver+'log'].info(stepHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700440
adminbae64d82013-08-01 10:50:15 -0700441 def case(self,testCaseName):
442 '''
443 Test's each test-case information will append to the logs.
444 '''
Jon Halld61331b2015-02-17 16:35:47 -0800445 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700446 testCaseName = " " + str(testCaseName) + ""
447 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800448 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700449 for driver in self.componentDictionary.keys():
450 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700451
adminbae64d82013-08-01 10:50:15 -0700452 def testDesc(self,description):
453 '''
454 Test description will append to the logs.
455 '''
456 description = "Test Description : " + str (description) + ""
457 self.log.info(description)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700458
adminbae64d82013-08-01 10:50:15 -0700459 def _getTest(self):
460 '''
461 This method will parse the test script to find required test information.
462 '''
463 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
464 testFileHandler = open(testFile, 'r')
465 testFileList = testFileHandler.readlines()
466 testFileHandler.close()
467 #self.TOTAL_TC_PLANNED = 0
468 counter = 0
469 for index in range(len(testFileList)):
470 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
471 if lineMatch:
472 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700473 self.TC_PLANNED = len(self.testcases_list)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700474
adminbae64d82013-08-01 10:50:15 -0700475 def response_parser(self,response, return_format):
476 ''' It will load the default response parser '''
477 response_dict = {}
478 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800479 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700480 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700481
adminbae64d82013-08-01 10:50:15 -0700482 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700483 response_dict = {}
484 json_match = re.search('^\s*{', response)
485 xml_match = re.search('^\s*\<', response)
486 ini_match = re.search('^\s*\[', response)
487 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800488 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800489 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700490 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
491 response = re.sub(r",\s*'?(\w)", r',"\1', response)
492 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
493 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700494 try :
495 import json
496 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800497 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800498 self.log.exception( e )
499 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700500 return response_dict
adminbae64d82013-08-01 10:50:15 -0700501 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800502 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700503 from configobj import ConfigObj
504 response_file = open("respnse_file.temp",'w')
505 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800506 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700507 response_dict = ConfigObj("respnse_file.temp")
508 return response_dict
adminbae64d82013-08-01 10:50:15 -0700509 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800510 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700511 try :
adminbae64d82013-08-01 10:50:15 -0700512 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
513 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800514 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700515 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700516
adminbae64d82013-08-01 10:50:15 -0700517 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700518 if return_format =='table' :
519 ''' Will return in table format'''
520 to_do = "Call the table output formatter"
521 global response_table
522 response_table = '\n'
523 response_table = response_table +'\t'.join(response_dict)+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700524
adminbae64d82013-08-01 10:50:15 -0700525 def get_table(value_to_convert):
526 ''' This will parse the dictionary recusrsively and print as table format'''
527 table_data = ""
528 if type(value_to_convert) == dict :
529 table_data = table_data +'\t'.join(value_to_convert)+"\n"
530 for temp_val in value_to_convert.values() :
531 table_data = table_data + get_table(temp_val)
532 else :
533 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800534 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700535
adminbae64d82013-08-01 10:50:15 -0700536 for value in response_dict.values() :
537 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800538 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700539 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700540
adminbae64d82013-08-01 10:50:15 -0700541 elif return_format =='config':
542 ''' Will return in config format'''
543 to_do = 'Call dict to config coverter'
544 response_string = str(response_dict)
545 print response_string
546 response_config = re.sub(",", "\n\t", response_string)
547 response_config = re.sub("u\'", "\'", response_config)
548 response_config = re.sub("{", "", response_config)
549 response_config = re.sub("}", "\n", response_config)
550 response_config = re.sub(":", " =", response_config)
551 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700552 elif return_format == 'xml':
553 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700554 response_xml = xmldict.dict_to_xml(response_dict)
555 response_xml = re.sub(">\s*<", ">\n<", response_xml)
556 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700557 elif return_format == 'json':
558 ''' Will return in json format'''
559 to_do = 'Call dict to xml coverter'
560 import json
561 response_json = json.dumps(response_dict)
562 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700563
adminbae64d82013-08-01 10:50:15 -0700564 def get_random(self):
565 self.random_order = self.random_order + 1
566 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700567
adminbae64d82013-08-01 10:50:15 -0700568 def exit(self):
569 __builtin__.testthread = None
570 sys.exit()
571
572def verifyOptions(options):
573 '''
574 This will verify the command line options and set to default values, if any option not given in command line.
575 '''
576 import pprint
577 pp = pprint.PrettyPrinter(indent=4)
578
Jon Hall88e498c2015-03-06 09:54:35 -0800579 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700580 verifyTest(options)
581 verifyExample(options)
582 verifyTestScript(options)
583 verifyParams()
584 verifyLogdir(options)
585 verifyMail(options)
586 verifyTestCases(options)
587
588def verifyTest(options):
589 if options.testname:
590 main.TEST = options.testname
591 main.classPath = "tests."+main.TEST+"."+main.TEST
592 main.tests_path = tests_path
593 elif options.example :
594 main.TEST = options.example
595 main.tests_path = path+"/examples/"
596 main.classPath = "examples."+main.TEST+"."+main.TEST
597 else :
598 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
599 self.exit()
600
601def verifyExample(options):
602 if options.example:
603 main.testDir = path+'/examples/'
604 main.tests_path = path+"/examples/"
605 main.classPath = "examples."+main.TEST+"."+main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700606
adminbae64d82013-08-01 10:50:15 -0700607def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800608 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700609 if options.logdir:
610 main.logdir = options.logdir
611 else :
Jon Halld61331b2015-02-17 16:35:47 -0800612 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700613
adminbae64d82013-08-01 10:50:15 -0700614def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800615 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700616 if options.mail:
617 main.mail = options.mail
618 elif main.params.has_key('mail'):
619 main.mail = main.params['mail']
620 else :
621 main.mail = 'paxweb@paxterrasolutions.com'
622
623def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800624 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700625 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800626 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800627 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700628 testcases_list = re.sub("(\[|\])", "", options.testcases)
629 main.testcases_list = eval(testcases_list+",")
630 else :
631 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700632 temp = eval(main.params['testcases']+",")
633 list1=[]
634 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800635 for test in temp:
636 for testcase in test:
637 if type(testcase)==int:
638 testcase=[testcase]
639 list1.extend(testcase)
640 else :
641 temp=list(temp)
642 for testcase in temp:
643 if type(testcase)==int:
644 testcase=[testcase]
645 list1.extend(testcase)
646 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700647 else :
648 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800649 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700650
adminbae64d82013-08-01 10:50:15 -0700651def verifyTestScript(options):
652 '''
653 Verifyies test script.
654 '''
Jon Halld61331b2015-02-17 16:35:47 -0800655 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700656 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
657 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
658 if os.path.exists(openspeakfile) :
659 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
660 elif os.path.exists(testfile):
661 print ''
662 else:
663 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
664 __builtin__.testthread = None
665 main.exit()
adminbae64d82013-08-01 10:50:15 -0700666 try :
adminbae64d82013-08-01 10:50:15 -0700667 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
668 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500669 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800670 main.exit()
adminbae64d82013-08-01 10:50:15 -0700671
672 testClass = getattr(testModule, main.TEST)
673 main.testObject = testClass()
674 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800675 main.params = main.parser.parseParams(main.classPath)
676 main.topology = main.parser.parseTopology(main.classPath)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700677
adminbae64d82013-08-01 10:50:15 -0700678def verifyParams():
679 try :
680 main.params = main.params['PARAMS']
681 except(KeyError):
682 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800683 main.exit()
adminbae64d82013-08-01 10:50:15 -0700684 try :
685 main.topology = main.topology['TOPOLOGY']
686 except(KeyError):
687 print "Error with the Topology file: Either the file not specified or the format is not correct"
688 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700689
adminbae64d82013-08-01 10:50:15 -0700690def load_parser() :
691 '''
692 It facilitates the loading customised parser for topology and params file.
693 It loads parser mentioned in tab named parser of teston.cfg file.
694 It also loads default xmlparser if no parser have specified in teston.cfg file.
695
696 '''
697 confighash = main.configDict
698 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
699 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
700 if os.path.exists(confighash['config']['parser']['file']) :
701 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
702 moduleList = module.split("/")
703 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
704 try :
705 parsingClass = confighash['config']['parser']['class']
706 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
707 parsingClass = getattr(parsingModule, parsingClass)
708 main.parser = parsingClass()
709 #hashobj = main.parser.parseParams(main.classPath)
710 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700711 pass
712 else:
713 main.exit()
adminbae64d82013-08-01 10:50:15 -0700714 except ImportError:
715 print sys.exc_info()[1]
716 main.exit()
717 else :
718 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800719 load_defaultParser()
720 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
721 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700722 else:
723 load_defaultParser()
724
725def load_defaultParser():
726 '''
727 It will load the default parser which is xml parser to parse the params and topology file.
728 '''
729 moduleList = main.parserPath.split("/")
730 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
731 try :
Jon Halld61331b2015-02-17 16:35:47 -0800732 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700733 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
734 parsingClass = getattr(parsingModule, parsingClass)
735 main.parser = parsingClass()
736 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
737 pass
738 else:
739 main.exit()
740
741 except ImportError:
742 print sys.exc_info()[1]
743
adminbae64d82013-08-01 10:50:15 -0700744def load_logger() :
745 '''
746 It facilitates the loading customised parser for topology and params file.
747 It loads parser mentioned in tab named parser of teston.cfg file.
748 It also loads default xmlparser if no parser have specified in teston.cfg file.
749
750 '''
751 confighash = main.configDict
752 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
753 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
754 if os.path.exists(confighash['config']['logger']['file']) :
755 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
756 moduleList = module.split("/")
757 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
758 try :
759 loggerClass = confighash['config']['logger']['class']
760 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
761 loggerClass = getattr(loggerModule, loggerClass)
762 main.logger = loggerClass()
763 #hashobj = main.parser.parseParams(main.classPath)
764
765 except ImportError:
766 print sys.exc_info()[1]
767 else :
768 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
769 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800770 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
771 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700772 else:
773 load_defaultlogger()
774
775def load_defaultlogger():
776 '''
777 It will load the default parser which is xml parser to parse the params and topology file.
778 '''
779 moduleList = main.loggerPath.split("/")
780 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
781 try :
Jon Halld61331b2015-02-17 16:35:47 -0800782 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700783 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
784 loggerClass = getattr(loggerModule, loggerClass)
785 main.logger = loggerClass()
786
787 except ImportError:
788 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800789 main.exit()
adminbae64d82013-08-01 10:50:15 -0700790
791def load_defaultlogger():
792 '''
793 It will load the default parser which is xml parser to parse the params and topology file.
794 '''
795 moduleList = main.loggerPath.split("/")
796 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
797 try :
Jon Halld61331b2015-02-17 16:35:47 -0800798 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700799 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
800 loggerClass = getattr(loggerModule, loggerClass)
801 main.logger = loggerClass()
802
803 except ImportError:
804 print sys.exc_info()[1]
805 main.exit()
806
adminbae64d82013-08-01 10:50:15 -0700807def _echo(self):
808 print "THIS IS ECHO"