#!/usr/bin/env ruby
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2017 Harald Sitter <sitter@kde.org>


require 'fileutils'
require 'optparse'
require 'tmpdir'

STDOUT.sync = true # force immediate flushing without internal caching

class Isolator
  def mangle_env(tmpdir)
    ENV['HOME'] = tmpdir
    ENV.keys.each { |k| ENV.delete(k) if k.start_with?('XDG_') }
  end

  private

  def dbus_run(cmd)
    warn dbus_run_cmd(cmd)
    system(dbus_run_cmd(cmd))
  end

  def dbus_run_cmd(cmd)
    "dbus-run-session -- #{cmd}"
  end
end

# Isolates GUI via xephyr
class XephyrIsolator < Isolator
  def run(cmd)
    ephemeral('Xephyr -screen 1024x768x24+32 :666') do
      ENV['DISPLAY'] = ':666'
      dbus_run(cmd) || raise
    end
  end

  private

  def ephemeral(*args)
    pid = spawn(*args)
    yield
  ensure
    Process.kill('KILL', pid) if pid
    Process.waitpid2(pid) if pid
  end
end

# Isolates GUI via xvfb-run
class XvfbIsolator < Isolator
  def run(cmd)
    warn "xvfb-run -a --server-args=\"-screen 0 1024x768x24\" #{dbus_run_cmd(cmd)}"
    system("xvfb-run -a --server-args=\"-screen 0 1024x768x24\" #{dbus_run_cmd(cmd)}") || raise
  end
end

class NoIsolator < Isolator
  def mangle_env(*)
    # noop without isolation
  end

  def run(cmd)
    # No X11 and no DBus isolation.
    warn cmd.to_s
    system(cmd) || raise
  end
end

def new_isolator
  return NoIsolator.new if ENV['JENKINS_SERVER_COOKIE'] || ENV['NO_ISOLATOR']
  return XephyrIsolator.new if ENV['XEPHYR']
  XvfbIsolator.new
end

OptionParser.new do |opts|
  opts.banner = "Usage: #{$0} ARGS"

  opts.separator('')

  opts.on('--drkonqi PATH', 'Path to drkonqi bin to test.') do |v|
    ENV['DRKONQI_PATH'] = v
  end

  opts.on('--at-spi-bus-launcher PATH',
          'Path to --at-spi-bus-launcher bin to use for testing.') do |v|
    ENV['AT_SPI_BUS_LAUNCHER_PATH'] = v
  end

  opts.on('--at-spi-registryd PATH',
          'Path to registry bin to use for testing.') do |v|
    ENV['AT_SPI_REGISTRY_PATH'] = v
  end
end.parse!

ENV['DRKONQI_PATH'] ||= '/usr/lib/x86_64-linux-gnu/libexec/drkonqi'
ENV['AT_SPI_BUS_LAUNCHER_PATH'] ||= '/usr/lib/at-spi2-core/at-spi-bus-launcher'
ENV['AT_SPI_REGISTRY_PATH'] ||= '/usr/lib/at-spi2-core/at-spi2-registryd'
ENV['KDE_FORK_SLAVES'] = '1' # fork slaves so they inherit env
ENV['KIO_DISABLE_CACHE_CLEANER'] = '1' # do not start the cleaner, it'll dangle
ENV['DRKONQI_IGNORE_QUALITY'] = '1'

# Isolate ourselves by forcing into a separate home and unsetting the XDG path
# variables. Then spin up a suitable virtual X, run a new dbus session bus
# and our test in that environment.
Dir.mktmpdir do |tmpdir|
  Dir.glob("#{__dir__}/*_test.rb").each do |test|
    isolator = new_isolator
    isolator.mangle_env(tmpdir)
    isolator.run("ruby '#{test}' -p")
  end
  sleep 2 # Wait a bit to make sure all children are dead.
end

warn 'all done'
system 'ps -ejH'
exit 0
