From 6b4fe9c1fb67280fa801b2383a011d657efe7172 Mon Sep 17 00:00:00 2001 From: dbs Date: Tue, 11 Dec 2007 00:46:47 +0000 Subject: [PATCH] Implement SQL localization tests. Refactor some test helper functions into a common module. Clean up db-seed-i18n.py SQL output. git-svn-id: svn://svn.open-ils.org/ILS/trunk@8194 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- build/i18n/scripts/db-seed-i18n.py | 4 +-- build/i18n/tests/data/po2sql.sql | 14 ++++++++ build/i18n/tests/data/sql2pot.pot | 72 +++++++++++++++++++++++++++++++++++++ build/i18n/tests/data/sqlsource.po | 72 +++++++++++++++++++++++++++++++++++++ build/i18n/tests/data/sqlsource.sql | 49 +++++++++++++++++++++++++ build/i18n/tests/testIDL.py | 36 ++++--------------- build/i18n/tests/testSQL.py | 59 ++++++++++++++++++++++++++++++ build/i18n/tests/testhelper.py | 36 +++++++++++++++++++ 8 files changed, 310 insertions(+), 32 deletions(-) create mode 100644 build/i18n/tests/data/po2sql.sql create mode 100644 build/i18n/tests/data/sql2pot.pot create mode 100644 build/i18n/tests/data/sqlsource.po create mode 100644 build/i18n/tests/data/sqlsource.sql create mode 100644 build/i18n/tests/testSQL.py create mode 100644 build/i18n/tests/testhelper.py diff --git a/build/i18n/scripts/db-seed-i18n.py b/build/i18n/scripts/db-seed-i18n.py index 09f4cd6086..48f0114cb9 100755 --- a/build/i18n/scripts/db-seed-i18n.py +++ b/build/i18n/scripts/db-seed-i18n.py @@ -104,7 +104,7 @@ class SQL(basel10n.BaseL10N): """ insert = "INSERT INTO config.i18n_core (fq_field, identity_value," \ - "translation, string) VALUES ('%s', '%s', '%s', '%s');" + " translation, string) VALUES ('%s', '%s', '%s', '%s');" for entry in self.pot: for table in entry.occurences: # Escape SQL single-quotes to avoid b0rkage @@ -148,7 +148,7 @@ def main(): else: outfile = open(options.outfile, 'w') for insert in pot.sql: - outfile.write(insert) + outfile.write(insert + "\n") else: opts.print_help() diff --git a/build/i18n/tests/data/po2sql.sql b/build/i18n/tests/data/po2sql.sql new file mode 100644 index 0000000000..a2694cdbf2 --- /dev/null +++ b/build/i18n/tests/data/po2sql.sql @@ -0,0 +1,14 @@ +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.bib_source', 'oclc', 'zz-ZZ', 'OCLC'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.bib_source', 'System Local', 'zz-ZZ', 'Lorem ipsum'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.bib_source', 'Project Gutenberg', 'zz-ZZ', 'Projekt Runeberg'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.standing', 'Good', 'zz-ZZ', 'Gut'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.standing', 'Barred', 'zz-ZZ', 'största'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Preschool', 'zz-ZZ', 'årligen'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Primary', 'zz-ZZ', 'bläddra'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Pre-adolescent', 'zz-ZZ', 'hjälp'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Adolescent', 'zz-ZZ', 'utgåvor'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Adult', 'zz-ZZ', 'öppet'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Specialized', 'zz-ZZ', 'datorföreningen'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'General', 'zz-ZZ', 'skapa'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('config.audience_map', 'Juvenile', 'zz-ZZ', 'klassisk'); +INSERT INTO config.i18n_core (fq_field, identity_value, translation, string) VALUES ('asset.copy_location', 'Stacks', 'zz-ZZ', 'Linköping'); diff --git a/build/i18n/tests/data/sql2pot.pot b/build/i18n/tests/data/sql2pot.pot new file mode 100644 index 0000000000..7bbbc51238 --- /dev/null +++ b/build/i18n/tests/data/sql2pot.pot @@ -0,0 +1,72 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Evergreen 1.4" +"Report-Msgid-Bugs-To: open-ils-dev@list.georgialibraries.org" +"POT-Creation-Date: +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE" +"Last-Translator: FULL NAME " +"Language-Team: LANGUAGE " +"MIME-Version: 1.0" +"Content-Type: text/plain; charset=utf-8" +"Content-Transfer-Encoding: 8-bit" + +#: config.bib_source:3 +msgid "oclc" +msgstr "" + +#: config.bib_source:4 +msgid "System Local" +msgstr "" + +#: config.bib_source:5 +msgid "Project Gutenberg" +msgstr "" + +#: config.standing:7 +msgid "Good" +msgstr "" + +#: config.standing:8 +msgid "Barred" +msgstr "" + +#: config.audience_map:31 +msgid "Unknown or unspecified" +msgstr "" + +#: config.audience_map:32 +msgid "Preschool" +msgstr "" + +#: config.audience_map:33 +msgid "Primary" +msgstr "" + +#: config.audience_map:34 +msgid "Pre-adolescent" +msgstr "" + +#: config.audience_map:35 +msgid "Adolescent" +msgstr "" + +#: config.audience_map:36 +msgid "Adult" +msgstr "" + +#: config.audience_map:37 +msgid "Specialized" +msgstr "" + +#: config.audience_map:38 +msgid "General" +msgstr "" + +#: config.audience_map:39 +msgid "Juvenile" +msgstr "" + +#: asset.copy_location:48 +msgid "Stacks" +msgstr "" diff --git a/build/i18n/tests/data/sqlsource.po b/build/i18n/tests/data/sqlsource.po new file mode 100644 index 0000000000..4e9b1c99b3 --- /dev/null +++ b/build/i18n/tests/data/sqlsource.po @@ -0,0 +1,72 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Evergreen 1.4" +"Report-Msgid-Bugs-To: open-ils-dev@list.georgialibraries.org" +"POT-Creation-Date: +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE" +"Last-Translator: FULL NAME " +"Language-Team: LANGUAGE " +"MIME-Version: 1.0" +"Content-Type: text/plain; charset=utf-8" +"Content-Transfer-Encoding: 8-bit" + +#: config.bib_source:3 +msgid "oclc" +msgstr "OCLC" + +#: config.bib_source:4 +msgid "System Local" +msgstr "Lorem ipsum" + +#: config.bib_source:5 +msgid "Project Gutenberg" +msgstr "Projekt Runeberg" + +#: config.standing:7 +msgid "Good" +msgstr "Gut" + +#: config.standing:8 +msgid "Barred" +msgstr "största" + +#: config.audience_map:31 +msgid "Unknown or unspecified" +msgstr "" + +#: config.audience_map:32 +msgid "Preschool" +msgstr "årligen" + +#: config.audience_map:33 +msgid "Primary" +msgstr "bläddra" + +#: config.audience_map:34 +msgid "Pre-adolescent" +msgstr "hjälp" + +#: config.audience_map:35 +msgid "Adolescent" +msgstr "utgåvor" + +#: config.audience_map:36 +msgid "Adult" +msgstr "öppet" + +#: config.audience_map:37 +msgid "Specialized" +msgstr "datorföreningen" + +#: config.audience_map:38 +msgid "General" +msgstr "skapa" + +#: config.audience_map:39 +msgid "Juvenile" +msgstr "klassisk" + +#: asset.copy_location:48 +msgid "Stacks" +msgstr "Linköping" diff --git a/build/i18n/tests/data/sqlsource.sql b/build/i18n/tests/data/sqlsource.sql new file mode 100644 index 0000000000..83280cff9a --- /dev/null +++ b/build/i18n/tests/data/sqlsource.sql @@ -0,0 +1,49 @@ +--002.schema.config.sql: +INSERT INTO config.bib_source (quality, source, transcendant) VALUES + (90, oils_i18n_gettext('oclc'), FALSE), + (10, oils_i18n_gettext('System Local'), FALSE), + (1, oils_i18n_gettext('Project Gutenberg'), TRUE); + +INSERT INTO config.standing (value) VALUES (oils_i18n_gettext('Good')); +INSERT INTO config.standing (value) VALUES (oils_i18n_gettext('Barred')); + +INSERT INTO config.xml_transform VALUES ( 'marcxml', 'http://www.loc.gov/MARC21/slim', 'marc', '---' ); +INSERT INTO config.xml_transform VALUES ( 'mods', 'http://www.loc.gov/mods/', 'mods', '/home/miker/MARC21slim2MODS.xsl' ); + +INSERT INTO config.metabib_field ( field_class, name, xpath ) VALUES + ( 'series', 'seriestitle', $$//mods:mods/mods:relatedItem[@type="series"]/mods:titleInfo$$ ), + ( 'title', 'abbreviated', $$//mods:mods/mods:titleInfo[mods:title and (@type='abbreviated')]$$ ), + ( 'title', 'translated', $$//mods:mods/mods:titleInfo[mods:title and (@type='translated')]$$ ), + ( 'title', 'uniform', $$//mods:mods/mods:titleInfo[mods:title and (@type='uniform')]$$ ), + ( 'title', 'proper', $$//mods:mods/mods:titleInfo[mods:title and not (@type)]$$ ), + ( 'author', 'corporate', $$//mods:mods/mods:name[@type='corporate']/mods:namePart[../mods:role/mods:text[text()='creator']]$$ ), + ( 'author', 'personal', $$//mods:mods/mods:name[@type='personal']/mods:namePart[../mods:role/mods:text[text()='creator']]$$ ), + ( 'author', 'conference', $$//mods:mods/mods:name[@type='conference']/mods:namePart[../mods:role/mods:text[text()='creator']]$$ ), + ( 'author', 'other', $$//mods:mods/mods:name[@type='personal']/mods:namePart[not(../mods:role)]$$ ), + ( 'subject', 'geographic', $$//mods:mods/mods:subject/mods:geographic$$ ), + ( 'subject', 'name', $$//mods:mods/mods:subject/mods:name$$ ), + ( 'subject', 'temporal', $$//mods:mods/mods:subject/mods:temporal$$ ), + ( 'subject', 'topic', $$//mods:mods/mods:subject/mods:topic$$ ), +-- ( field_class, name, xpath ) VALUES ( 'subject', 'genre', $$//mods:mods/mods:genre$$ ), + ( 'keyword', 'keyword', $$//mods:mods/*[not(local-name()='originInfo')]$$ ); -- /* to fool vim */ + +INSERT INTO config.audience_map (code, value, description) VALUES + ('', oils_i18n_gettext('Unknown or unspecified'), oils_i18n_gettext('The target audience for the item not known or not specified.')), + ('a', oils_i18n_gettext('Preschool'), oils_i18n_gettext('The item is intended for children, approximate ages 0-5 years.')), + ('b', oils_i18n_gettext('Primary'), oils_i18n_gettext('The item is intended for children, approximate ages 6-8 years.')), + ('c', oils_i18n_gettext('Pre-adolescent'), oils_i18n_gettext('The item is intended for young people, approximate ages 9-13 years.')), + ('d', oils_i18n_gettext('Adolescent'), oils_i18n_gettext('The item is intended for young people, approximate ages 14-17 years.')), + ('e', oils_i18n_gettext('Adult'), oils_i18n_gettext('The item is intended for adults.')), + ('f', oils_i18n_gettext('Specialized'), oils_i18n_gettext('The item is aimed at a particular audience and the nature of the presentation makes the item of little interest to another audience.')), + ('g', oils_i18n_gettext('General'), oils_i18n_gettext('The item is of general interest and not aimed at an audience of a particular intellectual level.')), + ('j', oils_i18n_gettext('Juvenile'), oils_i18n_gettext('The item is intended for children and young people, approximate ages 0-15 years.')); + +-- Admin user +INSERT INTO permission.usr_perm_map (usr,perm,depth) VALUES (1,-1,0); + +--010.schema.biblio.sql: +INSERT INTO biblio.record_entry VALUES (-1,1,1,1,-1,NOW(),NOW(),FALSE,FALSE,'','AUTOGEN','-1','','FOO'); + +--040.schema.asset.sql: +INSERT INTO asset.copy_location (name,owning_lib) VALUES (oils_i18n_gettext('Stacks'),1); +INSERT INTO asset.call_number VALUES (-1,1,NOW(),1,NOW(),-1,1,'UNCATALOGED'); diff --git a/build/i18n/tests/testIDL.py b/build/i18n/tests/testIDL.py index 9d90c9e1ab..08f74b0970 100644 --- a/build/i18n/tests/testIDL.py +++ b/build/i18n/tests/testIDL.py @@ -12,7 +12,7 @@ import os import polib import re import subprocess -import sys +import testhelper import unittest class TestIDLL10N(unittest.TestCase): @@ -30,17 +30,10 @@ class TestIDLL10N(unittest.TestCase): testpo = os.path.join(basedir, 'data/testidl.po') def setUp(self): - sys.path.append(os.path.join(self.basedir, '../scripts/')) - self.tearDown() - for dir in self.tmpdirs: - os.mkdir(dir) + testhelper.setUp(self) def tearDown(self): - for dir in self.tmpdirs: - if os.access(dir, os.F_OK): - for file in os.listdir(dir): - os.remove(os.path.join(dir, file)) - os.rmdir(dir) + testhelper.tearDown(self) def testentityize(self): """ @@ -64,8 +57,9 @@ class TestIDLL10N(unittest.TestCase): '--output', self.savepot), 0, None, None, devnull, devnull).wait() - mungepothead(self.savepot) - mungepothead(self.testpot) + # Avoid timestamp mismatches + testhelper.mungepothead(self.savepot) + testhelper.mungepothead(self.testpot) self.assertEqual(filecmp.cmp(self.savepot, self.testpot), 1) @@ -80,23 +74,5 @@ class TestIDLL10N(unittest.TestCase): 0, None, None, devnull, devnull).wait() self.assertEqual(filecmp.cmp(self.saveentities, self.idlentities), 1) - -def mungepothead(file): - """ - Change POT header to avoid annoying timestamp mismatch - """ - lines = [] - mungefile = open(file) - for line in mungefile: - line = re.sub(r'^("POT-Creation-Date: ).+"$', r'\1', line) - lines.append(line) - mungefile.close() - - # Write the changed lines back out - mungefile = open(file, 'w') - for line in lines: - mungefile.write(line) - mungefile.close() - if __name__ == '__main__': unittest.main() diff --git a/build/i18n/tests/testSQL.py b/build/i18n/tests/testSQL.py new file mode 100644 index 0000000000..9723e2dd2d --- /dev/null +++ b/build/i18n/tests/testSQL.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Perform the following tests: +# 1. Generate a POT file from a set of marked SQL statements +# 2. Generate an SQL file from a translated PO file + +import filecmp +import os +import subprocess +import testhelper +import unittest + +class TestSQLFramework(unittest.TestCase): + + basedir = os.path.dirname(__file__) + script = os.path.join(basedir, '../scripts/db-seed-i18n.py') + tmpdirs = [(os.path.join(basedir, 'tmp/'))] + sqlsource = os.path.join(basedir, 'data/sqlsource.sql') + canonpot = os.path.join(basedir, 'data/sql2pot.pot') + canonpo = os.path.join(basedir, 'data/sqlsource.po') + testpot = os.path.join(basedir, 'tmp/sql2pot.pot') + canonsql = os.path.join(basedir, 'data/po2sql.sql') + testsql = os.path.join(basedir, 'tmp/testi18n.sql') + + def setUp(self): + testhelper.setUp(self) + + def tearDown(self): + testhelper.tearDown(self) + + def testgenpot(self): + """ + Create a POT file from our test SQL statements. + """ + devnull = open('/dev/null', 'w') + proc = subprocess.Popen( + ('python', self.script, '--pot', self.sqlsource, + '--output', self.testpot), + 0, None, None).wait() + + # avoid basic timestamp conflicts + testhelper.mungepothead(self.testpot) + testhelper.mungepothead(self.canonpot) + + self.assertEqual(filecmp.cmp(self.canonpot, self.testpot), 1) + + def testgensql(self): + """ + Create a SQL file from a translated PO file. + """ + devnull = open('/dev/null', 'w') + proc = subprocess.Popen( + ('python', self.script, '--sql', self.canonpo, + '--locale', 'zz-ZZ', '--output', self.testsql), + 0, None, None, devnull, devnull).wait() + self.assertEqual(filecmp.cmp(self.canonsql, self.testsql), 1) + +if __name__ == '__main__': + unittest.main() diff --git a/build/i18n/tests/testhelper.py b/build/i18n/tests/testhelper.py new file mode 100644 index 0000000000..44f5007b63 --- /dev/null +++ b/build/i18n/tests/testhelper.py @@ -0,0 +1,36 @@ +import os +import re +import sys + +def mungepothead(file): + """ + Change POT header to avoid annoying timestamp mismatch + """ + lines = [] + mungefile = open(file) + for line in mungefile: + line = re.sub(r'^("POT-Creation-Date: ).+"$', r'\1', line) + lines.append(line) + mungefile.close() + + # Write the changed lines back out + mungefile = open(file, 'w') + for line in lines: + mungefile.write(line) + mungefile.close() + +def setUp(self): + sys.path.append(os.path.join(self.basedir, '../scripts/')) + sys.path.append(self.basedir) + self.tearDown() + for dir in self.tmpdirs: + os.mkdir(dir) + +def tearDown(self): + for dir in self.tmpdirs: + if os.access(dir, os.F_OK): + for file in os.listdir(dir): + os.remove(os.path.join(dir, file)) + os.rmdir(dir) + + -- 2.11.0