beaker 1.12.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/beaker.gemspec +1 -1
- data/lib/beaker/cli.rb +2 -1
- data/lib/beaker/dsl/helpers.rb +74 -18
- data/lib/beaker/dsl/install_utils.rb +172 -39
- data/lib/beaker/host.rb +6 -3
- data/lib/beaker/host/unix/pkg.rb +22 -1
- data/lib/beaker/host/windows.rb +1 -0
- data/lib/beaker/host/windows/pkg.rb +7 -2
- data/lib/beaker/host_prebuilt_steps.rb +22 -21
- data/lib/beaker/hypervisor/docker.rb +1 -1
- data/lib/beaker/hypervisor/vagrant.rb +13 -0
- data/lib/beaker/junit.xsl +268 -0
- data/lib/beaker/logger.rb +25 -5
- data/lib/beaker/options/command_line_parser.rb +8 -8
- data/lib/beaker/options/presets.rb +5 -1
- data/lib/beaker/platform.rb +1 -0
- data/lib/beaker/ssh_connection.rb +15 -11
- data/lib/beaker/tasks/rake_task.rb +114 -0
- data/lib/beaker/tasks/test.rb +18 -0
- data/lib/beaker/test_case.rb +6 -0
- data/lib/beaker/test_suite.rb +316 -191
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/helpers_spec.rb +98 -25
- data/spec/beaker/dsl/install_utils_spec.rb +26 -12
- data/spec/beaker/host/unix/pkg_spec.rb +109 -0
- data/spec/beaker/host_prebuilt_steps_spec.rb +2 -18
- data/spec/beaker/host_spec.rb +3 -2
- data/spec/beaker/hypervisor/docker_spec.rb +1 -1
- data/spec/beaker/options/command_line_parser_spec.rb +2 -2
- data/spec/beaker/puppet_command_spec.rb +2 -2
- data/spec/beaker/ssh_connection_spec.rb +9 -8
- data/spec/beaker/test_suite_spec.rb +108 -0
- metadata +9 -4
data/lib/beaker/host/unix/pkg.rb
CHANGED
@@ -7,7 +7,7 @@ module Unix::Pkg
|
|
7
7
|
@apt_needs_update = true
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def check_for_command(name)
|
11
11
|
result = exec(Beaker::Command.new("which #{name}"), :acceptable_exit_codes => (0...127))
|
12
12
|
case self['platform']
|
13
13
|
when /solaris-10/
|
@@ -17,6 +17,27 @@ module Unix::Pkg
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
def check_for_package(name)
|
21
|
+
case self['platform']
|
22
|
+
when /sles-/
|
23
|
+
result = exec(Beaker::Command.new("zypper se -i --match-exact #{name}"), :acceptable_exit_codes => (0...127))
|
24
|
+
when /el-4/
|
25
|
+
@logger.debug("Package query not supported on rhel4")
|
26
|
+
return false
|
27
|
+
when /fedora|centos|el-/
|
28
|
+
result = exec(Beaker::Command.new("rpm -q #{name}"), :acceptable_exit_codes => (0...127))
|
29
|
+
when /ubuntu|debian/
|
30
|
+
result = exec(Beaker::Command.new("dpkg -s #{name}"), :acceptable_exit_codes => (0...127))
|
31
|
+
when /solaris-11/
|
32
|
+
result = exec(Beaker::Command.new("pkg info #{name}"), :acceptable_exit_codes => (0...127))
|
33
|
+
when /solaris-10/
|
34
|
+
result = exec(Beaker::Command.new("pkginfo #{name}"), :acceptable_exit_codes => (0...127))
|
35
|
+
else
|
36
|
+
raise "Package #{name} cannot be queried on #{self}"
|
37
|
+
end
|
38
|
+
result.exit_code == 0
|
39
|
+
end
|
40
|
+
|
20
41
|
# If apt has not been updated since the last repo deployment it is
|
21
42
|
# updated. Otherwise this is a noop
|
22
43
|
def update_apt_if_needed
|
data/lib/beaker/host/windows.rb
CHANGED
@@ -43,6 +43,7 @@ module Windows
|
|
43
43
|
'hieralibdir' => '`cygpath -w /opt/puppet-git-repos/hiera/lib`',
|
44
44
|
'hierapuppetlibdir' => '`cygpath -w /opt/puppet-git-repos/hiera-puppet/lib`',
|
45
45
|
# PATH related variables need to be Unix, which cygwin converts
|
46
|
+
'puppetbindir' => '$( [ -d "/cygdrive/c/Program Files (x86)" ] && echo "/cygdrive/c/Program Files (x86)" || echo "/cygdrive/c/Program Files" )/Puppet Labs/Puppet/bin',
|
46
47
|
'hierabindir' => '/opt/puppet-git-repos/hiera/bin',
|
47
48
|
'pathseparator' => ';',
|
48
49
|
})
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module Windows::Pkg
|
2
2
|
include Beaker::CommandFactory
|
3
3
|
|
4
|
-
def
|
4
|
+
def check_for_command(name)
|
5
5
|
result = exec(Beaker::Command.new("which #{name}"), :acceptable_exit_codes => (0...127))
|
6
6
|
result.exit_code == 0
|
7
7
|
end
|
8
8
|
|
9
|
+
def check_for_package(name)
|
10
|
+
result = exec(Beaker::Command.new("cygcheck #{name}"), :acceptable_exit_codes => (0...127))
|
11
|
+
result.exit_code == 0
|
12
|
+
end
|
13
|
+
|
9
14
|
def install_package(name, cmdline_args = '')
|
10
15
|
cygwin = ""
|
11
16
|
rootdir = ""
|
@@ -20,7 +25,7 @@ module Windows::Pkg
|
|
20
25
|
cygwin = "setup-x86.exe"
|
21
26
|
end
|
22
27
|
|
23
|
-
if not
|
28
|
+
if not check_for_command(cygwin)
|
24
29
|
execute("curl --retry 5 http://cygwin.com/#{cygwin} -o /cygdrive/c/Windows/System32/#{cygwin}")
|
25
30
|
end
|
26
31
|
execute("#{cygwin} -q -n -N -d -R #{cmdline_args} #{rootdir} -s http://cygwin.osuosl.org -P #{name}")
|
@@ -8,9 +8,9 @@ module Beaker
|
|
8
8
|
NTPSERVER = 'pool.ntp.org'
|
9
9
|
SLEEPWAIT = 5
|
10
10
|
TRIES = 5
|
11
|
-
|
12
|
-
|
13
|
-
SLES_PACKAGES = ['ntp']
|
11
|
+
UNIX_PACKAGES = ['curl', 'ntpdate']
|
12
|
+
WINDOWS_PACKAGES = ['curl']
|
13
|
+
SLES_PACKAGES = ['curl', 'ntp']
|
14
14
|
ETC_HOSTS_PATH = "/etc/hosts"
|
15
15
|
ETC_HOSTS_PATH_SOLARIS = "/etc/inet/hosts"
|
16
16
|
ROOT_KEYS_SCRIPT = "https://raw.githubusercontent.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
|
@@ -67,9 +67,9 @@ module Beaker
|
|
67
67
|
end
|
68
68
|
|
69
69
|
#Validate that hosts are prepared to be used as SUTs, if packages are missing attempt to
|
70
|
-
#install them. Verifies the presence of {HostPrebuiltSteps::
|
71
|
-
#{HostPrebuiltSteps::
|
72
|
-
#
|
70
|
+
#install them. Verifies the presence of #{HostPrebuiltSteps::UNIX_PACKAGES} on unix platform hosts,
|
71
|
+
#{HostPrebuiltSteps::SLES_PACKAGES} on SUSE platform hosts and {HostPrebuiltSteps::WINDOWS_PACKAGES} on windows
|
72
|
+
#platforms.
|
73
73
|
# @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
|
74
74
|
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
75
75
|
# @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
|
@@ -78,24 +78,25 @@ module Beaker
|
|
78
78
|
if host.is_a? Array
|
79
79
|
host.map { |h| validate_host(h, opts) }
|
80
80
|
else
|
81
|
-
PACKAGES.each do |pkg|
|
82
|
-
if not host.check_for_package pkg
|
83
|
-
host.install_package pkg
|
84
|
-
end
|
85
|
-
end
|
86
81
|
case
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
82
|
+
when host['platform'] =~ /sles-/
|
83
|
+
SLES_PACKAGES.each do |pkg|
|
84
|
+
if not host.check_for_package pkg
|
85
|
+
host.install_package pkg
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when host['platform'] =~ /windows/
|
89
|
+
WINDOWS_PACKAGES.each do |pkg|
|
90
|
+
if not host.check_for_package pkg
|
91
|
+
host.install_package pkg
|
92
92
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
93
|
+
end
|
94
|
+
when host['platform'] !~ /aix|solaris|windows|sles-/
|
95
|
+
UNIX_PACKAGES.each do |pkg|
|
96
|
+
if not host.check_for_package pkg
|
97
|
+
host.install_package pkg
|
98
98
|
end
|
99
|
+
end
|
99
100
|
end
|
100
101
|
end
|
101
102
|
rescue => e
|
@@ -32,7 +32,7 @@ module Beaker
|
|
32
32
|
})
|
33
33
|
|
34
34
|
@logger.debug("Starting container #{container.id}")
|
35
|
-
container.start({"PublishAllPorts" => true})
|
35
|
+
container.start({"PublishAllPorts" => true, "Privileged" => true})
|
36
36
|
|
37
37
|
# Find out where the ssh port is from the container
|
38
38
|
ip = container.json["NetworkSettings"]["Ports"]["22/tcp"][0]["HostIp"]
|
@@ -30,11 +30,24 @@ module Beaker
|
|
30
30
|
v_file << " v.vm.box_url = '#{host['box_url']}'\n" unless host['box_url'].nil?
|
31
31
|
v_file << " v.vm.base_mac = '#{randmac}'\n"
|
32
32
|
v_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\", :netmask => \"#{host['netmask'] ||= "255.255.0.0"}\"\n"
|
33
|
+
|
34
|
+
if host['disk_path']
|
35
|
+
v_file << " v.vm.provider :virtualbox do |vb|\n"
|
36
|
+
v_file << " vb.name = '#{host.name}'\n"
|
37
|
+
unless File.exist?(host['disk_path'])
|
38
|
+
host['disk_path'] = File.join(host['disk_path'], "#{host.name}.vmdk")
|
39
|
+
v_file << " vb.customize ['createhd', '--filename', '#{host['disk_path']}', '--size', #{host['disk_size'] ||= 5 * 1024}, '--format', 'vmdk']\n"
|
40
|
+
end
|
41
|
+
v_file << " vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium','#{host['disk_path']}']\n"
|
42
|
+
v_file << " end\n"
|
43
|
+
end
|
44
|
+
|
33
45
|
if /windows/i.match(host['platform'])
|
34
46
|
v_file << " v.vm.network :forwarded_port, guest: 3389, host: 3389\n"
|
35
47
|
v_file << " v.vm.network :forwarded_port, guest: 5985, host: 5985, id: 'winrm', auto_correct: true\n"
|
36
48
|
v_file << " v.vm.guest = :windows"
|
37
49
|
end
|
50
|
+
|
38
51
|
v_file << " end\n"
|
39
52
|
@logger.debug "created Vagrantfile for VagrantHost #{host.name}"
|
40
53
|
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
2
|
+
<xsl:output method="html" indent="yes"/>
|
3
|
+
<xsl:decimal-format decimal-separator="." grouping-separator="," />
|
4
|
+
|
5
|
+
<xsl:template match="testsuites">
|
6
|
+
<html>
|
7
|
+
<head>
|
8
|
+
<meta charset="utf-8"/>
|
9
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
11
|
+
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
|
12
|
+
</head>
|
13
|
+
|
14
|
+
<body>
|
15
|
+
<!-- jQuery 2.1.1 -->
|
16
|
+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
17
|
+
<!-- Latest compiled and minified JavaScript -->
|
18
|
+
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
|
19
|
+
|
20
|
+
|
21
|
+
<xsl:variable name="time_format"><xsl:value-of select="'#0.00000'"/></xsl:variable>
|
22
|
+
|
23
|
+
<div class="container-fluid">
|
24
|
+
<div class="page-header">
|
25
|
+
<h1>Beaker <small>Puppet Labs Automated Acceptance Testing System</small></h1>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<!-- calculate overall stats for this run -->
|
29
|
+
<xsl:variable name="total_tests"><xsl:value-of select="sum(testsuite/@tests)"/></xsl:variable>
|
30
|
+
<xsl:variable name="total_errors"><xsl:value-of select="sum(testsuite/@errors)"/></xsl:variable>
|
31
|
+
<xsl:variable name="total_failures"><xsl:value-of select="sum(testsuite/@failures)"/></xsl:variable>
|
32
|
+
<xsl:variable name="total_time"><xsl:value-of select="sum(testsuite/@time)"/></xsl:variable>
|
33
|
+
<xsl:variable name="total_skip"><xsl:value-of select="sum(testsuite/@skip)"/></xsl:variable>
|
34
|
+
<xsl:variable name="total_pending"><xsl:value-of select="sum(testsuite/@pending)"/></xsl:variable>
|
35
|
+
|
36
|
+
<!-- determine if we overall passed or failed -->
|
37
|
+
<xsl:variable name="total_panel_type">
|
38
|
+
<xsl:choose>
|
39
|
+
<xsl:when test="$total_errors > 0 or $total_failures > 0">danger</xsl:when>
|
40
|
+
<xsl:otherwise>success</xsl:otherwise>
|
41
|
+
</xsl:choose>
|
42
|
+
</xsl:variable>
|
43
|
+
<!-- create the overall panel with stats, colored correctly based upon results -->
|
44
|
+
<div class="panel panel-{$total_panel_type}">
|
45
|
+
<div class="panel-heading">
|
46
|
+
<div class="panel-title">
|
47
|
+
<div class="row">
|
48
|
+
<div class="col-md-4">
|
49
|
+
<h2>Elapsed Time: <xsl:value-of select="format-number($total_time, $time_format)"/> sec </h2>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
<div class="row">
|
53
|
+
<div class="col-md-4">
|
54
|
+
</div>
|
55
|
+
<div class="col-md-2">
|
56
|
+
<h2>Total: <xsl:value-of select="$total_tests" /> </h2>
|
57
|
+
</div>
|
58
|
+
<div class="col-md-2">
|
59
|
+
<h2>Failed: <xsl:value-of select="$total_errors + $total_failures" /></h2>
|
60
|
+
</div>
|
61
|
+
<div class="col-md-2">
|
62
|
+
<h2>Skipped: <xsl:value-of select="$total_skip" /> </h2>
|
63
|
+
</div>
|
64
|
+
<div class="col-md-2">
|
65
|
+
<h2>Pending: <xsl:value-of select="$total_pending" /> </h2>
|
66
|
+
</div>
|
67
|
+
</div> <!-- row -->
|
68
|
+
</div> <!-- panel-title -->
|
69
|
+
</div> <!--panel-heading -->
|
70
|
+
|
71
|
+
<div class="panel-body">
|
72
|
+
<div class="panel-group" id="accordion_one">
|
73
|
+
<xsl:for-each select="testsuite">
|
74
|
+
<!-- let's loop over the availables test suites -->
|
75
|
+
<xsl:variable name="testsuite_name"><xsl:value-of select="@name"/></xsl:variable>
|
76
|
+
|
77
|
+
<xsl:variable name="testsuite_name_safe" select="translate($testsuite_name,'.','_')" />
|
78
|
+
<xsl:variable name="testsuite_tests"><xsl:value-of select="@tests"/></xsl:variable>
|
79
|
+
<xsl:variable name="testsuite_errors"><xsl:value-of select="@errors"/></xsl:variable>
|
80
|
+
<xsl:variable name="testsuite_failures"><xsl:value-of select="@failures"/></xsl:variable>
|
81
|
+
<xsl:variable name="testsuite_time"><xsl:value-of select="@time"/></xsl:variable>
|
82
|
+
<xsl:variable name="testsuite_skip"><xsl:value-of select="@skip"/></xsl:variable>
|
83
|
+
<xsl:variable name="testsuite_pending"><xsl:value-of select="@pending"/></xsl:variable>
|
84
|
+
<xsl:variable name="testsuite_panel_type">
|
85
|
+
<xsl:choose>
|
86
|
+
<xsl:when test="$testsuite_errors > 0 or $testsuite_failures > 0">danger</xsl:when>
|
87
|
+
<xsl:otherwise>success</xsl:otherwise>
|
88
|
+
</xsl:choose>
|
89
|
+
</xsl:variable>
|
90
|
+
<div class="panel panel-{$testsuite_panel_type}">
|
91
|
+
<div class="panel-heading">
|
92
|
+
<div class="panel-title">
|
93
|
+
<a data-toggle="collapse" data-parent="#accordion_one" href="#{$testsuite_name_safe}">
|
94
|
+
<div class="row">
|
95
|
+
<div class="col-md-2">
|
96
|
+
<h4><xsl:value-of select="$testsuite_name" /></h4>
|
97
|
+
</div>
|
98
|
+
<div class="col-md-4">
|
99
|
+
<h4>Elapsed Time: <xsl:value-of select="format-number($testsuite_time, $time_format)"/> sec</h4>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
<div class="row">
|
103
|
+
<div class="col-md-2">
|
104
|
+
</div>
|
105
|
+
<div class="col-md-2">
|
106
|
+
<h4>Total: <xsl:value-of select="$testsuite_tests" /></h4>
|
107
|
+
</div>
|
108
|
+
<div class="col-md-2">
|
109
|
+
<h4>Failed: <xsl:value-of select="$testsuite_errors + $testsuite_failures" /></h4>
|
110
|
+
</div>
|
111
|
+
<div class="col-md-2">
|
112
|
+
<h4>Skipped: <xsl:value-of select="$testsuite_skip" /></h4>
|
113
|
+
</div>
|
114
|
+
<div class="col-md-2">
|
115
|
+
<h4>Pending: <xsl:value-of select="$testsuite_pending" /></h4>
|
116
|
+
</div>
|
117
|
+
</div> <!-- row -->
|
118
|
+
</a>
|
119
|
+
</div> <!-- panel-title -->
|
120
|
+
</div> <!-- panel-heading -->
|
121
|
+
<div id="{$testsuite_name_safe}" class="panel-collapse collapse">
|
122
|
+
<div class="panel-body">
|
123
|
+
<div class="panel-group" id="accordion_two">
|
124
|
+
<div class="panel panel-primary">
|
125
|
+
<div class="panel-heading">
|
126
|
+
<h5 class="panel-title">
|
127
|
+
<a data-toggle="collapse" data-parent="#accordion_two" href="#{$testsuite_name_safe}-properties">
|
128
|
+
<div class="row">
|
129
|
+
<div class="col-md-4">
|
130
|
+
Properties
|
131
|
+
</div>
|
132
|
+
<div class="col-md-4">
|
133
|
+
</div>
|
134
|
+
</div> <!-- row -->
|
135
|
+
</a>
|
136
|
+
</h5> <!-- panel-title -->
|
137
|
+
</div> <!-- panel-heading -->
|
138
|
+
<div id="{$testsuite_name_safe}-properties" class="panel-collapse collapse in">
|
139
|
+
<div class="panel-body" style="height:425px">
|
140
|
+
<div class="panel panel-info" style="overflow-y: auto">
|
141
|
+
<div style="overflow-y:scroll; max-height:400px">
|
142
|
+
<!-- Default panel contents -->
|
143
|
+
<!-- Table -->
|
144
|
+
<table class="table">
|
145
|
+
<xsl:for-each select="properties/property">
|
146
|
+
<xsl:variable name="property_name"><xsl:value-of select="@name"/></xsl:variable>
|
147
|
+
<xsl:variable name="property_value"><xsl:value-of select="@value"/></xsl:variable>
|
148
|
+
<tr>
|
149
|
+
<td>
|
150
|
+
<xsl:value-of select="$property_name" />
|
151
|
+
</td>
|
152
|
+
<td>
|
153
|
+
<xsl:value-of select="$property_value" />
|
154
|
+
</td>
|
155
|
+
</tr>
|
156
|
+
</xsl:for-each>
|
157
|
+
</table>
|
158
|
+
</div> <!-- overflow div -->
|
159
|
+
</div> <!-- panel panel-info -->
|
160
|
+
</div> <!-- panel-body -->
|
161
|
+
</div> <!-- panel-collapse collapse -->
|
162
|
+
</div> <!-- panel panel-info -->
|
163
|
+
<!-- Start: Here are the test cases for a given test suite -->
|
164
|
+
<xsl:for-each select="testcase">
|
165
|
+
<xsl:variable name="testcase_name"><xsl:value-of select="@name"/></xsl:variable>
|
166
|
+
<xsl:variable name="testcase_classname"><xsl:value-of select="@classname"/></xsl:variable>
|
167
|
+
<xsl:variable name="testcase_fullpath"><xsl:value-of select="concat($testcase_classname, '/', $testcase_name)"/></xsl:variable>
|
168
|
+
<xsl:variable name="testcase_time"><xsl:value-of select="@time"/></xsl:variable>
|
169
|
+
<xsl:variable name="testcase_link" select="translate(translate($testcase_fullpath, '/', '_'), '.', '_')" />
|
170
|
+
<xsl:variable name="testcase_panel_type">
|
171
|
+
<xsl:choose>
|
172
|
+
<xsl:when test="failure or error">danger</xsl:when>
|
173
|
+
<xsl:when test="skip">warning</xsl:when>
|
174
|
+
<xsl:when test="pending">info</xsl:when>
|
175
|
+
<xsl:otherwise>success</xsl:otherwise>
|
176
|
+
</xsl:choose>
|
177
|
+
</xsl:variable>
|
178
|
+
<div class="panel panel-{$testcase_panel_type}">
|
179
|
+
<div class="panel-heading">
|
180
|
+
<div class="panel-title">
|
181
|
+
<a data-toggle="collapse" data-parent="#accordion_two" href="#{$testcase_link}">
|
182
|
+
<div class="row">
|
183
|
+
<div class="col-md-7">
|
184
|
+
<h5><xsl:value-of select="$testcase_name" /></h5>
|
185
|
+
</div>
|
186
|
+
</div>
|
187
|
+
<div class="row">
|
188
|
+
<div class="col-md-1">
|
189
|
+
</div>
|
190
|
+
<div class="col-md-7">
|
191
|
+
<h5>Path: <xsl:value-of select="$testcase_fullpath" /></h5>
|
192
|
+
</div>
|
193
|
+
<div class="col-md-4">
|
194
|
+
<h5>Elapsed Time: <xsl:value-of select="format-number($testcase_time, $time_format)"/> sec</h5>
|
195
|
+
</div>
|
196
|
+
</div> <!-- row -->
|
197
|
+
</a>
|
198
|
+
</div> <!-- panel-title -->
|
199
|
+
</div> <!-- panel-heading -->
|
200
|
+
<div id="{$testcase_link}" class="panel-collapse collapse in">
|
201
|
+
<div class="panel-body" style="height:425px">
|
202
|
+
<ul class="nav nav-tabs">
|
203
|
+
<li class="active"><a href="#tab1" data-toggle="tab">output</a></li>
|
204
|
+
<xsl:choose>
|
205
|
+
<xsl:when test="system-err and string(system-err)">
|
206
|
+
<li><a href="#tab2" data-toggle="tab">stderr</a></li>
|
207
|
+
</xsl:when>
|
208
|
+
<xsl:otherwise>
|
209
|
+
<li class="disabled"><a href="#tab2">stderr</a></li>
|
210
|
+
</xsl:otherwise>
|
211
|
+
</xsl:choose>
|
212
|
+
<xsl:choose>
|
213
|
+
<xsl:when test="failure">
|
214
|
+
<li><a href="#tab3" data-toggle="tab">failure</a></li>
|
215
|
+
</xsl:when>
|
216
|
+
<xsl:otherwise>
|
217
|
+
<li class="disabled"><a href="#tab3">failure</a></li>
|
218
|
+
</xsl:otherwise>
|
219
|
+
</xsl:choose>
|
220
|
+
</ul>
|
221
|
+
<div class="tab-content">
|
222
|
+
<div class="tab-pane active" id="tab1">
|
223
|
+
<pre class="pre-scrollable">
|
224
|
+
<xsl:value-of select="system-out" />
|
225
|
+
</pre>
|
226
|
+
</div>
|
227
|
+
<div class="tab-pane" id="tab2">
|
228
|
+
<pre class="pre-scrollable">
|
229
|
+
<xsl:value-of select="system-err" />
|
230
|
+
</pre>
|
231
|
+
</div>
|
232
|
+
<div class="tab-pane" id="tab3">
|
233
|
+
<div class="panel panel-default">
|
234
|
+
<div class="panel-heading"><xsl:value-of select="failure/@type" /></div>
|
235
|
+
<div class="panel-body">
|
236
|
+
<pre class="pre-scrollable">
|
237
|
+
<xsl:value-of select="failure/@message" />
|
238
|
+
</pre>
|
239
|
+
</div>
|
240
|
+
</div>
|
241
|
+
</div>
|
242
|
+
</div> <!-- tab-content -->
|
243
|
+
</div> <!-- panel-body -->
|
244
|
+
</div> <!-- panel-collapse collapse -->
|
245
|
+
</div> <!-- panel panel-default -->
|
246
|
+
</xsl:for-each>
|
247
|
+
</div> <!-- panel-group -->
|
248
|
+
<!-- Stop: Here are the test cases for a given test suite -->
|
249
|
+
</div> <!-- panel-body -->
|
250
|
+
</div> <!-- panel-collapse collapse -->
|
251
|
+
</div> <!-- panel panel-default -->
|
252
|
+
</xsl:for-each>
|
253
|
+
</div> <!-- panel-group -->
|
254
|
+
|
255
|
+
</div> <!-- panel-body -->
|
256
|
+
</div> <!-- panel panel -->
|
257
|
+
</div> <!-- container -->
|
258
|
+
|
259
|
+
<script type="text/javascript">
|
260
|
+
$('.collapse').collapse()
|
261
|
+
</script>
|
262
|
+
</body>
|
263
|
+
|
264
|
+
</html>
|
265
|
+
|
266
|
+
|
267
|
+
</xsl:template>
|
268
|
+
</xsl:stylesheet>
|
data/lib/beaker/logger.rb
CHANGED
@@ -50,6 +50,7 @@ module Beaker
|
|
50
50
|
def initialize(*args)
|
51
51
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
52
52
|
@color = options[:color]
|
53
|
+
@sublog = nil
|
53
54
|
case options[:log_level]
|
54
55
|
when /debug/i, :debug
|
55
56
|
@log_level = :debug
|
@@ -78,6 +79,8 @@ module Beaker
|
|
78
79
|
case dest
|
79
80
|
when IO
|
80
81
|
@destinations << dest
|
82
|
+
when StringIO
|
83
|
+
@destinations << dest
|
81
84
|
when String
|
82
85
|
@destinations << File.open(dest, 'w')
|
83
86
|
else
|
@@ -91,6 +94,8 @@ module Beaker
|
|
91
94
|
case dest
|
92
95
|
when IO
|
93
96
|
@destinations.delete(dest)
|
97
|
+
when StringIO
|
98
|
+
@destinations.delete(dest)
|
94
99
|
when String
|
95
100
|
@destinations.delete_if {|d| d.respond_to?(:path) and d.path == dest}
|
96
101
|
else
|
@@ -144,7 +149,7 @@ module Beaker
|
|
144
149
|
# @param args[Array<String>] Strings to be reported
|
145
150
|
def debug *args
|
146
151
|
return unless is_verbose?
|
147
|
-
optionally_color WHITE, args
|
152
|
+
optionally_color WHITE, *args
|
148
153
|
end
|
149
154
|
|
150
155
|
# Report a warning message.
|
@@ -162,14 +167,14 @@ module Beaker
|
|
162
167
|
# @param args[Array<String>] Strings to be reported
|
163
168
|
def info *args
|
164
169
|
return unless is_info?
|
165
|
-
optionally_color BLUE, args
|
170
|
+
optionally_color BLUE, *args
|
166
171
|
end
|
167
172
|
|
168
173
|
# Report a success message.
|
169
174
|
# Will always be reported.
|
170
175
|
# @param args[Array<String>] Strings to be reported
|
171
176
|
def success *args
|
172
|
-
optionally_color GREEN, args
|
177
|
+
optionally_color GREEN, *args
|
173
178
|
end
|
174
179
|
|
175
180
|
# Report a notify message.
|
@@ -177,14 +182,14 @@ module Beaker
|
|
177
182
|
# @param args[Array<String>] Strings to be reported
|
178
183
|
def notify *args
|
179
184
|
return unless is_notify?
|
180
|
-
optionally_color BRIGHT_WHITE, args
|
185
|
+
optionally_color BRIGHT_WHITE, *args
|
181
186
|
end
|
182
187
|
|
183
188
|
# Report an error message.
|
184
189
|
# Will always be reported.
|
185
190
|
# @param args[Array<String>] Strings to be reported
|
186
191
|
def error *args
|
187
|
-
optionally_color BRIGHT_RED, args
|
192
|
+
optionally_color BRIGHT_RED, *args
|
188
193
|
end
|
189
194
|
|
190
195
|
# Strip any color codes from provided string(s)
|
@@ -220,6 +225,21 @@ module Beaker
|
|
220
225
|
expand_symlinks( trace ).join "\n"
|
221
226
|
end
|
222
227
|
|
228
|
+
# Create a new StringIO log to track the current output
|
229
|
+
def start_sublog
|
230
|
+
if @sublog
|
231
|
+
remove_destination(@sublog)
|
232
|
+
end
|
233
|
+
@sublog = StringIO.new
|
234
|
+
add_destination(@sublog)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Return the contents of the sublog
|
238
|
+
def get_sublog
|
239
|
+
@sublog.rewind
|
240
|
+
@sublog.read
|
241
|
+
end
|
242
|
+
|
223
243
|
private
|
224
244
|
# Expand each symlink found to its full path
|
225
245
|
# Lines are assumed to be in the format "String : Integer"
|