blob: a15bb8c762283f543aabf06dcc2049f3320a955a [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)
adminbae64d82013-08-01 10:50:15 -0700282 except TypeError,e:
Jon Hall79bec222015-04-30 16:23:30 -0700283 print "\nException in the following section of code: " +\
284 str(testCaseNumber) + "." + str(step) + ": " +\
285 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 Hall30b82fa2015-03-04 17:15:43 -0800288 self.log.exception(e)
Jon Hall79bec222015-04-30 16:23:30 -0700289 self.logger.updateCaseResults(self)
290 #WIKI results
291 self.log.wiki( "<ul>" )
Jon Hall50157552015-05-04 16:20:03 -0700292 for line in self.stepCache.splitlines():
Jon Hall79bec222015-04-30 16:23:30 -0700293 if re.search( " - PASS$", line ):
294 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
295 elif re.search( " - FAIL$", line ):
296 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
297 elif re.search( " - No Result$", line ):
298 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
299 self.log.wiki( "</ul>" )
300 #summary results
301 self.log.summary( self.stepCache )
302 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700303 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700304 self.exit()
adminbae64d82013-08-01 10:50:15 -0700305 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700306 if cli.stop:
307 cli.stop = False
308 stopped = True
309 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
310 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
311 self.logger.updateCaseResults(self)
312 result = self.cleanup()
313 return main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700314
adminbae64d82013-08-01 10:50:15 -0700315 def addCaseHeader(self):
316 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800317 self.log.exact(caseHeader)
318 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700319 for driver in self.componentDictionary.keys():
320 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700321
adminbae64d82013-08-01 10:50:15 -0700322 def addCaseFooter(self):
323 if self.stepCount-1 > 0 :
324 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
325 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700326
adminbae64d82013-08-01 10:50:15 -0700327 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700328
adminbae64d82013-08-01 10:50:15 -0700329 for driver in self.driversList:
330 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
331
332 def cleanup(self):
333 '''
334 Release all the component handles and the close opened file handles.
335 This will return TRUE if all the component handles and log handles closed properly,
336 else return FALSE
337
338 '''
339 result = self.TRUE
340 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800341
adminbae64d82013-08-01 10:50:15 -0700342 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800343
admin2c7034f2013-08-02 15:09:17 -0700344 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700345 for component in self.componentDictionary.keys():
346 try :
Jon Halld61331b2015-02-17 16:35:47 -0800347 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700348 print "Disconnecting from " + str(tempObject.name) + ": " + \
349 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700350 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800351 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700352
Jon Hall00539b12015-04-03 13:55:46 -0700353 except (Exception):
354 self.log.exception( "Exception while disconnecting from " +
355 str( component ) )
356 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700357 # Closing all the driver's session files
358 for driver in self.componentDictionary.keys():
359 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800360
adminbae64d82013-08-01 10:50:15 -0700361 return result
Jon Halld61331b2015-02-17 16:35:47 -0800362
adminbae64d82013-08-01 10:50:15 -0700363 def pause(self):
364 '''
365 This function will pause the test's execution, and will continue after user provide 'resume' command.
366 '''
367 __builtin__.testthread.pause()
Jon Hall81d3d392015-04-24 14:40:35 -0700368
adminbae64d82013-08-01 10:50:15 -0700369 def onfail(self,*components):
370 '''
Jon Hall81d3d392015-04-24 14:40:35 -0700371 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700372 '''
adminbae64d82013-08-01 10:50:15 -0700373 if not components:
374 try :
375 for component in self.componentDictionary.keys():
376 tempObject = vars(self)[component]
377 result = tempObject.onfail()
378 except(Exception),e:
379 print str(e)
380 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700381 else:
382 try :
383 for component in components:
384 tempObject = vars(self)[component]
385 result = tempObject.onfail()
386 except(Exception),e:
387 print str(e)
388 result = self.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700389
adminbae64d82013-08-01 10:50:15 -0700390 def getDriverPath(self,driverName):
391 '''
392 Based on the component 'type' specified in the params , this method will find the absolute path ,
393 by recursively searching the name of the component.
394 '''
395 import commands
396
397 cmd = "find "+drivers_path+" -name "+driverName+".py"
398 result = commands.getoutput(cmd)
Jon Hall81d3d392015-04-24 14:40:35 -0700399
adminbae64d82013-08-01 10:50:15 -0700400 result_array = str(result).split('\n')
401 result_count = 0
Jon Hall81d3d392015-04-24 14:40:35 -0700402
adminbae64d82013-08-01 10:50:15 -0700403 for drivers_list in result_array:
404 result_count = result_count+1
405 if result_count > 1 :
406 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
407 self.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700408
adminbae64d82013-08-01 10:50:15 -0700409 result = re.sub("(.*)drivers","",result)
410 result = re.sub("\.py","",result)
411 result = re.sub("\.pyc","",result)
412 result = re.sub("\/",".",result)
413 result = "drivers"+result
414 return result
adminbae64d82013-08-01 10:50:15 -0700415
416 def step(self,stepDesc):
417 '''
418 The step information of the test-case will append to the logs.
419 '''
420 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
421 self.stepName = stepDesc
422
423 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
424 try :
425 if self.stepCount == 0:
426 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
427 except AttributeError:
428 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
Jon Hall81d3d392015-04-24 14:40:35 -0700429
adminbae64d82013-08-01 10:50:15 -0700430 self.log.step(stepName)
431 stepHeader = ""
432 if self.stepCount > 1 :
433 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700434
Jon Halld61331b2015-02-17 16:35:47 -0800435 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700436 for driver in self.componentDictionary.keys():
437 vars(self)[driver+'log'].info(stepHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700438
adminbae64d82013-08-01 10:50:15 -0700439 def case(self,testCaseName):
440 '''
441 Test's each test-case information will append to the logs.
442 '''
Jon Halld61331b2015-02-17 16:35:47 -0800443 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700444 testCaseName = " " + str(testCaseName) + ""
445 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800446 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700447 for driver in self.componentDictionary.keys():
448 vars(self)[driver+'log'].info(caseHeader)
Jon Hall81d3d392015-04-24 14:40:35 -0700449
adminbae64d82013-08-01 10:50:15 -0700450 def testDesc(self,description):
451 '''
452 Test description will append to the logs.
453 '''
454 description = "Test Description : " + str (description) + ""
455 self.log.info(description)
Jon Hall81d3d392015-04-24 14:40:35 -0700456
adminbae64d82013-08-01 10:50:15 -0700457 def _getTest(self):
458 '''
459 This method will parse the test script to find required test information.
460 '''
461 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
462 testFileHandler = open(testFile, 'r')
463 testFileList = testFileHandler.readlines()
464 testFileHandler.close()
465 #self.TOTAL_TC_PLANNED = 0
466 counter = 0
467 for index in range(len(testFileList)):
468 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
469 if lineMatch:
470 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700471 self.TC_PLANNED = len(self.testcases_list)
Jon Hall81d3d392015-04-24 14:40:35 -0700472
adminbae64d82013-08-01 10:50:15 -0700473 def response_parser(self,response, return_format):
474 ''' It will load the default response parser '''
475 response_dict = {}
476 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800477 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700478 return return_format_string
Jon Hall81d3d392015-04-24 14:40:35 -0700479
adminbae64d82013-08-01 10:50:15 -0700480 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700481 response_dict = {}
482 json_match = re.search('^\s*{', response)
483 xml_match = re.search('^\s*\<', response)
484 ini_match = re.search('^\s*\[', response)
485 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800486 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800487 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700488 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
489 response = re.sub(r",\s*'?(\w)", r',"\1', response)
490 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
491 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700492 try :
493 import json
494 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800495 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800496 self.log.exception( e )
497 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700498 return response_dict
adminbae64d82013-08-01 10:50:15 -0700499 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800500 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700501 from configobj import ConfigObj
502 response_file = open("respnse_file.temp",'w')
503 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800504 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700505 response_dict = ConfigObj("respnse_file.temp")
506 return response_dict
adminbae64d82013-08-01 10:50:15 -0700507 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800508 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700509 try :
adminbae64d82013-08-01 10:50:15 -0700510 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
511 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800512 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700513 return response_dict
Jon Hall81d3d392015-04-24 14:40:35 -0700514
adminbae64d82013-08-01 10:50:15 -0700515 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700516 if return_format =='table' :
517 ''' Will return in table format'''
518 to_do = "Call the table output formatter"
519 global response_table
520 response_table = '\n'
521 response_table = response_table +'\t'.join(response_dict)+"\n"
Jon Hall81d3d392015-04-24 14:40:35 -0700522
adminbae64d82013-08-01 10:50:15 -0700523 def get_table(value_to_convert):
524 ''' This will parse the dictionary recusrsively and print as table format'''
525 table_data = ""
526 if type(value_to_convert) == dict :
527 table_data = table_data +'\t'.join(value_to_convert)+"\n"
528 for temp_val in value_to_convert.values() :
529 table_data = table_data + get_table(temp_val)
530 else :
531 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800532 return table_data
Jon Hall81d3d392015-04-24 14:40:35 -0700533
adminbae64d82013-08-01 10:50:15 -0700534 for value in response_dict.values() :
535 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800536 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700537 return response_table
Jon Hall81d3d392015-04-24 14:40:35 -0700538
adminbae64d82013-08-01 10:50:15 -0700539 elif return_format =='config':
540 ''' Will return in config format'''
541 to_do = 'Call dict to config coverter'
542 response_string = str(response_dict)
543 print response_string
544 response_config = re.sub(",", "\n\t", response_string)
545 response_config = re.sub("u\'", "\'", response_config)
546 response_config = re.sub("{", "", response_config)
547 response_config = re.sub("}", "\n", response_config)
548 response_config = re.sub(":", " =", response_config)
549 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700550 elif return_format == 'xml':
551 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700552 response_xml = xmldict.dict_to_xml(response_dict)
553 response_xml = re.sub(">\s*<", ">\n<", response_xml)
554 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700555 elif return_format == 'json':
556 ''' Will return in json format'''
557 to_do = 'Call dict to xml coverter'
558 import json
559 response_json = json.dumps(response_dict)
560 return response_json
Jon Hall81d3d392015-04-24 14:40:35 -0700561
adminbae64d82013-08-01 10:50:15 -0700562 def get_random(self):
563 self.random_order = self.random_order + 1
564 return self.random_order
Jon Hall81d3d392015-04-24 14:40:35 -0700565
adminbae64d82013-08-01 10:50:15 -0700566 def exit(self):
567 __builtin__.testthread = None
568 sys.exit()
569
570def verifyOptions(options):
571 '''
572 This will verify the command line options and set to default values, if any option not given in command line.
573 '''
574 import pprint
575 pp = pprint.PrettyPrinter(indent=4)
576
Jon Hall88e498c2015-03-06 09:54:35 -0800577 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700578 verifyTest(options)
579 verifyExample(options)
580 verifyTestScript(options)
581 verifyParams()
582 verifyLogdir(options)
583 verifyMail(options)
584 verifyTestCases(options)
585
586def verifyTest(options):
587 if options.testname:
588 main.TEST = options.testname
589 main.classPath = "tests."+main.TEST+"."+main.TEST
590 main.tests_path = tests_path
591 elif options.example :
592 main.TEST = options.example
593 main.tests_path = path+"/examples/"
594 main.classPath = "examples."+main.TEST+"."+main.TEST
595 else :
596 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
597 self.exit()
598
599def verifyExample(options):
600 if options.example:
601 main.testDir = path+'/examples/'
602 main.tests_path = path+"/examples/"
603 main.classPath = "examples."+main.TEST+"."+main.TEST
Jon Hall81d3d392015-04-24 14:40:35 -0700604
adminbae64d82013-08-01 10:50:15 -0700605def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800606 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700607 if options.logdir:
608 main.logdir = options.logdir
609 else :
Jon Halld61331b2015-02-17 16:35:47 -0800610 main.logdir = main.FALSE
Jon Hall81d3d392015-04-24 14:40:35 -0700611
adminbae64d82013-08-01 10:50:15 -0700612def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800613 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700614 if options.mail:
615 main.mail = options.mail
616 elif main.params.has_key('mail'):
617 main.mail = main.params['mail']
618 else :
619 main.mail = 'paxweb@paxterrasolutions.com'
620
621def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800622 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700623 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800624 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800625 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700626 testcases_list = re.sub("(\[|\])", "", options.testcases)
627 main.testcases_list = eval(testcases_list+",")
628 else :
629 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700630 temp = eval(main.params['testcases']+",")
631 list1=[]
632 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800633 for test in temp:
634 for testcase in test:
635 if type(testcase)==int:
636 testcase=[testcase]
637 list1.extend(testcase)
638 else :
639 temp=list(temp)
640 for testcase in temp:
641 if type(testcase)==int:
642 testcase=[testcase]
643 list1.extend(testcase)
644 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700645 else :
646 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800647 sys.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700648
adminbae64d82013-08-01 10:50:15 -0700649def verifyTestScript(options):
650 '''
651 Verifyies test script.
652 '''
Jon Halld61331b2015-02-17 16:35:47 -0800653 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700654 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
655 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
656 if os.path.exists(openspeakfile) :
657 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
658 elif os.path.exists(testfile):
659 print ''
660 else:
661 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
662 __builtin__.testthread = None
663 main.exit()
adminbae64d82013-08-01 10:50:15 -0700664 try :
adminbae64d82013-08-01 10:50:15 -0700665 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
666 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500667 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800668 main.exit()
adminbae64d82013-08-01 10:50:15 -0700669
670 testClass = getattr(testModule, main.TEST)
671 main.testObject = testClass()
672 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800673 main.params = main.parser.parseParams(main.classPath)
674 main.topology = main.parser.parseTopology(main.classPath)
Jon Hall81d3d392015-04-24 14:40:35 -0700675
adminbae64d82013-08-01 10:50:15 -0700676def verifyParams():
677 try :
678 main.params = main.params['PARAMS']
679 except(KeyError):
680 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800681 main.exit()
adminbae64d82013-08-01 10:50:15 -0700682 try :
683 main.topology = main.topology['TOPOLOGY']
684 except(KeyError):
685 print "Error with the Topology file: Either the file not specified or the format is not correct"
686 main.exit()
Jon Hall81d3d392015-04-24 14:40:35 -0700687
adminbae64d82013-08-01 10:50:15 -0700688def load_parser() :
689 '''
690 It facilitates the loading customised parser for topology and params file.
691 It loads parser mentioned in tab named parser of teston.cfg file.
692 It also loads default xmlparser if no parser have specified in teston.cfg file.
693
694 '''
695 confighash = main.configDict
696 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
697 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
698 if os.path.exists(confighash['config']['parser']['file']) :
699 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
700 moduleList = module.split("/")
701 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
702 try :
703 parsingClass = confighash['config']['parser']['class']
704 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
705 parsingClass = getattr(parsingModule, parsingClass)
706 main.parser = parsingClass()
707 #hashobj = main.parser.parseParams(main.classPath)
708 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700709 pass
710 else:
711 main.exit()
adminbae64d82013-08-01 10:50:15 -0700712 except ImportError:
713 print sys.exc_info()[1]
714 main.exit()
715 else :
716 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800717 load_defaultParser()
718 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
719 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700720 else:
721 load_defaultParser()
722
723def load_defaultParser():
724 '''
725 It will load the default parser which is xml parser to parse the params and topology file.
726 '''
727 moduleList = main.parserPath.split("/")
728 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
729 try :
Jon Halld61331b2015-02-17 16:35:47 -0800730 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700731 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
732 parsingClass = getattr(parsingModule, parsingClass)
733 main.parser = parsingClass()
734 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
735 pass
736 else:
737 main.exit()
738
739 except ImportError:
740 print sys.exc_info()[1]
741
adminbae64d82013-08-01 10:50:15 -0700742def load_logger() :
743 '''
744 It facilitates the loading customised parser for topology and params file.
745 It loads parser mentioned in tab named parser of teston.cfg file.
746 It also loads default xmlparser if no parser have specified in teston.cfg file.
747
748 '''
749 confighash = main.configDict
750 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
751 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
752 if os.path.exists(confighash['config']['logger']['file']) :
753 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
754 moduleList = module.split("/")
755 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
756 try :
757 loggerClass = confighash['config']['logger']['class']
758 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
759 loggerClass = getattr(loggerModule, loggerClass)
760 main.logger = loggerClass()
761 #hashobj = main.parser.parseParams(main.classPath)
762
763 except ImportError:
764 print sys.exc_info()[1]
765 else :
766 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
767 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800768 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
769 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700770 else:
771 load_defaultlogger()
772
773def load_defaultlogger():
774 '''
775 It will load the default parser which is xml parser to parse the params and topology file.
776 '''
777 moduleList = main.loggerPath.split("/")
778 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
779 try :
Jon Halld61331b2015-02-17 16:35:47 -0800780 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700781 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
782 loggerClass = getattr(loggerModule, loggerClass)
783 main.logger = loggerClass()
784
785 except ImportError:
786 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800787 main.exit()
adminbae64d82013-08-01 10:50:15 -0700788
789def load_defaultlogger():
790 '''
791 It will load the default parser which is xml parser to parse the params and topology file.
792 '''
793 moduleList = main.loggerPath.split("/")
794 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
795 try :
Jon Halld61331b2015-02-17 16:35:47 -0800796 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700797 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
798 loggerClass = getattr(loggerModule, loggerClass)
799 main.logger = loggerClass()
800
801 except ImportError:
802 print sys.exc_info()[1]
803 main.exit()
804
adminbae64d82013-08-01 10:50:15 -0700805def _echo(self):
806 print "THIS IS ECHO"