launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21539
[Merge] lp:~cjwatson/launchpad-buildd/pottery-tests into lp:launchpad-buildd
Colin Watson has proposed merging lp:~cjwatson/launchpad-buildd/pottery-tests into lp:launchpad-buildd.
Commit message:
Add tests for lpbuildd.pottery, extracted from Launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/pottery-tests/+merge/323843
I think these were accidentally left in the Launchpad tree when the code under test was extracted, and they really don't belong there.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad-buildd/pottery-tests into lp:launchpad-buildd.
=== modified file 'Makefile'
--- Makefile 2015-07-31 11:54:07 +0000
+++ Makefile 2017-05-10 11:28:32 +0000
@@ -21,12 +21,14 @@
.PHONY: all clean deb
PYTHON=python
-# NB: for this to pass, you must have txfixtures, lazr.restful, and lp on your pythonpath
-# already. lp is not packaged so this is not enforced as a build time
-# dependency. In practice you probably just want to run this with PYTHON=bin/py from
-# a Launchpad checkout.
+# NB: for this to pass, you must have txfixtures on your pythonpath already.
+# txfixtures is not packaged so this is not enforced as a build time
+# dependency. In practice you probably just want to run this with
+# PYTHON=bin/py from a Launchpad checkout.
check:
PYTHONPATH=$(PWD):$(PYTHONPATH) $(PYTHON) -m testtools.run -v \
+ lpbuildd.pottery.tests.test_generate_translation_templates \
+ lpbuildd.pottery.tests.test_intltool \
lpbuildd.tests.test_binarypackage \
lpbuildd.tests.test_buildd_slave \
lpbuildd.tests.test_buildrecipe \
=== modified file 'debian/changelog'
--- debian/changelog 2017-02-10 14:55:42 +0000
+++ debian/changelog 2017-05-10 11:28:32 +0000
@@ -1,3 +1,9 @@
+launchpad-buildd (143) UNRELEASED; urgency=medium
+
+ * Add tests for lpbuildd.pottery, extracted from Launchpad.
+
+ -- Colin Watson <cjwatson@xxxxxxxxxx> Wed, 10 May 2017 12:26:11 +0100
+
launchpad-buildd (142) trusty; urgency=medium
* lpbuildd.binarypackage: Pass DEB_BUILD_OPTIONS=noautodbgsym if we have
=== modified file 'lpbuildd/pottery/intltool.py'
--- lpbuildd/pottery/intltool.py 2016-12-09 18:04:00 +0000
+++ lpbuildd/pottery/intltool.py 2017-05-10 11:28:32 +0000
@@ -235,8 +235,11 @@
"""Represent a config file and return variables defined in it."""
def __init__(self, file_or_name):
- with open(file_or_name) as conf_file:
- self.content = conf_file.read()
+ if isinstance(file_or_name, str):
+ with open(file_or_name) as conf_file:
+ self.content = conf_file.read()
+ else:
+ self.content = file_or_name.read()
def _stripQuotes(self, identifier):
"""Strip surrounding quotes from `identifier`, if present.
=== added directory 'lpbuildd/pottery/tests'
=== added file 'lpbuildd/pottery/tests/__init__.py'
=== added file 'lpbuildd/pottery/tests/dummy_templates.tar.gz'
Binary files lpbuildd/pottery/tests/dummy_templates.tar.gz 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/dummy_templates.tar.gz 2017-05-10 11:28:32 +0000 differ
=== added directory 'lpbuildd/pottery/tests/pottery_test_data'
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_1.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_1.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_1.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_2.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_2.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_POTFILES_in_2.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_base.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_base.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_base.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_ac.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_ac.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_ac.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in_substitute_version.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in_substitute_version.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_configure_in_substitute_version.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_broken.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_broken.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_broken.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_file.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_file.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_file.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_name.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_name.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makefile_in_in_substitute_same_name.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makevars.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makevars.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_domain_makevars.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_full_ok.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_full_ok.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_full_ok.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/pottery_test_data/intltool_single_ok.tar.bz2'
Binary files lpbuildd/pottery/tests/pottery_test_data/intltool_single_ok.tar.bz2 1970-01-01 00:00:00 +0000 and lpbuildd/pottery/tests/pottery_test_data/intltool_single_ok.tar.bz2 2017-05-10 11:28:32 +0000 differ
=== added file 'lpbuildd/pottery/tests/test_generate_translation_templates.py'
--- lpbuildd/pottery/tests/test_generate_translation_templates.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/pottery/tests/test_generate_translation_templates.py 2017-05-10 11:28:32 +0000
@@ -0,0 +1,159 @@
+# Copyright 2010-2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import os
+from StringIO import StringIO
+import subprocess
+import sys
+import tarfile
+
+from bzrlib.bzrdir import BzrDir
+from bzrlib.generate_ids import (
+ gen_file_id,
+ gen_root_id,
+ )
+from bzrlib.transform import (
+ ROOT_PARENT,
+ TransformPreview,
+ )
+from fixtures import (
+ EnvironmentVariable,
+ TempDir,
+ )
+from testtools import TestCase
+from testtools.matchers import (
+ Equals,
+ MatchesSetwise,
+ )
+
+from lpbuildd import pottery
+from lpbuildd.pottery.generate_translation_templates import (
+ GenerateTranslationTemplates,
+ )
+from lpbuildd.tests.fakeslave import FakeMethod
+
+
+class TestGenerateTranslationTemplates(TestCase):
+ """Test generate-translation-templates script."""
+
+ result_name = "translation-templates.tar.gz"
+
+ def test_getBranch_url(self):
+ # If passed a branch URL, the template generation script will
+ # check out that branch into a directory called "source-tree."
+ branch_url = 'lp://~my/translation/branch'
+
+ generator = GenerateTranslationTemplates(
+ branch_url, self.result_name, self.useFixture(TempDir()).path,
+ log_file=StringIO())
+ generator._checkout = FakeMethod()
+ generator._getBranch()
+
+ self.assertEqual(1, generator._checkout.call_count)
+ self.assertTrue(generator.branch_dir.endswith('source-tree'))
+
+ def test_getBranch_dir(self):
+ # If passed a branch directory, the template generation script
+ # works directly in that directory.
+ branch_dir = '/home/me/branch'
+
+ generator = GenerateTranslationTemplates(
+ branch_dir, self.result_name, self.useFixture(TempDir()).path,
+ log_file=StringIO())
+ generator._checkout = FakeMethod()
+ generator._getBranch()
+
+ self.assertEqual(0, generator._checkout.call_count)
+ self.assertEqual(branch_dir, generator.branch_dir)
+
+ def _createBranch(self, content_map=None):
+ """Create a working branch.
+
+ :param content_map: optional dict mapping file names to file
+ contents. Each of these files with their contents will be
+ written to the branch. Currently only supports writing files at
+ the root directory of the branch.
+
+ :return: a tuple of a fresh bzr branch and its URL.
+ """
+ branch_url = 'file://' + self.useFixture(TempDir()).path
+ branch = BzrDir.create_branch_convenience(branch_url)
+
+ if content_map is not None:
+ branch.lock_write()
+ try:
+ revision_tree = branch.basis_tree()
+ transform_preview = TransformPreview(revision_tree)
+ try:
+ root_id = transform_preview.new_directory(
+ '', ROOT_PARENT, gen_root_id())
+ for name, contents in content_map.iteritems():
+ file_id = gen_file_id(name)
+ transform_preview.new_file(
+ name, root_id, [contents], file_id=file_id)
+ committer_id = 'Committer <committer@xxxxxxxxxxx>'
+ with EnvironmentVariable('BZR_EMAIL', committer_id):
+ transform_preview.commit(
+ branch, 'Populating branch.',
+ committer=committer_id)
+ finally:
+ transform_preview.finalize()
+ finally:
+ branch.unlock()
+
+ return branch, branch_url
+
+ def test_getBranch_bzr(self):
+ # _getBranch can retrieve branch contents from a branch URL.
+ bzr_home = self.useFixture(TempDir()).path
+ self.useFixture(EnvironmentVariable('BZR_HOME', bzr_home))
+ self.useFixture(EnvironmentVariable('BZR_EMAIL'))
+ self.useFixture(EnvironmentVariable('EMAIL'))
+
+ marker_text = "Ceci n'est pas cet branch."
+ branch, branch_url = self._createBranch({'marker.txt': marker_text})
+
+ generator = GenerateTranslationTemplates(
+ branch_url, self.result_name, self.useFixture(TempDir()).path,
+ log_file=StringIO())
+ generator._getBranch()
+
+ marker_path = os.path.join(generator.branch_dir, 'marker.txt')
+ with open(marker_path) as marker_file:
+ self.assertEqual(marker_text, marker_file.read())
+
+ def test_templates_tarball(self):
+ # Create a tarball from pot files.
+ workdir = self.useFixture(TempDir()).path
+ branchdir = os.path.join(workdir, 'branchdir')
+ dummy_tar = os.path.join(
+ os.path.dirname(__file__), 'dummy_templates.tar.gz')
+ with tarfile.open(dummy_tar, 'r|*') as tar:
+ tar.extractall(branchdir)
+ potnames = [
+ member.name
+ for member in tar.getmembers() if not member.isdir()]
+
+ generator = GenerateTranslationTemplates(
+ branchdir, self.result_name, workdir, log_file=StringIO())
+ generator._getBranch()
+ generator._makeTarball(potnames)
+ result_path = os.path.join(workdir, self.result_name)
+ with tarfile.open(result_path, 'r|*') as tar:
+ tarnames = tar.getnames()
+ self.assertThat(tarnames, MatchesSetwise(*(map(Equals, potnames))))
+
+ def test_script(self):
+ tempdir = self.useFixture(TempDir()).path
+ workdir = self.useFixture(TempDir()).path
+ command = [
+ sys.executable,
+ os.path.join(
+ os.path.dirname(pottery.__file__),
+ 'generate_translation_templates.py'),
+ tempdir, self.result_name, workdir]
+ retval = subprocess.call(
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ self.assertEqual(0, retval)
=== added file 'lpbuildd/pottery/tests/test_intltool.py'
--- lpbuildd/pottery/tests/test_intltool.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/pottery/tests/test_intltool.py 2017-05-10 11:28:32 +0000
@@ -0,0 +1,513 @@
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import errno
+import os
+from StringIO import StringIO
+import tarfile
+from textwrap import dedent
+
+from fixtures import TempDir
+from testtools import TestCase
+from testtools.matchers import (
+ Equals,
+ MatchesSetwise,
+ )
+
+from lpbuildd.pottery.intltool import (
+ check_potfiles_in,
+ ConfigFile,
+ find_intltool_dirs,
+ find_potfiles_in,
+ generate_pot,
+ generate_pots,
+ get_translation_domain,
+ )
+from lpbuildd.tests.fakeslave import FakeMethod
+
+
+class SetupTestPackageMixin:
+
+ test_data_dir = "pottery_test_data"
+
+ def prepare_package(self, packagename, buildfiles=None):
+ """Unpack the specified package in a temporary directory.
+
+ Change into the package's directory.
+
+ :param packagename: The name of the package to prepare.
+ :param buildfiles: A dictionary of path:content describing files to
+ add to the package.
+ """
+ # First build the path for the package.
+ cwd = os.getcwd()
+ packagepath = os.path.join(
+ cwd, os.path.dirname(__file__),
+ self.test_data_dir, packagename + ".tar.bz2")
+ # Then change into the temporary directory and unpack it.
+ os.chdir(self.useFixture(TempDir()).path)
+ self.addCleanup(os.chdir, cwd)
+ with tarfile.open(packagepath, "r|bz2") as tar:
+ tar.extractall()
+ os.chdir(packagename)
+
+ if buildfiles is None:
+ return
+
+ # Add files as requested.
+ for path, content in buildfiles.items():
+ directory = os.path.dirname(path)
+ if directory != '':
+ try:
+ os.makedirs(directory)
+ except OSError as e:
+ # Doesn't matter if it already exists.
+ if e.errno != errno.EEXIST:
+ raise
+ with open(path, 'w') as the_file:
+ the_file.write(content)
+
+
+class TestDetectIntltool(TestCase, SetupTestPackageMixin):
+
+ def test_detect_potfiles_in(self):
+ # Find POTFILES.in in a package with multiple dirs when only one has
+ # POTFILES.in.
+ self.prepare_package("intltool_POTFILES_in_1")
+ dirs = find_potfiles_in()
+ self.assertThat(dirs, MatchesSetwise(Equals("./po-intltool")))
+
+ def test_detect_potfiles_in_module(self):
+ # Find POTFILES.in in a package with POTFILES.in at different levels.
+ self.prepare_package("intltool_POTFILES_in_2")
+ dirs = find_potfiles_in()
+ self.assertThat(
+ dirs, MatchesSetwise(Equals("./po"), Equals("./module1/po")))
+
+ def test_check_potfiles_in_content_ok(self):
+ # Ideally all files listed in POTFILES.in exist in the source package.
+ self.prepare_package("intltool_single_ok")
+ self.assertTrue(check_potfiles_in("./po"))
+
+ def test_check_potfiles_in_content_ok_file_added(self):
+ # If a file is not listed in POTFILES.in, the file is still good for
+ # our purposes.
+ self.prepare_package("intltool_single_ok")
+ with open("./src/sourcefile_new.c", "w") as added_file:
+ added_file.write("/* Test file. */")
+ self.assertTrue(check_potfiles_in("./po"))
+
+ def test_check_potfiles_in_content_not_ok_file_removed(self):
+ # If a file is missing that is listed in POTFILES.in, the file
+ # intltool structure is probably broken and cannot be used for
+ # our purposes.
+ self.prepare_package("intltool_single_ok")
+ os.remove("./src/sourcefile1.c")
+ self.assertFalse(check_potfiles_in("./po"))
+
+ def test_check_potfiles_in_wrong_directory(self):
+ # Passing in the wrong directory will cause the check to fail
+ # gracefully and return False.
+ self.prepare_package("intltool_single_ok")
+ self.assertFalse(check_potfiles_in("./foo"))
+
+ def test_find_intltool_dirs(self):
+ # Complete run: find all directories with intltool structure.
+ self.prepare_package("intltool_full_ok")
+ self.assertEqual(
+ ["./po-module1", "./po-module2"], find_intltool_dirs())
+
+ def test_find_intltool_dirs_broken(self):
+ # Complete run: part of the intltool structure is broken.
+ self.prepare_package("intltool_full_ok")
+ os.remove("./src/module1/sourcefile1.c")
+ self.assertEqual(
+ ["./po-module2"], find_intltool_dirs())
+
+
+class TestIntltoolDomain(TestCase, SetupTestPackageMixin):
+
+ def test_get_translation_domain_makevars(self):
+ # Find a translation domain in Makevars.
+ self.prepare_package("intltool_domain_makevars")
+ self.assertEqual(
+ "translationdomain",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makevars_subst_1(self):
+ # Find a translation domain in Makevars, substituted from
+ # Makefile.in.in.
+ self.prepare_package(
+ "intltool_domain_base",
+ {
+ "po/Makefile.in.in": "PACKAGE=packagename-in-in\n",
+ "po/Makevars": "DOMAIN = $(PACKAGE)\n",
+ })
+ self.assertEqual(
+ "packagename-in-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makevars_subst_2(self):
+ # Find a translation domain in Makevars, substituted from
+ # configure.ac.
+ self.prepare_package(
+ "intltool_domain_base",
+ {
+ "configure.ac": "PACKAGE=packagename-ac\n",
+ "po/Makefile.in.in": "# No domain here.\n",
+ "po/Makevars": "DOMAIN = $(PACKAGE)\n",
+ })
+ self.assertEqual(
+ "packagename-ac",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makefile_in_in(self):
+ # Find a translation domain in Makefile.in.in.
+ self.prepare_package("intltool_domain_makefile_in_in")
+ self.assertEqual(
+ "packagename-in-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac(self):
+ # Find a translation domain in configure.ac.
+ self.prepare_package("intltool_domain_configure_ac")
+ self.assertEqual(
+ "packagename-ac",
+ get_translation_domain("po"))
+
+ def prepare_ac_init(self, parameters):
+ # Prepare test for various permutations of AC_INIT parameters
+ configure_ac_content = dedent("""
+ AC_INIT(%s)
+ GETTEXT_PACKAGE=AC_PACKAGE_NAME
+ """) % parameters
+ self.prepare_package(
+ "intltool_domain_base",
+ {
+ "configure.ac": configure_ac_content,
+ })
+
+ def test_get_translation_domain_configure_ac_init(self):
+ # Find a translation domain in configure.ac in AC_INIT.
+ self.prepare_ac_init("packagename-ac-init, 1.0, http://bug.org")
+ self.assertEqual(
+ "packagename-ac-init",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac_init_single_param(self):
+ # Find a translation domain in configure.ac in AC_INIT.
+ self.prepare_ac_init("[Just 1 param]")
+ self.assertIsNone(get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac_init_brackets(self):
+ # Find a translation domain in configure.ac in AC_INIT with brackets.
+ self.prepare_ac_init("[packagename-ac-init], 1.0, http://bug.org")
+ self.assertEqual(
+ "packagename-ac-init",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac_init_tarname(self):
+ # Find a translation domain in configure.ac in AC_INIT tar name
+ # parameter.
+ self.prepare_ac_init(
+ "[Package name], 1.0, http://bug.org, [package-tarname]")
+ self.assertEqual(
+ "package-tarname",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac_init_multiline(self):
+ # Find a translation domain in configure.ac in AC_INIT when it
+ # spans multiple lines.
+ self.prepare_ac_init(
+ "[packagename-ac-init],\n 1.0,\n http://bug.org")
+ self.assertEqual(
+ "packagename-ac-init",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_ac_init_multiline_tarname(self):
+ # Find a translation domain in configure.ac in AC_INIT tar name
+ # parameter that is on a different line.
+ self.prepare_ac_init(
+ "[Package name], 1.0,\n http://bug.org, [package-tarname]")
+ self.assertEqual(
+ "package-tarname",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_in(self):
+ # Find a translation domain in configure.in.
+ self.prepare_package("intltool_domain_configure_in")
+ self.assertEqual(
+ "packagename-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makefile_in_in_substitute(self):
+ # Find a translation domain in Makefile.in.in with substitution from
+ # configure.ac.
+ self.prepare_package("intltool_domain_makefile_in_in_substitute")
+ self.assertEqual(
+ "domainname-ac-in-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makefile_in_in_substitute_same_name(self):
+ # Find a translation domain in Makefile.in.in with substitution from
+ # configure.ac from a variable with the same name as in
+ # Makefile.in.in.
+ self.prepare_package(
+ "intltool_domain_makefile_in_in_substitute_same_name")
+ self.assertEqual(
+ "packagename-ac-in-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makefile_in_in_substitute_same_file(self):
+ # Find a translation domain in Makefile.in.in with substitution from
+ # the same file.
+ self.prepare_package(
+ "intltool_domain_makefile_in_in_substitute_same_file")
+ self.assertEqual(
+ "domain-in-in-in-in",
+ get_translation_domain("po"))
+
+ def test_get_translation_domain_makefile_in_in_substitute_broken(self):
+ # Find no translation domain in Makefile.in.in when the substitution
+ # cannot be fulfilled.
+ self.prepare_package(
+ "intltool_domain_makefile_in_in_substitute_broken")
+ self.assertIsNone(get_translation_domain("po"))
+
+ def test_get_translation_domain_configure_in_substitute_version(self):
+ # Find a translation domain in configure.in with Makefile-style
+ # substitution from the same file.
+ self.prepare_package(
+ "intltool_domain_configure_in_substitute_version")
+ self.assertEqual(
+ "domainname-in42",
+ get_translation_domain("po"))
+
+
+class TestGenerateTemplates(TestCase, SetupTestPackageMixin):
+
+ def test_generate_pot(self):
+ # Generate a given PO template.
+ self.prepare_package("intltool_full_ok")
+ self.assertTrue(
+ generate_pot("./po-module1", "module1"),
+ "PO template generation failed.")
+ expected_path = "./po-module1/module1.pot"
+ self.assertTrue(
+ os.access(expected_path, os.F_OK),
+ "Generated PO template '%s' not found." % expected_path)
+
+ def test_generate_pot_no_domain(self):
+ # Generate a generic PO template.
+ self.prepare_package("intltool_full_ok")
+ self.assertTrue(
+ generate_pot("./po-module1", None),
+ "PO template generation failed.")
+ expected_path = "./po-module1/messages.pot"
+ self.assertTrue(
+ os.access(expected_path, os.F_OK),
+ "Generated PO template '%s' not found." % expected_path)
+
+ def test_generate_pot_empty_domain(self):
+ # Generate a generic PO template.
+ self.prepare_package("intltool_full_ok")
+ self.assertTrue(
+ generate_pot("./po-module1", ""),
+ "PO template generation failed.")
+ expected_path = "./po-module1/messages.pot"
+ self.assertTrue(
+ os.access(expected_path, os.F_OK),
+ "Generated PO template '%s' not found." % expected_path)
+
+ def test_generate_pot_not_intltool(self):
+ # Fail when not an intltool setup.
+ self.prepare_package("intltool_full_ok")
+ # Cripple the setup.
+ os.remove("./po-module1/POTFILES.in")
+ self.assertFalse(
+ generate_pot("./po-module1", "nothing"),
+ "PO template generation should have failed.")
+ not_expected_path = "./po-module1/nothing.pot"
+ self.assertFalse(
+ os.access(not_expected_path, os.F_OK),
+ "Not expected PO template '%s' generated." % not_expected_path)
+
+ def test_generate_pots(self):
+ # Generate all PO templates in the package.
+ self.prepare_package("intltool_full_ok")
+ expected_paths = [
+ './po-module1/packagename-module1.pot',
+ './po-module2/packagename-module2.pot',
+ ]
+ pots_list = generate_pots()
+ self.assertEqual(expected_paths, pots_list)
+ for expected_path in expected_paths:
+ self.assertTrue(
+ os.access(expected_path, os.F_OK),
+ "Generated PO template '%s' not found." % expected_path)
+
+
+class TestConfigFile(TestCase):
+
+ def _makeConfigFile(self, text):
+ """Create a `ConfigFile` containing `text`."""
+ return ConfigFile(StringIO(dedent(text)))
+
+ def test_getVariable_smoke(self):
+ configfile = self._makeConfigFile("""
+ A = 1
+ B = 2
+ C = 3
+ """)
+ self.assertEqual('1', configfile.getVariable('A'))
+ self.assertEqual('2', configfile.getVariable('B'))
+ self.assertEqual('3', configfile.getVariable('C'))
+
+ def test_getVariable_exists(self):
+ configfile = self._makeConfigFile("DDD=dd.d")
+ self.assertEqual('dd.d', configfile.getVariable('DDD'))
+
+ def test_getVariable_ignores_mere_mention(self):
+ configfile = self._makeConfigFile("""
+ CCC
+ CCC = ccc # (this is the real definition)
+ CCC
+ """)
+ self.assertEqual('ccc', configfile.getVariable('CCC'))
+
+ def test_getVariable_ignores_irrelevancies(self):
+ configfile = self._makeConfigFile("""
+ A = a
+ ===
+ blah
+ FOO(n, m)
+ a = case-insensitive
+
+ Z = z
+ """)
+ self.assertEqual('a', configfile.getVariable('A'))
+ self.assertEqual('z', configfile.getVariable('Z'))
+
+ def test_getVariable_exists_spaces_comment(self):
+ configfile = self._makeConfigFile("CCC = ccc # comment")
+ self.assertEqual('ccc', configfile.getVariable('CCC'))
+
+ def test_getVariable_empty(self):
+ configfile = self._makeConfigFile("AAA=")
+ self.assertEqual('', configfile.getVariable('AAA'))
+
+ def test_getVariable_empty_spaces(self):
+ configfile = self._makeConfigFile("BBB = ")
+ self.assertEqual('', configfile.getVariable('BBB'))
+
+ def test_getVariable_nonexistent(self):
+ configfile = self._makeConfigFile("X = y")
+ self.assertIsNone(configfile.getVariable('FFF'))
+
+ def test_getVariable_broken(self):
+ configfile = self._makeConfigFile("EEE \n= eee")
+ self.assertIsNone(configfile.getVariable('EEE'))
+
+ def test_getVariable_strips_quotes(self):
+ # Quotes get stripped off variables.
+ configfile = self._makeConfigFile("QQQ = 'qqq'")
+ self.assertEqual('qqq', configfile.getVariable('QQQ'))
+
+ # This is done by invoking _stripQuotes (tested separately).
+ configfile._stripQuotes = FakeMethod(result='foo')
+ self.assertEqual('foo', configfile.getVariable('QQQ'))
+ self.assertNotEqual(0, configfile._stripQuotes.call_count)
+
+ def test_getFunctionParams_single(self):
+ configfile = self._makeConfigFile("FUNC_1(param1)")
+ self.assertEqual(['param1'], configfile.getFunctionParams('FUNC_1'))
+
+ def test_getFunctionParams_multiple(self):
+ configfile = self._makeConfigFile("FUNC_2(param1, param2, param3 )")
+ self.assertEqual(
+ ['param1', 'param2', 'param3'],
+ configfile.getFunctionParams('FUNC_2'))
+
+ def test_getFunctionParams_multiline_indented(self):
+ configfile = self._makeConfigFile("""
+ ML_FUNC_1(param1,
+ param2, param3)
+ """)
+ self.assertEqual(
+ ['param1', 'param2', 'param3'],
+ configfile.getFunctionParams('ML_FUNC_1'))
+
+ def test_getFunctionParams_multiline_not_indented(self):
+ configfile = self._makeConfigFile("""
+ ML_FUNC_2(
+ param1,
+ param2)
+ """)
+ self.assertEqual(
+ ['param1', 'param2'], configfile.getFunctionParams('ML_FUNC_2'))
+
+ def test_getFunctionParams_strips_quotes(self):
+ # Quotes get stripped off function parameters.
+ configfile = self._makeConfigFile('FUNC("param")')
+ self.assertEqual(['param'], configfile.getFunctionParams('FUNC'))
+
+ # This is done by invoking _stripQuotes (tested separately).
+ configfile._stripQuotes = FakeMethod(result='arg')
+ self.assertEqual(['arg'], configfile.getFunctionParams('FUNC'))
+ self.assertNotEqual(0, configfile._stripQuotes.call_count)
+
+ def test_stripQuotes_unquoted(self):
+ # _stripQuotes leaves unquoted identifiers intact.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('hello', configfile._stripQuotes('hello'))
+
+ def test_stripQuotes_empty(self):
+ configfile = self._makeConfigFile('')
+ self.assertEqual('', configfile._stripQuotes(''))
+
+ def test_stripQuotes_single_quotes(self):
+ # Single quotes are stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('x', configfile._stripQuotes("'x'"))
+
+ def test_stripQuotes_double_quotes(self):
+ # Double quotes are stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('y', configfile._stripQuotes('"y"'))
+
+ def test_stripQuotes_bracket_quotes(self):
+ # Brackets are stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('z', configfile._stripQuotes('[z]'))
+
+ def test_stripQuotes_opening_brackets(self):
+ # An opening bracket must be matched by a closing one.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('[x[', configfile._stripQuotes('[x['))
+
+ def test_stripQuotes_closing_brackets(self):
+ # A closing bracket is not accepted as an opening quote.
+ configfile = self._makeConfigFile('')
+ self.assertEqual(']x]', configfile._stripQuotes(']x]'))
+
+ def test_stripQuotes_multiple(self):
+ # Only a single layer of quotes is stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('"n"', configfile._stripQuotes("'\"n\"'"))
+
+ def test_stripQuotes_single_quote(self):
+ # A string consisting of just one quote is not stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual("'", configfile._stripQuotes("'"))
+
+ def test_stripQuotes_mismatched(self):
+ # Mismatched quotes are not stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual("'foo\"", configfile._stripQuotes("'foo\""))
+
+ def test_stripQuotes_unilateral(self):
+ # A quote that's only on one end doesn't get stripped.
+ configfile = self._makeConfigFile('')
+ self.assertEqual('"foo', configfile._stripQuotes('"foo'))