~ubuntu-branches/ubuntu/maverick/ldtp/maverick

« back to all changes in this revision

Viewing changes to python/ldtputils.py

  • Committer: Bazaar Package Importer
  • Author(s): Kartik Mistry
  • Date: 2010-02-04 10:36:08 UTC
  • mfrom: (1.4.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: james.westby@ubuntu.com-20100204103608-dhqdo7jk10ygwt40
Tags: 2.0.2-1
* New upstream release:
  + Packaging is based on Ubuntu packages, Thanks Ubuntu!
  + LDTPv2 is a complete rewrite of LDTPv1 in Python
  + LTFX is completely removed in LDTP v2 in favor of wnck
* debian/control:
  + Updated to Standards-Version 3.8.4 (no changes needed)
  + Fixed typo in description python->Python
  + ldtp is now arch: all package
* debian/rules:
  + Using dh to make it simple
* Removed unused manpages
* Updated package to use new source format 3.0 (quilt)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#############################################################################
2
 
#
3
 
#  Linux Desktop Testing Project http://ldtp.freedesktop.org
4
 
5
 
#  Author:
6
 
#     M Nagashree <mnagashree@novell.com>
7
 
#     Veerapuram Varadhan <v.varadhan@gmail.com>
8
 
#     Nagappan Alagappan <nagappan@gmail.com>
9
 
10
 
#  Copyright 2004 - 2006 Novell, Inc.
11
 
#  Copyright 2007 - 2009 Nagappan Alagappan
12
 
13
 
#  This library is free software; you can redistribute it and/or
14
 
#  modify it under the terms of the GNU Library General Public
15
 
#  License as published by the Free Software Foundation; either
16
 
#  version 2 of the License, or (at your option) any later version.
17
 
18
 
#  This library is distributed in the hope that it will be useful,
19
 
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
 
#  Library General Public License for more details.
22
 
23
 
#  You should have received a copy of the GNU Library General Public
24
 
#  License along with this library; if not, write to the
25
 
#  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26
 
#  Boston, MA 02110, USA.
27
 
#
28
 
#############################################################################
29
 
 
30
 
import gc
31
 
import os
32
 
import re
33
 
import sys
34
 
import time
35
 
import string
36
 
import thread
37
 
import fnmatch
38
 
import commands
39
 
import tempfile
40
 
import traceback
41
 
import threading
42
 
import xml.dom.minidom
43
 
 
44
 
# Let us not register our application under at-spi application list
45
 
os.environ ['GTK_MODULES'] = ''
46
 
 
47
 
import ldtp
48
 
 
49
 
_ldtpDebug = os.getenv('LDTP_DEBUG')
50
 
 
51
 
statGrabMsg = None
52
 
try:
53
 
    import statgrab
54
 
except ImportError:
55
 
    statGrabMsg = 'pystatgrab package not installed'
56
 
 
57
 
def tuplelist2list(lst):
58
 
        d = []
59
 
        for x in range(1, len(lst) + 1):
60
 
                for y in range(1, len(lst[x-1]) + 1):
61
 
                        d.append(lst[x-1][y-1])
62
 
        return d
63
 
 
64
 
def getFullPath(path):
65
 
    if path [0] == "~":
66
 
        path = os.path.expanduser(path)
67
 
    elif path [0] == ".":
68
 
        path = os.path.abspath(path)
69
 
 
70
 
    return path
71
 
 
72
 
def imagecompare(imgfile1, imgfile2):
73
 
    try:
74
 
        import ImageChops, Image
75
 
    except ImportError:
76
 
        ldtp.log('Python-Imaging package not installed', 'error')
77
 
        raise ldtp.LdtpExecutionError('Python-Imaging package not installed')
78
 
    try:
79
 
        diffcount = 0.0
80
 
        im1 = Image.open(imgfile1)
81
 
        im2 = Image.open(imgfile2)
82
 
 
83
 
        imgcompdiff = ImageChops.difference(im1, im2)
84
 
        diffboundrect = imgcompdiff.getbbox()
85
 
        imgdiffcrop = imgcompdiff.crop(diffboundrect)
86
 
 
87
 
        seq = list(imgdiffcrop.getdata())
88
 
        seq = tuplelist2list(seq)
89
 
        #print seq
90
 
        for i in range(0, imgdiffcrop.size[0] * imgdiffcrop.size[1] * 3, 3):
91
 
            if seq[i] != 0 or seq[i+1] != 0 or seq[i+2] != 0:
92
 
                diffcount = diffcount + 1.0
93
 
        
94
 
        diffImgLen = imgcompdiff.size[0] * imgcompdiff.size[1] * 1.0
95
 
        diffpercent = (diffcount * 100) / diffImgLen
96
 
        ldtp.log('length ' + str(diffImgLen))
97
 
        ldtp.log('diffcount ' + str(diffcount))
98
 
        ldtp.log('diff percent ' + str(diffpercent))
99
 
        return diffpercent
100
 
    except IOError:
101
 
        ldtp.log('Input file does not exist', 'error')
102
 
        raise ldtp.LdtpExecutionError('Input file does not exist')
103
 
 
104
 
def imagecapture(winName = None, outFile = None, width = None,
105
 
                  height = None, x = 0, y = 0):
106
 
    # winname == None, let us capture the entire screen
107
 
    # if output file name is not passed, then a random file name will be generated in
108
 
    # /tmp and it will be returned
109
 
    gtkImport = False
110
 
    tmpFile = None
111
 
    try:
112
 
        import gtk.gdk
113
 
        import gobject
114
 
        gobject.threads_init()
115
 
        gtkImport = True
116
 
    except ImportError:
117
 
        if _ldtpDebug:
118
 
            print 'pygtk package not installed'
119
 
    
120
 
    wnckImport = False
121
 
    try:
122
 
        import wnck
123
 
        wnckImport = True
124
 
    except ImportError:
125
 
        if _ldtpDebug:
126
 
            print 'wnck python package not installed'
127
 
 
128
 
    class ImageCapture:
129
 
        def __init__(self):
130
 
            self.count = 0
131
 
            self.tmpFile = None
132
 
 
133
 
        def getWinId(self, winName):
134
 
            if not wnckImport:
135
 
                ldtp.log('wnck package not installed, screen capture ' \
136
 
                              'disabled based on window name',
137
 
                          'warning')
138
 
                return False
139
 
 
140
 
            screen = wnck.screen_get_default()
141
 
            winid = None
142
 
            for window in screen.get_windows():
143
 
                if re.search(winName, window.get_name()):
144
 
                    winid = window.get_xid()
145
 
                    # Activate the window 
146
 
                    # http://faq.pygtk.org/index.py?req=show&file=faq10.027.htp
147
 
                    window.activate(gtk.get_current_event_time())
148
 
                    break
149
 
            return winid
150
 
 
151
 
        def generateTmpFile(self):
152
 
            if not outFile:
153
 
                fp = tempfile.NamedTemporaryFile()
154
 
                self.tmpFile = fp.name + '.png'
155
 
                fp.close()
156
 
            else:
157
 
                self.tmpFile = outFile
158
 
 
159
 
        def capturescreenshot(self):
160
 
            winid = None
161
 
            if self.count > 3:
162
 
                gtk.main_quit()
163
 
            self.count += 1
164
 
            if winName:
165
 
                winid = self.getWinId(winName)
166
 
                if not winid:
167
 
                    return True
168
 
 
169
 
            pb = None
170
 
            if gtkImport:
171
 
                if not winid:
172
 
                    # Based on http://ubuntuforums.org/showthread.php?t=448160
173
 
                    window = gtk.gdk.get_default_root_window()
174
 
                    size = window.get_size()
175
 
                    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 
176
 
                                         width or size [0], 
177
 
                                         height or size [1])
178
 
                    pb = pb.get_from_drawable(window, window.get_colormap(),
179
 
                                               x, y, 0, 0, 
180
 
                                               width or size [0],
181
 
                                               height or size [1])
182
 
            self.generateTmpFile()
183
 
            if pb:
184
 
                pb.save(self.tmpFile, "png")
185
 
                # based on http://faq.pygtk.org/index.py?req=show&file=faq08.004.htp
186
 
                del pb
187
 
                gc.collect()
188
 
            else:
189
 
                if  winid == None:
190
 
                    winid = 'root'
191
 
                cmd = "import -window %s" % winid
192
 
                if width and height:
193
 
                    cmd = "%s -crop %dx%d+%d+%d" % (cmd, width,
194
 
                                                    height, x, y)
195
 
                cmd = "%s %s" % (cmd, self.tmpFile)
196
 
                status = commands.getstatusoutput(cmd)
197
 
                if status [0] != 0:
198
 
                    ldtp.log('Unable to capture screenshot: %s' % status [1], 'error')
199
 
                    self.tmpFile = None
200
 
            gtk.main_quit()
201
 
        
202
 
 
203
 
    screenshot = ImageCapture()
204
 
    if gtkImport:
205
 
        gobject.idle_add(screenshot.capturescreenshot)
206
 
        #gobject.idle_add(gtk.main_quit)
207
 
        gtk.main()
208
 
    return screenshot.tmpFile
209
 
 
210
 
def _wnckFunction(wnckFunctionName, windowName = None):
211
 
    gtkImport = False
212
 
    try:
213
 
        import gtk.gdk
214
 
        import gobject
215
 
        gobject.threads_init()
216
 
        gtkImport = True
217
 
    except ImportError:
218
 
        if _ldtpDebug:
219
 
            print 'pygtk package not installed'
220
 
        return False
221
 
    
222
 
    wnckImport = False
223
 
    try:
224
 
        import wnck
225
 
        wnckImport = True
226
 
    except ImportError:
227
 
        if _ldtpDebug:
228
 
            print 'wnck python package not installed'
229
 
        return False
230
 
 
231
 
    class _wnckInternal:
232
 
        def __init__(self, windowName = None):
233
 
            self.count = 0
234
 
            self.windowName = windowName
235
 
 
236
 
        def _operateOnWindow(self, wnckFunctionName):
237
 
            screen = wnck.screen_get_default()
238
 
            windowList = screen.get_windows()
239
 
            self.count += 1
240
 
            if not windowList:
241
 
                if self.count <= 3:
242
 
                    return True
243
 
            for w in windowList:
244
 
                if windowName:
245
 
                    _currentWindow = w.get_name()
246
 
                    if re.search(fnmatch.translate(windowName), _currentWindow, re.I) or \
247
 
                            re.search(fnmatch.translate(windowName),
248
 
                                      re.sub(" *\t*\n*", "", _currentWindow), re.I):
249
 
                        if wnckFunctionName not in dir(w):
250
 
                            break
251
 
                        function = getattr(w, wnckFunctionName)
252
 
                        if wnckFunctionName == 'activate':
253
 
                            function(0L)
254
 
                        else:
255
 
                            function()
256
 
                        break
257
 
                else:
258
 
                    if wnckFunctionName not in dir(w):
259
 
                        continue
260
 
                    function = getattr(w, wnckFunctionName)
261
 
                    function()
262
 
            gtk.main_quit()
263
 
    
264
 
    _wnckInst = _wnckInternal(windowName)
265
 
    gobject.idle_add(_wnckInst._operateOnWindow, wnckFunctionName)
266
 
    #gobject.idle_add(gtk.main_quit)
267
 
    gtk.main()
268
 
 
269
 
def activatewindow(windowName = None):
270
 
    _wnckFunction('activate', windowName)
271
 
 
272
 
def minimizewindow(windowName = None):
273
 
    _wnckFunction('minimize', windowName)
274
 
 
275
 
def maximizewindow(windowName = None):
276
 
    _wnckFunction('maximize', windowName)
277
 
 
278
 
def closewindow(windowName):
279
 
    _wnckFunction('close', windowName)
280
 
 
281
 
def blackoutregion(infile, outfile, topx, topy, botx, boty):
282
 
    try:
283
 
        import ImageChops, Image
284
 
    except ImportError:
285
 
        ldtp.log('Python-Imaging package not installed', 'error')
286
 
        raise ldtp.LdtpExecutionError('Python-Imaging package not installed')
287
 
    im = Image.open(infile)
288
 
    box = (topx, topy, botx, boty)
289
 
    region = im.crop(box)
290
 
    region = region.point(lambda i: i * 0)
291
 
    im.paste(region, box)
292
 
    im.save(outfile)
293
 
 
294
 
# XML Data file parser
295
 
class LdtpDataFileParser:
296
 
    def __init__(self, filename = None):
297
 
        self.ldtpdataxml = []
298
 
        if filename:
299
 
            try:
300
 
                dom = xml.dom.minidom.parse(filename)
301
 
                self.ldtpdataxml = dom.getElementsByTagName("data")
302
 
                if self.ldtpdataxml == []:
303
 
                    ldtp.log('data xml tag not present')
304
 
                    if _ldtpDebug and _ldtpDebug == '2':
305
 
                        print 'data xml tag not present'
306
 
            except xml.parsers.expat.ExpatError, msg:
307
 
                ldtp.log('XML Error: ' + str(msg), 'error')
308
 
            except IOError:
309
 
                ldtp.log('XML \"' + filename + '\" file not found', 'error')
310
 
    def setfilename(self, filename):
311
 
        self.ldtpdataxml = []
312
 
        if filename:
313
 
            try:
314
 
                dom = xml.dom.minidom.parse(filename)
315
 
                self.ldtpdataxml = dom.getElementsByTagName("data")
316
 
                if self.ldtpdataxml == []:
317
 
                    ldtp.log('data xml tag not present')
318
 
                    if _ldtpDebug and _ldtpDebug == '2':
319
 
                        print 'data xml tag not present'
320
 
            except xml.parsers.expat.ExpatError, msg:
321
 
                if _ldtpDebug and _ldtpDebug == '2':
322
 
                    print 'XML Error: ' + str(msg)
323
 
                ldtp.log('XML Error: ' + str(msg), 'error')
324
 
            except IOError:
325
 
                if _ldtpDebug and _ldtpDebug == '2':
326
 
                    print 'XML \"' + filename + '\" file not found'
327
 
                ldtp.log('XML \"' + filename + '\" file not found', 'error')
328
 
    def getText(self, nodelist):
329
 
        rc = ""
330
 
        for node in nodelist:
331
 
            if node.nodeType == node.TEXT_NODE:
332
 
                rc = rc + node.data
333
 
        return rc
334
 
    def gettagvalue(self, tagname):
335
 
        self.taglist = []
336
 
        if self.ldtpdataxml == []:
337
 
            return self.taglist
338
 
        for dataelements in self.ldtpdataxml:
339
 
            for data in dataelements.getElementsByTagName(tagname):
340
 
                self.taglist.append(self.getText(data.childNodes))
341
 
        return self.taglist
342
 
 
343
 
class pstats(threading.Thread):
344
 
    """Capturing Memory and CPU Utilization statistics for an application and its related processes
345
 
    EXAMPLE USAGE:
346
 
        xstats = pstats('evolution', 2)
347
 
        # Start Logging by calling start
348
 
        xstats.start()
349
 
        # Stop the process statistics gathering thread by calling the stopstats method
350
 
        xstats.stop()"""
351
 
 
352
 
    def __init__(self, appname, inter = 2):
353
 
        if statGrabMsg is not None:
354
 
            ldtp.log(statGrabMsg, 'error')
355
 
            raise ldtp.LdtpExecutionError(statGrabMsg)
356
 
        threading.Thread.__init__(self)
357
 
        self.processname = appname
358
 
        self.interval = inter
359
 
        self.stop_flag = 0
360
 
    def run(self):
361
 
        while self.stop_flag == 0:
362
 
            for i in statgrab.sg_get_process_stats():
363
 
                if self.stop_flag == 1:
364
 
                    break
365
 
                result = re.search(self.processname, str(i['process_name']))
366
 
                if result:
367
 
                    title = str(i['proctitle'])
368
 
                    proctitle = re.split("\s", title)
369
 
                    procname = re.split("\/", proctitle[0])
370
 
                    # Put the stats into ldtp log file    
371
 
                    ldtp.log(procname[-1] + ' - ' + str(i['proc_resident'] / (1024*1024)) + 'M',
372
 
                          'meminfo')
373
 
                    ldtp.log(procname[-1] + ' - ' + str(round(i['cpu_percent'], 2)),
374
 
                          'cpuinfo')
375
 
            # Wait for interval seconds before gathering stats again
376
 
            time.sleep(self.interval)
377
 
 
378
 
    def stop(self):
379
 
        self.stop_flag = 1
380
 
 
381
 
############# Application Functions #################
382
 
 
383
 
def execute(cmd):
384
 
    status = commands.getstatusoutput(cmd)
385
 
    if status[0] != 0:
386
 
        ldtp.log(status[1], 'error')
387
 
        raise ldtp.LdtpExecutionError(status[1])
388
 
    return 1
389
 
    
390
 
########### LTFX Functions ###############
391
 
def getactivewin():
392
 
    #Get currently active window title name
393
 
    cmd = "ltfx -e 'get_active_win'"
394
 
    status = commands.getstatusoutput(cmd)
395
 
    if status[0] != 0:
396
 
        ldtp.log(status[1], 'error')
397
 
        raise ldtp.LdtpExecutionError(status[1])
398
 
    return status[1]
399
 
    
400
 
def windowexists(window_name):
401
 
    #Check window name exists with the given name
402
 
    cmd = "ltfx -e \'win_exists \"" +  window_name + "\"\'"
403
 
    return execute(cmd)
404
 
 
405
 
def partialexists(window_name):
406
 
    #Check window name exists with the given partial name
407
 
    cmd = "ltfx -e \'win_exists_partial \"" +  window_name + "\"\'"
408
 
    return execute(cmd)
409
 
 
410
 
def activatewinpartialname(window_name):
411
 
    # Set active window based on the given partial name"
412
 
    cmd = "ltfx -e \'activate_win_partial \"" +  window_name + "\"\'"
413
 
    return execute(cmd)
414
 
 
415
 
def activatewin(window_name):
416
 
    #Set active window based on the given name
417
 
    cmd = "ltfx -e \'activate_win \"" +  window_name + "\"\'"    
418
 
    return execute(cmd)
419
 
 
420
 
def activatewinid(window_id):
421
 
    #Set active window based on the given window-id
422
 
    cmd = "ltfx -e \'activate_win_id \"" +  window_id + "\"\'"    
423
 
    return execute(cmd)
424
 
 
425
 
def closewindow(window_name):
426
 
    #Close the window with the given title
427
 
    return 0
428
 
 
429
 
def waitwinname(window_name):
430
 
    #Wait for window with name to appear
431
 
    cmd = "ltfx -e 'wait_for_win \"" +  window_name + "\"\'"    
432
 
    return execute(cmd)
433
 
 
434
 
def waitwinpartialname(window_name):
435
 
    #Wait for window with partial name to appear
436
 
    cmd = "ltfx -e 'wait_for_win_partial \"" +  window_name + "\"\'"    
437
 
    return execute(cmd)
438
 
 
439
 
def waitwinclose(window_name):
440
 
    #Wait for window to close with the given name
441
 
    cmd = "ltfx -e 'wait_for_close \"" +  window_name + "\"\'"    
442
 
    return execute(cmd)
443
 
 
444
 
def waitwinpartialclose(window_name):
445
 
    #Wait for window to close with the given partial name
446
 
    cmd = "ltfx -e 'wait_for_close_partial \"" +  window_name + "\"\'"        
447
 
    return execute(cmd)
448
 
 
449
 
def typekey(window_name):
450
 
    #Type the given text in the focused window
451
 
    cmd = "ltfx -e 'type \"" +  window_name + "\"\'"    
452
 
    return execute(cmd)