#!/usr/bin/python
import datetime
import glob
import multiprocessing
import os
import stat
import subprocess
import shutil
import tempfile
import time
import unittest
from mock import patch
from testutils import setup_test_env
setup_test_env()
from softwarecenter.utils import (decode_xml_char_reference,
release_filename_in_lists_from_deb_line,
get_http_proxy_string_from_libproxy,
get_file_path_from_iconname,
get_oem_channel_descriptor,
)
from softwarecenter.testutils import (do_events,
get_test_gtk3_icon_cache,
)
class TestSCUtils(unittest.TestCase):
""" tests the sc utils """
def test_encode(self):
xml = "What’s New"
python = u"What\u2019s New"
self.assertEqual(decode_xml_char_reference(xml), python)
# fails currently
#self.assertEqual(encode_for_xml(python), xml)
def test_lists_filename(self):
debline = "deb http://foo:pass@security.ubuntu.com/ubuntu maverick-security main restricted"
self.assertEqual(release_filename_in_lists_from_deb_line(debline),
"security.ubuntu.com_ubuntu_dists_maverick-security_Release")
def test_get_http_proxy_from_gsettings(self):
from softwarecenter.utils import get_http_proxy_string_from_gsettings
# FIXME: do something more meaningful here once I figured out
# how to create a private fake gsettings
proxy = get_http_proxy_string_from_gsettings()
self.assertTrue(type(proxy) in [type(None), type("")])
# disabled, we don't use libproxy currently, its really rather
# out of date
def disabled_test_get_http_proxy_from_libproxy(self):
# test url
url = "http://archive.ubuntu.com"
# ensure we look at environment first
os.environ["PX_CONFIG_ORDER"] = "config_envvar"
# normal proxy
os.environ["http_proxy"] = "http://localhost:3128/"
proxy = get_http_proxy_string_from_libproxy(url)
self.assertEqual(proxy, "http://localhost:3128/")
# direct
os.environ["http_proxy"] = ""
proxy = get_http_proxy_string_from_libproxy(url)
self.assertEqual(proxy, "")
# user/pass
os.environ["http_proxy"] = "http://user:pass@localhost:3128/"
proxy = get_http_proxy_string_from_libproxy(url)
self.assertEqual(proxy, "http://user:pass@localhost:3128/")
def test_get_title_from_html(self):
from softwarecenter.utils import get_title_from_html
html = """
Title & text
header1
"""
# get the title from the html
self.assertEqual(get_title_from_html(html),
"Title & text")
# fallback to the first h1 if there is no title
html = "foo >
bar
"
self.assertEqual(get_title_from_html(html), "foo >")
# broken
html = "dsf"
self.assertEqual(get_title_from_html(html),
"")
# not supported to have sub-html tags in the extractor
html = "foo bar
"
self.assertEqual(get_title_from_html(html),
"")
html = "foo bar x
some text
"
self.assertEqual(get_title_from_html(html),
"")
def test_no_display_desktop_file(self):
from softwarecenter.utils import is_no_display_desktop_file
d = "/usr/share/app-install/desktop/wine1.4:wine.desktop"
self.assertTrue(is_no_display_desktop_file(d))
d = "/usr/share/app-install/desktop/software-center:ubuntu-software-center.desktop"
self.assertFalse(is_no_display_desktop_file(d))
def test_split_icon_ext(self):
from softwarecenter.utils import split_icon_ext
for unchanged in ["foo.bar.baz", "foo.bar", "foo",
"foo.pngx", "foo.png.xxx"]:
self.assertEqual(split_icon_ext(unchanged), unchanged)
for changed in ["foo.png", "foo.tiff", "foo.jpg", "foo.jpeg"]:
self.assertEqual(split_icon_ext(changed),
os.path.splitext(changed)[0])
def test_get_nice_date_string(self):
from softwarecenter.utils import get_nice_date_string
now = datetime.datetime.utcnow()
ten_secs_ago = now + datetime.timedelta(seconds=-10)
self.assertEqual(get_nice_date_string(ten_secs_ago), 'a few minutes ago')
two_mins_ago = now + datetime.timedelta(minutes=-2)
self.assertEqual(get_nice_date_string(two_mins_ago), '2 minutes ago')
under_a_day = now + datetime.timedelta(hours=-23, minutes=-59, seconds=-59)
self.assertEqual(get_nice_date_string(under_a_day), '23 hours ago')
under_a_week = now + datetime.timedelta(days=-4, hours=-23, minutes=-59, seconds=-59)
self.assertEqual(get_nice_date_string(under_a_week), '4 days ago')
over_a_week = now + datetime.timedelta(days=-7)
self.assertEqual(get_nice_date_string(over_a_week), over_a_week.isoformat().split('T')[0])
def test_get_uuid(self):
from softwarecenter.utils import get_uuid
uuid = get_uuid()
self.assertTrue(uuid and len(uuid) > 0)
def test_clear_credentials(self):
from softwarecenter.utils import clear_token_from_ubuntu_sso_sync
clear_token_from_ubuntu_sso_sync("fo")
do_events()
def test_make_string_from_list(self):
from softwarecenter.utils import make_string_from_list
base = "There was a problem posting this review to %s (omg!)"
# test the various forms
l = ["twister"]
self.assertEqual(
make_string_from_list(base, l),
"There was a problem posting this review to twister (omg!)")
# two
l = ["twister", "factbook"]
self.assertEqual(
make_string_from_list(base, l),
"There was a problem posting this review to twister and factbook (omg!)")
# three
l = ["twister", "factbook", "identi.catz"]
self.assertEqual(
make_string_from_list(base, l),
"There was a problem posting this review to twister, factbook and identi.catz (omg!)")
# four
l = ["twister", "factbook", "identi.catz", "baz"]
self.assertEqual(
make_string_from_list(base, l),
"There was a problem posting this review to twister, factbook, identi.catz and baz (omg!)")
def test_capitalize_first_word(self):
from softwarecenter.utils import capitalize_first_word
test_synopsis = "feature-rich console based todo list manager"
capitalized = capitalize_first_word(test_synopsis)
self.assertTrue(
capitalized == "Feature-rich console based todo list manager")
test_synopsis = "MPlayer's Movie Encoder"
capitalized = capitalize_first_word(test_synopsis)
self.assertTrue(
capitalized == "MPlayer's Movie Encoder")
# ensure it does not crash for empty strings, LP: #1002271
self.assertEqual(capitalize_first_word(""), "")
def test_ensure_file_writable_and_delete_if_not(self):
from softwarecenter.utils import ensure_file_writable_and_delete_if_not
from tempfile import NamedTemporaryFile
# first test that a non-writable file (0400) is deleted
test_file_not_writeable = NamedTemporaryFile()
os.chmod(test_file_not_writeable.name, stat.S_IRUSR)
self.assertFalse(os.access(test_file_not_writeable.name, os.W_OK))
ensure_file_writable_and_delete_if_not(test_file_not_writeable.name)
self.assertFalse(os.path.exists(test_file_not_writeable.name))
# then test that a writable file (0600) is not deleted
test_file_writeable = NamedTemporaryFile()
os.chmod(test_file_writeable.name, stat.S_IRUSR|stat.S_IWUSR)
self.assertTrue(os.access(test_file_writeable.name, os.W_OK))
ensure_file_writable_and_delete_if_not(test_file_writeable.name)
self.assertTrue(os.path.exists(test_file_writeable.name))
def test_safe_makedirs(self):
from softwarecenter.utils import safe_makedirs
from tempfile import mkdtemp
tmp = mkdtemp()
# create base dir
target = os.path.join(tmp, "foo", "bar")
safe_makedirs(target)
# we need the patch to ensure that the code is actually executed
with patch("os.path.exists") as mock_:
mock_.return_value = False
self.assertTrue(os.path.isdir(target))
# ensure that creating the base dir again does not crash
safe_makedirs(target)
self.assertTrue(os.path.isdir(target))
# ensure we still get regular errors like permission denied
# (stat.S_IRUSR)
os.chmod(os.path.join(tmp, "foo"), 0400)
self.assertRaises(OSError, safe_makedirs, target)
# set back to stat.(S_IRUSR|S_IWUSR|S_IXUSR) to make rmtree work
os.chmod(os.path.join(tmp, "foo"), 0700)
# cleanup
shutil.rmtree(tmp)
def test_get_file_path_from_iconname(self):
icons = get_test_gtk3_icon_cache()
icon_path = get_file_path_from_iconname(
icons,
"softwarecenter")
self.assertEqual(
icon_path,
"/usr/share/icons/hicolor/48x48/apps/softwarecenter.svg")
class TestExpungeCache(unittest.TestCase):
def test_expunge_cache(self):
dirname = tempfile.mkdtemp('s-c-testsuite')
for name, content in [ ("foo-301", "status: 301"),
("foo-200", "status: 200"),
("foo-random", "random"),
]:
fullpath = os.path.join(dirname, name)
open(fullpath, "w").write(content)
# set to 1970+1s time to ensure the cleaner finds it
os.utime(fullpath, (1,1))
res = subprocess.call(["../utils/expunge-cache.py", dirname])
# no arguments
self.assertEqual(res, 1)
# by status
res = subprocess.call(["../utils/expunge-cache.py",
"--debug",
"--by-unsuccessful-http-states",
dirname])
self.assertFalse(os.path.exists(os.path.join(dirname, "foo-301")))
self.assertTrue(os.path.exists(os.path.join(dirname, "foo-200")))
self.assertTrue(os.path.exists(os.path.join(dirname, "foo-random")))
# by time
res = subprocess.call(["../utils/expunge-cache.py",
"--debug",
"--by-days", "1",
dirname])
# now we expect the old file to be gone but the unknown one not to
# be touched
self.assertFalse(os.path.exists(os.path.join(dirname, "foo-200")))
self.assertTrue(os.path.exists(os.path.join(dirname, "foo-random")))
def test_expunge_cache_lock(self):
def set_marker(d):
time.sleep(0.5)
target = os.path.join(d, "marker.%s." % os.getpid())
open(target, "w")
from softwarecenter.expunge import ExpungeCache
tmpdir = tempfile.mkdtemp()
# create two ExpungeCache processes
e1 = ExpungeCache([tmpdir], by_days=0, by_unsuccessful_http_states=True)
e1._cleanup_dir = set_marker
e2 = ExpungeCache([tmpdir], by_days=0, by_unsuccessful_http_states=True)
e2._cleanup_dir = set_marker
t1 = multiprocessing.Process(target=e1.clean)
t1.start()
t2 = multiprocessing.Process(target=e2.clean)
t2.start()
# wait for finish
t1.join()
t2.join()
# ensure that the second one was not called
self.assertEqual(len(glob.glob(os.path.join(tmpdir, "marker.*"))), 1)
def test_oem_channel_extractor(self):
s = get_oem_channel_descriptor("./data/ubuntu_dist_channel")
self.assertEqual(s, "canonical-oem-watauga-precise-amd64-20120517-2")
if __name__ == "__main__":
import logging
logging.basicConfig(level=logging.DEBUG)
unittest.main()