meson-junit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +113 -0
- data/Rakefile +16 -0
- data/bin/meson-junit +7 -0
- data/lib/meson-junit.rb +13 -0
- data/lib/meson-junit/cli.rb +20 -0
- data/lib/meson-junit/junit.rb +6 -0
- data/lib/meson-junit/junit/xml-builder.rb +173 -0
- data/lib/meson-junit/meson.rb +7 -0
- data/lib/meson-junit/meson/test-log.rb +18 -0
- data/lib/meson-junit/meson/test.rb +48 -0
- data/test/data/testlog.json +5 -0
- data/test/test_junit.rb +24 -0
- data/test/test_meson.rb +59 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 14fb11afe0ddfca3654a9d4e9603072b30a4b39448156140691ed49247e2cd4b
|
4
|
+
data.tar.gz: 4fa62e089335d45d9127cf0efc3169a0078363bc9fe3e01d2eb52dec05ad384a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6c8b2efa2b3f70624ed8e20fb77185bae8acecd2c1fb6d337425c34bbc24468f939e1a792298010c5fc61cb4d6d78ca394f2d54cbfa79789e1f9c7045d2a13ce
|
7
|
+
data.tar.gz: 82caabd3b3a07102cf54decdf54a3553d01acaecdefbcdc196ad8861f1c4e17adbdfc99a194e719edf85ea2937dccf5461319b3ca5e5bca69c50fbb8ad5eebac
|
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
meson-junit
|
2
|
+
===========
|
3
|
+
|
4
|
+
Overview
|
5
|
+
--------
|
6
|
+
Command-line tool to convert [Meson][] test results to a
|
7
|
+
[Jenkins][]-compatible [JUnit][] [XML][].
|
8
|
+
|
9
|
+
Usage:
|
10
|
+
|
11
|
+
#
|
12
|
+
# This command does the following:
|
13
|
+
#
|
14
|
+
# - Read Meson test results in JSON format from the file
|
15
|
+
# "meson-logs/testlog.json".
|
16
|
+
#
|
17
|
+
# - Convert the input from JSON to Jenkins-friendly, JUnit XML.
|
18
|
+
#
|
19
|
+
# - Write the generated XML to "junit.xml".
|
20
|
+
#
|
21
|
+
meson-junit < meson-logs/testlog.json > junit.xml
|
22
|
+
|
23
|
+
If you are running your [Meson][] tests via [Jenkins Pipeline][], you
|
24
|
+
would include `meson-junit` in your `steps` like this:
|
25
|
+
|
26
|
+
steps {
|
27
|
+
// run tests, generate output in build-dir/meson-logs/testlog.json
|
28
|
+
sh 'cd build && meson test || true'
|
29
|
+
|
30
|
+
// generate build/testlog.xml
|
31
|
+
sh 'cd build && meson-junit < meson-logs/testlog.json > testlog.xml'
|
32
|
+
|
33
|
+
// read junit results
|
34
|
+
junit 'build/testlog.xml'
|
35
|
+
}
|
36
|
+
|
37
|
+
Notes:
|
38
|
+
|
39
|
+
* [Meson][] test results are converted to [JUnit][] `<testsuite>`
|
40
|
+
elements, rather than `<testcase>` elements. This is so we can expose
|
41
|
+
the attributes of the [Meson][] test results (the test command,
|
42
|
+
return code, environment variables, etc) as `<property>` elements.
|
43
|
+
* The reference used to generate the [JUnit][] [XML][] is available here:
|
44
|
+
[JUnit XML reporting file format][junit-ref].
|
45
|
+
|
46
|
+
Installation
|
47
|
+
------------
|
48
|
+
Install `meson-junit` via [RubyGems][], like so:
|
49
|
+
|
50
|
+
# install meson-junit using rubygems
|
51
|
+
gem install meson-junit
|
52
|
+
|
53
|
+
Documentation
|
54
|
+
-------------
|
55
|
+
You can generate the API documentation in the `docs/` directory via
|
56
|
+
[RDoc][], like so:
|
57
|
+
|
58
|
+
# generate API documentation in docs/ directory
|
59
|
+
rake docs
|
60
|
+
|
61
|
+
Tests
|
62
|
+
-----
|
63
|
+
You can run the [minitest][] test suite via [Rake][], like so:
|
64
|
+
|
65
|
+
# run the test suite
|
66
|
+
rake test
|
67
|
+
|
68
|
+
To generate a [JUnit][]-compatible XML report, install the
|
69
|
+
[minitest-junit][] gem and then do the following:
|
70
|
+
|
71
|
+
# run the test suite and generate a junit-compatible report.xml
|
72
|
+
rake test TESTOPTS=--junit
|
73
|
+
|
74
|
+
Author
|
75
|
+
------
|
76
|
+
Paul Duncan ([pabs@pablotron.org][me])<br/>
|
77
|
+
<https://pablotron.org/>
|
78
|
+
|
79
|
+
License
|
80
|
+
-------
|
81
|
+
Copyright 2019 Paul Duncan ([pabs@pablotron.org][me])
|
82
|
+
|
83
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
84
|
+
copy of this software and associated documentation files (the
|
85
|
+
"Software"), to deal in the Software without restriction, including
|
86
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
87
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
88
|
+
permit persons to whom the Software is furnished to do so, subject to
|
89
|
+
the following conditions:
|
90
|
+
|
91
|
+
The above copyright notice and this permission notice shall be included
|
92
|
+
in all copies or substantial portions of the Software.
|
93
|
+
|
94
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
95
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
96
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
97
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
98
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
99
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
100
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
101
|
+
|
102
|
+
[junit-ref]: https://llg.cubic.org/docs/junit/
|
103
|
+
[xml]: https://en.wikipedia.org/wiki/XML
|
104
|
+
[meson]: https://mesonbuild.com/
|
105
|
+
[jenkins]: https://jenkins-ci.org/
|
106
|
+
[jenkins pipeline]: https://jenkins.io/doc/book/pipeline/
|
107
|
+
[RubyGems]: https://rubygems.org/
|
108
|
+
[JUnit]: https://junit.org/
|
109
|
+
[me]: mailto:pabs@pablotron.org
|
110
|
+
[minitest]: https://github.com/seattlerb/minitest
|
111
|
+
[minitest-junit]: https://github.com/aespinosa/minitest-junit
|
112
|
+
[RDoc]: https://github.com/ruby/rdoc
|
113
|
+
[Rake]: https://github.com/ruby/rake
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rdoc/task'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.libs << 'test'
|
6
|
+
end
|
7
|
+
|
8
|
+
RDoc::Task.new :docs do |t|
|
9
|
+
t.main = "lib/meson-junit"
|
10
|
+
t.rdoc_files.include('lib/**/*.rb')
|
11
|
+
t.rdoc_dir = 'docs'
|
12
|
+
# t.options << "--all"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run tests"
|
16
|
+
task :default => :test
|
data/bin/meson-junit
ADDED
data/lib/meson-junit.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Meson to JUnit test case generator.
|
6
|
+
#
|
7
|
+
module MesonJunit
|
8
|
+
VERSION = '0.1.0'
|
9
|
+
|
10
|
+
autoload :Meson, File.join(__dir__, 'meson-junit', 'meson.rb')
|
11
|
+
autoload :Junit, File.join(__dir__, 'meson-junit', 'junit.rb')
|
12
|
+
autoload :CLI, File.join(__dir__, 'meson-junit', 'cli.rb')
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Command-line interface.
|
3
|
+
#
|
4
|
+
module MesonJunit::CLI
|
5
|
+
#
|
6
|
+
# Allow command-line invocation.
|
7
|
+
#
|
8
|
+
def self.run(app, args)
|
9
|
+
# TODO: parse command-line arguments
|
10
|
+
|
11
|
+
# parse meson test log json from standard input
|
12
|
+
log = MesonJunit::Meson::TestLog.new(STDIN)
|
13
|
+
|
14
|
+
# build junit xml from meson testlog
|
15
|
+
xml = MesonJunit::Junit::XMLBuilder.build(log)
|
16
|
+
|
17
|
+
# write xml to standard output
|
18
|
+
puts xml
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#
|
2
|
+
# Read parsed Meson test log and build JUnit-compatible XML.
|
3
|
+
#
|
4
|
+
class MesonJunit::Junit::XMLBuilder
|
5
|
+
def self.build(log)
|
6
|
+
new.build(log)
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
# Build JUnit-compatible XML from parsed Meson test log.
|
11
|
+
#
|
12
|
+
def build(log)
|
13
|
+
::Nokogiri::XML::Builder.new do |xml|
|
14
|
+
xml.testsuites(**testsuites_el_attrs(log)) do
|
15
|
+
emit_testsuite_els(xml, log)
|
16
|
+
end
|
17
|
+
end.to_xml
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
#
|
23
|
+
# Convert Meson test log to a series of JUnit test suites.
|
24
|
+
#
|
25
|
+
# We map Meson tests to a series of JUnit test suites with a single
|
26
|
+
# test case because that allows us to map the per-test attributes and
|
27
|
+
# environment variables to JUnit test suite properties.
|
28
|
+
#
|
29
|
+
def emit_testsuite_els(xml, log)
|
30
|
+
log.tests.each_with_index do |test, test_num|
|
31
|
+
xml.testsuite(**testsuite_el_attrs(test, test_num)) do
|
32
|
+
# emit testsuite properties
|
33
|
+
emit_properties(xml, test)
|
34
|
+
|
35
|
+
# emit testcase
|
36
|
+
emit_testcase(xml, test)
|
37
|
+
|
38
|
+
# emit standard output and standard error
|
39
|
+
xml.send('system-out', test.data['stdout'])
|
40
|
+
xml.send('system-err', test.data['stderr'])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Emit Meson test attributes as JUnit `testsuite` properties.
|
47
|
+
#
|
48
|
+
def emit_properties(xml, test)
|
49
|
+
xml.properties do
|
50
|
+
# convert all non-environment variable meson test attributes to
|
51
|
+
# junit test suite properties
|
52
|
+
test.data.each do |key, val|
|
53
|
+
unless key == 'env'
|
54
|
+
emit_property(xml, key, val)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# convert meson test environment variables to junit test suite
|
59
|
+
# properties
|
60
|
+
(test.data['env'] || {}).each do |key, val|
|
61
|
+
emit_property(xml, 'env.%s' % [key], val)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Emit details of Meson test as a JUnit `testcase` element.
|
68
|
+
def emit_testcase(xml, test)
|
69
|
+
xml.testcase(**testcase_el_attrs(test)) do
|
70
|
+
if test.failed?
|
71
|
+
# emit a `failure` element with a body that contains the
|
72
|
+
# standard error output from the Meson test.
|
73
|
+
xml.failure(test.data['stderr'], message: 'Test failed.')
|
74
|
+
end
|
75
|
+
|
76
|
+
# emit standard io elements
|
77
|
+
emit_stdio(xml, test)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Emit standard output and standard error from a Meson test case as
|
83
|
+
# JUnit-compatible `system-out` and `system-err` elements.
|
84
|
+
#
|
85
|
+
def emit_stdio(xml, test)
|
86
|
+
# emit standard output and standard error
|
87
|
+
xml.send('system-out', test.data['stdout'])
|
88
|
+
xml.send('system-err', test.data['stderr'])
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Emit a Meson test attribute as a JUnit test suite property.
|
93
|
+
#
|
94
|
+
def emit_property(xml, key, val)
|
95
|
+
case val
|
96
|
+
when Array, Hash
|
97
|
+
# serialize arrays and hashes as JSON
|
98
|
+
xml.property(name: key, value: ::JSON.unparse(val))
|
99
|
+
else
|
100
|
+
xml.property(name: key, value: val)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Get hash of attributes for root JUnit `testsuites` element.
|
106
|
+
#
|
107
|
+
def testsuites_el_attrs(log)
|
108
|
+
{
|
109
|
+
# total number of tests
|
110
|
+
tests: log.tests.size,
|
111
|
+
|
112
|
+
# total number of failed tests
|
113
|
+
failures: log.tests.reduce(0) do |r, test|
|
114
|
+
r + (test.failed? ? 1 : 0)
|
115
|
+
end,
|
116
|
+
|
117
|
+
# total amount of time across all tests
|
118
|
+
time: log.tests.reduce(0) do |r, test|
|
119
|
+
r + test.duration
|
120
|
+
end,
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Get hash of attributes for JUnit `testsuite` element.
|
126
|
+
#
|
127
|
+
def testsuite_el_attrs(test, test_num)
|
128
|
+
{
|
129
|
+
# test number, starting from zero
|
130
|
+
id: test_num,
|
131
|
+
|
132
|
+
# junit-friendly class name
|
133
|
+
name: safe_name(test.name),
|
134
|
+
|
135
|
+
# total number of tests (always 1)
|
136
|
+
tests: 1,
|
137
|
+
|
138
|
+
# total number of errors (always either 0 or 1)
|
139
|
+
errors: test.failed? ? 1 : 0,
|
140
|
+
|
141
|
+
# total amount of time for this test
|
142
|
+
time: test.duration,
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# Get hash of attributes for JUnit `testcase` element.
|
148
|
+
#
|
149
|
+
def testcase_el_attrs(test)
|
150
|
+
{
|
151
|
+
# test case name
|
152
|
+
name: 'main',
|
153
|
+
|
154
|
+
# test case class name
|
155
|
+
classname: safe_name(test.name),
|
156
|
+
|
157
|
+
# time taken (in seconds) to execute test.
|
158
|
+
time: test.duration,
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Invalid characters in JUnit class name.
|
164
|
+
#
|
165
|
+
BAD_CHARS = /[^a-z0-9_]+/
|
166
|
+
|
167
|
+
#
|
168
|
+
# Sanitize a Meson test name as a JUnit-friendly class name.
|
169
|
+
#
|
170
|
+
def safe_name(s)
|
171
|
+
s.gsub(BAD_CHARS, '_')
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Single Meson test result.
|
3
|
+
#
|
4
|
+
class MesonJunit::Meson::TestLog
|
5
|
+
#
|
6
|
+
# Individual Meson test results.
|
7
|
+
#
|
8
|
+
attr :tests
|
9
|
+
|
10
|
+
#
|
11
|
+
# Parse a testlog.json file.
|
12
|
+
#
|
13
|
+
def initialize(io)
|
14
|
+
@tests = io.readlines.map do |line|
|
15
|
+
::MesonJunit::Meson::Test.new(::JSON.parse(line))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# Single Meson test result.
|
3
|
+
#
|
4
|
+
class MesonJunit::Meson::Test
|
5
|
+
#
|
6
|
+
# Parsed JSON data.
|
7
|
+
#
|
8
|
+
attr :data
|
9
|
+
|
10
|
+
#
|
11
|
+
# Test name.
|
12
|
+
#
|
13
|
+
attr :name
|
14
|
+
|
15
|
+
#
|
16
|
+
# Duration of test run, in seconds.
|
17
|
+
#
|
18
|
+
attr :duration
|
19
|
+
|
20
|
+
#
|
21
|
+
# Test result (either :OK or :FAIL).
|
22
|
+
#
|
23
|
+
attr :result
|
24
|
+
|
25
|
+
#
|
26
|
+
# Create a test case from parsed Meson JSON data.
|
27
|
+
#
|
28
|
+
def initialize(data)
|
29
|
+
@data = data.freeze
|
30
|
+
@name = @data['name']
|
31
|
+
@duration = @data['duration'] || 0
|
32
|
+
@result = @data['result'].intern
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Did this test succeed?
|
37
|
+
#
|
38
|
+
def ok?
|
39
|
+
@result == :OK
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Did this test fail?
|
44
|
+
#
|
45
|
+
def failed?
|
46
|
+
@result == :FAIL
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
{"name": "test-io-logger", "stdout": "", "result": "OK", "duration": 0.017489910125732422, "returncode": 0, "command": ["/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-io-logger"], "env": {"GIT_PREVIOUS_SUCCESSFUL_COMMIT": "980602362882ea45fe08b67e01eecf8114e663b9", "HOSTNAME": "d38bcdc0a0f0", "RUN_CHANGES_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect?page=changes", "GIT_COMMIT": "0a342a9d5f2058e9f2872078c45d791cd62a3b61", "NODE_LABELS": "master", "HUDSON_URL": "http://hive:9090/", "HOME": "/", "OLDPWD": "/var/lib/jenkins/workspace/raggle_master", "BUILD_URL": "http://hive:9090/job/raggle/job/master/32/", "GIT_LOCAL_BRANCH": "master", "JENKINS_SERVER_COOKIE": "durable-a623a7ae73afbc86e3205e2d30ff0631", "LDFLAGS": "-lasan", "WORKSPACE": "/var/lib/jenkins/workspace/raggle_master", "NODE_NAME": "master", "EXECUTOR_NUMBER": "1", "GIT_BRANCH": "master", "STAGE_NAME": "address", "BUILD_DISPLAY_NAME": "#32", "HUDSON_HOME": "/var/lib/jenkins", "JOB_BASE_NAME": "master", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "BUILD_ID": "32", "CFLAGS": "-g", "BUILD_TAG": "jenkins-raggle-master-32", "JENKINS_URL": "http://hive:9090/", "JOB_URL": "http://hive:9090/job/raggle/job/master/", "GIT_URL": "git://u3/raggle.git", "BUILD_NUMBER": "32", "JENKINS_NODE_COOKIE": "5384bb4a-0b67-4e96-8d36-afa4e39e8bff", "RUN_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect", "HUDSON_SERVER_COOKIE": "44bd36d136089097", "JOB_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/display/redirect", "CLASSPATH": "", "JOB_NAME": "raggle/master", "PWD": "/var/lib/jenkins/workspace/raggle_master/build/sanitize/address", "GIT_PREVIOUS_COMMIT": "d1721a6594f2688dbac2be0c1142edf49ff634da", "CC": "clang-7", "BRANCH_NAME": "master", "LC_CTYPE": "C.UTF-8"}}
|
2
|
+
{"name": "test-file-logger", "stdout": "", "result": "OK", "duration": 0.027406692504882812, "returncode": 0, "command": ["/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-file-logger"], "env": {"GIT_PREVIOUS_SUCCESSFUL_COMMIT": "980602362882ea45fe08b67e01eecf8114e663b9", "HOSTNAME": "d38bcdc0a0f0", "RUN_CHANGES_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect?page=changes", "GIT_COMMIT": "0a342a9d5f2058e9f2872078c45d791cd62a3b61", "NODE_LABELS": "master", "HUDSON_URL": "http://hive:9090/", "HOME": "/", "OLDPWD": "/var/lib/jenkins/workspace/raggle_master", "BUILD_URL": "http://hive:9090/job/raggle/job/master/32/", "GIT_LOCAL_BRANCH": "master", "JENKINS_SERVER_COOKIE": "durable-a623a7ae73afbc86e3205e2d30ff0631", "LDFLAGS": "-lasan", "WORKSPACE": "/var/lib/jenkins/workspace/raggle_master", "NODE_NAME": "master", "EXECUTOR_NUMBER": "1", "GIT_BRANCH": "master", "STAGE_NAME": "address", "BUILD_DISPLAY_NAME": "#32", "HUDSON_HOME": "/var/lib/jenkins", "JOB_BASE_NAME": "master", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "BUILD_ID": "32", "CFLAGS": "-g", "BUILD_TAG": "jenkins-raggle-master-32", "JENKINS_URL": "http://hive:9090/", "JOB_URL": "http://hive:9090/job/raggle/job/master/", "GIT_URL": "git://u3/raggle.git", "BUILD_NUMBER": "32", "JENKINS_NODE_COOKIE": "5384bb4a-0b67-4e96-8d36-afa4e39e8bff", "RUN_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect", "HUDSON_SERVER_COOKIE": "44bd36d136089097", "JOB_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/display/redirect", "CLASSPATH": "", "JOB_NAME": "raggle/master", "PWD": "/var/lib/jenkins/workspace/raggle_master/build/sanitize/address", "GIT_PREVIOUS_COMMIT": "d1721a6594f2688dbac2be0c1142edf49ff634da", "CC": "clang-7", "BRANCH_NAME": "master", "LC_CTYPE": "C.UTF-8"}}
|
3
|
+
{"name": "test-mem-store", "stdout": "", "result": "FAIL", "duration": 0.3238527774810791, "returncode": 1, "command": ["/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store"], "env": {"GIT_PREVIOUS_SUCCESSFUL_COMMIT": "980602362882ea45fe08b67e01eecf8114e663b9", "HOSTNAME": "d38bcdc0a0f0", "RUN_CHANGES_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect?page=changes", "GIT_COMMIT": "0a342a9d5f2058e9f2872078c45d791cd62a3b61", "NODE_LABELS": "master", "HUDSON_URL": "http://hive:9090/", "HOME": "/", "OLDPWD": "/var/lib/jenkins/workspace/raggle_master", "BUILD_URL": "http://hive:9090/job/raggle/job/master/32/", "GIT_LOCAL_BRANCH": "master", "JENKINS_SERVER_COOKIE": "durable-a623a7ae73afbc86e3205e2d30ff0631", "LDFLAGS": "-lasan", "WORKSPACE": "/var/lib/jenkins/workspace/raggle_master", "NODE_NAME": "master", "EXECUTOR_NUMBER": "1", "GIT_BRANCH": "master", "STAGE_NAME": "address", "BUILD_DISPLAY_NAME": "#32", "HUDSON_HOME": "/var/lib/jenkins", "JOB_BASE_NAME": "master", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "BUILD_ID": "32", "CFLAGS": "-g", "BUILD_TAG": "jenkins-raggle-master-32", "JENKINS_URL": "http://hive:9090/", "JOB_URL": "http://hive:9090/job/raggle/job/master/", "GIT_URL": "git://u3/raggle.git", "BUILD_NUMBER": "32", "JENKINS_NODE_COOKIE": "5384bb4a-0b67-4e96-8d36-afa4e39e8bff", "RUN_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect", "HUDSON_SERVER_COOKIE": "44bd36d136089097", "JOB_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/display/redirect", "CLASSPATH": "", "JOB_NAME": "raggle/master", "PWD": "/var/lib/jenkins/workspace/raggle_master/build/sanitize/address", "GIT_PREVIOUS_COMMIT": "d1721a6594f2688dbac2be0c1142edf49ff634da", "CC": "clang-7", "BRANCH_NAME": "master", "LC_CTYPE": "C.UTF-8"}, "stderr": "\n=================================================================\n==305==ERROR: LeakSanitizer: detected memory leaks\n\nDirect leak of 384 byte(s) in 1 object(s) allocated from:\n #0 0x4c5552 in realloc (/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store+0x4c5552)\n #1 0x4f4759 in on_rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:27:26\n #2 0x4f4539 in rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:125:10\n #3 0x4f891f in rg_mem_store_resize_folders /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:43:37\n #4 0x4f8656 in rg_mem_store_init /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:377:8\n #5 0x4fb769 in mem_store_test_run /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/shared/mem-store-test.c:23:8\n #6 0x4fb8ce in main /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/mem-store/main.c:18:3\n #7 0x7f47cc22f09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)\n\nSUMMARY: AddressSanitizer: 384 byte(s) leaked in 1 allocation(s).\n"}
|
4
|
+
{"name": "test-mem-store-add-feeds", "stdout": "", "result": "FAIL", "duration": 0.325427770614624, "returncode": 1, "command": ["/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store-add-feeds"], "env": {"GIT_PREVIOUS_SUCCESSFUL_COMMIT": "980602362882ea45fe08b67e01eecf8114e663b9", "HOSTNAME": "d38bcdc0a0f0", "RUN_CHANGES_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect?page=changes", "GIT_COMMIT": "0a342a9d5f2058e9f2872078c45d791cd62a3b61", "NODE_LABELS": "master", "HUDSON_URL": "http://hive:9090/", "HOME": "/", "OLDPWD": "/var/lib/jenkins/workspace/raggle_master", "BUILD_URL": "http://hive:9090/job/raggle/job/master/32/", "GIT_LOCAL_BRANCH": "master", "JENKINS_SERVER_COOKIE": "durable-a623a7ae73afbc86e3205e2d30ff0631", "LDFLAGS": "-lasan", "WORKSPACE": "/var/lib/jenkins/workspace/raggle_master", "NODE_NAME": "master", "EXECUTOR_NUMBER": "1", "GIT_BRANCH": "master", "STAGE_NAME": "address", "BUILD_DISPLAY_NAME": "#32", "HUDSON_HOME": "/var/lib/jenkins", "JOB_BASE_NAME": "master", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "BUILD_ID": "32", "CFLAGS": "-g", "BUILD_TAG": "jenkins-raggle-master-32", "JENKINS_URL": "http://hive:9090/", "JOB_URL": "http://hive:9090/job/raggle/job/master/", "GIT_URL": "git://u3/raggle.git", "BUILD_NUMBER": "32", "JENKINS_NODE_COOKIE": "5384bb4a-0b67-4e96-8d36-afa4e39e8bff", "RUN_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect", "HUDSON_SERVER_COOKIE": "44bd36d136089097", "JOB_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/display/redirect", "CLASSPATH": "", "JOB_NAME": "raggle/master", "PWD": "/var/lib/jenkins/workspace/raggle_master/build/sanitize/address", "GIT_PREVIOUS_COMMIT": "d1721a6594f2688dbac2be0c1142edf49ff634da", "CC": "clang-7", "BRANCH_NAME": "master", "LC_CTYPE": "C.UTF-8"}, "stderr": "\n=================================================================\n==307==ERROR: LeakSanitizer: detected memory leaks\n\nDirect leak of 384 byte(s) in 1 object(s) allocated from:\n #0 0x4c5552 in realloc (/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store-add-feeds+0x4c5552)\n #1 0x4f4759 in on_rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:27:26\n #2 0x4f4539 in rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:125:10\n #3 0x4f891f in rg_mem_store_resize_folders /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:43:37\n #4 0x4f8656 in rg_mem_store_init /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:377:8\n #5 0x4fb769 in mem_store_test_run /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/shared/mem-store-test.c:23:8\n #6 0x4fb8ce in main /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/mem-store-add-feeds/main.c:34:3\n #7 0x7f92456a509a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)\n\nSUMMARY: AddressSanitizer: 384 byte(s) leaked in 1 allocation(s).\n"}
|
5
|
+
{"name": "test-mem-store-add-folders", "stdout": "", "result": "FAIL", "duration": 0.37346959114074707, "returncode": 1, "command": ["/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store-add-folders"], "env": {"GIT_PREVIOUS_SUCCESSFUL_COMMIT": "980602362882ea45fe08b67e01eecf8114e663b9", "HOSTNAME": "d38bcdc0a0f0", "RUN_CHANGES_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect?page=changes", "GIT_COMMIT": "0a342a9d5f2058e9f2872078c45d791cd62a3b61", "NODE_LABELS": "master", "HUDSON_URL": "http://hive:9090/", "HOME": "/", "OLDPWD": "/var/lib/jenkins/workspace/raggle_master", "BUILD_URL": "http://hive:9090/job/raggle/job/master/32/", "GIT_LOCAL_BRANCH": "master", "JENKINS_SERVER_COOKIE": "durable-a623a7ae73afbc86e3205e2d30ff0631", "LDFLAGS": "-lasan", "WORKSPACE": "/var/lib/jenkins/workspace/raggle_master", "NODE_NAME": "master", "EXECUTOR_NUMBER": "1", "GIT_BRANCH": "master", "STAGE_NAME": "address", "BUILD_DISPLAY_NAME": "#32", "HUDSON_HOME": "/var/lib/jenkins", "JOB_BASE_NAME": "master", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "BUILD_ID": "32", "CFLAGS": "-g", "BUILD_TAG": "jenkins-raggle-master-32", "JENKINS_URL": "http://hive:9090/", "JOB_URL": "http://hive:9090/job/raggle/job/master/", "GIT_URL": "git://u3/raggle.git", "BUILD_NUMBER": "32", "JENKINS_NODE_COOKIE": "5384bb4a-0b67-4e96-8d36-afa4e39e8bff", "RUN_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/32/display/redirect", "HUDSON_SERVER_COOKIE": "44bd36d136089097", "JOB_DISPLAY_URL": "http://hive:9090/job/raggle/job/master/display/redirect", "CLASSPATH": "", "JOB_NAME": "raggle/master", "PWD": "/var/lib/jenkins/workspace/raggle_master/build/sanitize/address", "GIT_PREVIOUS_COMMIT": "d1721a6594f2688dbac2be0c1142edf49ff634da", "CC": "clang-7", "BRANCH_NAME": "master", "LC_CTYPE": "C.UTF-8"}, "stderr": "\n=================================================================\n==304==ERROR: LeakSanitizer: detected memory leaks\n\nDirect leak of 384 byte(s) in 1 object(s) allocated from:\n #0 0x4c5552 in realloc (/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store-add-folders+0x4c5552)\n #1 0x4f4759 in on_rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:27:26\n #2 0x4f4539 in rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:125:10\n #3 0x4f891f in rg_mem_store_resize_folders /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:43:37\n #4 0x4f8656 in rg_mem_store_init /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:377:8\n #5 0x4fb769 in mem_store_test_run /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/shared/mem-store-test.c:23:8\n #6 0x4fb8ce in main /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/mem-store-add-folders/main.c:34:3\n #7 0x7f967de4a09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)\n\nIndirect leak of 12 byte(s) in 3 object(s) allocated from:\n #0 0x4c5552 in realloc (/var/lib/jenkins/workspace/raggle_master/build/sanitize/address/test-mem-store-add-folders+0x4c5552)\n #1 0x4f4759 in on_rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:27:26\n #2 0x4f4539 in rg_ctx_realloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:125:10\n #3 0x4f44b3 in rg_ctx_malloc /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:116:10\n #4 0x4f45cf in rg_ctx_strndup /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-ctx.c:149:22\n #5 0x4fb0b1 in rg_folder_set_str /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-folder.c:68:38\n #6 0x4f91ec in on_mem_store_folder_add /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-mem-store.c:92:8\n #7 0x4f68b1 in rg_store_folder_add /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/core/rg-store.c:76:5\n #8 0x4fba48 in run /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/mem-store-add-folders/main.c:23:10\n #9 0x4fb793 in mem_store_test_run /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/shared/mem-store-test.c:28:3\n #10 0x4fb8ce in main /var/lib/jenkins/workspace/raggle_master/build/sanitize/address/../../../src/tests/mem-store-add-folders/main.c:34:3\n #11 0x7f967de4a09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)\n\nSUMMARY: AddressSanitizer: 396 byte(s) leaked in 4 allocation(s).\n"}
|
data/test/test_junit.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'meson-junit'
|
3
|
+
|
4
|
+
class JunitTest < MiniTest::Test
|
5
|
+
def test_junit_xmlbuilder_new
|
6
|
+
builder = ::MesonJunit::Junit::XMLBuilder.new
|
7
|
+
assert_instance_of ::MesonJunit::Junit::XMLBuilder, builder
|
8
|
+
end
|
9
|
+
|
10
|
+
TESTLOG_PATH = File.join(__dir__, 'data', 'testlog.json')
|
11
|
+
|
12
|
+
def test_junit_xmlbuilder_build
|
13
|
+
# parse sample testlog.json
|
14
|
+
log = File.open(TESTLOG_PATH) do |fh|
|
15
|
+
# parse input file as a Meson::TestLog
|
16
|
+
::MesonJunit::Meson::TestLog.new(fh)
|
17
|
+
end
|
18
|
+
|
19
|
+
# build junit xml
|
20
|
+
xml = ::MesonJunit::Junit::XMLBuilder.build(log)
|
21
|
+
|
22
|
+
assert_instance_of String, xml
|
23
|
+
end
|
24
|
+
end
|
data/test/test_meson.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'json'
|
3
|
+
require 'meson-junit'
|
4
|
+
|
5
|
+
class MesonTest < MiniTest::Test
|
6
|
+
# sample JSON
|
7
|
+
MOCK_JSON = '{
|
8
|
+
"name": "test-something",
|
9
|
+
"stdout": "",
|
10
|
+
"result": "OK",
|
11
|
+
"duration": 0.017489910125732422,
|
12
|
+
"returncode": 0,
|
13
|
+
"command": [
|
14
|
+
"/path/to/tests/test-something"
|
15
|
+
],
|
16
|
+
"env": {
|
17
|
+
"FOO": "some foo data",
|
18
|
+
"BAR": "some bar data",
|
19
|
+
"BAZ": "some baz data"
|
20
|
+
}
|
21
|
+
}'.freeze
|
22
|
+
|
23
|
+
def test_meson_test_new
|
24
|
+
data = ::JSON.parse(MOCK_JSON)
|
25
|
+
t = ::MesonJunit::Meson::Test.new(data)
|
26
|
+
assert_instance_of ::MesonJunit::Meson::Test, t
|
27
|
+
end
|
28
|
+
|
29
|
+
# path to sample testlog.json
|
30
|
+
TESTLOG_PATH = File.join(__dir__, 'data', 'testlog.json').freeze
|
31
|
+
|
32
|
+
# expected sums
|
33
|
+
EXPECTED_SUMS = {
|
34
|
+
all: 5,
|
35
|
+
OK: 2,
|
36
|
+
FAIL: 3,
|
37
|
+
}
|
38
|
+
|
39
|
+
def test_meson_testlog_new
|
40
|
+
# parse sample testlog.json
|
41
|
+
log = File.open(TESTLOG_PATH) do |fh|
|
42
|
+
::MesonJunit::Meson::TestLog.new(fh)
|
43
|
+
end
|
44
|
+
|
45
|
+
# verify that it parsed as a test log
|
46
|
+
assert_instance_of ::MesonJunit::Meson::TestLog, log
|
47
|
+
|
48
|
+
sums = log.tests.reduce(Hash.new { |h, k| h[k] = 0 }) do |r, test|
|
49
|
+
r[:all] += 1
|
50
|
+
r[test.result] += 1
|
51
|
+
r
|
52
|
+
end
|
53
|
+
|
54
|
+
# verify test counts
|
55
|
+
EXPECTED_SUMS.each do |key, sum|
|
56
|
+
assert_equal sum, sums[key]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meson-junit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paul Duncan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest-junit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0
|
55
|
+
description: "\n Command-line tool and library to convert Meson testlog JSOn files
|
56
|
+
to\n Jenkins-compatible JUnit XML files.\n "
|
57
|
+
email: pabs@pablotron.org
|
58
|
+
executables:
|
59
|
+
- meson-junit
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- bin/meson-junit
|
66
|
+
- lib/meson-junit.rb
|
67
|
+
- lib/meson-junit/cli.rb
|
68
|
+
- lib/meson-junit/junit.rb
|
69
|
+
- lib/meson-junit/junit/xml-builder.rb
|
70
|
+
- lib/meson-junit/meson.rb
|
71
|
+
- lib/meson-junit/meson/test-log.rb
|
72
|
+
- lib/meson-junit/meson/test.rb
|
73
|
+
- test/data/testlog.json
|
74
|
+
- test/test_junit.rb
|
75
|
+
- test/test_meson.rb
|
76
|
+
homepage: https://github.com/pablotron/meson-junit
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata:
|
80
|
+
bug_tracker_uri: https://github.com/pablotron/meson-junit/issues
|
81
|
+
documentation_uri: https://pablotron.github.io/meson-junit/
|
82
|
+
homepage_uri: https://github.com/pablotron/meson-junit
|
83
|
+
source_code_uri: https://github.com/pablotron/meson-junit
|
84
|
+
wiki_uri: https://github.com/pablotron/meson-junit/wiki
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.7.6.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Convert Meson testlog JSON to JUnit XML.
|
105
|
+
test_files: []
|