require 'cgi'
require 'json'
require 'time'
require 'debci/test/duration'
require 'debci/test/expired'
module Debci
class Status
include Debci::Test::Duration
include Debci::Test::Expired
attr_accessor :suite, :architecture, :run_id, :package, :version, :date, :trigger, :status, :previous_status, :duration_seconds, :message, :last_pass_version, :last_pass_date, :requestor
def newsworthy?
[
[:fail, :pass],
[:pass, :fail],
[:fail, :neutral],
[:pass, :neutral],
[:neutral, :pass],
[:neutral, :fail],
].include?([status, previous_status])
end
def title
{
:pass => "Pass",
:fail => "Fail",
:neutral => "No tests or all skipped",
:tmpfail => "Temporary failure",
:no_test_data => "No test data",
}.fetch(status, "Unknown")
end
def extended_status
case status
when :pass
:pass
when :fail
case last_pass_version
when "never"
:fail_passed_never
when version
:fail_passed_current
when "unknown"
:fail
else
:fail_passed_old
end
when :tmpfail
case previous_status
when :pass
:tmpfail_pass
when :fail
:tmpfail_fail
else
:tmpfail
end
else
status
end
end
def failmsg
{
:fail_passed_never => "never passed",
:fail_passed_current => "previously passed",
:fail_passed_old => "#{last_pass_version} passed"
}[extended_status]
end
def headline
msg = "#{package} #{version} #{status.upcase} on #{suite}/#{architecture}"
if status == :fail && failmsg
msg += " (#{failmsg})"
end
msg
end
def description
msg = "The tests for #{package} (version #{version}) resulted in #{status.upcase} on #{suite}/#{architecture}. Previously it was #{previous_status.upcase}"
msg += case extended_status
when :fail_passed_current
" for the current version."
when :fail_passed_old
" for version #{last_pass_version}."
else
"."
end
end
def time
days = (Time.now - date)/86400
if days >= 1 || days <= -1
"#{days.floor} day(s) ago"
else
"#{Time.at(Time.now - date).gmtime.strftime('%H')} hour(s) ago"
end
end
def self.from_file(file, suite, architecture)
status = new
status.suite = suite
status.architecture = architecture
unless File.exists?(file)
status.status = :no_test_data
return status
end
data = nil
begin
File.open(file, 'r') do |f|
data = JSON.load(f)
end
rescue JSON::ParserError
true end
return status unless data
from_data(data, suite, architecture)
end
def self.from_data(data, suite, architecture)
status = Debci::Status.new
status.suite = suite
status.architecture = architecture
status.run_id = data['run_id'] || data['date']
status.package = data['package']
status.version = data['version']
status.requestor = data['requestor']
status.date =
begin
d = data['date']
d ||= data['created_at']
d ||= 'unknown'
Time.parse(d + ' UTC')
rescue ArgumentError
nil
end
status.trigger = data['trigger']
status.status = (data['status'] || :unknown).to_sym
status.previous_status = (data['previous_status'] || :unknown).to_sym
status.duration_seconds =
begin
Integer(data['duration_seconds'] || 0)
rescue ArgumentError
nil
end
status.message = data['message']
status.last_pass_version = data.fetch('last_pass_version', 'unknown')
status.last_pass_date =
begin
Time.parse((data['last_pass_date'] || 'unknown') + ' UTC')
rescue ArgumentError
nil
end
status
end
def newer?(days)
return true if days <= 0
(Time.now - date) < days * (24 * 60 * 60)
end
def inspect
"<#{suite}/#{architecture} #{status}>"
end
def blacklisted?
Debci.blacklist.include?(
package, suite: suite, arch: architecture, version: version
)
end
end
end