[tracker/rss-enclosures] Adding common infrastructure for the new tests
- From: Roberto Guido <rguido src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/rss-enclosures] Adding common infrastructure for the new tests
- Date: Wed, 24 Nov 2010 01:23:02 +0000 (UTC)
commit 29187f500ccd09f8bd750a9be08acc7bbaad89db
Author: Ivan Frade <ivan frade nokia com>
Date: Wed Aug 18 18:20:43 2010 +0300
Adding common infrastructure for the new tests
tests/functional-tests/common/Makefile.am | 5 +
.../common/data/Doc/performance.doc | Bin 0 -> 82944 bytes
.../common/data/Images/Makefile.am | 10 +
.../common/data/Images/test-image-1.jpg | Bin 0 -> 7558 bytes
.../common/data/Images/test-image-2.png | Bin 0 -> 2374 bytes
.../common/data/Images/test-image-3.tif | Bin 0 -> 4594 bytes
tests/functional-tests/common/data/Makefile.am | 15 +
.../functional-tests/common/data/Music/Makefile.am | 8 +
.../common/data/Music/tracker-mp3-test.mp3 | Bin 0 -> 61547 bytes
.../common/data/Pdf/office-tools-test-document.pdf | Bin 0 -> 236639 bytes
tests/functional-tests/common/data/Ppt/al-cont.ppt | Bin 0 -> 1508864 bytes
.../functional-tests/common/data/Video/Makefile.am | 10 +
.../common/data/Video/test-video.mp4 | Bin 0 -> 211931 bytes
tests/functional-tests/common/data/pickled_Images | Bin 0 -> 1203 bytes
tests/functional-tests/common/data/pickled_Music | Bin 0 -> 877 bytes
tests/functional-tests/common/utils/.gitignore | 1 +
tests/functional-tests/common/utils/Makefile.am | 16 +
.../common/utils/configuration.py.in | 75 +++++
.../common/utils/expectedFailure.py | 48 +++
tests/functional-tests/common/utils/helpers.py | 281 +++++++++++++++++
tests/functional-tests/common/utils/html.py | 64 ++++
tests/functional-tests/common/utils/minertest.py | 99 ++++++
tests/functional-tests/common/utils/storetest.py | 47 +++
tests/functional-tests/common/utils/system.py | 329 ++++++++++++++++++++
24 files changed, 1008 insertions(+), 0 deletions(-)
---
diff --git a/tests/functional-tests/common/Makefile.am b/tests/functional-tests/common/Makefile.am
new file mode 100644
index 0000000..a29a93c
--- /dev/null
+++ b/tests/functional-tests/common/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = utils
+
+commondir = $(datadir)/tracker-tests/common
+
+common_SCRIPTS = __init__.py
\ No newline at end of file
diff --git a/tests/functional-tests/common/__init__.py b/tests/functional-tests/common/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/functional-tests/common/data/Doc/performance.doc b/tests/functional-tests/common/data/Doc/performance.doc
new file mode 100644
index 0000000..8450cdd
Binary files /dev/null and b/tests/functional-tests/common/data/Doc/performance.doc differ
diff --git a/tests/functional-tests/common/data/Images/Makefile.am b/tests/functional-tests/common/data/Images/Makefile.am
new file mode 100644
index 0000000..69d089e
--- /dev/null
+++ b/tests/functional-tests/common/data/Images/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/Makefile.decl
+
+configdir = $(datadir)/tracker-tests/data/Images
+
+config_DATA = \
+ test-image-1.jpg \
+ test-image-2.png \
+ test-image-3.tif
+
+EXTRA_DIST = $(config_DATA)
diff --git a/tests/functional-tests/common/data/Images/test-image-1.jpg b/tests/functional-tests/common/data/Images/test-image-1.jpg
new file mode 100644
index 0000000..f1f917b
Binary files /dev/null and b/tests/functional-tests/common/data/Images/test-image-1.jpg differ
diff --git a/tests/functional-tests/common/data/Images/test-image-2.png b/tests/functional-tests/common/data/Images/test-image-2.png
new file mode 100644
index 0000000..7ff9788
Binary files /dev/null and b/tests/functional-tests/common/data/Images/test-image-2.png differ
diff --git a/tests/functional-tests/common/data/Images/test-image-3.tif b/tests/functional-tests/common/data/Images/test-image-3.tif
new file mode 100644
index 0000000..8d91556
Binary files /dev/null and b/tests/functional-tests/common/data/Images/test-image-3.tif differ
diff --git a/tests/functional-tests/common/data/Makefile.am b/tests/functional-tests/common/data/Makefile.am
new file mode 100644
index 0000000..231f058
--- /dev/null
+++ b/tests/functional-tests/common/data/Makefile.am
@@ -0,0 +1,15 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS = \
+ Music \
+ Video \
+ Images \
+ Text
+
+configdir = $(datadir)/tracker-tests/data
+
+config_DATA = \
+ pickled_Music \
+ pickled_Images
+
+EXTRA_DIST = $(config_DATA)
diff --git a/tests/functional-tests/common/data/Music/Makefile.am b/tests/functional-tests/common/data/Music/Makefile.am
new file mode 100644
index 0000000..0166f9f
--- /dev/null
+++ b/tests/functional-tests/common/data/Music/Makefile.am
@@ -0,0 +1,8 @@
+include $(top_srcdir)/Makefile.decl
+
+configdir = $(datadir)/tracker-tests/data/Music
+
+config_DATA = \
+ tracker-mp3-test.mp3
+
+EXTRA_DIST = $(config_DATA)
diff --git a/tests/functional-tests/common/data/Music/tracker-mp3-test.mp3 b/tests/functional-tests/common/data/Music/tracker-mp3-test.mp3
new file mode 100644
index 0000000..bbd4c76
Binary files /dev/null and b/tests/functional-tests/common/data/Music/tracker-mp3-test.mp3 differ
diff --git a/tests/functional-tests/common/data/Pdf/office-tools-test-document.pdf b/tests/functional-tests/common/data/Pdf/office-tools-test-document.pdf
new file mode 100644
index 0000000..064645c
Binary files /dev/null and b/tests/functional-tests/common/data/Pdf/office-tools-test-document.pdf differ
diff --git a/tests/functional-tests/common/data/Ppt/al-cont.ppt b/tests/functional-tests/common/data/Ppt/al-cont.ppt
new file mode 100644
index 0000000..2fc0a73
Binary files /dev/null and b/tests/functional-tests/common/data/Ppt/al-cont.ppt differ
diff --git a/tests/functional-tests/common/data/Video/Makefile.am b/tests/functional-tests/common/data/Video/Makefile.am
new file mode 100644
index 0000000..fafae7d
--- /dev/null
+++ b/tests/functional-tests/common/data/Video/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/Makefile.decl
+
+if DIST_FUNCTIONAL_TESTS
+configdir = $(datadir)/tracker-tests/data/Video
+
+config_DATA = \
+ test-video.mp4
+
+EXTRA_DIST = $(config_DATA)
+endif
diff --git a/tests/functional-tests/common/data/Video/test-video.mp4 b/tests/functional-tests/common/data/Video/test-video.mp4
new file mode 100644
index 0000000..915e4be
Binary files /dev/null and b/tests/functional-tests/common/data/Video/test-video.mp4 differ
diff --git a/tests/functional-tests/common/data/pickled_Images b/tests/functional-tests/common/data/pickled_Images
new file mode 100644
index 0000000..330cf46
Binary files /dev/null and b/tests/functional-tests/common/data/pickled_Images differ
diff --git a/tests/functional-tests/common/data/pickled_Music b/tests/functional-tests/common/data/pickled_Music
new file mode 100644
index 0000000..1913fc4
Binary files /dev/null and b/tests/functional-tests/common/data/pickled_Music differ
diff --git a/tests/functional-tests/common/utils/.gitignore b/tests/functional-tests/common/utils/.gitignore
new file mode 100644
index 0000000..7c0b746
--- /dev/null
+++ b/tests/functional-tests/common/utils/.gitignore
@@ -0,0 +1 @@
+configuration.py
diff --git a/tests/functional-tests/common/utils/Makefile.am b/tests/functional-tests/common/utils/Makefile.am
new file mode 100644
index 0000000..8223d2f
--- /dev/null
+++ b/tests/functional-tests/common/utils/Makefile.am
@@ -0,0 +1,16 @@
+include $(top_srcdir)/Makefile.decl
+
+utilsdir = $(datadir)/tracker-tests/common/utils
+
+utils_SCRIPTS = \
+ __init__.py \
+ configuration.py \
+ expectedFailure.py \
+ helpers.py \
+ storetest.py \
+ minertest.py \
+ system.py
+
+EXTRA_DIST = \
+ configuration.py.in \
+ $(utils_SCRIPTS)
diff --git a/tests/functional-tests/common/utils/__init__.py b/tests/functional-tests/common/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/functional-tests/common/utils/configuration.py.in b/tests/functional-tests/common/utils/configuration.py.in
new file mode 100644
index 0000000..d745dd4
--- /dev/null
+++ b/tests/functional-tests/common/utils/configuration.py.in
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2010, Nokia <jean-luc lamadon nokia com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+"Constants describing Tracker D-Bus services"
+
+import os
+
+TRACKER_BUSNAME = 'org.freedesktop.Tracker1'
+TRACKER_OBJ_PATH = '/org/freedesktop/Tracker1/Resources'
+RESOURCES_IFACE = "org.freedesktop.Tracker1.Resources"
+
+MINERFS_BUSNAME = "org.freedesktop.Tracker1.Miner.Files"
+MINERFS_OBJ_PATH = "/org/freedesktop/Tracker1/Miner/Files"
+MINER_IFACE = "org.freedesktop.Tracker1.Miner"
+
+TRACKER_BACKUP_OBJ_PATH = "/org/freedesktop/Tracker1/Backup"
+BACKUP_IFACE = "org.freedesktop.Tracker1.Backup"
+
+TRACKER_EXTRACT_BUSNAME = "org.freedesktop.Tracker1.Extract"
+TRACKER_EXTRACT_OBJ_PATH = "/org/freedesktop/Tracker1/Extract"
+TRACKER_EXTRACT_IFACE = "org.freedesktop.Tracker1.Extract"
+
+WRITEBACK_BUSNAME = "org.freedesktop.Tracker1.Writeback"
+
+def expandvars (variable):
+ # Note: the order matters!
+ result = variable
+ for var, value in [("${datarootdir}", RAW_DATAROOT_DIR),
+ ("${exec_prefix}", RAW_EXEC_PREFIX),
+ ("${prefix}", PREFIX)]:
+ result = result.replace (var, value)
+
+
+ return result
+
+
+
+PREFIX = "@prefix@"
+#
+# This raw variables are set by autotools without translating vars:
+# E.G. bindir='${exec_prefix}/bin
+#
+# So we do the translation by hand in the expandvars function
+#
+RAW_EXEC_PREFIX = "@exec_prefix@"
+RAW_EXEC_DIR = "@libexecdir@"
+RAW_DATA_DIR = "@datadir@"
+RAW_DATAROOT_DIR = "@datarootdir@"
+RAW_BINDIR = "@bindir@"
+
+EXEC_PREFIX = os.path.normpath (expandvars (RAW_EXEC_DIR))
+DATADIR = os.path.normpath (expandvars (RAW_DATA_DIR))
+BINDIR = os.path.normpath (expandvars (RAW_BINDIR))
+
+haveMaemo = ("@HAVE_MAEMO_TRUE@" == "")
+
+TEST_TMP_DIR = os.path.join (os.environ["HOME"], ".tracker-tests")
+
diff --git a/tests/functional-tests/common/utils/expectedFailure.py b/tests/functional-tests/common/utils/expectedFailure.py
new file mode 100644
index 0000000..f8ced47
--- /dev/null
+++ b/tests/functional-tests/common/utils/expectedFailure.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+
+## Code taken and modified from unittest2 framework (case.py)
+
+## Copyright (c) 1999-2003 Steve Purcell
+## Copyright (c) 2003-2010 Python Software Foundation
+## Copyright (c) 2010, Nokia (ivan frade nokia com)
+
+## This module is free software, and you may redistribute it and/or modify
+## it under the same terms as Python itself, so long as this copyright message
+## and disclaimer are retained in their original form.
+
+## IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+## SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+## THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+## DAMAGE.
+
+## THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+## PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+## AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+## SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+"""
+Write values in tracker and check the actual values are written
+on the files. Note that these tests are highly platform dependant.
+"""
+import sys
+import unittest2 as ut
+from unittest2.compatibility import wraps
+
+def expectedFailureBug(bugnumber):
+ """
+ Decorator to mark bugs with ExpectedFailure. In case that a expected failure PASS
+ it will raise an exception pointing to the Bug number.
+
+ Keep your bugs and tests in sync!
+ """
+ def decorator (func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ func(*args, **kwargs)
+ except Exception:
+ raise ut.case._ExpectedFailure(sys.exc_info())
+ raise Exception ("Unexpected success. This should fail because of bug " +str(bugnumber))
+ return wrapper
+ return decorator
diff --git a/tests/functional-tests/common/utils/helpers.py b/tests/functional-tests/common/utils/helpers.py
new file mode 100644
index 0000000..b3b78be
--- /dev/null
+++ b/tests/functional-tests/common/utils/helpers.py
@@ -0,0 +1,281 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2010, Nokia <jean-luc lamadon nokia com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+import dbus
+import gobject
+import commands
+import os
+import signal
+from dbus.mainloop.glib import DBusGMainLoop
+import configuration as cfg
+import re
+
+class StoreHelper:
+ """
+ Wrapper for the Store API
+
+ Every method tries to reconnect once if there is a dbus exception
+ (some tests kill the daemon and make the connection useless)
+ """
+
+ def __init__ (self):
+ self.connect ()
+
+ def connect (self):
+ dbus_loop = DBusGMainLoop(set_as_default=True)
+ bus = dbus.SessionBus (mainloop=dbus_loop)
+ tracker = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_OBJ_PATH)
+ self.resources = dbus.Interface (tracker,
+ dbus_interface=cfg.RESOURCES_IFACE)
+ tracker_backup = bus.get_object (cfg.TRACKER_BUSNAME, cfg.TRACKER_BACKUP_OBJ_PATH)
+ self.backup_iface = dbus.Interface (tracker_backup, dbus_interface=cfg.BACKUP_IFACE)
+
+ def query (self, query, timeout=5000):
+ try:
+ return self.resources.SparqlQuery (query, timeout=timeout)
+ except dbus.DBusException:
+ self.connect ()
+ return self.resources.SparqlQuery (query, timeout=timeout)
+
+ def update (self, update_sparql, timeout=5000):
+ try:
+ return self.resources.SparqlUpdate (update_sparql, timeout=timeout)
+ except dbus.DBusException:
+ self.connect ()
+ return self.resources.SparqlUpdate (update_sparql, timeout=timeout)
+
+ def batch_update (self, update_sparql):
+ try:
+ return self.resources.BatchSparqlUpdate (update_sparql)
+ except dbus.DBusException:
+ self.connect ()
+ return self.resources.BatchSparqlUpdate (update_sparql)
+
+ def batch_commit (self):
+ return self.resources.BatchCommit ()
+
+ def backup (self, backup_file):
+ try:
+ self.backup_iface.Save (backup_file)
+ except dbus.DBusException:
+ self.connect ()
+ self.backup_iface.Save (backup_file)
+
+ def restore (self, backup_file):
+ try:
+ return self.backup_iface.Restore (backup_file)
+ except dbus.DBusException:
+ self.connect ()
+ return self.backup_iface.Restore (backup_file)
+
+ def get_tracker_iface (self):
+ return self.resources
+
+ def count_instances (self, ontology_class):
+ QUERY = """
+ SELECT COUNT(?u) WHERE {
+ ?u a %s .
+ }
+ """
+ try:
+ result = self.resources.SparqlQuery (QUERY % (ontology_class))
+ except dbus.DBusException:
+ self.connect ()
+ result = self.resources.SparqlQuery (QUERY % (ontology_class))
+
+ if (len (result) == 1):
+ return int (result [0][0])
+ else:
+ return -1
+
+
+class MinerHelper ():
+
+ def __init__ (self):
+ self.connect ()
+
+ def connect (self):
+ dbus_loop = DBusGMainLoop(set_as_default=True)
+ bus = dbus.SessionBus (mainloop=dbus_loop)
+ minerfs = bus.get_object (cfg.MINERFS_BUSNAME, cfg.MINERFS_OBJ_PATH)
+ self.miner_fs = dbus.Interface (minerfs,
+ dbus_interface=cfg.MINER_IFACE)
+
+ def ignore (self, filelist):
+ self.miner_fs.IgnoreNextUpdate (filelist)
+
+
+class ExtractorHelper ():
+
+ def __init__ (self):
+ self.connect ()
+
+ def connect (self):
+ dbus_loop = DBusGMainLoop(set_as_default=True)
+ bus = dbus.SessionBus (mainloop=dbus_loop)
+ tracker = bus.get_object (cfg.TRACKER_EXTRACT_BUSNAME, cfg.TRACKER_EXTRACT_OBJ_PATH)
+ self.extractor = dbus.Interface (tracker,
+ dbus_interface=cfg.TRACKER_EXTRACT_IFACE)
+
+
+ def get_metadata (self, filename, mime):
+ """
+ Calls the extractor a returns a dictionary of property, value.
+ Example:
+ { 'nie:filename': 'a.jpeg' ,
+ 'tracker:added': '2008-12-12T12:23:34Z'
+ }
+ """
+ metadata = {}
+ preupdate, embedded = self.extractor.GetMetadata (filename, mime)
+ for attribute_value in self.__process_lines (embedded):
+ att, value = attribute_value.split (" ", 1)
+ if metadata.has_key (att):
+ metadata [att].append (value)
+ else:
+ metadata [att] = [value]
+
+ return metadata
+
+ def __process_lines (self, embedded):
+ """
+ Would be so cool to implement this with yield and generators... :)
+ """
+ grouped_lines = []
+ current_line = ""
+ anon_node_open = False
+ for l in embedded.split ("\n\t"):
+ if "[" in l:
+ current_line = current_line + l
+ anon_node_open = True
+ continue
+
+ if "]" in l:
+ anon_node_open = False
+ current_line += l
+ final_lines = self.__handle_anon_nodes (current_line.strip ())
+ grouped_lines = grouped_lines + final_lines
+ current_line = ""
+ continue
+
+ if anon_node_open:
+ current_line += l
+ else:
+ if (len (l.strip ()) == 0):
+ continue
+
+ final_lines = self.__handle_multivalues (l.strip ())
+ grouped_lines = grouped_lines + final_lines
+
+ return map (self.__clean_value, grouped_lines)
+
+ def __handle_multivalues (self, line):
+ """
+ Split multivalues like:
+ a nfo:Image, nmm:Photo ;
+ -> a nfo:Image ;
+ -> a nmm:Photo ;
+ """
+ hasEscapedComma = re.compile ("\".+,.+\"")
+
+ if "," in line and not hasEscapedComma.search (line):
+ prop, multival = line.split (" ", 1)
+ results = []
+ for value in multival.split (","):
+ results.append ("%s %s" % (prop, value.strip ()))
+ return results
+ else:
+ return [line]
+
+
+
+
+ def __handle_anon_nodes (self, line):
+ """
+ Traslates anonymous nodes in 'flat' properties:
+
+ nao:hasTag [a nao:Tag; nao:prefLabel "xxx"]
+ -> nao:hasTag:prefLabel "xxx"
+
+ mlo:location [a mlo:GeoPoint; mlo:city "Delhi"; mlo:country "India"]
+ -> mlo:location:city "Delhi"
+ -> mlo:location:country "India"
+ """
+
+ # hasTag case
+ if line.startswith ("nao:hasTag"):
+ getlabel = re.compile ("nao:prefLabel\ \"(\w+)\"")
+ match = getlabel.search (line)
+ if (match):
+ line = 'nao:hasTag:prefLabel "%s" ;' % (match.group(1))
+ return [line]
+ else:
+ print "Whats wrong on line", line, "?"
+ return [line]
+
+ # location case
+ elif line.startswith ("mlo:location"):
+
+ results = []
+
+ # Can have country AND/OR city
+ getcountry = re.compile ("mlo:country\ \"(\w+)\"")
+ getcity = re.compile ("mlo:city\ \"(\w+)\"")
+
+ country_match = getcountry.search (line)
+ city_match = getcity.search (line)
+
+ if (country_match):
+ results.append ('mlo:location:country "%s" ;' % (country_match.group(1)))
+
+ if (city_match):
+ results.append ('mlo:location:city "%s" ;' % (city_match.group(1)))
+
+ if (not country_match and not city_match):
+ print "FIXME another location subproperty in ", line
+
+ return results
+ elif line.startswith ("nco:creator"):
+ getcreator = re.compile ("nco:fullname\ \"(\w+)\"")
+ creator_match = getcreator.search (line)
+
+ if (creator_match):
+ new_line = 'nco:creator:fullname "%s" ;' % (creator_match.group (1))
+ return [new_line]
+ else:
+ print "Something special in this line '%s'" % (line)
+
+ else:
+ return [line]
+
+ def __clean_value (self, value):
+ """
+ the value comes with a ';' or a '.' at the end
+ """
+ if (len (value) < 2):
+ return value.strip ()
+
+ clean = value.strip ()
+ if value[-1] in [';', '.']:
+ clean = value [:-1]
+
+ clean = clean.replace ("\"", "")
+
+ return clean.strip ()
+
diff --git a/tests/functional-tests/common/utils/html.py b/tests/functional-tests/common/utils/html.py
new file mode 100644
index 0000000..0acf513
--- /dev/null
+++ b/tests/functional-tests/common/utils/html.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python2.5
+import unittest
+import os
+
+class html:
+
+ def top(self):
+
+ os.remove('indexing-performance')
+ self.file = 'indexing-performance'
+ self.f = open(self.file, "a")
+ self.f.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' + "\n" +
+ '<html>' + "\n" +
+ ' <head>' + "\n" +
+ ' <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">' + "\n" +
+ ' <title>Tracker Indexing Performance</title>' + "\n" +
+ ' <H1 align="center"><font color="#CC0000" face="verdana" size="6">Tracker Indexing Performance</font></H1>' + "\n" +
+ ' <body>' + "\n" +
+ ' <table border="1", align="center">' + "\n" +
+ '<th><font color="#8000FF" face="verdana" size="4">Test data</font></th>' + "\n" +
+ '<th><font color="#8000FF" face="verdana" size="4">Minimum</font></th>' + "\n" +
+ '<th><font color="#8000FF" face="verdana" size="4">Maximum</font></th>' + "\n" +
+ '<th><font color="#8000FF" face="verdana" size="4">Average</font></th>' + "\n" +
+ '<th><font color="#8000FF" face="verdana" size="4">Median</font></th>' + "\n"
+ )
+ self.f.close()
+
+
+ def mid(self,title,min,max,avg,median):
+
+ self.file = 'indexing-performance'
+ self.f = open(self.file, "a")
+ self.f.write( '<tr>' + "\n" +
+ '<td>' + title + '</td>' + "\n" +
+ '<td>' + str(min) + '</td>' + "\n" +
+ '<td>' + str(max) + '</td>' + "\n" +
+ '<td>' + str(avg) + '</td>' + "\n" +
+ '<td>' + str(median) + '</td>' + "\n" +
+ '</tr>' + "\n"
+ )
+ self.f.close()
+
+ def bottom(self):
+
+ self.file = 'indexing-performance'
+ self.f = open(self.file, "a")
+ self.f.write( '</table>' + "\n" +
+ ' </body>' + "\n" +
+ ' </head>' + "\n" +
+ ' </html>' + "\n"
+ )
+ self.f.close()
+
+class report(unittest.TestCase):
+
+ def first(self):
+ self.file = html()
+ self.file.top()
+
+ def last(self):
+ self.file = html()
+ self.file.bottom()
+
+
diff --git a/tests/functional-tests/common/utils/minertest.py b/tests/functional-tests/common/utils/minertest.py
new file mode 100644
index 0000000..77ff45f
--- /dev/null
+++ b/tests/functional-tests/common/utils/minertest.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2010, Nokia <ivan frade nokia com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+from common.utils import configuration as cfg
+from common.utils.system import TrackerSystemAbstraction
+from common.utils.helpers import StoreHelper
+import unittest2 as ut
+
+import shutil
+import os
+
+BASEDIR = os.environ['HOME']
+
+def path (filename):
+ return os.path.join (BASEDIR, filename)
+
+def uri (filename):
+ return "file://" + os.path.join (BASEDIR, filename)
+
+
+DEFAULT_TEXT = "Some stupid content, to have a test file"
+
+class CommonTrackerMinerTest (ut.TestCase):
+
+ @classmethod
+ def __prepare_directories (self):
+ #
+ # ~/test-monitored/
+ # /file1.txt
+ # /dir1/
+ # /file2.txt
+ # /dir2/
+ # /file3.txt
+ #
+ #
+ # ~/test-no-monitored/
+ # /file0.txt
+ #
+
+ for d in ["test-monitored",
+ "test-monitored/dir1",
+ "test-monitored/dir1/dir2",
+ "test-no-monitored"]:
+ directory = os.path.join (BASEDIR, d)
+ if (os.path.exists (directory)):
+ shutil.rmtree (directory)
+ os.makedirs (directory)
+
+ for tf in ["test-monitored/file1.txt",
+ "test-monitored/dir1/file2.txt",
+ "test-monitored/dir1/dir2/file3.txt",
+ "test-no-monitored/file0.txt"]:
+ testfile = os.path.join (BASEDIR, tf)
+ if (os.path.exists (testfile)):
+ os.remove (testfile)
+ f = open (testfile, 'w')
+ f.write (DEFAULT_TEXT)
+ f.close ()
+
+
+ @classmethod
+ def setUpClass (self):
+ #print "Starting the daemon in test mode"
+ self.__prepare_directories ()
+
+ self.system = TrackerSystemAbstraction ()
+
+ if (os.path.exists (os.getcwd() + "/test-configurations/miner-basic-ops")):
+ # Use local directory if available
+ confdir = os.getcwd() + "/test-configurations/miner-basic-ops"
+ else:
+ confdir = os.path.join (cfg.DATADIR, "tracker-tests",
+ "test-configurations", "miner-basic-ops")
+ self.system.tracker_miner_fs_testing_start (confdir)
+ # Returns when ready
+ self.tracker = StoreHelper ()
+ print "Ready to go!"
+
+ @classmethod
+ def tearDownClass (self):
+ #print "Stopping the daemon in test mode (Doing nothing now)"
+ self.system.tracker_miner_fs_testing_stop ()
+
diff --git a/tests/functional-tests/common/utils/storetest.py b/tests/functional-tests/common/utils/storetest.py
new file mode 100644
index 0000000..47af43e
--- /dev/null
+++ b/tests/functional-tests/common/utils/storetest.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2010, Nokia <ivan frade nokia com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+import time
+
+#sys.path.insert (0, "../..")
+
+from common.utils.system import TrackerSystemAbstraction
+from common.utils.helpers import StoreHelper
+from common.utils import configuration as cfg
+
+import unittest2 as ut
+#import unittest as ut
+
+class CommonTrackerStoreTest (ut.TestCase):
+ """
+ Common superclass for tests that just require a fresh store running
+ """
+ @classmethod
+ def setUpClass (self):
+ #print "Starting the daemon in test mode"
+ self.system = TrackerSystemAbstraction ()
+ self.system.tracker_store_testing_start ()
+ time.sleep (1)
+ self.tracker = StoreHelper ()
+
+ @classmethod
+ def tearDownClass (self):
+ #print "Stopping the daemon in test mode (Doing nothing now)"
+ self.system.tracker_store_testing_stop ()
+ time.sleep (2)
diff --git a/tests/functional-tests/common/utils/system.py b/tests/functional-tests/common/utils/system.py
new file mode 100644
index 0000000..8cb4286
--- /dev/null
+++ b/tests/functional-tests/common/utils/system.py
@@ -0,0 +1,329 @@
+import os
+import subprocess
+import shutil
+import configuration as cfg
+
+import gobject
+import glib
+import dbus
+from dbus.mainloop.glib import DBusGMainLoop
+import time
+
+# Don't use /tmp (not enough space there)
+
+TEST_ENV_VARS = { "XDG_DATA_HOME" : os.path.join (cfg.TEST_TMP_DIR, "xdg-data-home"),
+ "XDG_CACHE_HOME": os.path.join (cfg.TEST_TMP_DIR, "xdg-cache-home")}
+EXTRA_DIRS = [os.path.join (cfg.TEST_TMP_DIR, "xdg-data-home", "tracker"),
+ os.path.join (cfg.TEST_TMP_DIR, "xdg-cache-home", "tracker")]
+
+# This variable is not in the dictionary because not all tests need to modify it!
+XDG_CONFIG_HOME_DIR = os.path.join (cfg.TEST_TMP_DIR, "xdg-config-home")
+
+REASONABLE_TIMEOUT = 30
+
+class TrackerMinerFsLifeCycle():
+ """
+ Starts and monitors the miner-fs life cycle
+ """
+ def __init__ (self):
+ self.timeout_id = 0
+
+ def start (self):
+ """
+ call this method to start and instance of miner-fs. It will return when the miner is 'Idle'
+ after all the initial crawling
+ """
+ self.loop = gobject.MainLoop()
+ dbus_loop = DBusGMainLoop(set_as_default=True)
+ self.bus = dbus.SessionBus (dbus_loop)
+
+ obj = self.bus.get_object ("org.freedesktop.DBus",
+ "/org/freedesktop/DBus")
+ self.admin = dbus.Interface (obj, dbus_interface="org.freedesktop.DBus")
+ if (self.admin.NameHasOwner (cfg.MINERFS_BUSNAME)):
+ raise Exception ("Miner is already running! kill it before starting this one")
+
+ self.name_owner_match = self.bus.add_signal_receiver (self.__name_owner_changed_cb,
+ signal_name="NameOwnerChanged",
+ path="/org/freedesktop/DBus",
+ dbus_interface="org.freedesktop.DBus")
+ self.__start_tracker_miner_fs ()
+
+ # It should step out of this loop when the miner is visible in DBus
+ self.loop.run ()
+
+ self.status_match = self.bus.add_signal_receiver (self.__minerfs_status_cb,
+ signal_name="Progress",
+ path=cfg.MINERFS_OBJ_PATH,
+ dbus_interface=cfg.MINER_IFACE)
+ # It should step out of this loop after to "Idle" progress changes
+ self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
+ self.loop.run ()
+
+
+ def stop (self):
+ self.__stop_tracker_miner_fs ()
+ # It should step out of this loop when the miner disappear from the bus
+ self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
+ self.loop.run ()
+
+ # Disconnect the signals of the next start we get duplicated messages
+ self.bus._clean_up_signal_match (self.name_owner_match)
+ self.bus._clean_up_signal_match (self.status_match)
+
+
+ def wait_for_idle (self, timeout=REASONABLE_TIMEOUT):
+ # The signal is already connected
+ print "Waiting for Idle"
+ self.timeout_id = glib.timeout_add_seconds (timeout, self.__timeout_on_idle)
+ self.loop.run ()
+
+ def __timeout_on_idle (self):
+ print "Timeout... asumming idle"
+ self.loop.quit ()
+ return False
+
+ def __minerfs_status_cb (self, status, handle):
+ print "Miner status is now", status.encode ("utf-8")
+ if (status == "Idle"):
+ if (self.timeout_id != 0):
+ glib.source_remove (self.timeout_id)
+ self.timeout_id = 0
+ self.loop.quit ()
+
+
+ def __name_owner_changed_cb (self, name, old_owner, new_owner):
+ if name == cfg.MINERFS_BUSNAME:
+ print "Miner name change %s -> %s" % (old_owner, new_owner)
+ self.loop.quit ()
+
+ def __start_tracker_miner_fs (self):
+ miner_fs_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-miner-fs")
+ FNULL = open ('/dev/null', 'w')
+ return subprocess.Popen ([miner_fs_binary], stdout=FNULL, stderr=FNULL)
+
+ def __stop_tracker_miner_fs (self):
+ control_binary = os.path.join (cfg.BINDIR, "tracker-control")
+ FNULL = open('/dev/null', 'w')
+ subprocess.call ([control_binary, "-t"], stdout=FNULL)
+
+
+class TrackerWritebackLifeCycle():
+ """
+ Starts and monitors the writeback life cycle
+ """
+ def __init__ (self):
+ self.timeout_id = 0
+
+ def start (self):
+ """
+ call this method to start and instance of writeback.
+ It will return when the Writeback object is visible in dbus
+ """
+ self.loop = gobject.MainLoop()
+ dbus_loop = DBusGMainLoop(set_as_default=True)
+ bus = dbus.SessionBus (dbus_loop)
+
+ obj = bus.get_object ("org.freedesktop.DBus",
+ "/org/freedesktop/DBus")
+ self.admin = dbus.Interface (obj, dbus_interface="org.freedesktop.DBus")
+ if (self.admin.NameHasOwner (cfg.WRITEBACK_BUSNAME)):
+ raise Exception ("Writeback is already running! kill it before starting this one")
+
+ bus.add_signal_receiver (self.__name_owner_changed_cb,
+ signal_name="NameOwnerChanged",
+ path="/org/freedesktop/DBus",
+ dbus_interface="org.freedesktop.DBus")
+ self.__start_tracker_writeback ()
+
+ # It should step out of this loop when the writeback is visible in DBus
+ self.timeout_id = glib.timeout_add_seconds (REASONABLE_TIMEOUT, self.__timeout_on_idle)
+ self.loop.run ()
+
+ def stop (self):
+ assert self.process
+ self.process.kill ()
+
+ def __name_owner_changed_cb (self, name, old_owner, new_owner):
+ if name == cfg.WRITEBACK_BUSNAME:
+ print "Writeback changed named '%s' -> '%s'" % (old_owner, new_owner)
+ if (self.timeout_id != 0):
+ glib.source_remove (self.timeout_id)
+ self.timeout_id = 0
+ self.loop.quit ()
+
+ def __timeout_on_idle (self):
+ print "Timeout... asumming idle"
+ self.loop.quit ()
+ return False
+
+ def __start_tracker_writeback (self):
+ writeback_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-writeback")
+ writeback = [writeback_binary]
+ # The env variables can be passed as parameters!
+ FNULL = open('/dev/null', 'w')
+ self.process = subprocess.Popen (writeback, stdout=FNULL, stderr=FNULL)
+
+
+class TrackerSystemAbstraction:
+
+ def set_up_environment (self, confdir):
+ """
+ Sets up the XDG_*_HOME variables and make sure the directories exist
+ """
+ for var, directory in TEST_ENV_VARS.iteritems ():
+ print "Setting %s - %s" %(var, directory)
+ self.__recreate_directory (directory)
+ os.environ [var] = directory
+
+ for directory in EXTRA_DIRS:
+ self.__recreate_directory (directory)
+
+ if confdir :
+ self.__recreate_directory (XDG_CONFIG_HOME_DIR)
+ shutil.copytree (os.path.join (confdir, "tracker"),
+ os.path.join (XDG_CONFIG_HOME_DIR, "tracker"))
+ print "Setting %s - %s" % ("XDG_CONFIG_HOME", XDG_CONFIG_HOME_DIR)
+ print " taking configuration from", confdir
+ os.environ ["XDG_CONFIG_HOME"] = XDG_CONFIG_HOME_DIR
+
+ def unset_up_environment (self):
+ """
+ Unset the XDG_*_HOME variables from the environment
+ """
+ for var, directory in TEST_ENV_VARS.iteritems ():
+ if os.environ.has_key (var):
+ del os.environ [var]
+
+ if (os.environ.has_key ("XDG_CONFIG_HOME")):
+ del os.environ ["XDG_CONFIG_HOME"]
+
+
+ def tracker_store_testing_start (self, confdir=None):
+ """
+ Stops any previous instance of the store, calls set_up_environment,
+ and starts a new instances of the store
+ """
+ self.__stop_tracker_processes ()
+ self.set_up_environment (confdir)
+
+ self.tracker_running = self.__start_tracker_store ()
+
+ def tracker_store_brutal_restart (self):
+ self.tracker_running.kill ()
+ time.sleep (1)
+ self.tracker_running = self.__start_tracker_store ()
+ time.sleep (1)
+
+ def tracker_store_remove_dbs (self):
+ db_location = os.path.join (TEST_ENV_VARS ['XDG_CACHE_HOME'], "tracker")
+ shutil.rmtree (db_location)
+ os.mkdir (db_location)
+
+ def tracker_store_corrupt_dbs (self):
+ db_path = os.path.join (TEST_ENV_VARS ['XDG_CACHE_HOME'], "tracker", "meta.db")
+ f = open (db_path, "w")
+ for i in range (0, 100):
+ f.write ("Some stupid content... hohohoho, not a sqlite file anymore!\n")
+ f.close ()
+
+ def tracker_store_remove_journal (self):
+ db_location = os.path.join (TEST_ENV_VARS ['XDG_DATA_HOME'], "tracker", "data")
+ shutil.rmtree (db_location)
+ os.mkdir (db_location)
+
+ def tracker_store_testing_stop (self):
+ """
+ Stops a running tracker-store and unset all the XDG_*_HOME vars
+ """
+ self.__stop_tracker_processes ()
+ self.unset_up_environment ()
+
+
+ def tracker_miner_fs_testing_start (self, confdir=None):
+ """
+ Stops any previous instance of the store and miner, calls set_up_environment,
+ and starts a new instance of the store and miner-fs
+ """
+ self.__stop_tracker_processes ()
+ self.set_up_environment (confdir)
+
+ self.tracker_running = self.__start_tracker_store ()
+ self.miner_fs = TrackerMinerFsLifeCycle ()
+ self.miner_fs.start ()
+
+ def tracker_miner_fs_wait_for_idle (self, timeout=REASONABLE_TIMEOUT):
+ """
+ Copy the files physically in the filesyste and wait for the miner to complete the work
+ """
+ self.miner_fs.wait_for_idle (timeout)
+ time.sleep (1)
+
+
+ def tracker_miner_fs_testing_stop (self):
+ """
+ Stops the miner-fs and store running and unset all the XDG_*_HOME vars
+ """
+ self.miner_fs.stop ()
+ self.__stop_tracker_processes ()
+ self.unset_up_environment ()
+
+
+ def tracker_writeback_testing_start (self, confdir=None):
+ # Start the miner-fs (and store) and then the writeback process
+ self.tracker_miner_fs_testing_start (confdir)
+ self.writeback = TrackerWritebackLifeCycle ()
+ self.writeback.start ()
+
+ def tracker_writeback_testing_stop (self):
+ # Tracker write must have been started before
+ self.writeback.stop ()
+ self.tracker_miner_fs_testing_stop ()
+
+ #
+ # Private API
+ #
+ def __start_tracker_store (self):
+ tracker_binary = os.path.join (cfg.EXEC_PREFIX, "tracker-store")
+ tracker = [tracker_binary]
+ # The env variables can be passed as parameters!
+ FNULL = open('/dev/null', 'w')
+ return subprocess.Popen (tracker, stdout=FNULL, stderr=FNULL)
+
+
+ def __stop_tracker_processes (self):
+ control_binary = os.path.join (cfg.BINDIR, "tracker-control")
+ FNULL = open('/dev/null', 'w')
+ subprocess.call ([control_binary, "-t"], stdout=FNULL)
+ time.sleep (1)
+
+
+
+ def __recreate_directory (self, directory):
+ if (os.path.exists (directory)):
+ shutil.rmtree (directory)
+ os.makedirs (directory)
+
+
+if __name__ == "__main__":
+ import gtk, glib, time
+
+ def destroy_the_world (a):
+ a.tracker_store_testing_stop ()
+ print " stopped"
+ gtk.main_quit()
+
+ print "-- Starting store --"
+ a = TrackerSystemAbstraction ()
+ a.tracker_store_testing_start ()
+ print " started, waiting 5 sec. to stop it"
+ glib.timeout_add_seconds (5, destroy_the_world, a)
+ gtk.main ()
+
+ print "-- Starting miner-fs --"
+ b = TrackerMinerFsLifeCycle ()
+ b.start ()
+ print " started, waiting 3 secs. to stop it"
+ time.sleep (3)
+ b.stop ()
+ print " stopped"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]