blob: e4dbf9d6ea9292ea1df3195567a31ee24a4cea43 [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
Jon Hall5b586732015-06-11 11:39:39 -070035import threading
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 Hall5b586732015-06-11 11:39:39 -070094 self.cleanupFlag = False
95 self.cleanupLock = threading.Lock()
Jon Hall0fc0d452015-07-14 09:49:58 -070096 self.initiated = False
Jon Hall65844a32015-03-09 19:09:37 -070097
adminbae64d82013-08-01 10:50:15 -070098 self.configparser()
99 verifyOptions(options)
100 load_logger()
101 self.componentDictionary = {}
102 self.componentDictionary = self.topology ['COMPONENT']
103 self.driversList=[]
104 if type(self.componentDictionary) == str :
105 self.componentDictionary = dict(self.componentDictionary)
Jon Hall65844a32015-03-09 19:09:37 -0700106
adminbae64d82013-08-01 10:50:15 -0700107 for component in self.componentDictionary :
108 self.driversList.append(self.componentDictionary[component]['type'])
Jon Hall65844a32015-03-09 19:09:37 -0700109
adminbae64d82013-08-01 10:50:15 -0700110 self.driversList = list(set(self.driversList)) # Removing duplicates.
111 # Checking the test_target option set for the component or not
112 if type(self.componentDictionary) == dict:
113 for component in self.componentDictionary.keys():
114 if 'test_target' in self.componentDictionary[component].keys():
115 self.test_target = component
Jon Hall65844a32015-03-09 19:09:37 -0700116
Jon Halld61331b2015-02-17 16:35:47 -0800117 # Checking for the openspeak file and test script
adminbae64d82013-08-01 10:50:15 -0700118 self.logger.initlog(self)
119
120 # Creating Drivers Handles
121 initString = "\n"+"*" * 30+"\n CASE INIT \n"+"*" * 30+"\n"
122 self.log.exact(initString)
123 self.driverObject = {}
124 self.random_order = 111 # Random order id to connect the components
125 components_connect_order = {}
126 #component_list.append()
127 if type(self.componentDictionary) == dict:
128 for component in self.componentDictionary.keys():
129 self.componentDictionary[component]['connect_order'] = self.componentDictionary[component]['connect_order'] if ('connect_order' in self.componentDictionary[component].keys()) else str(self.get_random())
130 components_connect_order[component] = eval(self.componentDictionary[component]['connect_order'])
131 #Ordering components based on the connect order.
132 ordered_component_list =sorted(components_connect_order, key=lambda key: components_connect_order[key])
133 print ordered_component_list
adminbae64d82013-08-01 10:50:15 -0700134 for component in ordered_component_list:
135 self.componentInit(component)
136
137 def configparser(self):
138 '''
139 It will parse the config file (teston.cfg) and return as dictionary
140 '''
141 matchFileName = re.match(r'(.*)\.cfg', self.configFile, re.M | re.I)
142 if matchFileName:
143 xml = open(self.configFile).read()
144 try :
145 self.configDict = xmldict.xml_to_dict(xml)
146 return self.configDict
Jon Hallfebb1c72015-03-05 13:30:09 -0800147 except Exception:
adminbae64d82013-08-01 10:50:15 -0700148 print "There is no such file to parse " + self.configFile
kelvin-onlabf70fd542015-05-07 18:41:40 -0700149
adminbae64d82013-08-01 10:50:15 -0700150 def componentInit(self,component):
151 '''
152 This method will initialize specified component
153 '''
154 global driver_options
Jon Hall0fc0d452015-07-14 09:49:58 -0700155 self.initiated = False
adminbae64d82013-08-01 10:50:15 -0700156 self.log.info("Creating component Handle: "+component)
Jon Halld61331b2015-02-17 16:35:47 -0800157 driver_options = {}
adminbae64d82013-08-01 10:50:15 -0700158 if 'COMPONENTS' in self.componentDictionary[component].keys():
159 driver_options =dict(self.componentDictionary[component]['COMPONENTS'])
160
161 driver_options['name']=component
162 driverName = self.componentDictionary[component]['type']
163 driver_options ['type'] = driverName
kelvin-onlabf70fd542015-05-07 18:41:40 -0700164
adminbae64d82013-08-01 10:50:15 -0700165 classPath = self.getDriverPath(driverName.lower())
Jon Hall30b82fa2015-03-04 17:15:43 -0800166 driverModule = importlib.import_module(classPath)
adminbae64d82013-08-01 10:50:15 -0700167 driverClass = getattr(driverModule, driverName)
168 driverObject = driverClass()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700169
adminbae64d82013-08-01 10:50:15 -0700170 connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
171 ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
172 pwd = self.componentDictionary[component]['password'] if ('password' in self.componentDictionary[component].keys()) else 'changeme',
173 port = self.componentDictionary[component]['port'] if ('port' in self.componentDictionary[component].keys()) else None,
174 options = driver_options)
cameron@onlab.us5cc6a372015-05-11 17:18:07 -0700175
adminbae64d82013-08-01 10:50:15 -0700176 if not connect_result:
177 self.log.error("Exiting form the test execution because the connecting to the "+component+" component failed.")
Jon Halld61331b2015-02-17 16:35:47 -0800178 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700179
adminbae64d82013-08-01 10:50:15 -0700180 vars(self)[component] = driverObject
Jon Hall0fc0d452015-07-14 09:49:58 -0700181 self.initiated = True
kelvin-onlabf70fd542015-05-07 18:41:40 -0700182
adminbae64d82013-08-01 10:50:15 -0700183 def run(self):
184 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700185 The Execution of the test script's cases listed in the Test params file will be done here.
186 And Update each test case result.
187 This method will return TRUE if it executed all the test cases successfully,
adminbae64d82013-08-01 10:50:15 -0700188 else will retun FALSE
189 '''
adminbae64d82013-08-01 10:50:15 -0700190 self.testCaseResult = {}
Jon Halla1185982014-09-15 14:55:10 -0700191 self.TOTAL_TC = 0
adminbae64d82013-08-01 10:50:15 -0700192 self.TOTAL_TC_RUN = 0
Jon Halld61331b2015-02-17 16:35:47 -0800193 self.TOTAL_TC_PLANNED = 0
adminbae64d82013-08-01 10:50:15 -0700194 self.TOTAL_TC_NORESULT = 0
195 self.TOTAL_TC_FAIL = 0
196 self.TOTAL_TC_PASS = 0
Jon Halla1185982014-09-15 14:55:10 -0700197 self.TEST_ITERATION = 0
adminbae64d82013-08-01 10:50:15 -0700198 self.stepCount = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700199 self.CASERESULT = self.NORESULT
200
Jon Halld61331b2015-02-17 16:35:47 -0800201 import testparser
adminbae64d82013-08-01 10:50:15 -0700202 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
203 test = testparser.TestParser(testFile)
204 self.testscript = test.testscript
205 self.code = test.getStepCode()
Jon Hallfebb1c72015-03-05 13:30:09 -0800206 repeat= int(self.params['repeat']) if ('repeat' in self.params) else 1
207 self.TOTAL_TC_PLANNED = len(self.testcases_list)*repeat
kelvin-onlabf70fd542015-05-07 18:41:40 -0700208
adminbae64d82013-08-01 10:50:15 -0700209 result = self.TRUE
Jon Hallfebb1c72015-03-05 13:30:09 -0800210 while(repeat):
Jon Halla1185982014-09-15 14:55:10 -0700211 for self.CurrentTestCaseNumber in self.testcases_list:
Jon Halld61331b2015-02-17 16:35:47 -0800212 result = self.runCase(self.CurrentTestCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800213 repeat-=1
adminbae64d82013-08-01 10:50:15 -0700214 return result
kelvin-onlabf70fd542015-05-07 18:41:40 -0700215
adminbae64d82013-08-01 10:50:15 -0700216 def runCase(self,testCaseNumber):
217 self.CurrentTestCaseNumber = testCaseNumber
kelvin-onlabf70fd542015-05-07 18:41:40 -0700218 self.CurrentTestCase = ""
219 self.stepResults = []
220 self.stepName = ""
221 self.caseExplaination = ""
adminbae64d82013-08-01 10:50:15 -0700222 result = self.TRUE
223 self.stepCount = 0
224 self.EXPERIMENTAL_MODE = self.FALSE
225 self.addCaseHeader()
226 self.testCaseNumber = str(testCaseNumber)
227 stopped = False
228 try :
229 self.stepList = self.code[self.testCaseNumber].keys()
Jon Halld61331b2015-02-17 16:35:47 -0800230 except KeyError:
Jon Hallfebb1c72015-03-05 13:30:09 -0800231 self.log.error("There is no Test-Case "+ self.testCaseNumber)
232 return self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700233
adminbae64d82013-08-01 10:50:15 -0700234 self.stepCount = 0
235 while self.stepCount < len(self.code[self.testCaseNumber].keys()):
236 result = self.runStep(self.stepList,self.code,self.testCaseNumber)
Jon Hallfebb1c72015-03-05 13:30:09 -0800237 if result == self.FALSE:
adminbae64d82013-08-01 10:50:15 -0700238 break
Jon Hallfebb1c72015-03-05 13:30:09 -0800239 elif result == self.TRUE:
adminbae64d82013-08-01 10:50:15 -0700240 continue
adminbae64d82013-08-01 10:50:15 -0700241 if not stopped :
kelvin-onlabf70fd542015-05-07 18:41:40 -0700242 if all( self.TRUE == i for i in self.stepResults ):
243 # ALL PASSED
244 self.CASERESULT = self.TRUE
245 elif self.FALSE in self.stepResults:
246 # AT LEAST ONE FAILED
247 self.CASERESULT = self.FALSE
248 elif self.TRUE in self.stepResults:
249 # AT LEAST ONE PASSED
250 self.CASERESULT = self.TRUE
251 else:
252 self.CASERESULT = self.NORESULT
adminbae64d82013-08-01 10:50:15 -0700253 self.testCaseResult[str(self.CurrentTestCaseNumber)] = self.CASERESULT
254 self.logger.updateCaseResults(self)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700255 self.log.wiki( "<p>" + self.caseExplaination + "</p>" )
256 self.log.summary( self.caseExplaination )
257 self.log.wiki( "<ul>" )
258 for line in self.stepCache.splitlines():
259 if re.search( " - PASS$", line ):
260 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"tick\" /></li>\n" )
261 elif re.search( " - FAIL$", line ):
262 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"cross\" /></li>\n" )
263 elif re.search( " - No Result$", line ):
264 self.log.wiki( "<li>" + line + " <ac:emoticon ac:name=\"warning\" /></li>\n" )
Jon Hall90627612015-06-09 14:57:02 -0700265 else: # Should only be on fail message
266 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700267 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
Jon Hall90627612015-06-09 14:57:02 -0700277 self.onFailMsg = "\t\tNo on fail message given"
adminbae64d82013-08-01 10:50:15 -0700278 exec code[testCaseNumber][step] in module.__dict__
279 self.stepCount = self.stepCount + 1
kelvin-onlabf70fd542015-05-07 18:41:40 -0700280 if step > 0:
281 self.stepCache += "\t"+str(testCaseNumber)+"."+str(step)+" "+self.stepName+" - "
282 if self.STEPRESULT == self.TRUE:
283 self.stepCache += "PASS\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700284 elif self.STEPRESULT == self.FALSE:
285 self.stepCache += "FAIL\n"
Jon Hall8ce34e82015-06-05 10:41:45 -0700286 # TODO: Print the on-fail statement here
Jon Hall90627612015-06-09 14:57:02 -0700287 self.stepCache += "\t\t" + self.onFailMsg + "\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700288 else:
289 self.stepCache += "No Result\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700290 self.stepResults.append(self.STEPRESULT)
Jon Hall5b586732015-06-11 11:39:39 -0700291 except StandardError:
Jon Hall40d2cbd2015-06-03 16:24:29 -0700292 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" )
Jon Hall90627612015-06-09 14:57:02 -0700307 else: # Should only be on fail message
308 self.log.wiki( "<ul><li>" + line + "</li></ul>\n" )
kelvin-onlabf70fd542015-05-07 18:41:40 -0700309 self.log.wiki( "</ul>" )
310 #summary results
311 self.log.summary( self.stepCache )
312 self.stepCache = ""
shahshreya957feaa2015-03-23 16:08:29 -0700313 self.cleanup()
Jon Hall00539b12015-04-03 13:55:46 -0700314 self.exit()
adminbae64d82013-08-01 10:50:15 -0700315 return main.TRUE
adminbae64d82013-08-01 10:50:15 -0700316 if cli.stop:
317 cli.stop = False
318 stopped = True
319 self.TOTAL_TC_NORESULT = self.TOTAL_TC_NORESULT + 1
320 self.testCaseResult[str(self.CurrentTestCaseNumber)] = "Stopped"
321 self.logger.updateCaseResults(self)
322 result = self.cleanup()
323 return main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700324
adminbae64d82013-08-01 10:50:15 -0700325 def addCaseHeader(self):
326 caseHeader = "\n"+"*" * 30+"\n Result summary for Testcase"+str(self.CurrentTestCaseNumber)+"\n"+"*" * 30+"\n"
Jon Halld61331b2015-02-17 16:35:47 -0800327 self.log.exact(caseHeader)
328 caseHeader = "\n"+"*" * 40 +"\nStart of Test Case"+str(self.CurrentTestCaseNumber)+" : "
adminbae64d82013-08-01 10:50:15 -0700329 for driver in self.componentDictionary.keys():
330 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700331
adminbae64d82013-08-01 10:50:15 -0700332 def addCaseFooter(self):
333 if self.stepCount-1 > 0 :
334 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
335 stepHeader = "\n"+"*" * 40+"\nEnd of Step "+previousStep+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700336
adminbae64d82013-08-01 10:50:15 -0700337 caseFooter = "\n"+"*" * 40+"\nEnd of Test case "+str(self.CurrentTestCaseNumber)+"\n"+"*" * 40+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700338
adminbae64d82013-08-01 10:50:15 -0700339 for driver in self.driversList:
340 vars(self)[driver].write(stepHeader+"\n"+caseFooter)
341
342 def cleanup(self):
343 '''
Jon Hall5b586732015-06-11 11:39:39 -0700344 Print a summary of the current test's results then attempt to release
345 all the component handles and the close opened file handles.
adminbae64d82013-08-01 10:50:15 -0700346
Jon Hall5b586732015-06-11 11:39:39 -0700347 This function shouldbe threadsafe such that cleanup will only be
348 executed once per test.
349
350 This will return TRUE if all the component handles and log handles
351 closed properly, else return FALSE.
adminbae64d82013-08-01 10:50:15 -0700352 '''
353 result = self.TRUE
Jon Hall5b586732015-06-11 11:39:39 -0700354 lock = self.cleanupLock
355 if lock.acquire( False ):
356 try:
357 if self.cleanupFlag is False: # First thread to run this
358 self.cleanupFlag = True
Jon Hall0fc0d452015-07-14 09:49:58 -0700359 if self.initiated:
360 self.logger.testSummary(self)
Jon Hall5b586732015-06-11 11:39:39 -0700361 for component in self.componentDictionary.keys():
362 try :
363 tempObject = vars(self)[component]
364 print "Disconnecting from " + str(tempObject.name) + ": " + \
365 str(tempObject)
366 tempObject.disconnect()
367 except Exception:
368 self.log.exception( "Exception while disconnecting from " +
369 str( component ) )
370 result = self.FALSE
371 # Closing all the driver's session files
372 for driver in self.componentDictionary.keys():
373 try:
374 vars(self)[driver].close_log_handles()
375 except Exception:
376 self.log.exception( "Exception while closing log files for " +
377 str( driver ) )
378 result = self.FALSE
379 else:
380 pass # Someone else already ran through this function
381 finally:
382 lock.release()
383 else: # Someone already has a lock
384 # NOTE: This could cause problems if we don't release the lock
385 # correctly
386 lock.acquire() # Wait for the other thread to finish
387 # NOTE: If we don't wait, exit could be called while the thread
388 # with the lock is still cleaning up
389 lock.release()
adminbae64d82013-08-01 10:50:15 -0700390 return result
Jon Halld61331b2015-02-17 16:35:47 -0800391
adminbae64d82013-08-01 10:50:15 -0700392 def pause(self):
393 '''
394 This function will pause the test's execution, and will continue after user provide 'resume' command.
395 '''
396 __builtin__.testthread.pause()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700397
adminbae64d82013-08-01 10:50:15 -0700398 def onfail(self,*components):
399 '''
kelvin-onlabf70fd542015-05-07 18:41:40 -0700400 When test step failed, calling all the components onfail.
adminbae64d82013-08-01 10:50:15 -0700401 '''
adminbae64d82013-08-01 10:50:15 -0700402 if not components:
403 try :
404 for component in self.componentDictionary.keys():
405 tempObject = vars(self)[component]
406 result = tempObject.onfail()
407 except(Exception),e:
408 print str(e)
409 result = self.FALSE
adminbae64d82013-08-01 10:50:15 -0700410 else:
411 try :
412 for component in components:
413 tempObject = vars(self)[component]
414 result = tempObject.onfail()
415 except(Exception),e:
416 print str(e)
417 result = self.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700418
adminbae64d82013-08-01 10:50:15 -0700419 def getDriverPath(self,driverName):
420 '''
421 Based on the component 'type' specified in the params , this method will find the absolute path ,
422 by recursively searching the name of the component.
423 '''
424 import commands
425
426 cmd = "find "+drivers_path+" -name "+driverName+".py"
427 result = commands.getoutput(cmd)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700428
adminbae64d82013-08-01 10:50:15 -0700429 result_array = str(result).split('\n')
430 result_count = 0
kelvin-onlabf70fd542015-05-07 18:41:40 -0700431
adminbae64d82013-08-01 10:50:15 -0700432 for drivers_list in result_array:
433 result_count = result_count+1
434 if result_count > 1 :
435 print "found "+driverName+" "+ str(result_count) + " times"+str(result_array)
436 self.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700437
adminbae64d82013-08-01 10:50:15 -0700438 result = re.sub("(.*)drivers","",result)
439 result = re.sub("\.py","",result)
440 result = re.sub("\.pyc","",result)
441 result = re.sub("\/",".",result)
442 result = "drivers"+result
443 return result
adminbae64d82013-08-01 10:50:15 -0700444
445 def step(self,stepDesc):
446 '''
447 The step information of the test-case will append to the logs.
448 '''
449 previousStep = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount-1)+": "+ str(self.stepName) + ""
450 self.stepName = stepDesc
451
452 stepName = " "+str(self.CurrentTestCaseNumber)+"."+str(self.stepCount)+": "+ str(stepDesc) + ""
453 try :
454 if self.stepCount == 0:
455 stepName = " INIT : Initializing the test case :"+self.CurrentTestCase
456 except AttributeError:
457 stepName = " INIT : Initializing the test case :"+str(self.CurrentTestCaseNumber)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700458
adminbae64d82013-08-01 10:50:15 -0700459 self.log.step(stepName)
460 stepHeader = ""
461 if self.stepCount > 1 :
462 stepHeader = "\n"+"-"*45+"\nEnd of Step "+previousStep+"\n"+"-"*45+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700463
Jon Halld61331b2015-02-17 16:35:47 -0800464 stepHeader += "\n"+"-"*45+"\nStart of Step"+stepName+"\n"+"-"*45+"\n"
adminbae64d82013-08-01 10:50:15 -0700465 for driver in self.componentDictionary.keys():
466 vars(self)[driver+'log'].info(stepHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700467
adminbae64d82013-08-01 10:50:15 -0700468 def case(self,testCaseName):
469 '''
470 Test's each test-case information will append to the logs.
471 '''
Jon Halld61331b2015-02-17 16:35:47 -0800472 self.CurrentTestCase = testCaseName
adminbae64d82013-08-01 10:50:15 -0700473 testCaseName = " " + str(testCaseName) + ""
474 self.log.case(testCaseName)
Jon Halld61331b2015-02-17 16:35:47 -0800475 caseHeader = testCaseName+"\n"+"*" * 40+"\n"
adminbae64d82013-08-01 10:50:15 -0700476 for driver in self.componentDictionary.keys():
477 vars(self)[driver+'log'].info(caseHeader)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700478
adminbae64d82013-08-01 10:50:15 -0700479 def testDesc(self,description):
480 '''
481 Test description will append to the logs.
482 '''
483 description = "Test Description : " + str (description) + ""
484 self.log.info(description)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700485
adminbae64d82013-08-01 10:50:15 -0700486 def _getTest(self):
487 '''
488 This method will parse the test script to find required test information.
489 '''
490 testFile = self.tests_path + "/"+self.TEST + "/"+self.TEST + ".py"
491 testFileHandler = open(testFile, 'r')
492 testFileList = testFileHandler.readlines()
493 testFileHandler.close()
494 #self.TOTAL_TC_PLANNED = 0
495 counter = 0
496 for index in range(len(testFileList)):
497 lineMatch = re.match('\s+def CASE(\d+)(.*):',testFileList[index],0)
498 if lineMatch:
499 counter = counter + 1
Jon Halla1185982014-09-15 14:55:10 -0700500 self.TC_PLANNED = len(self.testcases_list)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700501
adminbae64d82013-08-01 10:50:15 -0700502 def response_parser(self,response, return_format):
503 ''' It will load the default response parser '''
504 response_dict = {}
505 response_dict = self.response_to_dict(response, return_format)
Jon Halld61331b2015-02-17 16:35:47 -0800506 return_format_string = self.dict_to_return_format(response,return_format,response_dict)
adminbae64d82013-08-01 10:50:15 -0700507 return return_format_string
kelvin-onlabf70fd542015-05-07 18:41:40 -0700508
adminbae64d82013-08-01 10:50:15 -0700509 def response_to_dict(self,response,return_format):
adminbae64d82013-08-01 10:50:15 -0700510 response_dict = {}
511 json_match = re.search('^\s*{', response)
512 xml_match = re.search('^\s*\<', response)
513 ini_match = re.search('^\s*\[', response)
514 if json_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800515 self.log.info(" Response is in 'JSON' format and Converting to '"+return_format+"' format")
Jon Halld61331b2015-02-17 16:35:47 -0800516 # Formatting the json string
adminbae64d82013-08-01 10:50:15 -0700517 response = re.sub(r"{\s*'?(\w)", r'{"\1', response)
518 response = re.sub(r",\s*'?(\w)", r',"\1', response)
519 response = re.sub(r"(\w)'?\s*:", r'\1":', response)
520 response = re.sub(r":\s*'(\w)'\s*([,}])", r':"\1"\2', response)
adminbae64d82013-08-01 10:50:15 -0700521 try :
522 import json
523 response_dict = json.loads(response)
Jon Hall30b82fa2015-03-04 17:15:43 -0800524 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800525 self.log.exception( e )
526 self.log.error("Json Parser is unable to parse the string")
adminbae64d82013-08-01 10:50:15 -0700527 return response_dict
adminbae64d82013-08-01 10:50:15 -0700528 elif ini_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800529 self.log.info(" Response is in 'INI' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700530 from configobj import ConfigObj
531 response_file = open("respnse_file.temp",'w')
532 response_file.write(response)
Jon Halld61331b2015-02-17 16:35:47 -0800533 response_file.close()
adminbae64d82013-08-01 10:50:15 -0700534 response_dict = ConfigObj("respnse_file.temp")
535 return response_dict
adminbae64d82013-08-01 10:50:15 -0700536 elif xml_match :
Jon Hallfebb1c72015-03-05 13:30:09 -0800537 self.log.info(" Response is in 'XML' format and Converting to '"+return_format+"' format")
adminbae64d82013-08-01 10:50:15 -0700538 try :
adminbae64d82013-08-01 10:50:15 -0700539 response_dict = xmldict.xml_to_dict("<response> "+str(response)+" </response>")
540 except Exception, e:
Jon Hallfebb1c72015-03-05 13:30:09 -0800541 self.log.exception( e )
adminbae64d82013-08-01 10:50:15 -0700542 return response_dict
kelvin-onlabf70fd542015-05-07 18:41:40 -0700543
adminbae64d82013-08-01 10:50:15 -0700544 def dict_to_return_format(self,response,return_format,response_dict):
adminbae64d82013-08-01 10:50:15 -0700545 if return_format =='table' :
546 ''' Will return in table format'''
547 to_do = "Call the table output formatter"
548 global response_table
549 response_table = '\n'
550 response_table = response_table +'\t'.join(response_dict)+"\n"
kelvin-onlabf70fd542015-05-07 18:41:40 -0700551
adminbae64d82013-08-01 10:50:15 -0700552 def get_table(value_to_convert):
553 ''' This will parse the dictionary recusrsively and print as table format'''
554 table_data = ""
555 if type(value_to_convert) == dict :
556 table_data = table_data +'\t'.join(value_to_convert)+"\n"
557 for temp_val in value_to_convert.values() :
558 table_data = table_data + get_table(temp_val)
559 else :
560 table_data = table_data + str(value_to_convert) +"\t"
Jon Halld61331b2015-02-17 16:35:47 -0800561 return table_data
kelvin-onlabf70fd542015-05-07 18:41:40 -0700562
adminbae64d82013-08-01 10:50:15 -0700563 for value in response_dict.values() :
564 response_table = response_table + get_table(value)
Jon Hall88e498c2015-03-06 09:54:35 -0800565 # response_table = response_table + '\t'.join(response_dict.values())
adminbae64d82013-08-01 10:50:15 -0700566 return response_table
kelvin-onlabf70fd542015-05-07 18:41:40 -0700567
adminbae64d82013-08-01 10:50:15 -0700568 elif return_format =='config':
569 ''' Will return in config format'''
570 to_do = 'Call dict to config coverter'
571 response_string = str(response_dict)
572 print response_string
573 response_config = re.sub(",", "\n\t", response_string)
574 response_config = re.sub("u\'", "\'", response_config)
575 response_config = re.sub("{", "", response_config)
576 response_config = re.sub("}", "\n", response_config)
577 response_config = re.sub(":", " =", response_config)
578 return "[response]\n\t "+response_config
adminbae64d82013-08-01 10:50:15 -0700579 elif return_format == 'xml':
580 ''' Will return in xml format'''
adminbae64d82013-08-01 10:50:15 -0700581 response_xml = xmldict.dict_to_xml(response_dict)
582 response_xml = re.sub(">\s*<", ">\n<", response_xml)
583 return "\n"+response_xml
adminbae64d82013-08-01 10:50:15 -0700584 elif return_format == 'json':
585 ''' Will return in json format'''
586 to_do = 'Call dict to xml coverter'
587 import json
588 response_json = json.dumps(response_dict)
589 return response_json
kelvin-onlabf70fd542015-05-07 18:41:40 -0700590
adminbae64d82013-08-01 10:50:15 -0700591 def get_random(self):
592 self.random_order = self.random_order + 1
593 return self.random_order
kelvin-onlabf70fd542015-05-07 18:41:40 -0700594
adminbae64d82013-08-01 10:50:15 -0700595 def exit(self):
596 __builtin__.testthread = None
Jon Hall5b586732015-06-11 11:39:39 -0700597 for thread in threading.enumerate():
598 if thread.isAlive():
599 try:
600 thread._Thread__stop()
601 except:
602 print(str(thread.getName()) + ' could not be terminated' )
adminbae64d82013-08-01 10:50:15 -0700603 sys.exit()
604
605def verifyOptions(options):
606 '''
607 This will verify the command line options and set to default values, if any option not given in command line.
608 '''
609 import pprint
610 pp = pprint.PrettyPrinter(indent=4)
611
Jon Hall88e498c2015-03-06 09:54:35 -0800612 # pp.pprint(options)
adminbae64d82013-08-01 10:50:15 -0700613 verifyTest(options)
614 verifyExample(options)
615 verifyTestScript(options)
616 verifyParams()
617 verifyLogdir(options)
618 verifyMail(options)
619 verifyTestCases(options)
Hari Krishna03f530e2015-07-10 17:28:27 -0700620 verifyOnosCell(options)
adminbae64d82013-08-01 10:50:15 -0700621
622def verifyTest(options):
623 if options.testname:
624 main.TEST = options.testname
625 main.classPath = "tests."+main.TEST+"."+main.TEST
626 main.tests_path = tests_path
627 elif options.example :
628 main.TEST = options.example
629 main.tests_path = path+"/examples/"
630 main.classPath = "examples."+main.TEST+"."+main.TEST
631 else :
632 print "Test or Example not specified please specify the --test <test name > or --example <example name>"
Jon Hall5b586732015-06-11 11:39:39 -0700633 main.exit()
adminbae64d82013-08-01 10:50:15 -0700634
635def verifyExample(options):
636 if options.example:
637 main.testDir = path+'/examples/'
638 main.tests_path = path+"/examples/"
639 main.classPath = "examples."+main.TEST+"."+main.TEST
kelvin-onlabf70fd542015-05-07 18:41:40 -0700640
adminbae64d82013-08-01 10:50:15 -0700641def verifyLogdir(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800642 # Verifying Log directory option
adminbae64d82013-08-01 10:50:15 -0700643 if options.logdir:
644 main.logdir = options.logdir
645 else :
Jon Halld61331b2015-02-17 16:35:47 -0800646 main.logdir = main.FALSE
kelvin-onlabf70fd542015-05-07 18:41:40 -0700647
adminbae64d82013-08-01 10:50:15 -0700648def verifyMail(options):
Jon Halld61331b2015-02-17 16:35:47 -0800649 # Checking the mailing list
adminbae64d82013-08-01 10:50:15 -0700650 if options.mail:
651 main.mail = options.mail
652 elif main.params.has_key('mail'):
653 main.mail = main.params['mail']
654 else :
655 main.mail = 'paxweb@paxterrasolutions.com'
656
657def verifyTestCases(options):
Jon Hall88e498c2015-03-06 09:54:35 -0800658 # Getting Test cases list
adminbae64d82013-08-01 10:50:15 -0700659 if options.testcases:
Jon Hallfebb1c72015-03-05 13:30:09 -0800660 testcases_list = options.testcases
Jon Hall88e498c2015-03-06 09:54:35 -0800661 # sys.exit()
adminbae64d82013-08-01 10:50:15 -0700662 testcases_list = re.sub("(\[|\])", "", options.testcases)
663 main.testcases_list = eval(testcases_list+",")
664 else :
665 if 'testcases' in main.params.keys():
Jon Halla1185982014-09-15 14:55:10 -0700666 temp = eval(main.params['testcases']+",")
667 list1=[]
668 if type(temp[0])==list:
Jon Hallfebb1c72015-03-05 13:30:09 -0800669 for test in temp:
670 for testcase in test:
671 if type(testcase)==int:
672 testcase=[testcase]
673 list1.extend(testcase)
674 else :
675 temp=list(temp)
676 for testcase in temp:
677 if type(testcase)==int:
678 testcase=[testcase]
679 list1.extend(testcase)
680 main.testcases_list=list1
adminbae64d82013-08-01 10:50:15 -0700681 else :
682 print "testcases not specifed in params, please provide in params file or 'testcases' commandline argument"
Jon Halld61331b2015-02-17 16:35:47 -0800683 sys.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700684
Hari Krishna03f530e2015-07-10 17:28:27 -0700685def verifyOnosCell(options):
686 # Verifying onoscell option. This could be extended to do even more from here.
687 if options.onoscell:
688 main.onoscell = options.onoscell
689 else :
690 main.onoscell = main.FALSE
691
adminbae64d82013-08-01 10:50:15 -0700692def verifyTestScript(options):
693 '''
694 Verifyies test script.
695 '''
Jon Halld61331b2015-02-17 16:35:47 -0800696 main.openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700697 openspeakfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".ospk"
698 testfile = main.testDir+"/" + main.TEST + "/" + main.TEST + ".py"
699 if os.path.exists(openspeakfile) :
700 main.openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
701 elif os.path.exists(testfile):
702 print ''
703 else:
704 print "\nThere is no :\""+main.TEST+"\" test, Please Provide OpenSpeak Script/ test script"
705 __builtin__.testthread = None
706 main.exit()
adminbae64d82013-08-01 10:50:15 -0700707 try :
adminbae64d82013-08-01 10:50:15 -0700708 testModule = __import__(main.classPath, globals(), locals(), [main.TEST], -1)
709 except(ImportError):
Jon Hallf8ecf732014-12-02 21:14:16 -0500710 print "There was an import error, it might mean that there is no test like "+main.TEST
Jon Halld61331b2015-02-17 16:35:47 -0800711 main.exit()
adminbae64d82013-08-01 10:50:15 -0700712
713 testClass = getattr(testModule, main.TEST)
714 main.testObject = testClass()
715 load_parser()
Jon Halld61331b2015-02-17 16:35:47 -0800716 main.params = main.parser.parseParams(main.classPath)
717 main.topology = main.parser.parseTopology(main.classPath)
kelvin-onlabf70fd542015-05-07 18:41:40 -0700718
adminbae64d82013-08-01 10:50:15 -0700719def verifyParams():
720 try :
721 main.params = main.params['PARAMS']
722 except(KeyError):
723 print "Error with the params file: Either the file not specified or the format is not correct"
Jon Halld61331b2015-02-17 16:35:47 -0800724 main.exit()
adminbae64d82013-08-01 10:50:15 -0700725 try :
726 main.topology = main.topology['TOPOLOGY']
727 except(KeyError):
728 print "Error with the Topology file: Either the file not specified or the format is not correct"
729 main.exit()
kelvin-onlabf70fd542015-05-07 18:41:40 -0700730
adminbae64d82013-08-01 10:50:15 -0700731def load_parser() :
732 '''
733 It facilitates the loading customised parser for topology and params file.
734 It loads parser mentioned in tab named parser of teston.cfg file.
735 It also loads default xmlparser if no parser have specified in teston.cfg file.
736
737 '''
738 confighash = main.configDict
739 if 'file' in confighash['config']['parser'] and 'class' in confighash['config']['parser']:
740 if confighash['config']['parser']['file'] != None or confighash['config']['parser']['class']!= None :
741 if os.path.exists(confighash['config']['parser']['file']) :
742 module = re.sub(r".py\s*$","",confighash['config']['parser']['file'])
743 moduleList = module.split("/")
744 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
745 try :
746 parsingClass = confighash['config']['parser']['class']
747 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
748 parsingClass = getattr(parsingModule, parsingClass)
749 main.parser = parsingClass()
750 #hashobj = main.parser.parseParams(main.classPath)
751 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
adminbae64d82013-08-01 10:50:15 -0700752 pass
753 else:
754 main.exit()
adminbae64d82013-08-01 10:50:15 -0700755 except ImportError:
756 print sys.exc_info()[1]
757 main.exit()
758 else :
759 print "No Such File Exists !!"+ confighash['config']['parser']['file'] +"using default parser"
Jon Halld61331b2015-02-17 16:35:47 -0800760 load_defaultParser()
761 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
762 load_defaultParser()
adminbae64d82013-08-01 10:50:15 -0700763 else:
764 load_defaultParser()
765
766def load_defaultParser():
767 '''
768 It will load the default parser which is xml parser to parse the params and topology file.
769 '''
770 moduleList = main.parserPath.split("/")
771 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
772 try :
Jon Halld61331b2015-02-17 16:35:47 -0800773 parsingClass = main.parsingClass
adminbae64d82013-08-01 10:50:15 -0700774 parsingModule = __import__(newModule, globals(), locals(), [parsingClass], -1)
775 parsingClass = getattr(parsingModule, parsingClass)
776 main.parser = parsingClass()
777 if hasattr(main.parser,"parseParams") and hasattr(main.parser,"parseTopology") and hasattr(main.parser,"parse") :
778 pass
779 else:
780 main.exit()
781
782 except ImportError:
783 print sys.exc_info()[1]
784
adminbae64d82013-08-01 10:50:15 -0700785def load_logger() :
786 '''
787 It facilitates the loading customised parser for topology and params file.
788 It loads parser mentioned in tab named parser of teston.cfg file.
789 It also loads default xmlparser if no parser have specified in teston.cfg file.
790
791 '''
792 confighash = main.configDict
793 if 'file' in confighash['config']['logger'] and 'class' in confighash['config']['logger']:
794 if confighash['config']['logger']['file'] != None or confighash['config']['logger']['class']!= None :
795 if os.path.exists(confighash['config']['logger']['file']) :
796 module = re.sub(r".py\s*$","",confighash['config']['logger']['file'])
797 moduleList = module.split("/")
798 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
799 try :
800 loggerClass = confighash['config']['logger']['class']
801 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
802 loggerClass = getattr(loggerModule, loggerClass)
803 main.logger = loggerClass()
804 #hashobj = main.parser.parseParams(main.classPath)
805
806 except ImportError:
807 print sys.exc_info()[1]
808 else :
809 print "No Such File Exists !!"+confighash['config']['logger']['file']+ "Using default logger"
810 load_defaultlogger()
Jon Halld61331b2015-02-17 16:35:47 -0800811 elif confighash['config']['parser']['file'] == None or confighash['config']['parser']['class'] == None :
812 load_defaultlogger()
adminbae64d82013-08-01 10:50:15 -0700813 else:
814 load_defaultlogger()
815
816def load_defaultlogger():
817 '''
818 It will load the default parser which is xml parser to parse the params and topology file.
819 '''
820 moduleList = main.loggerPath.split("/")
821 newModule = ".".join([moduleList[len(moduleList) - 2],moduleList[len(moduleList) - 1]])
822 try :
Jon Halld61331b2015-02-17 16:35:47 -0800823 loggerClass = main.loggerClass
adminbae64d82013-08-01 10:50:15 -0700824 loggerModule = __import__(newModule, globals(), locals(), [loggerClass], -1)
825 loggerClass = getattr(loggerModule, loggerClass)
826 main.logger = loggerClass()
827
828 except ImportError:
829 print sys.exc_info()[1]
Jon Halld61331b2015-02-17 16:35:47 -0800830 main.exit()
adminbae64d82013-08-01 10:50:15 -0700831
adminbae64d82013-08-01 10:50:15 -0700832def _echo(self):
833 print "THIS IS ECHO"