blob: ba4e74f79678cc9f8a3af77d02723065ed10b66c [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
cameron@onlab.us5cc6a372015-05-11 17:18:07 -070035import os
adminbae64d82013-08-01 10:50:15 -070036module = new.module("test")
37import openspeak
38global path, drivers_path, core_path, tests_path,logs_path
39path = re.sub("(core|bin)$", "", os.getcwd())
40drivers_path = path+"drivers/"
41core_path = path+"core"
42tests_path = path+"tests"
43logs_path = path+"logs/"
44config_path = path + "config/"
45sys.path.append(path)
46sys.path.append( drivers_path)
47sys.path.append(core_path )
48sys.path.append(tests_path)
49
50from core.utilities import Utilities
kelvin-onlabfb521662015-02-27 09:52:40 -080051from core.Thread import Thread
adminbae64d82013-08-01 10:50:15 -070052
adminbae64d82013-08-01 10:50:15 -070053
54class TestON:
55 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -070056 TestON will initiate the specified test.
57 The main tasks are :
58 * Initiate the required Component handles for the test.
adminbae64d82013-08-01 10:50:15 -070059 * Create Log file Handles.
adminbae64d82013-08-01 10:50:15 -070060 '''
61 def __init__(self,options):
62 '''
63 Initialise the component handles specified in the topology file of the specified test.
adminbae64d82013-08-01 10:50:15 -070064 '''
65 # Initialization of the variables.
66 __builtin__.main = self
adminbae64d82013-08-01 10:50:15 -070067 __builtin__.path = path
68 __builtin__.utilities = Utilities()
69 self.TRUE = 1
70 self.FALSE = 0
71 self.ERROR = -1
kelvin-onlabf70fd542015-05-07 18:41:40 -070072 self.NORESULT = 2
adminbae64d82013-08-01 10:50:15 -070073 self.FAIL = False
74 self.PASS = True
kelvin-onlabf70fd542015-05-07 18:41:40 -070075 self.CASERESULT = self.ERROR
76 self.STEPRESULT = self.NORESULT
77 self.stepResults = []
adminbae64d82013-08-01 10:50:15 -070078 self.init_result = self.TRUE
79 self.testResult = "Summary"
kelvin-onlabf70fd542015-05-07 18:41:40 -070080 self.stepName = ""
81 self.stepCache = ""
Jon Halld61331b2015-02-17 16:35:47 -080082 self.EXPERIMENTAL_MODE = False
adminbae64d82013-08-01 10:50:15 -070083 self.test_target = None
84 self.lastcommand = None
Jon Halld61331b2015-02-17 16:35:47 -080085 self.testDir = tests_path
86 self.configFile = config_path + "teston.cfg"
adminbae64d82013-08-01 10:50:15 -070087 self.parsingClass = "xmlparser"
88 self.parserPath = core_path + "/xmlparser"
89 self.loggerPath = core_path + "/logger"
90 self.loggerClass = "Logger"
91 self.logs_path = logs_path
92 self.driver = ''
kelvin-onlabfb521662015-02-27 09:52:40 -080093 self.Thread = Thread
Jon Hall65844a32015-03-09 19:09:37 -070094
adminbae64d82013-08-01 10:50:15 -070095 self.configparser()
96 verifyOptions(options)
97 load_logger()
98 self.componentDictionary = {}
99 self.componentDictionary = self.topology ['COMPONENT']
100 self.driversList=[]
101 if type(self.componentDictionary) == str :
102 self.componentDictionary = dict(self.componentDictionary)
Jon Hall65844a32015-03-09 19:09:37 -0700103
adminbae64d82013-08-01 10:50:15 -0700104 for component in self.componentDictionary :
105 self.driversList.append(self.componentDictionary[component]['type'])
Jon Hall65844a32015-03-09 19:09:37 -0700106
adminbae64d82013-08-01 10:50:15 -0700107 self.driversList = list(set(self.driversList)) # Removing duplicates.
108 # Checking the test_target option set for the component or not
109 if type(self.componentDictionary) == dict:
110 for component in self.componentDictionary.keys():
111 if 'test_target' in self.componentDictionary[component].keys():
112 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700113
Jon Halld61331b2015-02-17 16:35:47 -0800114 # Checking for the openspeak file and test script
adminbae64d82013-08-01 10:50:15 -0700115 self.logger.initlog(self)
116
117 # Creating Drivers Handles
118 initString = "\n"+"*" * 30+"\n CASE INIT \n"+"*" * 30+"\n"
119 self.log.exact(initString)
120 self.driverObject = {}
121 self.random_order = 111 # Random order id to connect the components
122 components_connect_order = {}
123 #component_list.append()
124 if type(self.componentDictionary) == dict:
125 for component in self.componentDictionary.keys():
126 self.componentDictionary[component]['connect_order'] = self.componentDictionary[component]['connect_order'] if ('connect_order' in self.componentDictionary[component].keys()) else str(self.get_random())
127 components_connect_order[component] = eval(self.componentDictionary[component]['connect_order'])
128 #Ordering components based on the connect order.
129 ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
130 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700131 for component in ordered_component_list:
132 self.componentInit(component)
133
134 def configparser(self):
135 '''
136 It will parse the config file (teston.cfg) and return as dictionary
137 '''
138 matchFileName = re.match(r'(.*)\.cfg', self.configFile, re.M | re.I)
139 if matchFileName:
140 xml = open(self.configFile).read()
141 try :
142 self.configDict = xmldict.xml_to_dict(xml)
143 return self.configDict
Jon Hallfebb1c72015-03-05 13:30:09 -0800144 except Exception:
adminbae64d82013-08-01 10:50:15 -0700145 print "There is no such file to parse " + self.configFile
kelvin-onlabf70fd542015-05-07 18:41:40 -0700146
adminbae64d82013-08-01 10:50:15 -0700147 def componentInit(self,component):
148 '''
149 This method will initialize specified component
150 '''
151 global driver_options
152 self.log.info("Creating component Handle: "+component)
Jon Halld61331b2015-02-17 16:35:47 -0800153 driver_options = {}
adminbae64d82013-08-01 10:50:15 -0700154 if 'COMPONENTS' in self.componentDictionary[component].keys():
155 driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
156
157 driver_options['name']=component
158 driverName = self.componentDictionary[component]['type']
159 driver_options ['type'] = driverName
kelvin-onlabf70fd542015-05-07 18:41:40 -0700160
adminbae64d82013-08-01 10:50:15 -0700161 classPath = self.getDriverPath(driverName.lower())
Jon Hall30b82fa2015-03-04 17:15:43 -0800162 driverModule = importlib.import_module(classPath)
adminbae64d82013-08-01 10:50:15 -0700163 driverClass = getattr(driverModule, driverName)
164 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700165
kelvin-onlab0a28a742015-05-18 16:03:13 -0700166 try:
167 self.componentDictionary[component]['host'] = os.environ[str( self.componentDictionary[component]['host'])]
168 except KeyError:
169 self.log.info("Missing OC environment variable! Using stored IPs")
170 except Exception as inst:
171 self.log.error("Uncaught exception: " + str(inst))
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700172
adminbae64d82013-08-01 10:50:15 -0700173 connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
174 ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
175 pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
176 port = self.componentDictionary[component]['port'] if ('port' in self.componentDictionary[component].keys()) else None,
177 options = driver_options)
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700178
adminbae64d82013-08-01 10:50:15 -0700179 if not connect_result:
180 self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
Jon Halld61331b2015-02-17 16:35:47 -0800181 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700182
adminbae64d82013-08-01 10:50:15 -0700183 vars(self)[component] = driverObject
kelvin-onlabf70fd542015-05-07 18:41:40 -0700184
adminbae64d82013-08-01 10:50:15 -0700185 def run(self):
186 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700187 The Execution of the test script's cases listed in the Test params file will be done here.
188 And Update each test case result.
189 This method will return TRUE if it executed all the test cases successfully,
adminbae64d82013-08-01 10:50:15 -0700190 else will retun FALSE
191 '''
adminbae64d82013-08-01 10:50:15 -0700192 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700193 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700194 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800195 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700196 self.TOTAL_TC_NORESULT = 0
197 self.TOTAL_TC_FAIL = 0
198 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700199 self.TEST_ITERATION = 0
adminbae64d82013-08-01 10:50:15 -0700200 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700201 self.CASERESULT = self.NORESULT
202
Jon Halld61331b2015-02-17 16:35:47 -0800203 import testparser
adminbae64d82013-08-01 10:50:15 -0700204 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
205 test = testparser.TestParser(testFile)
206 self.testscript = test.testscript
207 self.code = test.getStepCode()
Jon Hallfebb1c72015-03-05 13:30:09 -0800208 repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
209 self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700210
adminbae64d82013-08-01 10:50:15 -0700211 result = self.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800212 while(repeat):
Jon Halla1185982014-09-15 14:55:10 -0700213 for self.CurrentTestCaseNumber in self.testcases_list:
Jon Halld61331b2015-02-17 16:35:47 -0800214 result = self.runCase(self.CurrentTestCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800215 repeat-=1
adminbae64d82013-08-01 10:50:15 -0700216 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700217
adminbae64d82013-08-01 10:50:15 -0700218 def runCase(self,testCaseNumber):
219 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700220 self.CurrentTestCase = ""
221 self.stepResults = []
222 self.stepName = ""
223 self.caseExplaination = ""
adminbae64d82013-08-01 10:50:15 -0700224 result = self.TRUE
225 self.stepCount = 0
226 self.EXPERIMENTAL_MODE = self.FALSE
227 self.addCaseHeader()
228 self.testCaseNumber = str(testCaseNumber)
229 stopped = False
230 try :
231 self.stepList = self.code[self.testCaseNumber].keys()
Jon Halld61331b2015-02-17 16:35:47 -0800232 except KeyError:
Jon Hallfebb1c72015-03-05 13:30:09 -0800233 self.log.error("There is no Test-Case "+ self.testCaseNumber)
234 return self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700235
adminbae64d82013-08-01 10:50:15 -0700236 self.stepCount = 0
237 while self.stepCount < len(self.code[self.testCaseNumber].keys()):
238 result = self.runStep(self.stepList,self.code,self.testCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800239 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700240 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800241 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700242 continue
adminbae64d82013-08-01 10:50:15 -0700243 if not stopped :
kelvin-onlabf70fd542015-05-07 18:41:40 -0700244 if all( self.TRUE == i for i in self.stepResults ):
245 # ALL PASSED
246 self.CASERESULT = self.TRUE
247 elif self.FALSE in self.stepResults:
248 # AT LEAST ONE FAILED
249 self.CASERESULT = self.FALSE
250 elif self.TRUE in self.stepResults:
251 # AT LEAST ONE PASSED
252 self.CASERESULT = self.TRUE
253 else:
254 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700255 self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
256 self.logger.updateCaseResults(self)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700257 self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
258 self.log.summary( self.caseExplaination )
259 self.log.wiki( "<ul>" )
260 for line in self.stepCache.splitlines():
261 if re.search( " - PASS$", line ):
262 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
263 elif re.search( " - FAIL$", line ):
264 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
265 elif re.search( " - No Result$", line ):
266 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
267 self.log.wiki( "</ul>" )
268 self.log.summary( self.stepCache )
269 self.stepCache = ""
adminbae64d82013-08-01 10:50:15 -0700270 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700271
adminbae64d82013-08-01 10:50:15 -0700272 def runStep(self,stepList,code,testCaseNumber):
273 if not cli.pause:
274 try :
275 step = stepList[self.stepCount]
kelvin-onlabf70fd542015-05-07 18:41:40 -0700276 self.STEPRESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700277 exec code[testCaseNumber][step] in module.__dict__
278 self.stepCount = self.stepCount + 1
kelvin-onlabf70fd542015-05-07 18:41:40 -0700279 if step > 0:
280 self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
281 if self.STEPRESULT == self.TRUE:
282 self.stepCache += "PASS\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700283 elif self.STEPRESULT == self.FALSE:
284 self.stepCache += "FAIL\n"
Jon Hall8ce34e82015-06-05 10:41:45 -0700285 # TODO: Print the on-fail statement here
kelvin-onlabf70fd542015-05-07 18:41:40 -0700286 else:
287 self.stepCache += "No Result\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700288 self.stepResults.append(self.STEPRESULT)
Jon Hall40d2cbd2015-06-03 16:24:29 -0700289 except StandardError as e:
290 self.log.exception( "\nException in the following section of" +
291 " code: " + str(testCaseNumber) + "." +
292 str(step) + ": " + self.stepName )
Jon Hall63604932015-02-26 17:09:50 -0800293 #print code[testCaseNumber][step]
adminbae64d82013-08-01 10:50:15 -0700294 self.stepCount = self.stepCount + 1
kelvin-onlabf70fd542015-05-07 18:41:40 -0700295 self.logger.updateCaseResults(self)
296 #WIKI results
297 self.log.wiki( "<ul>" )
298 for line in self.stepCache.splitlines():
299 if re.search( " - PASS$", line ):
300 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
301 elif re.search( " - FAIL$", line ):
302 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
303 elif re.search( " - No Result$", line ):
304 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
305 self.log.wiki( "</ul>" )
306 #summary results
307 self.log.summary( self.stepCache )
308 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700309 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700310 self.exit()
adminbae64d82013-08-01 10:50:15 -0700311 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700312 if cli.stop:
313 cli.stop = False
314 stopped = True
315 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
316 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
317 self.logger.updateCaseResults(self)
318 result = self.cleanup()
319 return main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700320
adminbae64d82013-08-01 10:50:15 -0700321 def addCaseHeader(self):
322 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800323 self.log.exact(caseHeader)
324 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700325 for driver in self.componentDictionary.keys():
326 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700327
adminbae64d82013-08-01 10:50:15 -0700328 def addCaseFooter(self):
329 if self.stepCount-1 > 0 :
330 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
331 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700332
adminbae64d82013-08-01 10:50:15 -0700333 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700334
adminbae64d82013-08-01 10:50:15 -0700335 for driver in self.driversList:
336 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
337
338 def cleanup(self):
339 '''
340 Release all the component handles and the close opened file handles.
341 This will return TRUE if all the component handles and log handles closed properly,
342 else return FALSE
343
344 '''
345 result = self.TRUE
346 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800347
adminbae64d82013-08-01 10:50:15 -0700348 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800349
admin2c7034f2013-08-02 15:09:17 -0700350 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700351 for component in self.componentDictionary.keys():
352 try :
Jon Halld61331b2015-02-17 16:35:47 -0800353 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700354 print "Disconnecting from " + str(tempObject.name) + ": " + \
355 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700356 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800357 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700358
Jon Hall00539b12015-04-03 13:55:46 -0700359 except (Exception):
360 self.log.exception( "Exception while disconnecting from " +
361 str( component ) )
362 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700363 # Closing all the driver's session files
364 for driver in self.componentDictionary.keys():
365 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800366
adminbae64d82013-08-01 10:50:15 -0700367 return result
Jon Halld61331b2015-02-17 16:35:47 -0800368
adminbae64d82013-08-01 10:50:15 -0700369 def pause(self):
370 '''
371 This function will pause the test's execution, and will continue after user provide 'resume' command.
372 '''
373 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700374
adminbae64d82013-08-01 10:50:15 -0700375 def onfail(self,*components):
376 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700377 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700378 '''
adminbae64d82013-08-01 10:50:15 -0700379 if not components:
380 try :
381 for component in self.componentDictionary.keys():
382 tempObject = vars(self)[component]
383 result = tempObject.onfail()
384 except(Exception),e:
385 print str(e)
386 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700387 else:
388 try :
389 for component in components:
390 tempObject = vars(self)[component]
391 result = tempObject.onfail()
392 except(Exception),e:
393 print str(e)
394 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700395
adminbae64d82013-08-01 10:50:15 -0700396 def getDriverPath(self,driverName):
397 '''
398 Based on the component 'type' specified in the params , this method will find the absolute path ,
399 by recursively searching the name of the component.
400 '''
401 import commands
402
403 cmd = "find "+drivers_path+" -name "+driverName+".py"
404 result = commands.getoutput(cmd)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700405
adminbae64d82013-08-01 10:50:15 -0700406 result_array = str(result).split('\n')
407 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700408
adminbae64d82013-08-01 10:50:15 -0700409 for drivers_list in result_array:
410 result_count = result_count+1
411 if result_count > 1 :
412 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
413 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700414
adminbae64d82013-08-01 10:50:15 -0700415 result = re.sub("(.*)drivers","",result)
416 result = re.sub("\.py","",result)
417 result = re.sub("\.pyc","",result)
418 result = re.sub("\/",".",result)
419 result = "drivers"+result
420 return result
adminbae64d82013-08-01 10:50:15 -0700421
422 def step(self,stepDesc):
423 '''
424 The step information of the test-case will append to the logs.
425 '''
426 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
427 self.stepName = stepDesc
428
429 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
430 try :
431 if self.stepCount == 0:
432 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
433 except AttributeError:
434 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700435
adminbae64d82013-08-01 10:50:15 -0700436 self.log.step(stepName)
437 stepHeader = ""
438 if self.stepCount > 1 :
439 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700440
Jon Halld61331b2015-02-17 16:35:47 -0800441 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700442 for driver in self.componentDictionary.keys():
443 vars(self)[driver+'log'].info(stepHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700444
adminbae64d82013-08-01 10:50:15 -0700445 def case(self,testCaseName):
446 '''
447 Test's each test-case information will append to the logs.
448 '''
Jon Halld61331b2015-02-17 16:35:47 -0800449 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700450 testCaseName = " " + str(testCaseName) + ""
451 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800452 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700453 for driver in self.componentDictionary.keys():
454 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700455
adminbae64d82013-08-01 10:50:15 -0700456 def testDesc(self,description):
457 '''
458 Test description will append to the logs.
459 '''
460 description = "Test Description : " + str (description) + ""
461 self.log.info(description)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700462
adminbae64d82013-08-01 10:50:15 -0700463 def _getTest(self):
464 '''
465 This method will parse the test script to find required test information.
466 '''
467 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
468 testFileHandler = open(testFile, 'r')
469 testFileList = testFileHandler.readlines()
470 testFileHandler.close()
471 #self.TOTAL_TC_PLANNED = 0
472 counter = 0
473 for index in range(len(testFileList)):
474 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
475 if lineMatch:
476 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700477 self.TC_PLANNED = len(self.testcases_list)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700478
adminbae64d82013-08-01 10:50:15 -0700479 def response_parser(self,response, return_format):
480 ''' It will load the default response parser '''
481 response_dict = {}
482 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800483 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700484 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700485
adminbae64d82013-08-01 10:50:15 -0700486 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700487 response_dict = {}
488 json_match = re.search('^\s*{', response)
489 xml_match = re.search('^\s*\<', response)
490 ini_match = re.search('^\s*\[', response)
491 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800492 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800493 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700494 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
495 response = re.sub(r",\s*'?(\w)", r',"\1', response)
496 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
497 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700498 try :
499 import json
500 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800501 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800502 self.log.exception( e )
503 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700504 return response_dict
adminbae64d82013-08-01 10:50:15 -0700505 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800506 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700507 from configobj import ConfigObj
508 response_file = open("respnse_file.temp",'w')
509 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800510 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700511 response_dict = ConfigObj("respnse_file.temp")
512 return response_dict
adminbae64d82013-08-01 10:50:15 -0700513 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800514 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700515 try :
adminbae64d82013-08-01 10:50:15 -0700516 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
517 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800518 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700519 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700520
adminbae64d82013-08-01 10:50:15 -0700521 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700522 if return_format =='table' :
523 ''' Will return in table format'''
524 to_do = "Call the table output formatter"
525 global response_table
526 response_table = '\n'
527 response_table = response_table +'\t'.join(response_dict)+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700528
adminbae64d82013-08-01 10:50:15 -0700529 def get_table(value_to_convert):
530 ''' This will parse the dictionary recusrsively and print as table format'''
531 table_data = ""
532 if type(value_to_convert) == dict :
533 table_data = table_data +'\t'.join(value_to_convert)+"\n"
534 for temp_val in value_to_convert.values() :
535 table_data = table_data + get_table(temp_val)
536 else :
537 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800538 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700539
adminbae64d82013-08-01 10:50:15 -0700540 for value in response_dict.values() :
541 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800542 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700543 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700544
adminbae64d82013-08-01 10:50:15 -0700545 elif return_format =='config':
546 ''' Will return in config format'''
547 to_do = 'Call dict to config coverter'
548 response_string = str(response_dict)
549 print response_string
550 response_config = re.sub(",", "\n\t", response_string)
551 response_config = re.sub("u\'", "\'", response_config)
552 response_config = re.sub("{", "", response_config)
553 response_config = re.sub("}", "\n", response_config)
554 response_config = re.sub(":", " =", response_config)
555 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700556 elif return_format == 'xml':
557 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700558 response_xml = xmldict.dict_to_xml(response_dict)
559 response_xml = re.sub(">\s*<", ">\n<", response_xml)
560 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700561 elif return_format == 'json':
562 ''' Will return in json format'''
563 to_do = 'Call dict to xml coverter'
564 import json
565 response_json = json.dumps(response_dict)
566 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700567
adminbae64d82013-08-01 10:50:15 -0700568 def get_random(self):
569 self.random_order = self.random_order + 1
570 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700571
adminbae64d82013-08-01 10:50:15 -0700572 def exit(self):
573 __builtin__.testthread = None
574 sys.exit()
575
576def verifyOptions(options):
577 '''
578 This will verify the command line options and set to default values, if any option not given in command line.
579 '''
580 import pprint
581 pp = pprint.PrettyPrinter(indent=4)
582
Jon Hall88e498c2015-03-06 09:54:35 -0800583 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700584 verifyTest(options)
585 verifyExample(options)
586 verifyTestScript(options)
587 verifyParams()
588 verifyLogdir(options)
589 verifyMail(options)
590 verifyTestCases(options)
591
592def verifyTest(options):
593 if options.testname:
594 main.TEST = options.testname
595 main.classPath = "tests."+main.TEST+"."+main.TEST
596 main.tests_path = tests_path
597 elif options.example :
598 main.TEST = options.example
599 main.tests_path = path+"/examples/"
600 main.classPath = "examples."+main.TEST+"."+main.TEST
601 else :
602 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
603 self.exit()
604
605def verifyExample(options):
606 if options.example:
607 main.testDir = path+'/examples/'
608 main.tests_path = path+"/examples/"
609 main.classPath = "examples."+main.TEST+"."+main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700610
adminbae64d82013-08-01 10:50:15 -0700611def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800612 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700613 if options.logdir:
614 main.logdir = options.logdir
615 else :
Jon Halld61331b2015-02-17 16:35:47 -0800616 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700617
adminbae64d82013-08-01 10:50:15 -0700618def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800619 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700620 if options.mail:
621 main.mail = options.mail
622 elif main.params.has_key('mail'):
623 main.mail = main.params['mail']
624 else :
625 main.mail = 'paxweb@paxterrasolutions.com'
626
627def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800628 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700629 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800630 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800631 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700632 testcases_list = re.sub("(\[|\])", "", options.testcases)
633 main.testcases_list = eval(testcases_list+",")
634 else :
635 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700636 temp = eval(main.params['testcases']+",")
637 list1=[]
638 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800639 for test in temp:
640 for testcase in test:
641 if type(testcase)==int:
642 testcase=[testcase]
643 list1.extend(testcase)
644 else :
645 temp=list(temp)
646 for testcase in temp:
647 if type(testcase)==int:
648 testcase=[testcase]
649 list1.extend(testcase)
650 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700651 else :
652 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800653 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700654
adminbae64d82013-08-01 10:50:15 -0700655def verifyTestScript(options):
656 '''
657 Verifyies test script.
658 '''
Jon Halld61331b2015-02-17 16:35:47 -0800659 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700660 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
661 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
662 if os.path.exists(openspeakfile) :
663 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
664 elif os.path.exists(testfile):
665 print ''
666 else:
667 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
668 __builtin__.testthread = None
669 main.exit()
adminbae64d82013-08-01 10:50:15 -0700670 try :
adminbae64d82013-08-01 10:50:15 -0700671 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
672 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500673 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800674 main.exit()
adminbae64d82013-08-01 10:50:15 -0700675
676 testClass = getattr(testModule, main.TEST)
677 main.testObject = testClass()
678 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800679 main.params = main.parser.parseParams(main.classPath)
680 main.topology = main.parser.parseTopology(main.classPath)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700681
adminbae64d82013-08-01 10:50:15 -0700682def verifyParams():
683 try :
684 main.params = main.params['PARAMS']
685 except(KeyError):
686 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800687 main.exit()
adminbae64d82013-08-01 10:50:15 -0700688 try :
689 main.topology = main.topology['TOPOLOGY']
690 except(KeyError):
691 print "Error with the Topology file: Either the file not specified or the format is not correct"
692 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700693
adminbae64d82013-08-01 10:50:15 -0700694def load_parser() :
695 '''
696 It facilitates the loading customised parser for topology and params file.
697 It loads parser mentioned in tab named parser of teston.cfg file.
698 It also loads default xmlparser if no parser have specified in teston.cfg file.
699
700 '''
701 confighash = main.configDict
702 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
703 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
704 if os.path.exists(confighash['config']['parser']['file']) :
705 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
706 moduleList = module.split("/")
707 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
708 try :
709 parsingClass = confighash['config']['parser']['class']
710 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
711 parsingClass = getattr(parsingModule, parsingClass)
712 main.parser = parsingClass()
713 #hashobj = main.parser.parseParams(main.classPath)
714 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700715 pass
716 else:
717 main.exit()
adminbae64d82013-08-01 10:50:15 -0700718 except ImportError:
719 print sys.exc_info()[1]
720 main.exit()
721 else :
722 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800723 load_defaultParser()
724 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
725 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700726 else:
727 load_defaultParser()
728
729def load_defaultParser():
730 '''
731 It will load the default parser which is xml parser to parse the params and topology file.
732 '''
733 moduleList = main.parserPath.split("/")
734 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
735 try :
Jon Halld61331b2015-02-17 16:35:47 -0800736 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700737 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
738 parsingClass = getattr(parsingModule, parsingClass)
739 main.parser = parsingClass()
740 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
741 pass
742 else:
743 main.exit()
744
745 except ImportError:
746 print sys.exc_info()[1]
747
adminbae64d82013-08-01 10:50:15 -0700748def load_logger() :
749 '''
750 It facilitates the loading customised parser for topology and params file.
751 It loads parser mentioned in tab named parser of teston.cfg file.
752 It also loads default xmlparser if no parser have specified in teston.cfg file.
753
754 '''
755 confighash = main.configDict
756 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
757 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
758 if os.path.exists(confighash['config']['logger']['file']) :
759 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
760 moduleList = module.split("/")
761 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
762 try :
763 loggerClass = confighash['config']['logger']['class']
764 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
765 loggerClass = getattr(loggerModule, loggerClass)
766 main.logger = loggerClass()
767 #hashobj = main.parser.parseParams(main.classPath)
768
769 except ImportError:
770 print sys.exc_info()[1]
771 else :
772 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
773 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800774 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
775 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700776 else:
777 load_defaultlogger()
778
779def load_defaultlogger():
780 '''
781 It will load the default parser which is xml parser to parse the params and topology file.
782 '''
783 moduleList = main.loggerPath.split("/")
784 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
785 try :
Jon Halld61331b2015-02-17 16:35:47 -0800786 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700787 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
788 loggerClass = getattr(loggerModule, loggerClass)
789 main.logger = loggerClass()
790
791 except ImportError:
792 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800793 main.exit()
adminbae64d82013-08-01 10:50:15 -0700794
795def load_defaultlogger():
796 '''
797 It will load the default parser which is xml parser to parse the params and topology file.
798 '''
799 moduleList = main.loggerPath.split("/")
800 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
801 try :
Jon Halld61331b2015-02-17 16:35:47 -0800802 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700803 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
804 loggerClass = getattr(loggerModule, loggerClass)
805 main.logger = loggerClass()
806
807 except ImportError:
808 print sys.exc_info()[1]
809 main.exit()
810
adminbae64d82013-08-01 10:50:15 -0700811def _echo(self):
812 print "THIS IS ECHO"