#!/usr/bin/ruby

require 'optparse'
require 'fileutils'
require 'stringio'

class Logger
  attr_reader :output

  def initialize
    @output = StringIO.new
    @start = Time.now.to_i
  end

  def string
    output.string
  end

  def puts(str)
    ts = Time.now.to_i - @start
    output.puts("#{ts}s #{str}")
  end

  def msg(str)
    self.puts "autopkgtest [%s]: %s\n" % [Time.now.strftime('%H:%M:%S'), str]
  end
end

log = Logger.new

now = Time.now.strftime('%Y-%m-%d %H:%M:%S')
log.msg "starting date and time: #{now}"
log.puts "command line arguments: #{ARGV.inspect}"

pkg = nil
outdir = nil

optparse = OptionParser.new do |opts|
  opts.banner = "Usage: test-package --output-dir OUTPUTDIR [AUTOPKGTEST-ARGS] PACKAGE"
  opts.separator "Options:"

  opts.on('--output-dir OUTPUTDIR') do |arg|
    outdir = arg
  end

  opts.on('--shell-fail', '-s') do |arg|
    true
  end

  # options with arguments
  %w[
    --user
    --trigger
    --add-apt-source
    --add-apt-release
    --pin-packages
    --copy
  ].each do |ign|
    opts.on("#{ign} IGNORED") do |arg|
      log.puts "Ignored option/argument: #{ign}=#{arg}"
    end
  end

  # options without arguments
  ['--apt-upgrade'].each do |ign|
    opts.on(ign) do
      log.puts "Ignored option:# {ign}"
    end
  end
end
optparse.parse!

if ARGV.length != 1 || outdir.nil?
  log.puts optparse
  puts log.string
  exit(1)
end

pkg  = ARGV.first

FileUtils.mkdir_p(outdir)

if ENV["DEBCI_FAKE_DEPS"]
  File.open(File.join(outdir, 'foo0t-mytest-packages'), 'w') do |f|
    ENV["DEBCI_FAKE_DEPS"].split('|').each do |line|
      f.puts line.gsub(" ", "\t")
    end
  end
end

suite = ENV['debci_suite'] || 'unstable'
version = `(apt-cache showsrc --only-source #{pkg} | awk '{if($1=="Version:"){print($2)}}' | sort -V | tail -n1) 2>/dev/null`.strip
if version == ''
  version = `date +0.0.0-1~%Y%m%d`.strip
end
File.open(File.join(outdir, 'testpkg-version'), 'w') { |f| f.puts "#{pkg} #{version}" }

log.msg("@@@@@@@@@@@@@@@@@@@@ test bed setup")
log.msg("test fake-test: preparing testbed")

if ENV["DEBCI_FAKE_COMMAND"]
  io = IO.popen(ENV["DEBCI_FAKE_COMMAND"])
  log.puts [ "$ #{ENV['DEBCI_FAKE_COMMAND']}", io.read]
  io.close
  rc = $?.exitstatus
  if rc != 0
    rc = 4
  end
else
  log.msg("test fake-test: [-----------------------")
  log.puts "Not really running anything .."
  log.puts "This has 70% chance of passing, 10% of all skipped, 10% of failing, and 10% of tmpfailing"
  result = ENV.fetch('DEBCI_FAKE_RESULT', nil)
  r = case result
      when 'pass'
        0
      when 'neutral'
        7
      when 'fail'
        8
      when 'tmpfail'
        9
      else
        rand(10)
      end

  case r
  when 0..6
    log.puts "Passed :-)"
    result = 'pass'
    rc = 0
  when 7
    log.puts "Neutral :-|"
    result = 'neutral'
    rc = 8
  when 8
    log.puts "Failed :-("
    result = 'fail'
    rc = 4
  when 9
    log.puts "Some error occurred"
    result = 'tmpfail'
    rc = 16
  end
  log.msg("test fake-test: -----------------------]")
  log.msg("test smoke-test:  - - - - - - - - - - results - - - - - - - - - -")
  log.puts("fake-test           #{result.upcase}")
end

if ENV["DEBCI_FAKE_KILLPARENT"]
  # find our parent which is the t
  p = Process.pid
  while p > 1
    File.open("/proc/#{p}/stat") do |f|
      stat = f.gets.split()
      if stat[1].include? ENV["DEBCI_FAKE_KILLPARENT"]
        # got it, kill that
        Process.kill('FPE', p)
        p = -1
      else
        p = Integer(stat[3])
      end
    end
  end
end

# this will produce values larger than 3600 (1h, the threshold for "slow
# running tests") ~6% of the time, with most values being small
duration = (50000/((1+rand(50))**2)).round - 20

log.puts "autopkgtest [%s]: finished\n" % (Time.now + duration).strftime('%Y-%m-%d %H:%M:%S')

File.open(File.join(outdir, 'duration.in'), 'w') do |f|
  f.puts(duration)
end
File.open(File.join(outdir, 'log'), 'w') do |f|
  f.puts log.string
end
File.open(File.join(outdir, 'exitcode'), 'w') do |f|
  f.puts rc
end
File.open(File.join(outdir, 'worker'), 'w') do |f|
  f.puts `hostname -s`.strip
end
puts log.string
exit rc
