beaker 1.12.2 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|