redo service menu ruby helpers from ground up more or less

Summary:
- apply ruby community style guidelines
- full rewrite fixing, among other things:
  - inefficient/unreadable String#end_with reimplementation
  - inefficient use of Kernel.system (forked shell to fork a shell)
  - inefficient/unreadable Dir.glob reimplementation
  - inefficient File initialization for single chmod
  - invocation conditions are now actually readable
  - invocation conditions now also force +x on argless scripts, not just
    scripts that need arguments
  - repetitive conditions are now expressed as loops on argument arrays
  - mime detection now uses xdg-mime instead of file (xdg-mime internally
    may fall back to mime but will prefer higher level tools such as
    kmimetypefinder5; giving better results overall)
  - return values of "backtick forks" are now checked and will produce
    suitable errors on stderr
  - fail now takes a log_msg argument which is printed to stderr. this
    is in addition to the error raised as notification for the user, as
    that is unfortunately not so useful for diagnostics
  - overall error handling and logging of problem causes is much improved
- add license headers. the original code was actually fairly exhaustive, so
  this really should have had a header to begin with. the code was
  originally introduced in svn r1045663 on Nov 6 14:56:35 2009 UTC
- add blackbox tests. in the interest of keeping the scripts actually
  simple scripts (as opposed to a bunch of classes used by even simpler
  scirpts) they are now also covered by test rigging which runs them as
  scripts (again, as opposed to individual unit testing of distinct units)
  - the tests optionally can use simplecov to gather coverage metrics
  - also wired up to ctest so it actually gets run

structurally there is actually a fair amount of overlap between the two
scripts, but again, in the interest of keeping things simple I think it's
better to live with that instead of refactoring a shared library out of
it and then use heavy-duty meta-programming

Reviewers: #dolphin, elvisangelaccio

Reviewed By: #dolphin, elvisangelaccio

Subscribers: elvisangelaccio, kfm-devel

Tags: #dolphin

Differential Revision: https://phabricator.kde.org/D19334
This commit is contained in:
Harald Sitter 2019-02-26 13:48:08 +01:00
parent 363fd1afa9
commit 644d6f8522
7 changed files with 540 additions and 110 deletions

View file

@ -1,37 +1,72 @@
#!/usr/bin/env ruby
# Copyright (C) 2009 Jonathan Schmidt-Dominé <devel@the-user.org>
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
require 'fileutils'
archive = ARGV[0]
if archive[(archive.length - 8)..(archive.length)] == ".desktop"
FileUtils.rm(`qtpaths --writable-path GenericDataLocation`.strip! + "/kservices5/ServiceMenus/" + File.basename(archive))
exit(0)
ARCHIVE = ARGV[0]
# @param log_msg [String] error that gets logged to CLI
def fail(log_msg: nil)
# FIXME: this is not translated...
msg = 'Dolphin service menu installation failed'
warn log_msg if log_msg
system('kdialog', '--passivepopup', msg, '15')
abort
end
dir = archive + "-dir"
# try: deinstall.sh
# try: deinstall
# try: installKDE4.sh
# try: installKDE4
# try: install.sh
# try: install
while true
dd = Dir.new(dir)
break if dd.count != 3
odir = dir
for entry in dd
dir += "/" + entry if entry != "." && entry != ".."
end
if !File.directory? dir
dir = odir
break
if ARCHIVE.end_with?('.desktop')
data_location = `qtpaths --writable-path GenericDataLocation`.strip
unless $?.success?
fail(log_msg: "Could not get GenericDataLocation #{data_location}")
end
FileUtils.rm("#{data_location}/kservices5/ServiceMenus/#{File.basename(ARCHIVE)}")
exit(0)
end
dir = "#{ARCHIVE}-dir"
deinstaller = nil
%w[deinstall.sh deinstall].find do |script|
deinstaller = Dir.glob("#{dir}/**/#{script}")[0]
end
installer = nil
%w[install-it.sh install-it installKDE4.sh installKDE4 install.sh install].find do |script|
installer = Dir.glob("#{dir}/**/#{script}")[0]
end
Dir.chdir(dir) do
deinstalled = false
[deinstaller, installer].uniq.compact.each { |f| File.chmod(0o700, f) }
if deinstaller
puts "[servicemenudeinstallation]: Trying to run deinstaller #{deinstaller}"
deinstalled = system(deinstaller)
elsif installer
puts "[servicemenudeinstallation]: Trying to run installer #{installer}"
%w[--remove --delete --uninstall --deinstall].any? do |arg|
deinstalled = system(installer, arg)
end
end
fail unless deinstalled
end
Dir.chdir(dir)
def fail()
system("kdialog --passivepopup \"Deinstallation failed\" 15")
exit(-1)
end
if !((File.exist?(file = "./deinstall.sh") || File.exist?(file = "./deinstall")) && system(file))
fail() if !File.exist?(file = "./installKDE4.sh") && !File.exist?(file = "./installKDE4") && !File.exist?(file = "./install.sh") && !File.exist?(file = "./install")
File.new(file).chmod(0700)
fail() if !system(file + " --remove") && !system(file + " --delete") && !system(file + " --uninstall") && !system(file + " --deinstall")
end
FileUtils.rm_r(dir)

View file

@ -1,88 +1,136 @@
#!/usr/bin/env ruby
require 'pathname'
# Copyright (C) 2009 Jonathan Schmidt-Dominé <devel@the-user.org>
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
require 'fileutils'
archive = ARGV[0]
$servicedir = `qtpaths --writable-path GenericDataLocation`.strip! + "/kservices5/ServiceMenus/"
FileUtils.mkdir_p($servicedir) if !File.exist?($servicedir)
if archive[(archive.length - 8)..(archive.length - 1)] == ".desktop"
puts "Single-File Service-Menu"
puts archive
puts $servicedir
FileUtils.cp(archive, $servicedir);
exit(0)
end
def mimeType(filename)
IO.popen("file --mime-type -b " + filename).gets().strip!()
end
$archivetypes = { "application/x-tar" => :"tar -xf %s -C %s",
"application/tar" => :"tar -xf %s -C %s",
"application/x-gzip" => :"tar -zxf %s -C %s",
"application/gzip" => :"tar -zxf %s -C %s",
"application/x-gzip-compressed-tar" => :"tar -zxf %s -C %s",
"application/gzip-compressed-tar" => :"tar -zxf %s -C %s",
"application/x-gzip-compressed" => :"tar -zxf %s -C %s",
"application/gzip-compressed" => :"tar -zxf %s -C %s",
"application/bzip" => :"tar -jxf %s -C %s",
"application/bzip2" => :"tar -jxf %s -C %s",
"application/x-bzip" => :"tar -jxf %s -C %s",
"application/x-bzip2" => :"tar -jxf %s -C %s",
"application/bzip-compressed" => :"tar -jxf %s -C %s",
"application/bzip2-compressed" => :"tar -jxf %s -C %s",
"application/x-bzip-compressed" => :"tar -jxf %s -C %s",
"application/x-bzip2-compressed" => :"tar -jxf %s -C %s",
"application/bzip-compressed-tar" => :"tar -jxf %s -C %s",
"application/bzip2-compressed-tar" => :"tar -jxf %s -C %s",
"application/x-bzip-compressed-tar" => :"tar -jxf %s -C %s",
"application/x-bzip2-compressed-tar" => :"tar -jxf %s -C %s",
"application/zip" => :"unzip %s -d %s",
"application/x-zip" => :"unzip %s -d %s",
"application/x-zip-compressed" => :"unzip %s -d %s",
"multipart/x-zip" => :"unzip %s -d %s",
"application/tgz" => :"tar -zxf %s -C %s",
"application/x-compressed-gtar" => :"tar -zxf %s -C %s",
"file/tgz" => :"tar -zxf %s -C %s",
"multipart/x-tar-gz" => :"tar -zxf %s -C %s",
"application/x-gunzip" => :"tar -zxf %s -C %s",
"application/gzipped" => :"tar -zxf %s -C %s",
"gzip/document" => :"tar -zxf %s -C %s",
"application/x-bz2 " => :"tar -jxf %s -C %s",
"application/x-gtar" => :"tar -xf %s -C %s",
"multipart/x-tar" => :"tar -xf %s -C %s"
ARCHIVE_UNCOMPRESSORS = {
'application/x-tar' => :"tar -xf %s -C %s",
'application/tar' => :"tar -xf %s -C %s",
'application/x-gzip' => :"tar -zxf %s -C %s",
'application/gzip' => :"tar -zxf %s -C %s",
'application/x-gzip-compressed-tar' => :"tar -zxf %s -C %s",
'application/gzip-compressed-tar' => :"tar -zxf %s -C %s",
'application/x-gzip-compressed' => :"tar -zxf %s -C %s",
'application/gzip-compressed' => :"tar -zxf %s -C %s",
'application/bzip' => :"tar -jxf %s -C %s",
'application/bzip2' => :"tar -jxf %s -C %s",
'application/x-bzip' => :"tar -jxf %s -C %s",
'application/x-bzip2' => :"tar -jxf %s -C %s",
'application/bzip-compressed' => :"tar -jxf %s -C %s",
'application/bzip2-compressed' => :"tar -jxf %s -C %s",
'application/x-bzip-compressed' => :"tar -jxf %s -C %s",
'application/x-bzip2-compressed' => :"tar -jxf %s -C %s",
'application/bzip-compressed-tar' => :"tar -jxf %s -C %s",
'application/bzip2-compressed-tar' => :"tar -jxf %s -C %s",
'application/x-bzip-compressed-tar' => :"tar -jxf %s -C %s",
'application/x-bzip2-compressed-tar' => :"tar -jxf %s -C %s",
'application/zip' => :"unzip %s -d %s",
'application/x-zip' => :"unzip %s -d %s",
'application/x-zip-compressed' => :"unzip %s -d %s",
'multipart/x-zip' => :"unzip %s -d %s",
'application/tgz' => :"tar -zxf %s -C %s",
'application/x-compressed-gtar' => :"tar -zxf %s -C %s",
'file/tgz' => :"tar -zxf %s -C %s",
'multipart/x-tar-gz' => :"tar -zxf %s -C %s",
'application/x-gunzip' => :"tar -zxf %s -C %s",
'application/gzipped' => :"tar -zxf %s -C %s",
'gzip/document' => :"tar -zxf %s -C %s",
'application/x-bz2 ' => :"tar -jxf %s -C %s",
'application/x-gtar' => :"tar -xf %s -C %s",
'multipart/x-tar' => :"tar -xf %s -C %s"
}
ARCHIVE = ARGV[0]
# @param log_msg [String] error that gets logged to CLI
def fail(log_msg: nil)
# FIXME: this is not translated...
msg = 'Dolphin service menu installation failed'
warn log_msg if log_msg
system('kdialog', '--passivepopup', msg, '15')
abort
end
def mime_type(filename)
ret = `xdg-mime query filetype #{filename}`.strip
return ret if $?.success?
warn 'Failed to xdg-mime'
fail(log_msg: "Failed to xdg-mime #{filename}: #{ret}")
end
def uncompress(filename, output)
system(sprintf($archivetypes[mimeType(filename)].to_s, filename, output))
uncompressor = ARCHIVE_UNCOMPRESSORS.fetch(mime_type(filename)).to_s
system(format(uncompressor, filename, output))
rescue KeyError => e
# If a mimetype doesn't have an uncompressor mapped we'll get a keyerror.
# we'll log the error but visually report the failure.
fail(log_msg: "Unmapped compression format #{filename}; #{e.message}")
end
dir = archive + "-dir"
if File.exist?(dir)
FileUtils.rm_r(dir)
data_location = `qtpaths --writable-path GenericDataLocation`.strip
unless $?.success?
fail(log_msg: "Could not get GenericDataLocation #{data_location}")
end
servicedir = "#{data_location}/kservices5/ServiceMenus/"
FileUtils.mkdir_p(servicedir) unless File.exist?(servicedir)
if ARCHIVE.end_with?('.desktop')
puts 'Single-File Service-Menu'
puts ARCHIVE
puts servicedir
FileUtils.cp(ARCHIVE, servicedir)
exit
end
dir = "#{ARCHIVE}-dir"
FileUtils.rm_r(dir) if File.exist?(dir)
FileUtils.mkdir(dir)
exit(-1) if !uncompress(archive, dir)
# try: install-it.sh
# try: install-it
# try: installKDE4.sh
# try: installKDE4
# try: install.sh
# try: install
while true
dd = Dir.new(dir)
break if dd.count != 3
odir = dir
for entry in dd
dir += "/" + entry if entry != "." && entry != ".."
end
if !File.directory? dir
dir = odir
break
end
fail(log_msg: 'uncompress failed') unless uncompress(ARCHIVE, dir)
install_it = nil
%w[install-it.sh install-it].find do |script|
install_it = Dir.glob("#{dir}/**/#{script}")[0]
end
Dir.chdir(dir)
def fail()
system("kdialog --passivepopup \"Installation failed\" 15")
exit(-1)
installer = nil
%w[installKDE4.sh installKDE4 install.sh install].find do |script|
installer = Dir.glob("#{dir}/**/#{script}")[0]
end
Dir.chdir(dir) do
installed = false
[install_it, installer].uniq.compact.each { |f| File.chmod(0o700, f) }
if install_it
puts "[servicemenuinstallation]: Trying to run install_it #{install_it}"
installed = system(install_it)
elsif installer
puts "[servicemenuinstallation]: Trying to run installer #{installer}"
%w[--local --local-install --install].any? do |arg|
installed = system(installer, arg)
end
end
fail unless installed
end
if !((File.exist?(file = "./install-it.sh") || File.exist?(file = "./install-it")) && system(file))
fail() if !File.exist?(file = "./installKDE4.sh") && !File.exist?(file = "./installKDE4") && !File.exist?(file = "./install.sh") && !File.exist?(file = "./install")
File.new(file).chmod(0700)
fail() if !system(file + " --local") && !system(file + "--local-install") && !system(file + " --install")
end

View file

@ -0,0 +1,121 @@
#!/usr/bin/env ruby
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
require_relative 'test_helper'
require 'tmpdir'
class ServiceMenuDeinstallationTest < Test::Unit::TestCase
def setup
@tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}")
@pwdir = Dir.pwd
Dir.chdir(@tmpdir)
ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data')
end
def teardown
Dir.chdir(@pwdir)
FileUtils.rm_rf(@tmpdir)
ENV.delete('XDG_DATA_HOME')
end
def test_run_deinstall
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
archive_base = "#{service_dir}/foo.zip"
archive_dir = "#{archive_base}-dir/foo-1.1/"
FileUtils.mkpath(archive_dir)
File.write("#{archive_dir}/deinstall.sh", <<-DEINSTALL_SH)
#!/bin/sh
touch #{@tmpdir}/deinstall.sh-run
DEINSTALL_SH
File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
#!/bin/sh
touch #{@tmpdir}/install.sh-run
INSTALL_SH
assert(covered_system('servicemenudeinstallation', archive_base))
# deinstaller should be run
# installer should not be run
# archive_dir should have been correctly removed
assert_path_exist('deinstall.sh-run')
assert_path_not_exist('install.sh-run')
assert_path_not_exist(archive_dir)
end
def test_run_install_with_arg
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
archive_base = "#{service_dir}/foo.zip"
archive_dir = "#{archive_base}-dir/foo-1.1/"
FileUtils.mkpath(archive_dir)
File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
#!/bin/sh
if [ "$@" = "--uninstall" ]; then
touch #{@tmpdir}/install.sh-run
exit 0
fi
exit 1
INSTALL_SH
assert(covered_system('servicemenudeinstallation', archive_base))
assert_path_not_exist('deinstall.sh-run')
assert_path_exist('install.sh-run')
assert_path_not_exist(archive_dir)
end
# no scripts in sight
def test_run_fail
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
archive_base = "#{service_dir}/foo.zip"
archive_dir = "#{archive_base}-dir/foo-1.1/"
FileUtils.mkpath(archive_dir)
refute(covered_system('servicemenudeinstallation', archive_base))
# I am unsure if deinstallation really should keep the files around. But
# that's how it behaved originally so it's supposedly intentional
# - sitter, 2019
assert_path_exist(archive_dir)
end
# For desktop files things are a bit special. There is one in .local/share/servicemenu-download
# and another in the actual ServiceMenus dir. The latter gets removed by the
# script, the former by KNS.
def test_run_desktop
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
downloaded_file = "#{service_dir}/foo.desktop"
FileUtils.mkpath(service_dir)
FileUtils.touch(downloaded_file)
menu_dir = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/"
installed_file = "#{menu_dir}/foo.desktop"
FileUtils.mkpath(menu_dir)
FileUtils.touch(installed_file)
assert(covered_system('servicemenudeinstallation', downloaded_file))
assert_path_exist(downloaded_file)
assert_path_not_exist(installed_file)
end
end

View file

@ -0,0 +1,122 @@
#!/usr/bin/env ruby
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
require_relative 'test_helper'
require 'tmpdir'
class ServiceMenuInstallationTest < Test::Unit::TestCase
def setup
@tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}")
@pwdir = Dir.pwd
Dir.chdir(@tmpdir)
ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data')
end
def teardown
Dir.chdir(@pwdir)
FileUtils.rm_rf(@tmpdir)
ENV.delete('XDG_DATA_HOME')
end
def test_run_install
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
FileUtils.mkpath(service_dir)
archive = "#{service_dir}/foo.tar"
archive_dir = 'foo' # relative so tar cf is relative without fuzz
FileUtils.mkpath(archive_dir)
File.write("#{archive_dir}/install-it.sh", <<-INSTALL_IT_SH)
#!/bin/sh
touch #{@tmpdir}/install-it.sh-run
INSTALL_IT_SH
File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
#!/bin/sh
touch #{@tmpdir}/install.sh-run
INSTALL_SH
assert(system('tar', '-cf', archive, archive_dir))
assert(covered_system('servicemenuinstallation', archive))
tar_dir = "#{service_dir}/foo.tar-dir"
tar_extract_dir = "#{service_dir}/foo.tar-dir/foo"
assert_path_exist(tar_dir)
assert_path_exist(tar_extract_dir)
assert_path_exist("#{tar_extract_dir}/install-it.sh")
assert_path_exist("#{tar_extract_dir}/install.sh")
end
def test_run_install_with_arg
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
FileUtils.mkpath(service_dir)
archive = "#{service_dir}/foo.tar"
archive_dir = 'foo' # relative so tar cf is relative without fuzz
FileUtils.mkpath(archive_dir)
File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
#!/bin/sh
if [ "$@" = "--install" ]; then
touch #{@tmpdir}/install.sh-run
exit 0
fi
exit 1
INSTALL_SH
assert(system('tar', '-cf', archive, archive_dir))
assert(covered_system('servicemenuinstallation', archive))
tar_dir = "#{service_dir}/foo.tar-dir"
tar_extract_dir = "#{service_dir}/foo.tar-dir/foo"
assert_path_exist(tar_dir)
assert_path_exist(tar_extract_dir)
assert_path_not_exist("#{tar_extract_dir}/install-it.sh")
assert_path_exist("#{tar_extract_dir}/install.sh")
end
def test_run_fail
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
FileUtils.mkpath(service_dir)
archive = "#{service_dir}/foo.tar"
archive_dir = 'foo' # relative so tar cf is relative without fuzz
FileUtils.mkpath(archive_dir)
assert(system('tar', '-cf', archive, archive_dir))
refute(covered_system('servicemenuinstallation', archive))
end
def test_run_desktop
service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
downloaded_file = "#{service_dir}/foo.desktop"
FileUtils.mkpath(service_dir)
FileUtils.touch(downloaded_file)
menu_dir = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/"
installed_file = "#{menu_dir}/foo.desktop"
FileUtils.mkpath(menu_dir)
FileUtils.touch(installed_file)
assert(covered_system('servicemenuinstallation', downloaded_file))
assert_path_exist(downloaded_file)
assert_path_exist(installed_file)
end
end

View file

@ -0,0 +1,78 @@
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
begin
require 'simplecov'
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
[
SimpleCov::Formatter::HTMLFormatter
]
)
SimpleCov.start
rescue LoadError
warn 'SimpleCov not loaded'
end
# FIXME: add coverage report for jenkins?
$LOAD_PATH.unshift(File.absolute_path('../', __dir__)) # ../
def __test_method_name__
return @method_name if defined?(:@method_name)
index = 0
caller = ''
until caller.start_with?('test_')
caller = caller_locations(index, 1)[0].label
index += 1
end
caller
end
# system() variant which sets up merge-coverage. simplecov supports merging
# of multiple coverage sets. we use this to get coverage metrics on the
# binaries without having to refactor the script into runnable classes.
def covered_system(cmd, *argv)
pid = fork do
Kernel.module_exec do
alias_method(:real_system, :system)
define_method(:system) do |*args|
return true if args.include?('kdialog') # disable kdialog call
real_system(*args)
end
end
begin
require 'simplecov'
SimpleCov.start do
command_name "#{cmd}_#{__test_method_name__}"
merge_timeout 16
end
rescue LoadError
warn 'SimpleCov not loaded'
end
ARGV.replace(argv)
load "#{__dir__}/../#{cmd}"
puts 'all good, fork ending!'
exit 0
end
waitedpid, status = Process.waitpid2(pid)
assert_equal(pid, waitedpid)
status.success? # behave like system and return the success only
end
require 'test/unit'

View file

@ -0,0 +1,24 @@
#!/usr/bin/env ruby
# Copyright (C) 2019 Harald Sitter <sitter@kde.org>
#
# 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
# This is a fancy wrapper around test_helper to prevent the collector from
# loading the helper twice as it would occur if we ran the helper directly.
require_relative 'test_helper'
Test::Unit::AutoRunner.run(true, File.absolute_path(__dir__))

View file

@ -69,3 +69,5 @@ ecm_add_test(placesitemmodeltest.cpp
TEST_NAME placesitemmodeltest
LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
add_test(NAME servicemenutest
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../settings/services/test/test_run.rb)