#!/usr/bin/python3
import unittest
import subprocess
import tempfile
import shutil
import os
from glob import glob

class T(unittest.TestCase):
    def setUp(self):
        '''Call ubuntu-defaults-template to build a test project.

        This will build ubuntu-defaults-test (self.pkgdir) in self.workdir (a
        temporary directory), and leave the files untouched. Call
        self.enable_example() to enable the example content of a customization
        file, or change the files manually.
        '''
        self.srcdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        self.workdir = tempfile.mkdtemp()
        env = os.environ.copy()
        env['UBUNTU_DEFAULTS_TEMPLATE_DIR'] = os.path.join(self.srcdir, 'template')

        builder = subprocess.Popen([os.path.join(self.srcdir, 'bin', 'ubuntu-defaults-template'),
            '--quiet', 'ubuntu-defaults-test'], cwd=self.workdir, env=env)
        builder.communicate()
        self.assertEqual(builder.returncode, 0)
        self.pkgdir = os.path.join(self.workdir, 'ubuntu-defaults-test')
        self.assertTrue(os.path.isdir(self.pkgdir))

    def tearDown(self):
        shutil.rmtree(self.workdir)

    def build(self):
        '''Build the defaults package and run lintian check.
        
        Return the result of dpkg -I. After running this, self.debdir contains
        the unpacked .deb.
        '''
        env = os.environ.copy()
        env['PATH'] = os.path.join(self.srcdir, 'bin') + ':' + env.get('PATH', '')
        env['UBUNTU_DEFAULTS_TEMPLATE_DIR'] = os.getcwd()
        env['DH_AUTOSCRIPTDIR'] = os.path.join(self.srcdir, 'debhelper-scripts')
        dpkg = subprocess.Popen(['dpkg-buildpackage', '-us', '-uc', '-d'],
                cwd=self.pkgdir, stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT, env=env)
        out = dpkg.communicate()[0].decode()
        self.assertEqual(dpkg.returncode, 0, 'dpkg-buildpackage failed:\n' + out)

        changes = glob(os.path.join(self.workdir, 'ubuntu-defaults-test_*.changes'))
        self.assertEqual(len(changes), 1)
        changes = changes[0]

        (code, lintian) = subprocess.getstatusoutput('lintian ' + changes)
        # filter out warnings we don't care about
        for line in lintian.splitlines():
            if 'unknown-section metapackages' in line or \
               'empty-binary-package' in line:
                   continue
            self.fail('lintian errors:\n' + lintian)
        self.assertEqual(code, 0, 'lintian failed')

        deb = glob(os.path.join(self.workdir, 'ubuntu-defaults-test_*.deb'))
        self.assertEqual(len(deb), 1)
        deb = deb[0]

        self.debdir = os.path.join(self.workdir, 'deb')
        subprocess.check_call(['dpkg', '-x', deb, self.debdir],
                cwd=self.workdir)

        return subprocess.check_output(['dpkg', '-I', deb], cwd=self.workdir).decode()

    def enable_example(self, file):
        file = os.path.join(self.pkgdir, file)
        lines = []
        line = ''
        with open(file) as f:
            for line in f:
                if line.startswith('# Example:'):
                    break
            for line in f:
                assert line.startswith('# ')
                lines.append(line[2:])
        with open(file, 'w') as f:
            for line in lines:
                f.write(line)

    def set_file(self, file, contents):
        with open(os.path.join(self.pkgdir, file), 'w') as f:
            f.write(contents)

    def test_template(self):
        '''Pure template without any customizations.'''

        control = self.build()

        files = subprocess.check_output(['find', '-type', 'f', '!', '-path',
            './usr/share/doc/ubuntu-defaults-test*'], cwd=self.debdir).decode()
        self.assertTrue(files == '', 'unexpected files in package:\n' + files)

        self.assertTrue('Package: ubuntu-defaults-test' in control)
        self.assertFalse('Depends:' in control)
        self.assertFalse('Recommends:' in control)

    def test_empty(self):
        '''Empty defaults package with no example files'''

        # only keep the Debianization
        for f in os.listdir(self.pkgdir):
            if f != 'debian':
                path = os.path.join(self.pkgdir, f)
                if os.path.isdir(path):
                    shutil.rmtree(path)
                else:
                    os.unlink(path)

        control = self.build()

        self.assertTrue('Package: ubuntu-defaults-test' in control)
        self.assertFalse('Depends:' in control)
        self.assertFalse('Recommends:' in control)

    def test_dependencies(self):
        '''depends.txt, recommends.txt'''

        self.enable_example('depends.txt')
        self.enable_example('recommends.txt')

        control = self.build()
        self.assertTrue('Depends: manpages-de, texlive-lang-german\n' in control, control)
        self.assertTrue('Recommends: fortunes-de\n' in control)

    def test_desktop(self):
        '''desktop/background.jpg'''

        test_jpg = os.path.join('test', 'test.jpg')
        shutil.copy(test_jpg, os.path.join(self.pkgdir,
            'desktop', 'background.jpg'))
        self.build()
        with open(os.path.join(self.debdir, 'usr/share/backgrounds/ubuntu-defaults-test.jpg'), 'rb') as dest:
            with open(test_jpg, 'rb') as src:
                self.assertEqual(src.read(), dest.read())
        with open(os.path.join(self.debdir,
            'usr/share/glib-2.0/schemas/ubuntu-defaults-test.gschema.override')) as f:
            self.assertTrue('usr/share/backgrounds/ubuntu-defaults-test.jpg' in f.read())

    def test_unity(self):
        '''unity/launchers.txt'''

        self.enable_example('unity/launchers.txt')
        self.build()

        # check Unity gsettings
        with open(os.path.join(self.debdir,
            'usr/share/glib-2.0/schemas/ubuntu-defaults-test.gschema.override')) as f:
            contents = f.read()
        self.assertTrue("favorites=[" in contents, 'has correct array formatting')
        self.assertTrue("'firefox.desktop'," in contents, 'has standard launchers')
        self.assertTrue("'gnome-sudoku.desktop'," in contents, 'has custom launchers')

    def test_multimedia(self):
        '''multimedia/radiostations.txt'''

        self.enable_example('multimedia/radiostations.txt')
        with open(os.path.join(self.pkgdir, 'multimedia', 'radiostations.txt'), 'a') as f:
            f.write('invalid;line\n');
        self.build()

        with open(os.path.join(self.debdir,
            'usr/lib/rhythmbox/plugins/iradio/iradio-initial.xspf')) as f:
            contents = f.read()

        self.assertTrue('Paradise' in contents)
        self.assertTrue('SWR3' in contents)
        self.assertFalse('invalid' in contents)
        self.assertTrue('&amp;channel' in contents)

    def test_firefox(self):
        '''firefox/'''

        self.enable_example('firefox/startpage.txt')
        self.enable_example('firefox/searchengine.txt')
        self.enable_example('firefox/bookmarks-toolbar.txt')
        self.enable_example('firefox/bookmarks-menu.txt')
        self.build()

        with open(glob(os.path.join(self.debdir,
            'usr/lib/firefox*/distribution/distribution.ini'))[0]) as f:
            contents = f.read()

        self.assertTrue('http://www.ubuntuforums.org' in contents)
        self.assertTrue('"Wikipedia (de)"' in contents)
        self.assertTrue('www.zeit.de' in contents)
        self.assertTrue('www.ubuntu.de' in contents)
        self.assertTrue('heise.de' in contents)

unittest.main()
