blob: cdf6c1adc0377c97057ac50678679c4ffab4fd17 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 23-Oct-2012
Jon Hall4ba53f02015-07-29 13:07:41 -07004
adminbae64d82013-08-01 10:50:15 -07005@authors: Anil Kumar (anilkumar.s@paxterrasolutions.com),
6 Raghav Kashyap(raghavkashyap@paxterrasolutions.com)
7
8
9
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
14
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
Jon Hall4ba53f02015-07-29 13:07:41 -070021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
Jon Hall4ba53f02015-07-29 13:07:41 -070023
adminbae64d82013-08-01 10:50:15 -070024Utilities will take care about the basic functions like :
25 * Extended assertion,
26 * parse_args for key-value pair handling
27 * Parsing the params or topology file.
28
29'''
30import re
31from configobj import ConfigObj
adminbae64d82013-08-01 10:50:15 -070032from core import ast as ast
33import smtplib
34
adminbae64d82013-08-01 10:50:15 -070035import email
36import os
37import email.mime.application
38
39class Utilities:
40 '''
41 Utilities will take care about the basic functions like :
42 * Extended assertion,
43 * parse_args for key-value pair handling
44 * Parsing the params or topology file.
45 '''
Jon Hall4ba53f02015-07-29 13:07:41 -070046
adminbae64d82013-08-01 10:50:15 -070047 def __init__(self):
48 self.wrapped = sys.modules[__name__]
49
50 def __getattr__(self, name):
51 '''
52 This will invoke, if the attribute wasn't found the usual ways.
53 Here it will look for assert_attribute and will execute when AttributeError occurs.
54 It will return the result of the assert_attribute.
55 '''
56 try:
57 return getattr(self.wrapped, name)
58 except AttributeError:
59 def assertHandling(**kwargs):
Jon Hall4ba53f02015-07-29 13:07:41 -070060 nameVar = re.match("^assert",name,flags=0)
adminbae64d82013-08-01 10:50:15 -070061 matchVar = re.match("assert(_not_|_)(equals|matches|greater|lesser)",name,flags=0)
62 notVar = 0
63 operators = ""
64
65 try :
66 if matchVar.group(1) == "_not_" and matchVar.group(2) :
67 notVar = 1
68 operators = matchVar.group(2)
69 elif matchVar.group(1) == "_" and matchVar.group(2):
70 operators = matchVar.group(2)
adminbae64d82013-08-01 10:50:15 -070071 except AttributeError:
72 if matchVar==None and nameVar:
73 operators ='equals'
Jon Hall79bec222015-04-30 16:23:30 -070074 result = self._assert(NOT=notVar,operator=operators,**kwargs)
adminbae64d82013-08-01 10:50:15 -070075 if result == main.TRUE:
76 main.log.info("Assertion Passed")
Jon Hall79bec222015-04-30 16:23:30 -070077 main.STEPRESULT = main.TRUE
adminbae64d82013-08-01 10:50:15 -070078 elif result == main.FALSE:
79 main.log.warn("Assertion Failed")
Jon Hall79bec222015-04-30 16:23:30 -070080 main.STEPRESULT = main.FALSE
81 else:
adminbae64d82013-08-01 10:50:15 -070082 main.log.error("There is an Error in Assertion")
Jon Hall79bec222015-04-30 16:23:30 -070083 main.STEPRESULT = main.ERROR
adminbae64d82013-08-01 10:50:15 -070084 return result
adminbae64d82013-08-01 10:50:15 -070085 return assertHandling
Jon Hall79bec222015-04-30 16:23:30 -070086
Jon Hall8ce34e82015-06-05 10:41:45 -070087 def _assert (self,**assertParam):
adminbae64d82013-08-01 10:50:15 -070088 '''
89 It will take the arguments :
Jon Hall8ce34e82015-06-05 10:41:45 -070090 expect:'Expected output'
91 actual:'Actual output'
adminbae64d82013-08-01 10:50:15 -070092 onpass:'Action or string to be triggered or displayed respectively when the assert passed'
93 onfail:'Action or string to be triggered or displayed respectively when the assert failed'
94 not:'optional argument to specify the negation of the each assertion type'
95 operator:'assertion type will be defined by using operator. Like equal , greater, lesser, matches.'
Jon Hall8ce34e82015-06-05 10:41:45 -070096
adminbae64d82013-08-01 10:50:15 -070097 It will return the assertion result.
Jon Hall8ce34e82015-06-05 10:41:45 -070098
adminbae64d82013-08-01 10:50:15 -070099 '''
Jon Hall8ce34e82015-06-05 10:41:45 -0700100
adminbae64d82013-08-01 10:50:15 -0700101 arguments = self.parse_args(["EXPECT","ACTUAL","ONPASS","ONFAIL","NOT","OPERATOR"],**assertParam)
Jon Hall8ce34e82015-06-05 10:41:45 -0700102
adminbae64d82013-08-01 10:50:15 -0700103 result = 0
104 valuetype = ''
105 operation = "not "+ str(arguments["OPERATOR"]) if arguments['NOT'] and arguments['NOT'] == 1 else arguments["OPERATOR"]
106 operators = {'equals':{'STR':'==','NUM':'=='}, 'matches' : '=~', 'greater':'>' ,'lesser':'<'}
Jon Hall8ce34e82015-06-05 10:41:45 -0700107
adminbae64d82013-08-01 10:50:15 -0700108 expectMatch = re.match('^\s*[+-]?0(e0)?\s*$', str(arguments["EXPECT"]), re.I+re.M)
109 if not ((not expectMatch) and (arguments["EXPECT"]==0)):
110 valuetype = 'NUM'
111 else :
112 if arguments["OPERATOR"] == 'greater' or arguments["OPERATOR"] == 'lesser':
113 main.log.error("Numeric comparison on strings is not possibele")
114 return main.ERROR
Jon Hall8ce34e82015-06-05 10:41:45 -0700115
adminbae64d82013-08-01 10:50:15 -0700116 valuetype = 'STR'
117 arguments["ACTUAL"] = str(arguments["ACTUAL"])
118 if arguments["OPERATOR"] != 'matches':
119 arguments["EXPECT"] = str(arguments["EXPECT"])
Jon Hall8ce34e82015-06-05 10:41:45 -0700120
adminbae64d82013-08-01 10:50:15 -0700121 try :
122 opcode = operators[str(arguments["OPERATOR"])][valuetype] if arguments["OPERATOR"] == 'equals' else operators[str(arguments["OPERATOR"])]
Jon Hall8ce34e82015-06-05 10:41:45 -0700123
Jon Hall1306a562015-09-04 11:21:24 -0700124 except KeyError as e:
adminbae64d82013-08-01 10:50:15 -0700125 print "Key Error in assertion"
Jon Hall1306a562015-09-04 11:21:24 -0700126 print e
adminbae64d82013-08-01 10:50:15 -0700127 return main.FALSE
Jon Hall8ce34e82015-06-05 10:41:45 -0700128
adminbae64d82013-08-01 10:50:15 -0700129 if opcode == '=~':
130 try:
131 assert re.search(str(arguments["EXPECT"]),str(arguments["ACTUAL"]))
132 result = main.TRUE
133 except AssertionError:
134 try :
Jon Hall8ce34e82015-06-05 10:41:45 -0700135 assert re.match(str(arguments["EXPECT"]),str(arguments["ACTUAL"]))
adminbae64d82013-08-01 10:50:15 -0700136 result = main.TRUE
137 except AssertionError:
138 main.log.error("Assertion Failed")
139 result = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700140 else :
141 try:
142 if str(opcode)=="==":
143 main.log.info("Verifying the Expected is equal to the actual or not using assert_equal")
144 if (arguments["EXPECT"] == arguments["ACTUAL"]):
145 result = main.TRUE
146 else :
147 result = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700148 elif str(opcode) == ">":
149 main.log.info("Verifying the Expected is Greater than the actual or not using assert_greater")
150 if (ast.literal_eval(arguments["EXPECT"]) > ast.literal_eval(arguments["ACTUAL"])) :
151 result = main.TRUE
152 else :
153 result = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700154 elif str(opcode) == "<":
155 main.log.info("Verifying the Expected is Lesser than the actual or not using assert_lesser")
156 if (ast.literal_eval(arguments["EXPECT"]) < ast.literal_eval(arguments["ACTUAL"])):
157 result = main.TRUE
158 else :
159 result = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700160 except AssertionError:
161 main.log.error("Assertion Failed")
162 result = main.FALSE
adminbae64d82013-08-01 10:50:15 -0700163 result = result if result else 0
164 result = not result if arguments["NOT"] and arguments["NOT"] == 1 else result
165 resultString = ""
166 if result :
167 resultString = str(resultString) + "PASS"
168 main.log.info(arguments["ONPASS"])
169 else :
170 resultString = str(resultString) + "FAIL"
171 if not isinstance(arguments["ONFAIL"],str):
172 eval(str(arguments["ONFAIL"]))
173 else :
174 main.log.error(arguments["ONFAIL"])
175 main.log.report(arguments["ONFAIL"])
Jon Hall90627612015-06-09 14:57:02 -0700176 main.onFailMsg = arguments[ 'ONFAIL' ]
Jon Hall8ce34e82015-06-05 10:41:45 -0700177
adminbae64d82013-08-01 10:50:15 -0700178 msg = arguments["ON" + str(resultString)]
179
180 if not isinstance(msg,str):
181 try:
182 eval(str(msg))
Jon Hall1306a562015-09-04 11:21:24 -0700183 except SyntaxError as e:
184 print "function definition is not right"
185 print e
adminbae64d82013-08-01 10:50:15 -0700186
187 main.last_result = result
Jon Hall80577e72015-09-29 14:07:25 -0700188 if main.stepResults[2]:
189 main.stepResults[2][-1] = result
190 try:
191 main.stepResults[3][-1] = arguments[ 'ONFAIL' ]
192 except AttributeError:
193 pass
194 else:
195 main.log.warn( "Assertion called before a test step" )
adminbae64d82013-08-01 10:50:15 -0700196 return result
Jon Hall8ce34e82015-06-05 10:41:45 -0700197
adminbae64d82013-08-01 10:50:15 -0700198 def parse_args(self,args, **kwargs):
199 '''
200 It will accept the (key,value) pair and will return the (key,value) pairs with keys in uppercase.
201 '''
202 newArgs = {}
203 for key,value in kwargs.iteritems():
adminbae64d82013-08-01 10:50:15 -0700204 if isinstance(args,list) and str.upper(key) in args:
Jon Hall4ba53f02015-07-29 13:07:41 -0700205 for each in args:
adminbae64d82013-08-01 10:50:15 -0700206 if each==str.upper(key):
207 newArgs [str(each)] = value
208 elif each != str.upper(key) and (newArgs.has_key(str(each)) == False ):
209 newArgs[str(each)] = None
Jon Hall4ba53f02015-07-29 13:07:41 -0700210
adminbae64d82013-08-01 10:50:15 -0700211 return newArgs
Jon Hall4ba53f02015-07-29 13:07:41 -0700212
adminbae64d82013-08-01 10:50:15 -0700213 def send_mail(self):
214 # Create a text/plain message
215 msg = email.mime.Multipart.MIMEMultipart()
216 try :
217 if main.test_target:
Jon Hall25079782015-10-13 13:54:39 -0700218 sub = "Result summary of \"" + main.TEST + "\" run on component \"" +\
219 main.test_target + "\" Version \"" +\
220 vars( main )[main.test_target].get_version() + "\": " +\
221 str( main.TOTAL_TC_SUCCESS ) + "% Passed"
adminbae64d82013-08-01 10:50:15 -0700222 else :
Jon Hall25079782015-10-13 13:54:39 -0700223 sub = "Result summary of \"" + main.TEST + "\": " +\
224 str( main.TOTAL_TC_SUCCESS ) + "% Passed"
Jon Hall1306a562015-09-04 11:21:24 -0700225 except ( KeyError, AttributeError ):
Jon Hall25079782015-10-13 13:54:39 -0700226 sub = "Result summary of \"" + main.TEST + "\": " +\
227 str( main.TOTAL_TC_SUCCESS ) + "% Passed"
Jon Hall4ba53f02015-07-29 13:07:41 -0700228
adminbae64d82013-08-01 10:50:15 -0700229 msg['Subject'] = sub
Jon Hall25079782015-10-13 13:54:39 -0700230 msg['From'] = main.sender
adminbae64d82013-08-01 10:50:15 -0700231 msg['To'] = main.mail
Jon Hall4ba53f02015-07-29 13:07:41 -0700232
adminbae64d82013-08-01 10:50:15 -0700233 # The main body is just another attachment
Jon Hall25079782015-10-13 13:54:39 -0700234 body = email.mime.Text.MIMEText( main.logHeader + "\n" +
235 main.testResult)
236 msg.attach( body )
Jon Hall4ba53f02015-07-29 13:07:41 -0700237
Jon Hall25079782015-10-13 13:54:39 -0700238 # Attachments
239 for filename in os.listdir( main.logdir ):
240 filepath = main.logdir + "/" + filename
241 fp = open( filepath, 'rb' )
242 att = email.mime.application.MIMEApplication( fp.read(),
243 _subtype="" )
adminbae64d82013-08-01 10:50:15 -0700244 fp.close()
Jon Hall25079782015-10-13 13:54:39 -0700245 att.add_header( 'Content-Disposition',
246 'attachment',
247 filename=filename )
248 msg.attach( att )
249 try:
250 smtp = smtplib.SMTP( main.smtp )
251 smtp.starttls()
252 smtp.login( main.sender, main.senderPwd )
253 smtp.sendmail( msg['From'], [msg['To']], msg.as_string() )
254 smtp.quit()
255 except Exception:
256 main.log.exception( "Error sending email" )
Jon Hall4ba53f02015-07-29 13:07:41 -0700257 return main.TRUE
258
Jon Hall25079782015-10-13 13:54:39 -0700259 def send_warning_email( self, subject=None ):
260 try:
261 if not subject:
262 subject = main.TEST + " PAUSED!"
263 # Create a text/plain message
264 msg = email.mime.Multipart.MIMEMultipart()
265
266 msg['Subject'] = subject
267 msg['From'] = main.sender
268 msg['To'] = main.mail
269
270 smtp = smtplib.SMTP( main.smtp )
271 smtp.starttls()
272 smtp.login( main.sender, main.senderPwd )
273 smtp.sendmail( msg['From'], [msg['To']], msg.as_string() )
274 smtp.quit()
275 except Exception:
276 main.log.exception( "" )
277 return main.FALSE
278 return main.TRUE
Jon Hall4ba53f02015-07-29 13:07:41 -0700279
adminbae64d82013-08-01 10:50:15 -0700280 def parse(self,fileName):
281 '''
282 This will parse the params or topo or cfg file and return content in the file as Dictionary
283 '''
284 self.fileName = fileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700285 matchFileName = re.match(r'(.*)\.(cfg|params|topo)',self.fileName,re.M|re.I)
adminbae64d82013-08-01 10:50:15 -0700286 if matchFileName:
287 try :
288 parsedInfo = ConfigObj(self.fileName)
289 return parsedInfo
Jon Hall1306a562015-09-04 11:21:24 -0700290 except StandardError:
Jon Hall4ba53f02015-07-29 13:07:41 -0700291 print "There is no such file to parse "+fileName
adminbae64d82013-08-01 10:50:15 -0700292 else:
Jon Hall4ba53f02015-07-29 13:07:41 -0700293 return 0
adminbae64d82013-08-01 10:50:15 -0700294
295
296if __name__ != "__main__":
297 import sys
Jon Hall4ba53f02015-07-29 13:07:41 -0700298
299 sys.modules[__name__] = Utilities()