meson-junit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # load library
4
+ require_relative '../lib/meson-junit'
5
+
6
+ # invoke command-line interface
7
+ MesonJunit::CLI.run($0, ARGV)
@@ -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,6 @@
1
+ #
2
+ # JUnit XML builder namespace.
3
+ #
4
+ module MesonJunit::Junit
5
+ autoload :XMLBuilder, File.join(__dir__, 'junit', 'xml-builder.rb')
6
+ 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,7 @@
1
+ #
2
+ # Meson parsing namespace.
3
+ #
4
+ module MesonJunit::Meson
5
+ autoload :Test, File.join(__dir__, 'meson', 'test.rb')
6
+ autoload :TestLog, File.join(__dir__, 'meson', 'test-log.rb')
7
+ 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"}
@@ -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
@@ -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: []