diff --git a/test/documentation_test.rb b/test/documentation_test.rb index ad74ea8..7a92a72 100644 --- a/test/documentation_test.rb +++ b/test/documentation_test.rb @@ -1,208 +1,225 @@ #-- # Copyright (C) 2014-2017 Harald Sitter # # 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) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # 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, see . #++ require 'fileutils' require_relative 'lib/testme' require_relative '../lib/releaseme/documentation.rb' +require_relative '../lib/releaseme/tmpdir' # FIXME: test stable branch class TestDocumentation < Testme - def setup - # FIXME: code copy with l10n - @repo_data_dir = data('l10nrepo/') + # Initialize a persistent reference repo. This repo will get copied for each + # test to start from a pristine state. svn is fairly expensive so creating + # new repos when the content doesn't change is costing multiple seconds! + # FIXME: code copy with l10n + REFERENCE_TMPDIR, REFERENCE_REPO_PATH = begin + tmpdir = ReleaseMe.mktmpdir(self.class.to_s) # cleaned via after_run hook + repo_data_dir = data('l10nrepo/') + + svn_template_dir = "#{tmpdir}/tmp_l10n_repo" + + assert_run('svnadmin', 'create', svn_template_dir) + raise unless File.exist?(svn_template_dir) + + ReleaseMe.mktmpdir(self.class.to_s) do |checkout_dir| + checkout_dir = File.join(checkout_dir, "checkout") + assert_run('svn', 'co', "file://#{svn_template_dir}", checkout_dir) + FileUtils.cp_r("#{repo_data_dir}/trunk", checkout_dir) + FileUtils.cp_r("#{repo_data_dir}/branches", checkout_dir) + assert_run('svn', 'add', '--force', '.', chdir: checkout_dir) + assert_run('svn', 'ci', '-m', 'yolo', chdir: checkout_dir) + end - @i18n_path = 'extragear-multimedia' + [tmpdir, svn_template_dir] + end + + Minitest.after_run do + FileUtils.rm_rf(REFERENCE_TMPDIR) + end + def setup + @i18n_path = 'extragear-multimedia' @trunk_url = 'trunk/l10n-kf5/' @stable_url = 'branches/stable/l10n-kf5' - @dir = 'tmp_l10n_' + (0...16).map{ ('a'..'z').to_a[rand(26)] }.join - @svn_template_dir = 'tmp_l10n_repo_' + (0...16).map{ ('a'..'z').to_a[rand(26)] }.join - @svn_checkout_dir = 'tmp_l10n_check_' + (0...16).map{ ('a'..'z').to_a[rand(26)] }.join - - system("svnadmin create #{@svn_template_dir}", [:out] => File::NULL) + @dir = 'tmp_l10n' + @svn_template_dir = 'tmp_l10n_repo' + FileUtils.cp_r(REFERENCE_REPO_PATH, @svn_template_dir) assert_path_exist(@svn_template_dir) - system("svn co file:///#{Dir.pwd}/#{@svn_template_dir} #{@svn_checkout_dir}", - [:out] => File::NULL) - FileUtils.cp_r("#{@repo_data_dir}/trunk", @svn_checkout_dir) - FileUtils.cp_r("#{@repo_data_dir}/branches", @svn_checkout_dir) - system('svn add *', chdir: @svn_checkout_dir, [:out] => File::NULL) - system("svn ci -m 'yolo'", chdir: @svn_checkout_dir, [:out] => File::NULL) - ReleaseMe::DocumentationL10n.languages = nil end # TODO: attributes of documentation are not tested.... def create_doc ReleaseMe::DocumentationL10n.new(ReleaseMe::DocumentationL10n::TRUNK, 'amarok', @i18n_path) end def create_doc_without_translation ReleaseMe::DocumentationL10n.new(ReleaseMe::DocumentationL10n::TRUNK, 'frenchfries', 'frenchfries') end def test_no_doc # no doc present d = ReleaseMe::DocumentationL10n.new(ReleaseMe::DocumentationL10n::TRUNK, 'frenchfries', @i18n_path) d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('variable-pot'), @dir) d.get(@dir) assert_path_exist("#{@dir}/Messages.sh") refute_path_exist("#{@dir}/doc") assert_equal([], Dir.glob("#{@dir}/po/*/docs")) refute_path_exist('CMakeLists.txt') end def test_get_doc # en & de d = create_doc d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) d.get(@dir) Dir.chdir(@dir) do assert_includes(File.read('CMakeLists.txt'), 'kdoctools_install(po)') docs = Dir.glob('po/*/docs/*') assert_includes(docs, 'po/fr/docs/amarok') assert_includes(docs, 'po/de/docs/amarok') assert_equal(2, docs.size) # en tree is ok assert_path_exist('doc/index.docbook') # FIXME: should we require a cmakelists? end end def test_get_doc_without_l10n # en only (everything works if only doc/ is present in git but not # translated) d = create_doc_without_translation d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) d.get(@dir) Dir.chdir(@dir) do refute_includes(File.read('CMakeLists.txt'), 'kdoctools_install(po)') assert_empty(Dir.glob('po/*/docs/*')) assert_path_exist('doc/CMakeLists.txt') assert_path_exist('doc/index.docbook') end end def test_get_doc_multi_doc d = ReleaseMe::DocumentationL10n.new(ReleaseMe::DocumentationL10n::TRUNK, 'plasma-desktop', 'kde-workspace') d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-doc'), @dir) d.get(@dir) # fr mustn't appear, it's empty expected_files = %w[ CMakeLists.txt doc doc/CMakeLists.txt doc/doc-valid2 doc/doc-valid2/CMakeLists.txt doc/doc-valid2/index.docbook doc/doc-valid2/doc-valid2.1 doc/doc-valid2/doc-valid2.1/CMakeLists.txt doc/doc-valid2/doc-valid2.1/index.docbook doc/doc-valid2/doc-valid2.1/doc-valid2.1.1 doc/doc-valid2/doc-valid2.1/doc-valid2.1.1/CMakeLists.txt doc/doc-valid2/doc-valid2.1/doc-valid2.1.1/index.docbook doc/doc-invalid1 doc/doc-valid1 doc/doc-valid1/CMakeLists.txt doc/doc-valid1/index.docbook po po/de po/de/docs po/de/docs/doc-valid2 po/de/docs/doc-valid2/index.docbook po/de/docs/doc-valid2/doc-valid2.1 po/de/docs/doc-valid2/doc-valid2.1/index.docbook po/de/docs/doc-valid2/doc-valid2.1/doc-valid2.1.1 po/de/docs/doc-valid2/doc-valid2.1/doc-valid2.1.1/index.docbook po/de/docs/doc-valid1 po/de/docs/doc-valid1/index.docbook ] present_files = Dir.chdir(@dir) { Dir.glob('**/**') } missing_files = [] expected_files.each do |f| missing_files << f unless present_files.include?(f) present_files.delete(f) end assert(missing_files.empty?, "missing file(s): #{missing_files}") assert(present_files.empty?, "unexpected file(s): #{present_files}") Dir.chdir(@dir) do assert_includes(File.read('CMakeLists.txt'), 'kdoctools_install(po)') end end def test_man d = create_doc d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('source-with-manpage'), @dir) d.get(@dir) Dir.chdir(@dir) do assert_includes(File.read('CMakeLists.txt'), 'kdoctools_install(po)') # NOTE: Our manpage line up is different from applications releases. # We pack them into their original subdir whereas the other script # packs them into the main dir. The reason is that we use the same code # paths as for documentation which makes it cheaper for us to preserver # the dir. docs = Dir.glob('po/*/docs/**/*.docbook') assert_includes(docs, 'po/de/docs/amarok/man-amarok.1.docbook') assert_includes(docs, 'po/de/docs/amarok/unicorn/man-unicorn.1.docbook') assert_equal(2, docs.size) end end def test_doc_excess_spacing # CMakeLists contains lots of excess spacing, regex should handle this and # be able to retrieve the l10n. d = create_doc d.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('excess-spacing-doc'), @dir) d.get(@dir) Dir.chdir(@dir) do docs = Dir.glob('po/*/docs/*') assert_includes(docs, 'po/fr/docs/amarok') assert_includes(docs, 'po/de/docs/amarok') assert_equal(2, docs.size) end end end diff --git a/test/l10n_test.rb b/test/l10n_test.rb index 4f77d6b..7356197 100644 --- a/test/l10n_test.rb +++ b/test/l10n_test.rb @@ -1,441 +1,453 @@ #-- # Copyright (C) 2015-2019 Harald Sitter # # 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) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # 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, see . #++ require 'fileutils' require_relative 'lib/testme' require_relative '../lib/releaseme/l10n.rb' require_relative '../lib/releaseme/l10n_statistics.rb' require_relative '../lib/releaseme/documentation.rb' +require_relative '../lib/releaseme/tmpdir' # FIXME: test stable class TestL10n < Testme - def setup - @repo_data_dir = data('l10nrepo/') + # Initialize a persistent reference repo. This repo will get copied for each + # test to start from a pristine state. svn is fairly expensive so creating + # new repos when the content doesn't change is costing multiple seconds! + REFERENCE_TMPDIR, REFERENCE_REPO_PATH = begin + tmpdir = ReleaseMe.mktmpdir(name) # cleaned via after_run hook + repo_data_dir = data('l10nrepo/') + + svn_template_dir = "#{tmpdir}/tmp_l10n_repo" + + assert_run('svnadmin', 'create', svn_template_dir) + raise unless File.exist?(svn_template_dir) + + ReleaseMe.mktmpdir(name) do |checkout_dir| + checkout_dir = File.join(checkout_dir, "checkout") + assert_run('svn', 'co', "file://#{svn_template_dir}", checkout_dir) + FileUtils.cp_r("#{repo_data_dir}/trunk", checkout_dir) + FileUtils.cp_r("#{repo_data_dir}/branches", checkout_dir) + assert_run('svn', 'add', '--force', '.', chdir: checkout_dir) + assert_run('svn', 'ci', '-m', 'yolo', chdir: checkout_dir) + end - @i18n_path = 'extragear-multimedia' + [tmpdir, svn_template_dir] + end + + Minitest.after_run do + FileUtils.rm_rf(REFERENCE_TMPDIR) + end + def setup + @i18n_path = 'extragear-multimedia' @trunk_url = 'trunk/l10n-kf5/' @stable_url = 'branches/stable/l10n-kf5' @dir = 'tmp_l10n' @svn_template_dir = 'tmp_l10n_repo' - @svn_checkout_dir = 'tmp_l10n_check' - - `svnadmin create #{@svn_template_dir}` - assert($?.success?) + FileUtils.cp_r(REFERENCE_REPO_PATH, @svn_template_dir) assert_path_exist(@svn_template_dir) - `svn co file:///#{Dir.pwd}/#{@svn_template_dir} #{@svn_checkout_dir}` - assert($?.success?) - FileUtils.cp_r("#{@repo_data_dir}/trunk", @svn_checkout_dir) - FileUtils.cp_r("#{@repo_data_dir}/branches", @svn_checkout_dir) - Dir.chdir(@svn_checkout_dir) do - `svn add *` - assert($?.success?) - `svn ci -m 'yolo'` - assert($?.success?) - end - ReleaseMe::L10n.languages = nil end def create_l10n(name = 'amarok', i18n_path = @i18n_path, origin: ReleaseMe::L10n::TRUNK) l = ReleaseMe::L10n.new(origin, name, i18n_path) l.target = "#{@dir}/l10n" l end def assert_no_dotsvn(dir) svns = Dir.glob("#{dir}/**/.svn") assert_empty(svns, "There should be no lingering .svn dirs:\n #{svns}") end def test_find_templates l = create_l10n templates = l.send(:find_templates, data('multi-pot'), skip_dir: nil) assert_equal(templates.count, 2) templates = l.send(:find_templates, data('single-pot'), skip_dir: nil) assert_equal(templates.count, 1) end def test_get_po # For visual string consinstency we actually interpolate pointlessly below. # rubocop:disable Style/UnneededInterpolation l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) l.get(@dir) assert_path_exist("#{@dir}") assert_path_exist("#{@dir}/CMakeLists.txt") refute_path_exist("#{@dir}/l10n") # temp dir must not be there assert_path_exist("#{@dir}/po") assert_path_exist("#{@dir}/po/de/amarok.po") refute_path_exist("#{@dir}/poqm") # qt translation dir must not be there FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot'), @dir) l.get(@dir) assert_path_exist("#{@dir}") assert_path_exist("#{@dir}/CMakeLists.txt") refute_path_exist("#{@dir}/l10n") # temp dir must not be there assert_path_exist("#{@dir}/po") assert_path_exist("#{@dir}/po/de/amarok.po") assert_path_exist("#{@dir}/po/de/amarokcollectionscanner.po") end def test_get_po_elsewhere l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") @elsewhere = "#{Dir.pwd}/elsewhere_tmp_l10n" FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) l.get(@dir, @elsewhere, edit_cmake: false) assert_path_exist("#{@elsewhere}/de/amarok.po") end def test_get_po_absolute_srcdir # Make sure we can pass an absolute dir as srcdir param. l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) l.get(File.absolute_path(@dir)) assert_path_exist("#{@dir}/po/de/amarok.po") end def test_get_po_edit_cmake l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) l.get(@dir, edit_cmake: true) assert_path_exist("#{@dir}/CMakeLists.txt") assert_includes(File.read("#{@dir}/CMakeLists.txt"), 'ki18n_install(po)') end def test_get_po_no_edit_cmake l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot'), @dir) l.get(@dir, edit_cmake: false) assert_path_exist("#{@dir}/CMakeLists.txt") refute_includes(File.read("#{@dir}/CMakeLists.txt"), 'ki18n_install(po)') end def test_statistics l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot'), @dir) l.get(@dir) statistics = ReleaseMe::L10nStatistics.new(["#{@dir}/po"]) de = statistics.languages.find { |x| x.name == 'de' } assert(de) assert_equal(de.all, 4) assert_equal(de.shown, 3) assert_equal(de.notshown, 1) assert_equal(de.percent_translated, 75.0) fr = statistics.languages.find { |x| x.name == 'fr' } assert(fr) assert_equal(fr.all, 4) assert_equal(fr.shown, 3) assert_equal(fr.notshown, 1) assert_equal(fr.fuzzy, 1) assert_equal(fr.percent_translated, 75.0) # Tuck this on to the test, we only care if the printer implodes. # Output is not aaaaallll that important and fairly hard to validate # without golden-references which are of course a bit shitty to manage. printer = ReleaseMe::L10nStatisticsHTMLPrinter.new(statistics, '123') out = '123.l10n.html' printer.write(out) assert_path_exist(out) refute(File.size(out) <= 0) # Bring up coverage for failure case fake_stat = mock('stat') fake_stat.stubs(:percent_translated).returns(-1) assert_equal('', printer.stat_color(fake_stat)) end def test_variable_potname l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('variable-pot'), @dir) assert_raises RuntimeError do l.get(@dir) end end def test_space_and_declared_multi_pot l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('space-and-declared-multi-pot'), @dir) l.get(@dir) assert_path_exist("#{@dir}/po/de/amarok.po") assert_path_exist("#{@dir}/po/de/amarokcollectionscanner.po") end def test_find_templates_bogus l = create_l10n templates = l.send(:find_templates, data('bogus-pot'), skip_dir: nil) assert_equal(templates, []) end def test_diff_output_some_not_found_all_not_found # When no translations were found we expect different output versus when # only some were not found. l = create_l10n l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot'), @dir) l.get(@dir) ENV.delete('RELEASEME_SHUTUP') # Reset by testme setup some_missing_stdout = StringIO.open do |io| $stdout = io l.instance_variable_set(:@__logger, nil) # Reset l.send(:print_missing_languages, [l.languages.pop]) io.string.strip end all_missing_stdout = StringIO.open do |io| $stdout = io l.instance_variable_set(:@__logger, nil) # Reset l.send(:print_missing_languages, l.languages) io.string.strip end $stdout = STDOUT refute_empty(some_missing_stdout) refute_empty(all_missing_stdout) refute_equal(some_missing_stdout, all_missing_stdout) ensure $stdout = STDOUT end def test_script # https://techbase.kde.org/Localization/Concepts/Transcript l = create_l10n('ki18n', 'frameworks') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot-script'), @dir) l.get(@dir) assert_path_exist("#{@dir}/po/sr/scripts") assert_path_exist("#{@dir}/po/sr/scripts/ki18n5") assert_path_exist("#{@dir}/po/sr/scripts/libplasma5") refute_path_exist("#{@dir}/po/sr/scripts/proto") assert_path_exist("#{@dir}/po/sr/scripts/ki18n5/ki18n5.js") assert_path_exist("#{@dir}/po/sr/scripts/ki18n5/trapnakron.pmap") assert_path_exist("#{@dir}/po/sr/scripts/libplasma5/libplasma5.js") assert_path_exist("#{@dir}/po/sr/scripts/libplasma5/plasmoid.js") assert_no_dotsvn("#{@dir}/po") end def test_pot_detection_without_releaseme # Do not find templates in the releaseme directory itself. # If releaseme was cloned into a source directory (or submoduled') # we'd otherwise trip over test fixtures. # One such fixture is: assert_path_exist("#{__dir__}/data/variable-pot/Messages.sh") l = ReleaseMe::L10n.new(ReleaseMe::L10n::TRUNK, 'ki18n', 'frameworks') # Make sure this doesn't raise anything. pos = l.send(:find_templates, __dir__) assert_empty(pos) end def test_releaseme_dir # This is a bit of a silly test. It is meant as an additional safeguard # against breaking relative path resolution. RELEASEME_DIR is meant # to be resolved to the main releaseme directory. The idea here is that # it's less likely both the test AND the lib get moved, so we'd get a # failing teset if any of the two move. # If you have come here because you moved the lib and get a failure: # Make sure RELEASEME_DIR still resolves to the main releasme dir! # If you have come here because you moved the test and get a failure: # Simply adjust the assertion to match reality. assert_equal(File.absolute_path(__dir__), ReleaseMe::L10n::RELEASEME_TEST_DIR) end def test_data # https://techbase.kde.org/Localization/Concepts/Non_Text_Resources # Data assets actually have no identifying quality, translators are expected # to manually pick them out of the source VCS and put them into their l10n # tree without breaking anything. As such we need no source tree for the # test at all. l = create_l10n('ktuberling', 'kdegames') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") Dir.mkdir(@dir) File.write("#{@dir}/CMakeLists.txt", '') l.get(@dir) assert_path_exist("#{@dir}/po") assert_path_exist("#{@dir}/po/CMakeLists.txt") assert_path_exist("#{@dir}/po/de/data/ktuberling/CMakeLists.txt") assert_path_exist("#{@dir}/po/de/data/ktuberling/foo.fake.ogg") assert_path_exist("#{@dir}/po/de/data/ktuberling/bar.fake.ogg") assert_path_exist("#{@dir}/po/sr/data/ktuberling/CMakeLists.txt") assert_path_exist("#{@dir}/po/sr/data/ktuberling/foo.fake.ogg") assert_path_exist("#{@dir}/po/sr/data/ktuberling/bar.fake.ogg") # SR is a special snow flake, it needs cmake modules, the other 100 # languages magically don't. # For testing reasons there's also one in our de directory to make sure # things wouldn't break with >1. assert_path_exist("#{@dir}/po/cmake_modules/deDataMacros.cmake") assert_path_exist("#{@dir}/po/cmake_modules/srDataMacros.cmake") # Make sure the CMakeLists properly adds our asset dir. assert(File.read("#{@dir}/po/CMakeLists.txt").include?('add_subdirectory(de/data/ktuberling)')) assert(File.read("#{@dir}/CMakeLists.txt").include?('ecm_optional_add_subdirectory(po)')) assert_no_dotsvn("#{@dir}/po") end def test_multi_pot_kde4 # In KDE4 you could have foo_qt.po to mean anything. In KF5 based code this # explicitly means that this is a qt translation compiled to qm. # We'll assert that KDE4 origins are treated as previously expected, the new # behavior is checked elsewhere. l = create_l10n(origin: ReleaseMe::Origin::TRUNK_KDE4) l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot-kde4'), @dir) l.get(@dir) assert_path_exist("#{@dir}") assert_path_exist("#{@dir}/CMakeLists.txt") refute_path_exist("#{@dir}/l10n") # temp dir must not be there assert_path_exist("#{@dir}/po") assert_path_exist("#{@dir}/po/de/amarok.po") assert(File.exist?("#{@dir}/po/de/amarokcollectionscanner_qt.po")) refute(File.read("#{@dir}/CMakeLists.txt").include?('ecm_install_po_files_as_qm')) end def test_poqm # Qt strings get put into a foo_qt.po, they are meant to get installed via # ecm_install_po_files_as_qm from ECM. l = create_l10n('step', 'kdeedu') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot-qt'), @dir) l.get(@dir) assert_path_exist("#{@dir}/poqm") assert_path_exist("#{@dir}/po/de/step.po") assert_path_exist("#{@dir}/poqm/de/step_qt.po") assert(File.read("#{@dir}/CMakeLists.txt").include?('ki18n_install(po)')) assert(File.read("#{@dir}/CMakeLists.txt").include?('ecm_install_po_files_as_qm(poqm)')) end def test_poqm_frameworks_movery # In frameworks po/ is used in place of poqm/ when a source uses Qt # translations exclusively. I couldn't actually find an example of # frameworks using both, but I'd like to think that it would be consistent # with how applications handle it: po/ and poqm/. l = create_l10n('solid', 'frameworks') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot-qt-frameworks'), @dir) l.get(@dir) assert_path_exist("#{@dir}/po") assert_path_exist("#{@dir}/po/de/solid_qt.po") refute_path_exist("#{@dir}/poqm") assert(File.read("#{@dir}/CMakeLists.txt").include?('ecm_install_po_files_as_qm(po)')) assert(!File.read("#{@dir}/CMakeLists.txt").include?('ecm_install_po_files_as_qm(poqm)')) end def test_drop_worthless_po # When a translations has 0 strings translated there is no point in shipping # it, we'll drop it (including data and assets because we can't qualify # them, so we'll use lack of UI translations as indication for poor quality # everywhere). l = create_l10n('solid', 'frameworks') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('multi-pot-qt-frameworks'), @dir) l.get(@dir) assert_equal(%w[sr], l.zero_percent_dropped) assert_path_exist("#{@dir}/po") refute_path_exist("#{@dir}/po/sr/") end def test_pot_with_pot_in_name # Make sure multiple '.pot' aren't messing up the template detection by # incorrectly mangling more than the terminal .pot. # e.g. org.kde.potd.pot is org.kde.potd.po not org.kde.pod.po nor # org.kde.pod.pot # https://bugs.kde.org/show_bug.cgi?id=420574 l = create_l10n('kdeplasmas-addons', 'kde-workspace') l.init_repo_url("file:///#{Dir.pwd}/#{@svn_template_dir}") FileUtils.rm_rf(@dir) FileUtils.cp_r(data('single-pot-pot-name'), @dir) l.get(@dir) assert_path_exist("#{@dir}/po/de/org.kde.potd.po") end end diff --git a/test/lib/testme.rb b/test/lib/testme.rb index 296649f..e6d1869 100644 --- a/test/lib/testme.rb +++ b/test/lib/testme.rb @@ -1,114 +1,156 @@ -require 'tmpdir' require 'fileutils' +require 'open3' +require 'tmpdir' require_relative '../test_helper' require 'minitest/unit' begin require 'mocha/minitest' rescue LoadError # 1.0 changed the name, try older name as well for good measure require 'mocha/mini_test' end require 'webmock/minitest' module TestMeExtension + module TestMeClassExtension + def testdir + File.expand_path(File.dirname(File.dirname(__FILE__))).to_s + end + + def datadir + "#{testdir}/data" + end + + def data(path) + path = path.partition('data/').last if path.start_with?('data/') + "#{datadir}/#{path}" + end + + # see instance method. this is a raise-only variant for use in global + # test hooks (outside test instances). + def assert_run(*args) + out, result = Open3.capture2e(*args) + raise <<-ERROR unless result.success? + === assert_run[#{args.join(' ')}] === + #{out.strip} + === + ERROR + end + end + + def self.prepended(base) + class << base + prepend TestMeClassExtension + end + end + attr_reader :tmpdir attr_reader :testdir attr_reader :datadir def initialize(*args) @dir = nil @git_config_name = nil @git_config_email = nil super end def setup_git if `git config --global user.email`.strip.empty? @git_config_email = true `git config --global user.email "you@example.com"` end if `git config --global user.name`.strip.empty? @git_config_name = true `git config --global user.name "Your Name"` end end def teardown_git `git config --global --unset user.email` unless @git_config_email.nil? `git config --global --unset user.name` unless @git_config_name.nil? end def setup_env ENV['GNUPGHOME'] = data('keyring') end def before_setup @orig_env = ENV.to_h # to_h causes a full deserialization ENV['RELEASEME_SHUTUP'] = 'true' ENV['SANITIZED_PREFIX_SUFFIX'] = '1' @tmpdir = Dir.mktmpdir("testme-#{self.class.to_s.tr(':', '_')}") ENV['TEST_SETUP'] = nil - @testdir = File.expand_path(File.dirname(File.dirname(__FILE__))).to_s - @datadir = "#{@testdir}/data" + @testdir = self.class.testdir + @datadir = self.class.datadir @pwdir = Dir.pwd Dir.chdir(@tmpdir) setup_git setup_env super end def after_teardown Dir.chdir(@pwdir) FileUtils.rm_rf(@tmpdir) # Restore original env ## Explicitly clear to be on the safe side. Sometimes restoring the env ## may bug out slightly (on windows). ENV.clear ENV.replace(@orig_env) teardown_git super end def data(path) - path = path.partition('data/').last if path.start_with?('data/') - "#{@datadir}/#{path}" + self.class.data(path) end def assert_path_exist(path, msg = nil) msg = message(msg) { "Expected path '#{path}' to exist" } assert File.exist?(path), msg end def refute_path_exist(path, msg = nil) msg = message(msg) { "Expected path '#{path}' to NOT exist" } refute File.exist?(path), msg end + + # handy overload to assert a command succeeds and if not print its output + def assert_run(*args) + out, result = Open3.capture2e(*args) + assert(result.success?, <<-ERROR) +=== assert_run[#{args.join(' ')}] === +#{out.strip} +=== + ERROR + end end class Testme < Minitest::Test prepend TestMeExtension # WARNING: with minitest one should extend through a prepend otherwise hooks # such as mocha may not get properly applied and cause test malfunctions! end # Only set SANITIZED_PREFIX_SUFFIX in tests. Actual lib code mustn't ever # set it as that'd bypass the test. module MkTmpDirOverlay def mktmpdir(*) return super if ENV['SANITIZED_PREFIX_SUFFIX'] raise 'Dir.mktmpdir must not be used! Use Releaseme.mktmpdir!' ensure ENV['SANITIZED_PREFIX_SUFFIX'] = nil end end # Prevent tests from using mktmpdir directly and instead expect them to go # through our mktmpdir such that the prefix_suffix gets cleaned up. # https://bugs.kde.org/show_bug.cgi?id=393011 class Dir class << self prepend MkTmpDirOverlay end end