blob: fc85c55a039f3adcb1a8440b506f37977d67d1c4 [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"
283 #self.stepCache += "PASS <ac:emoticon ac:name=\"tick\" /></li>\n"
284 elif self.STEPRESULT == self.FALSE:
285 self.stepCache += "FAIL\n"
286 #self.stepCache += "FAIL <ac:emoticon ac:name=\"cross\" /></li>\n"
287 else:
288 self.stepCache += "No Result\n"
289 #self.stepCache += "No Result <ac:emoticon ac:name=\"warning\" /></li>\n"
290 self.stepResults.append(self.STEPRESULT)
Jon Hall40d2cbd2015-06-03 16:24:29 -0700291 except StandardError as e:
292 self.log.exception( "\nException in the following section of" +
293 " code: " + str(testCaseNumber) + "." +
294 str(step) + ": " + self.stepName )
Jon Hall63604932015-02-26 17:09:50 -0800295 #print code[testCaseNumber][step]
adminbae64d82013-08-01 10:50:15 -0700296 self.stepCount = self.stepCount + 1
kelvin-onlabf70fd542015-05-07 18:41:40 -0700297 self.logger.updateCaseResults(self)
298 #WIKI results
299 self.log.wiki( "<ul>" )
300 for line in self.stepCache.splitlines():
301 if re.search( " - PASS$", line ):
302 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
303 elif re.search( " - FAIL$", line ):
304 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
305 elif re.search( " - No Result$", line ):
306 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
307 self.log.wiki( "</ul>" )
308 #summary results
309 self.log.summary( self.stepCache )
310 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700311 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700312 self.exit()
adminbae64d82013-08-01 10:50:15 -0700313 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700314 if cli.stop:
315 cli.stop = False
316 stopped = True
317 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
318 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
319 self.logger.updateCaseResults(self)
320 result = self.cleanup()
321 return main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700322
adminbae64d82013-08-01 10:50:15 -0700323 def addCaseHeader(self):
324 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800325 self.log.exact(caseHeader)
326 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700327 for driver in self.componentDictionary.keys():
328 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700329
adminbae64d82013-08-01 10:50:15 -0700330 def addCaseFooter(self):
331 if self.stepCount-1 > 0 :
332 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
333 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700334
adminbae64d82013-08-01 10:50:15 -0700335 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700336
adminbae64d82013-08-01 10:50:15 -0700337 for driver in self.driversList:
338 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
339
340 def cleanup(self):
341 '''
342 Release all the component handles and the close opened file handles.
343 This will return TRUE if all the component handles and log handles closed properly,
344 else return FALSE
345
346 '''
347 result = self.TRUE
348 self.logger.testSummary(self)
Jon Halld61331b2015-02-17 16:35:47 -0800349
adminbae64d82013-08-01 10:50:15 -0700350 #self.reportFile.close()
Jon Halld61331b2015-02-17 16:35:47 -0800351
admin2c7034f2013-08-02 15:09:17 -0700352 #utilities.send_mail()
Jon Hall00539b12015-04-03 13:55:46 -0700353 for component in self.componentDictionary.keys():
354 try :
Jon Halld61331b2015-02-17 16:35:47 -0800355 tempObject = vars(self)[component]
Jon Hall1a77a1e2015-04-06 10:41:13 -0700356 print "Disconnecting from " + str(tempObject.name) + ": " + \
357 str(tempObject)
adminbae64d82013-08-01 10:50:15 -0700358 tempObject.disconnect()
Jon Halld61331b2015-02-17 16:35:47 -0800359 #tempObject.execute(cmd="exit",prompt="(.*)",timeout=120)
adminbae64d82013-08-01 10:50:15 -0700360
Jon Hall00539b12015-04-03 13:55:46 -0700361 except (Exception):
362 self.log.exception( "Exception while disconnecting from " +
363 str( component ) )
364 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700365 # Closing all the driver's session files
366 for driver in self.componentDictionary.keys():
367 vars(self)[driver].close_log_handles()
Jon Halld61331b2015-02-17 16:35:47 -0800368
adminbae64d82013-08-01 10:50:15 -0700369 return result
Jon Halld61331b2015-02-17 16:35:47 -0800370
adminbae64d82013-08-01 10:50:15 -0700371 def pause(self):
372 '''
373 This function will pause the test's execution, and will continue after user provide 'resume' command.
374 '''
375 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700376
adminbae64d82013-08-01 10:50:15 -0700377 def onfail(self,*components):
378 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700379 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700380 '''
adminbae64d82013-08-01 10:50:15 -0700381 if not components:
382 try :
383 for component in self.componentDictionary.keys():
384 tempObject = vars(self)[component]
385 result = tempObject.onfail()
386 except(Exception),e:
387 print str(e)
388 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700389 else:
390 try :
391 for component in components:
392 tempObject = vars(self)[component]
393 result = tempObject.onfail()
394 except(Exception),e:
395 print str(e)
396 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700397
adminbae64d82013-08-01 10:50:15 -0700398 def getDriverPath(self,driverName):
399 '''
400 Based on the component 'type' specified in the params , this method will find the absolute path ,
401 by recursively searching the name of the component.
402 '''
403 import commands
404
405 cmd = "find "+drivers_path+" -name "+driverName+".py"
406 result = commands.getoutput(cmd)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700407
adminbae64d82013-08-01 10:50:15 -0700408 result_array = str(result).split('\n')
409 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700410
adminbae64d82013-08-01 10:50:15 -0700411 for drivers_list in result_array:
412 result_count = result_count+1
413 if result_count > 1 :
414 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
415 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700416
adminbae64d82013-08-01 10:50:15 -0700417 result = re.sub("(.*)drivers","",result)
418 result = re.sub("\.py","",result)
419 result = re.sub("\.pyc","",result)
420 result = re.sub("\/",".",result)
421 result = "drivers"+result
422 return result
adminbae64d82013-08-01 10:50:15 -0700423
424 def step(self,stepDesc):
425 '''
426 The step information of the test-case will append to the logs.
427 '''
428 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
429 self.stepName = stepDesc
430
431 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
432 try :
433 if self.stepCount == 0:
434 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
435 except AttributeError:
436 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700437
adminbae64d82013-08-01 10:50:15 -0700438 self.log.step(stepName)
439 stepHeader = ""
440 if self.stepCount > 1 :
441 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700442
Jon Halld61331b2015-02-17 16:35:47 -0800443 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700444 for driver in self.componentDictionary.keys():
445 vars(self)[driver+'log'].info(stepHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700446
adminbae64d82013-08-01 10:50:15 -0700447 def case(self,testCaseName):
448 '''
449 Test's each test-case information will append to the logs.
450 '''
Jon Halld61331b2015-02-17 16:35:47 -0800451 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700452 testCaseName = " " + str(testCaseName) + ""
453 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800454 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700455 for driver in self.componentDictionary.keys():
456 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700457
adminbae64d82013-08-01 10:50:15 -0700458 def testDesc(self,description):
459 '''
460 Test description will append to the logs.
461 '''
462 description = "Test Description : " + str (description) + ""
463 self.log.info(description)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700464
adminbae64d82013-08-01 10:50:15 -0700465 def _getTest(self):
466 '''
467 This method will parse the test script to find required test information.
468 '''
469 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
470 testFileHandler = open(testFile, 'r')
471 testFileList = testFileHandler.readlines()
472 testFileHandler.close()
473 #self.TOTAL_TC_PLANNED = 0
474 counter = 0
475 for index in range(len(testFileList)):
476 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
477 if lineMatch:
478 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700479 self.TC_PLANNED = len(self.testcases_list)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700480
adminbae64d82013-08-01 10:50:15 -0700481 def response_parser(self,response, return_format):
482 ''' It will load the default response parser '''
483 response_dict = {}
484 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800485 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700486 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700487
adminbae64d82013-08-01 10:50:15 -0700488 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700489 response_dict = {}
490 json_match = re.search('^\s*{', response)
491 xml_match = re.search('^\s*\<', response)
492 ini_match = re.search('^\s*\[', response)
493 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800494 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800495 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700496 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
497 response = re.sub(r",\s*'?(\w)", r',"\1', response)
498 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
499 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700500 try :
501 import json
502 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800503 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800504 self.log.exception( e )
505 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700506 return response_dict
adminbae64d82013-08-01 10:50:15 -0700507 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800508 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700509 from configobj import ConfigObj
510 response_file = open("respnse_file.temp",'w')
511 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800512 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700513 response_dict = ConfigObj("respnse_file.temp")
514 return response_dict
adminbae64d82013-08-01 10:50:15 -0700515 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800516 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700517 try :
adminbae64d82013-08-01 10:50:15 -0700518 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
519 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800520 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700521 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700522
adminbae64d82013-08-01 10:50:15 -0700523 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700524 if return_format =='table' :
525 ''' Will return in table format'''
526 to_do = "Call the table output formatter"
527 global response_table
528 response_table = '\n'
529 response_table = response_table +'\t'.join(response_dict)+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700530
adminbae64d82013-08-01 10:50:15 -0700531 def get_table(value_to_convert):
532 ''' This will parse the dictionary recusrsively and print as table format'''
533 table_data = ""
534 if type(value_to_convert) == dict :
535 table_data = table_data +'\t'.join(value_to_convert)+"\n"
536 for temp_val in value_to_convert.values() :
537 table_data = table_data + get_table(temp_val)
538 else :
539 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800540 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700541
adminbae64d82013-08-01 10:50:15 -0700542 for value in response_dict.values() :
543 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800544 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700545 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700546
adminbae64d82013-08-01 10:50:15 -0700547 elif return_format =='config':
548 ''' Will return in config format'''
549 to_do = 'Call dict to config coverter'
550 response_string = str(response_dict)
551 print response_string
552 response_config = re.sub(",", "\n\t", response_string)
553 response_config = re.sub("u\'", "\'", response_config)
554 response_config = re.sub("{", "", response_config)
555 response_config = re.sub("}", "\n", response_config)
556 response_config = re.sub(":", " =", response_config)
557 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700558 elif return_format == 'xml':
559 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700560 response_xml = xmldict.dict_to_xml(response_dict)
561 response_xml = re.sub(">\s*<", ">\n<", response_xml)
562 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700563 elif return_format == 'json':
564 ''' Will return in json format'''
565 to_do = 'Call dict to xml coverter'
566 import json
567 response_json = json.dumps(response_dict)
568 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700569
adminbae64d82013-08-01 10:50:15 -0700570 def get_random(self):
571 self.random_order = self.random_order + 1
572 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700573
adminbae64d82013-08-01 10:50:15 -0700574 def exit(self):
575 __builtin__.testthread = None
576 sys.exit()
577
578def verifyOptions(options):
579 '''
580 This will verify the command line options and set to default values, if any option not given in command line.
581 '''
582 import pprint
583 pp = pprint.PrettyPrinter(indent=4)
584
Jon Hall88e498c2015-03-06 09:54:35 -0800585 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700586 verifyTest(options)
587 verifyExample(options)
588 verifyTestScript(options)
589 verifyParams()
590 verifyLogdir(options)
591 verifyMail(options)
592 verifyTestCases(options)
593
594def verifyTest(options):
595 if options.testname:
596 main.TEST = options.testname
597 main.classPath = "tests."+main.TEST+"."+main.TEST
598 main.tests_path = tests_path
599 elif options.example :
600 main.TEST = options.example
601 main.tests_path = path+"/examples/"
602 main.classPath = "examples."+main.TEST+"."+main.TEST
603 else :
604 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
605 self.exit()
606
607def verifyExample(options):
608 if options.example:
609 main.testDir = path+'/examples/'
610 main.tests_path = path+"/examples/"
611 main.classPath = "examples."+main.TEST+"."+main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700612
adminbae64d82013-08-01 10:50:15 -0700613def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800614 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700615 if options.logdir:
616 main.logdir = options.logdir
617 else :
Jon Halld61331b2015-02-17 16:35:47 -0800618 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700619
adminbae64d82013-08-01 10:50:15 -0700620def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800621 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700622 if options.mail:
623 main.mail = options.mail
624 elif main.params.has_key('mail'):
625 main.mail = main.params['mail']
626 else :
627 main.mail = 'paxweb@paxterrasolutions.com'
628
629def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800630 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700631 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800632 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800633 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700634 testcases_list = re.sub("(\[|\])", "", options.testcases)
635 main.testcases_list = eval(testcases_list+",")
636 else :
637 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700638 temp = eval(main.params['testcases']+",")
639 list1=[]
640 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800641 for test in temp:
642 for testcase in test:
643 if type(testcase)==int:
644 testcase=[testcase]
645 list1.extend(testcase)
646 else :
647 temp=list(temp)
648 for testcase in temp:
649 if type(testcase)==int:
650 testcase=[testcase]
651 list1.extend(testcase)
652 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700653 else :
654 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800655 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700656
adminbae64d82013-08-01 10:50:15 -0700657def verifyTestScript(options):
658 '''
659 Verifyies test script.
660 '''
Jon Halld61331b2015-02-17 16:35:47 -0800661 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700662 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
663 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
664 if os.path.exists(openspeakfile) :
665 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
666 elif os.path.exists(testfile):
667 print ''
668 else:
669 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
670 __builtin__.testthread = None
671 main.exit()
adminbae64d82013-08-01 10:50:15 -0700672 try :
adminbae64d82013-08-01 10:50:15 -0700673 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
674 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500675 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800676 main.exit()
adminbae64d82013-08-01 10:50:15 -0700677
678 testClass = getattr(testModule, main.TEST)
679 main.testObject = testClass()
680 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800681 main.params = main.parser.parseParams(main.classPath)
682 main.topology = main.parser.parseTopology(main.classPath)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700683
adminbae64d82013-08-01 10:50:15 -0700684def verifyParams():
685 try :
686 main.params = main.params['PARAMS']
687 except(KeyError):
688 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800689 main.exit()
adminbae64d82013-08-01 10:50:15 -0700690 try :
691 main.topology = main.topology['TOPOLOGY']
692 except(KeyError):
693 print "Error with the Topology file: Either the file not specified or the format is not correct"
694 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700695
adminbae64d82013-08-01 10:50:15 -0700696def load_parser() :
697 '''
698 It facilitates the loading customised parser for topology and params file.
699 It loads parser mentioned in tab named parser of teston.cfg file.
700 It also loads default xmlparser if no parser have specified in teston.cfg file.
701
702 '''
703 confighash = main.configDict
704 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
705 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
706 if os.path.exists(confighash['config']['parser']['file']) :
707 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
708 moduleList = module.split("/")
709 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
710 try :
711 parsingClass = confighash['config']['parser']['class']
712 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
713 parsingClass = getattr(parsingModule, parsingClass)
714 main.parser = parsingClass()
715 #hashobj = main.parser.parseParams(main.classPath)
716 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700717 pass
718 else:
719 main.exit()
adminbae64d82013-08-01 10:50:15 -0700720 except ImportError:
721 print sys.exc_info()[1]
722 main.exit()
723 else :
724 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800725 load_defaultParser()
726 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
727 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700728 else:
729 load_defaultParser()
730
731def load_defaultParser():
732 '''
733 It will load the default parser which is xml parser to parse the params and topology file.
734 '''
735 moduleList = main.parserPath.split("/")
736 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
737 try :
Jon Halld61331b2015-02-17 16:35:47 -0800738 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700739 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
740 parsingClass = getattr(parsingModule, parsingClass)
741 main.parser = parsingClass()
742 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
743 pass
744 else:
745 main.exit()
746
747 except ImportError:
748 print sys.exc_info()[1]
749
adminbae64d82013-08-01 10:50:15 -0700750def load_logger() :
751 '''
752 It facilitates the loading customised parser for topology and params file.
753 It loads parser mentioned in tab named parser of teston.cfg file.
754 It also loads default xmlparser if no parser have specified in teston.cfg file.
755
756 '''
757 confighash = main.configDict
758 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
759 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
760 if os.path.exists(confighash['config']['logger']['file']) :
761 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
762 moduleList = module.split("/")
763 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
764 try :
765 loggerClass = confighash['config']['logger']['class']
766 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
767 loggerClass = getattr(loggerModule, loggerClass)
768 main.logger = loggerClass()
769 #hashobj = main.parser.parseParams(main.classPath)
770
771 except ImportError:
772 print sys.exc_info()[1]
773 else :
774 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
775 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800776 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
777 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700778 else:
779 load_defaultlogger()
780
781def load_defaultlogger():
782 '''
783 It will load the default parser which is xml parser to parse the params and topology file.
784 '''
785 moduleList = main.loggerPath.split("/")
786 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
787 try :
Jon Halld61331b2015-02-17 16:35:47 -0800788 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700789 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
790 loggerClass = getattr(loggerModule, loggerClass)
791 main.logger = loggerClass()
792
793 except ImportError:
794 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800795 main.exit()
adminbae64d82013-08-01 10:50:15 -0700796
797def load_defaultlogger():
798 '''
799 It will load the default parser which is xml parser to parse the params and topology file.
800 '''
801 moduleList = main.loggerPath.split("/")
802 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
803 try :
Jon Halld61331b2015-02-17 16:35:47 -0800804 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700805 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
806 loggerClass = getattr(loggerModule, loggerClass)
807 main.logger = loggerClass()
808
809 except ImportError:
810 print sys.exc_info()[1]
811 main.exit()
812
adminbae64d82013-08-01 10:50:15 -0700813def _echo(self):
814 print "THIS IS ECHO"