#!/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()