Logo Search packages:      
Sourcecode: jockey version File versions  Download package

ui.py

# -*- coding: UTF-8 -*-

'''AbstractUI tests'''

# (c) 2007 Canonical Ltd.
#
# 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 unittest, sys, os, shutil, signal, time
from cStringIO import StringIO
import SimpleHTTPServer, BaseHTTPServer

from jockey.ui import AbstractUI
from jockey.oslib import OSLib
from jockey.handlers import KernelModuleHandler, Handler
from jockey.xorg_driver import XorgDriverHandler

import sandbox

00032 class UITest(unittest.TestCase):
    '''User interface tests.

    These save and restore sys.argv, so the individual tests are free to modify
    it to test various behaviours of the UI. It also captures sys.stdout and
    sys.stderr to self.stdout/self.stderr.
    
    A 50 kB dummy file is created in the OSLib workdir (path in self.big_file),
    which can be used for testing downloading.'''

    def setUp(self):
        self.orig_argv = sys.argv
        self.orig_stdout = sys.stdout
        sys.stdout = StringIO()
        self.orig_stderr = sys.stderr
        sys.stderr = StringIO()
        self.capturing = True

        # create a 50 kB demo file
        self.big_file_contents = 'AB' * 25000
        self.big_file = os.path.join(OSLib.inst.workdir, 'stuff')
        f = open(self.big_file, 'w')
        f.write(self.big_file_contents)
        f.close()

        self.open_app_log = os.path.join(OSLib.inst.workdir, 'open_app.log')

    def tearDown(self):
        sys.argv = self.orig_argv
        self.stop_capture()

        # remove all test handlers
        for f in os.listdir(OSLib.inst.handler_dir):
            os.unlink(os.path.join(OSLib.inst.handler_dir, f))

        # undo the effect of enabling/disabling handlers
        OSLib.inst._make_proc_modules()
        KernelModuleHandler.read_loaded_modules()
        try:
            os.unlink(OSLib.inst.module_blacklist_file)
        except OSError:
            pass
        OSLib.inst._load_module_blacklist()

        try:
            os.unlink(self.open_app_log)
        except OSError:
            pass

        os.unlink(self.big_file)

00083     def stop_capture(self):
        '''Stop redirecting and capturing stdout/stderr.'''

        if self.capturing:
            self.capturing = False
            sys.stdout.flush()
            sys.stderr.flush()
            self.stdout = sys.stdout.getvalue()
            self.stderr = sys.stderr.getvalue()
            sys.stdout = self.orig_stdout
            sys.stderr = self.orig_stderr

00095     def test_cli_help(self):
        '''calling with --help'''

        # --help will exit, so we have to fork
        if os.fork() == 0:
            sys.argv = ['ui-test', '--help']
            try:
                AbstractUI()
            except SystemExit:
                os._exit(0)
            os._exit(42) # we should not get here

        self.assertEqual(os.wait()[1], 0)

        # TODO: check output (forked process does not land in self.stdout for
        # some reason)

00112     def test_list(self):
        '''calling with --list'''

        open (os.path.join(OSLib.inst.handler_dir, 'kmod_nodetect.py'), 'w').write(
            sandbox.h_availability_py)
        sys.argv = ['ui-test', '--list']
        self.assertEqual(AbstractUI().run(), 0)

        self.stop_capture()

        self.assertEqual(len(self.stdout.strip().splitlines()), 5)
        self.assert_('free module with available hardware, graphics card' in self.stdout)
        self.assert_('kmod:mint ' in self.stdout)
        self.assert_('kmod:vanilla ' in self.stdout)
        self.assert_('kmod:vanilla3d ' in self.stdout)
        self.assert_('kmod:firmwifi ' in self.stdout)

00129     def test_disable(self):
        '''calling with --disable'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            sandbox.h_availability_py)

        sys.argv = ['ui-test', '--disable', 'kmod:mint']
        ui = sandbox.TestUI()
        self.assertEqual(ui.run(), 0)
        self.stop_capture()

        for h in ui.handlers:
            if h.id() == 'kmod:mint':
                self.failIf(h.enabled())
            else:
                self.assert_(h.enabled())

00146     def test_disable_nochange(self):
        '''calling with --disable on a non-changeable handler'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            'import jockey.handlers' + sandbox.h_nochangemod)

        sys.argv = ['ui-test', '--disable', 'kmod:vanilla']
        ui = sandbox.TestUI()
        self.assertNotEqual(ui.run(), 0)
        self.stop_capture()

        for h in ui.handlers:
            self.assert_(h.enabled())

        self.assert_('I must live' in self.stderr)

00162     def test_disable_confirm_cancel(self):
        '''calling with --disable --confirm cancelling'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            sandbox.h_availability_py)

        sys.argv = ['ui-test', '--confirm', '--disable', 'kmod:mint']
        ui = sandbox.TestUI()
        ui.confirm_response = False
        self.assertEqual(ui.run(), 1)
        self.stop_capture()

        for h in ui.handlers:
            self.assert_(h.enabled())

00177     def test_disable_confirm(self):
        '''calling with --disable --confirm OKing'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            sandbox.h_availability_py)

        sys.argv = ['ui-test', '--confirm', '--disable', 'kmod:mint']
        ui = sandbox.TestUI()
        ui.confirm_response = True
        self.assertEqual(ui.run(), 0)
        self.stop_capture()

        for h in ui.handlers:
            if h.id() == 'kmod:mint':
                self.failIf(h.enabled())
            else:
                self.assert_(h.enabled())

00195     def test_enable(self):
        '''calling with --enable'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            sandbox.h_availability_py)
        
        # disable mint driver and verify that in --list
        sys.argv = ['ui-test', '--list']
        ui = sandbox.TestUI()
        for h in ui.handlers:
            if h.id() == 'kmod:mint':
                h.disable()
                break
        self.assertEqual(ui.run(), 0)

        # enable it using the CLI
        sys.argv = ['ui-test', '--enable', 'kmod:mint']
        ui = sandbox.TestUI()
        self.assertEqual(ui.run(), 0)

        self.stop_capture()

        mint_disabled = False
        for l in self.stdout.strip().splitlines():
            if l.startswith('kmod:mint'):
                if ui.string_disabled in l:
                    mint_disabled = True
                break
        self.assert_(mint_disabled)

        for h in ui.handlers:
            self.assert_(h.enabled())

00228     def test_enable_invalid(self):
        '''calling with --enable on a nonexisting handler'''

        sys.argv = ['ui-test', '--enable', 'kmod:unknown']
        ui = sandbox.TestUI()
        self.assertNotEqual(ui.run(), 0)
        self.stop_capture()
        self.assert_(ui.string_unknown_driver in self.stderr)
        self.assert_('--list' in self.stderr)

00238     def test_handler_dir(self):
        '''calling with --handler-dir'''

        mydir = os.path.join(OSLib.inst.workdir, 'customdir')
        try:
            os.mkdir(mydir)
            open (os.path.join(mydir, 'kmod_nodetect.py'), 'w').write(
                sandbox.h_availability_py)
            sys.argv = ['ui-test', '--list', '-H', mydir]
            self.assertEqual(AbstractUI().run(), 0)

            self.stop_capture()

            self.assertEqual(len(self.stdout.strip().splitlines()), 5)
            self.assert_('free module with available hardware, graphics card' in self.stdout)
            self.assert_('kmod:mint ' in self.stdout)
            self.assert_('kmod:vanilla ' in self.stdout)
            self.assert_('kmod:vanilla3d ' in self.stdout)
            self.assert_('kmod:firmwifi ' in self.stdout)
        finally:
            shutil.rmtree(mydir)

00260     def test_get_handler_tooltip(self):
        '''get_handler_tooltip()'''

        sys.argv = ['ui-test']
        ui = AbstractUI()

        self.assertEqual(ui.get_handler_tooltip(None), None)

        h = KernelModuleHandler(ui, 'vanilla')
        self.assertEqual(ui.get_handler_tooltip(h), None)

        r = 'I am important'
        h = Handler(ui, 'shiny driver', rationale=r)
        self.assertEqual(ui.get_handler_tooltip(h), r)

00275     def test_toggle_handler(self):
        '''toggle_handler()'''

        open (os.path.join(OSLib.inst.handler_dir, 'h.py'), 'w').write(
            'import jockey.handlers' + sandbox.h_nochangemod)

        sys.argv = ['ui-test']
        ui = sandbox.TestUI()
        self.stop_capture()

        for h in ui.handlers:
            self.assert_(h.enabled())
            if h.can_change():
                no_change_h = h
            else:
                change_h = h
        assert no_change_h.can_change() != None
        assert change_h.can_change() == None

        # change an unchangeable handler
        # note: don't set a confirmation response, it shouldn't ask here
        self.assertEqual(ui.toggle_handler(no_change_h), False)
        self.assertEqual(ui.pop_error()[1], 'I must live')
        self.assertRaises(IndexError, ui.pop_error)

        # do not confirm change of handler
        ui.confirm_response = False
        self.assertEqual(ui.toggle_handler(change_h), False)
        self.assert_(change_h.enabled())
        self.assertRaises(IndexError, ui.pop_error)

        # confirm change of handler
        ui.confirm_response = True
        self.assertEqual(ui.toggle_handler(change_h), True)
        self.failIf(change_h.enabled())
        self.assertRaises(IndexError, ui.pop_error)

        # enable it again
        ui.confirm_response = True
        self.assertEqual(ui.toggle_handler(change_h), True)
        self.assert_(change_h.enabled())
        self.assertRaises(IndexError, ui.pop_error)

00318     def test_mode_any(self):
        '''calling with --mode any'''

        sys.argv = ['ui-test', '--mode', 'any']
        ui = sandbox.TestUI()
        self.stop_capture()

        self.assertEqual(set([h.module for h in ui.handlers]), 
            set(['vanilla', 'vanilla3d', 'mint', 'firmwifi', 'foodmi']))

        # mint is not enabled by default
        self.failIf('Restricted' in ui.main_window_title())
        (h, s) = ui.main_window_text()
        self.assert_('No proprietary drivers are in use' in h)
        self.assert_('risk' in s)

        # enable mint
        for h in ui.handlers:
            if h.module == 'mint':
                h.enable()
        (h, s) = ui.main_window_text()
        self.assert_('Proprietary drivers are being used' in h)
        self.assert_('risk' in s)

00342     def test_mode_free(self):
        '''calling with --mode free'''

        sys.argv = ['ui-test', '--mode', 'free']
        ui = sandbox.TestUI()
        self.stop_capture()

        self.assertEqual(set([h.module for h in ui.handlers]), 
            set(['vanilla', 'firmwifi', 'foodmi']))

        self.failIf('Restricted' in ui.main_window_title())

        (h, s) = ui.main_window_text()
        self.assert_('No proprietary drivers are in use' in h)
        self.assertEqual(s, '')

00358     def test_mode_nonfree(self):
        '''calling with --mode nonfree'''

        sys.argv = ['ui-test', '--mode', 'nonfree']
        ui = sandbox.TestUI()
        self.stop_capture()

        self.assertEqual(set([h.module for h in ui.handlers]), 
            set(['vanilla3d', 'mint']))

        self.assert_('Restricted' in ui.main_window_title())

        (h, s) = ui.main_window_text()
        self.assert_('No proprietary drivers are in use' in h, h)
        self.assert_('risk' in s)

00374     def test_check(self):
        '''calling with --check'''

        try:
            # new free and nonfree drivers which are already enabled -> no notification
            sys.argv = ['ui-test', '--check']
            ui = sandbox.TestUI()
            self.assertEqual(ui.run(), 1)
            self.stop_capture()

            self.assertRaises(IndexError, ui.pop_error)
            self.assertRaises(IndexError, ui.pop_notification)
            self.failIf(ui.main_loop_active)

            self.assert_(os.path.exists(OSLib.inst.check_cache))
            os.unlink(OSLib.inst.check_cache)

            # new free and nonfree drivers which are not enabled -> nonfree notification
            ui = sandbox.TestUI()
            for h in ui.handlers:
                h.disable()
            self.assertEqual(ui.run(), 0)

            self.assertRaises(IndexError, ui.pop_error)
            self.assertEqual('Restricted drivers available', ui.pop_notification()[0])
            
            # the next run does not report anything new
            self.assertEqual(ui.run(), 1)
            self.assertRaises(IndexError, ui.pop_error)
            self.assertRaises(IndexError, ui.pop_notification)
            self.assert_(ui.main_loop_active)
            os.unlink(OSLib.inst.check_cache)

            # new free drivers which are not enabled -> free notification
            sys.argv = ['ui-test', '--check', '-m', 'free']
            ui = sandbox.TestUI()
            self.assertEqual(ui.run(), 0)

            self.assertRaises(IndexError, ui.pop_error)
            self.assertEqual('New drivers available', ui.pop_notification()[0])
            self.assert_(ui.main_loop_active)

            # enable the free drivers again and load them -> no notification
            ui.main_loop_active = False
            for h in ui.handlers:
                h.enable()
                assert h.used()
            self.assertEqual(ui.run(), 1)
            self.assertRaises(IndexError, ui.pop_error)
            self.assertRaises(IndexError, ui.pop_notification)
            self.failIf(ui.main_loop_active)

            # enable the non-free drivers again, too and load them ->
            # notification about usage
            sys.argv = ['ui-test', '--check', '-m', 'nonfree']
            ui = sandbox.TestUI()
            for h in ui.handlers:
                h.enable()
                assert h.used()
            self.assertEqual(ui.run(), 1)
            self.assertRaises(IndexError, ui.pop_error)
            self.assertEqual('New restricted drivers in use', ui.pop_notification()[0])
            self.assert_(ui.main_loop_active)

            # the next run does not report anything new
            ui.main_loop_active = False
            self.assertEqual(ui.run(), 1)
            self.assertRaises(IndexError, ui.pop_error)
            self.assertRaises(IndexError, ui.pop_notification)
            self.failIf(ui.main_loop_active)
        finally:
            try:
                os.unlink(OSLib.inst.check_cache)
            except OSError:
                pass

00450     def test_download_local_nocancel(self):
        '''download_url(), local file://, no cancelling'''

        ui = sandbox.TestUI()

        # temporary file
        (fname, h) = ui.download_url('file://' + self.big_file)
        self.assertEqual(open(fname).read(), self.big_file_contents)
        os.unlink(fname)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download, ['file://' + self.big_file,
            len(self.big_file_contents), len(self.big_file_contents)])

        # specified file name
        dest = os.path.join(OSLib.inst.workdir, 'destfile')
        (fname, h) = ui.download_url('file://' + self.big_file, dest)
        self.assertEqual(fname, dest)
        self.assertEqual(open(dest).read(), self.big_file_contents)
        os.unlink(dest)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download, ['file://' + self.big_file,
            len(self.big_file_contents), len(self.big_file_contents)])

        # nonexisting file
        (fname, h) = ui.download_url('file://junk/nonexisting')
        self.assertEqual(fname, None)

        # one error message about download failure
        self.assert_(ui.pop_error())
        self.assertRaises(IndexError, ui.pop_error)

00487     def test_download_local_cancel(self):
        '''download_url(), local file://, cancelling'''

        ui = sandbox.TestUI()

        # temporary file
        ui.cancel_download = True
        (fname, h) = ui.download_url('file://' + self.big_file)
        self.assertEqual(fname, None)

        # we got progress reports
        self.assertEqual(ui.cur_download[0], 'file://' + self.big_file)
        self.assertEqual(ui.cur_download[2], len(self.big_file_contents))
        ratio = float(ui.cur_download[1])/len(self.big_file_contents)
        self.assert_(ratio >= 0.3, ratio)
        self.assert_(ratio < 0.5)

        # specified file name
        dest = os.path.join(OSLib.inst.workdir, 'destfile')
        ui.cancel_download = True
        (fname, h) = ui.download_url('file://' + self.big_file, dest)
        self.assertEqual(fname, None)

        # we got progress reports
        self.assertEqual(ui.cur_download[0], 'file://' + self.big_file)
        self.assertEqual(ui.cur_download[2], len(self.big_file_contents))
        ratio = float(ui.cur_download[1])/len(self.big_file_contents)
        self.assert_(ratio >= 0.3, ratio)
        self.assert_(ratio < 0.5)

00517     def _fork_http_server(self):
        '''fork a HTTP server on OSLib workdir which serves one request and
        terminates.'''

        # fork test HTTP server
        pid = os.fork()
        if pid == 0:
            os.chdir(OSLib.inst.workdir)
            httpd = BaseHTTPServer.HTTPServer(('', 8427),
                SimpleHTTPServer.SimpleHTTPRequestHandler)
            httpd.handle_request()
            os._exit(0)
        else:
            self.http_pid = pid
            time.sleep(0.5) # TODO: bad race condition fix

00533     def _join_http_server(self, kill=False):
        '''Wait for the forked HTTP server to finish and assert that it exits
        with zero.'''

        if kill:
            os.kill(self.http_pid, signal.SIGTERM)

        # TODO: check exit code
        #self.assertEqual(os.wait()[1], 0)
        os.wait()

00544     def test_download_http_nocancel(self):
        '''download_url(), HTTP, no cancelling'''

        ui = sandbox.TestUI()

        # temporary file
        self._fork_http_server()
        (fname, h) = ui.download_url('http://localhost:8427/stuff')
        self._join_http_server()
        self.assertEqual(open(fname).read(), self.big_file_contents)
        os.unlink(fname)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download, ['http://localhost:8427/stuff',
            len(self.big_file_contents), len(self.big_file_contents)])

        # specified file name
        dest = os.path.join(OSLib.inst.workdir, 'destfile')
        self._fork_http_server()
        (fname, h) = ui.download_url('http://localhost:8427/stuff', dest)
        self._join_http_server()
        self.assertEqual(fname, dest)
        self.assertEqual(open(dest).read(), self.big_file_contents)
        os.unlink(dest)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download, ['http://localhost:8427/stuff',
            len(self.big_file_contents), len(self.big_file_contents)])

        # nonexisting file
        self._fork_http_server()
        (fname, h) = ui.download_url('http://localhost:8427/nonexisting')
        self._join_http_server()
        self.assertEqual(fname, None)

        # one error message about download failure
        self.assert_(ui.pop_error())
        self.assertRaises(IndexError, ui.pop_error)

        # nonexisting server
        self._fork_http_server()
        (fname, h) = ui.download_url('http://i.do.not.exist/nonexisting')
        self._join_http_server(kill=True)
        self.assertEqual(fname, None)

        # one error message about download failure
        self.assert_(ui.pop_error())
        self.assertRaises(IndexError, ui.pop_error)

00597     def test_download_http_cancel(self):
        '''download_url(), HTTP, cancelling'''

        ui = sandbox.TestUI()

        # temporary file
        self._fork_http_server()
        ui.cancel_download = True
        (fname, h) = ui.download_url('http://localhost:8427/stuff')
        self._join_http_server()
        self.assertEqual(fname, None)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download[2], len(self.big_file_contents))
        ratio = float(ui.cur_download[1])/len(self.big_file_contents)
        self.assert_(ratio >= 0.3, ratio)
        self.assert_(ratio < 0.5)

        # specified file name
        dest = os.path.join(OSLib.inst.workdir, 'destfile')
        ui.cancel_download = True
        self._fork_http_server()
        (fname, h) = ui.download_url('http://localhost:8427/stuff', dest)
        self._join_http_server()
        self.assertEqual(fname, None)

        self.assertRaises(IndexError, ui.pop_error)

        # we got progress reports
        self.assertEqual(ui.cur_download[2], len(self.big_file_contents))
        ratio = float(ui.cur_download[1])/len(self.big_file_contents)
        self.assert_(ratio >= 0.3, ratio)
        self.assert_(ratio < 0.5)

00633     def test_install_packages(self):
        '''{install,remove}_package() and installed_packages logging'''

        pkglog = os.path.join(OSLib.inst.backup_dir, 'installed_packages')
        ui = sandbox.TestUI()
        self.failIf(os.path.exists(pkglog))

        # coreutils package is already installed
        self.assert_(OSLib.inst.package_installed('coreutils'))
        ui.install_package('coreutils')
        self.failIf(os.path.exists(pkglog))

        # install mesa-vanilla
        self.failIf(OSLib.inst.package_installed('mesa-vanilla'))
        ui.install_package('mesa-vanilla')
        self.assert_(OSLib.inst.package_installed('mesa-vanilla'))
        self.assertEqual(open(pkglog).read(), 'mesa-vanilla\n')

        # install pretzel
        self.failIf(OSLib.inst.package_installed('pretzel'))
        ui.install_package('pretzel')
        self.assert_(OSLib.inst.package_installed('pretzel'))
        inst = sorted(open(pkglog).readlines())
        self.assertEqual(inst, ['mesa-vanilla\n', 'pretzel\n'])

        # remove mesa-vanilla
        ui.remove_package('mesa-vanilla')
        self.failIf(OSLib.inst.package_installed('mesa-vanilla'))
        self.assertEqual(open(pkglog).read(), 'pretzel\n')

        # remove pretzel
        ui.remove_package('pretzel')
        self.failIf(OSLib.inst.package_installed('pretzel'))
        self.failIf(os.path.exists(pkglog))

00668     def test_check_composite_noavail(self):
        '''calling with --check-composite and no available driver'''

        sys.argv = ['ui-test', '--check-composite']
        ui = sandbox.TestUI()

        h = XorgDriverHandler(ui, 'vanilla3d', 'mesa-vanilla', 'v3d',
            'vanilla')
        self.failIf(h.enabled())
        ui.handlers.add(h)

        self.assertEqual(ui.run(), 1)
        self.stop_capture()

        self.assert_('no available' in self.stderr)
        self.failIf(os.path.exists(self.open_app_log))

00685     def test_check_composite_avail(self):
        '''calling with --check-composite and available driver'''

        sys.argv = ['ui-test', '--check-composite']
        ui = sandbox.TestUI()

        class XorgComp(XorgDriverHandler):
            def __init__(self, ui):
                XorgDriverHandler.__init__(self, ui, 'vanilla3d',
                    'mesa-vanilla', 'v3d', 'vanilla')
            def supports_composite(self):
                return True

        h = XorgComp(ui)
        self.failIf(h.enabled())
        ui.handlers.add(h)

        self.assertEqual(ui.run(), 0)

        self.stop_capture()
        self.assertEqual(open(self.open_app_log).read(), 
            '--confirm --enable kmod:vanilla3d\n')

00708     def test_check_composite_enabled(self):
        '''calling with --check-composite and already enabled driver'''

        sys.argv = ['ui-test', '--check-composite']
        ui = sandbox.TestUI()

        class XorgComp(XorgDriverHandler):
            def __init__(self, ui):
                XorgDriverHandler.__init__(self, ui, 'vanilla3d',
                    'mesa-vanilla', 'v3d', 'vanilla')
            def supports_composite(self):
                return True
            def enabled(self):
                return True

        h = XorgComp(ui)
        ui.handlers.add(h)

        self.assertEqual(ui.run(), 1)

        self.stop_capture()
        self.failIf(os.path.exists(self.open_app_log))
        self.assert_('already enabled' in self.stderr)

Generated by  Doxygen 1.6.0   Back to index