ruby-jing 0.0.2 → 0.1.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/README.rdoc +4 -4
- data/lib/jing.rb +28 -13
- data/test/test_jing.rb +49 -18
- metadata +22 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 41284b05a5ee61d28bbf52115ad2c910ee85791edf63880786ac413f9d190b71
|
|
4
|
+
data.tar.gz: e373a5ca42a69b3f6bd7a663155239904cc0f2fd8fd2033ebd19f8586ac2490a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 858919ea520690526014c81aeba7f77308933dbd4afcc52fe2a1e40d8a5f1d8f1267b2dd133c5617cdd60cec8f7934595d03fab0ac087c6fdadbb9203a91cddb
|
|
7
|
+
data.tar.gz: 94c9479f1a222b58b81d150806c3d937913436cdb4c2c35d29892ce06be0d7f405400ff8284cbddc9c1caa443ac38e76ab3f0706a65e435863b3b8d98efa57d7
|
data/README.rdoc
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
= Ruby Jing
|
|
2
2
|
|
|
3
|
-
{<img src="https://
|
|
3
|
+
{<img src="https://github.com/sshaw/ruby-jing/actions/workflows/rake.yml/badge.svg"/>}[https://github.com/sshaw/ruby-jing/actions/workflows/rake.yml]
|
|
4
4
|
{<img src="https://codeclimate.com/github/sshaw/ruby-jing.png" />}[https://codeclimate.com/github/sshaw/ruby-jing]
|
|
5
5
|
|
|
6
6
|
RELAX NG schema validation using the {Jing CLI}[http://www.thaiopensource.com/relaxng/jing.html]
|
|
@@ -55,7 +55,7 @@ Simple: good error messages. Let's look at the error messages provided by each o
|
|
|
55
55
|
|
|
56
56
|
<!-- XML B -->
|
|
57
57
|
<addressBook>
|
|
58
|
-
<card verison="v100">
|
|
58
|
+
<card verison="v100">
|
|
59
59
|
<name>John Smith</name>
|
|
60
60
|
<oops>Doh!</oops>
|
|
61
61
|
</card>
|
|
@@ -65,7 +65,7 @@ Simple: good error messages. Let's look at the error messages provided by each o
|
|
|
65
65
|
|
|
66
66
|
schema = Nokogiri::XML::RelaxNG(File.read(rng))
|
|
67
67
|
doc = Nokogiri::XML(File.read(xml))
|
|
68
|
-
errors = schema.validate(doc)
|
|
68
|
+
errors = schema.validate(doc)
|
|
69
69
|
errors.each { |e| puts e }
|
|
70
70
|
|
|
71
71
|
Resulting errors:
|
|
@@ -87,7 +87,7 @@ Resulting errors:
|
|
|
87
87
|
|
|
88
88
|
Fails for XML A and XML B --it treats the XML declaration as a validation error!
|
|
89
89
|
|
|
90
|
-
Validation error. Expected: :start_element( addressBook ) from < S.1 #:start_element( addressBook ), < Z.2 #:start_element( card ), :start_attribute( version ), < C.3 :text( v1 ) or :text( v2 ) >, :end_attribute( ), :start_element( name ), :text( ), :end_element( ), :start_element( email ), :text( ), :end_element( ), :end_element( ) >, :end_element( ), :end_document( ) > but got <?xml ... ?>(
|
|
90
|
+
Validation error. Expected: :start_element( addressBook ) from < S.1 #:start_element( addressBook ), < Z.2 #:start_element( card ), :start_attribute( version ), < C.3 :text( v1 ) or :text( v2 ) >, :end_attribute( ), :start_element( name ), :text( ), :end_element( ), :start_element( email ), :text( ), :end_element( ), :end_element( ) >, :end_element( ), :end_document( ) > but got <?xml ... ?>(
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
==== Jing
|
data/lib/jing.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
require "open3"
|
|
1
2
|
require "optout"
|
|
2
3
|
|
|
3
4
|
class Jing
|
|
4
|
-
VERSION = "0.0
|
|
5
|
+
VERSION = "0.1.0"
|
|
5
6
|
DEFAULT_JAR = File.join(File.dirname(__FILE__), "jing-20091111.jar")
|
|
6
7
|
|
|
7
8
|
Error = Class.new(StandardError)
|
|
@@ -32,6 +33,7 @@ class Jing
|
|
|
32
33
|
# === Options
|
|
33
34
|
#
|
|
34
35
|
# [:java (String)] Name and/or location of the java executable. Defaults to <code>"java"</code>.
|
|
36
|
+
# [:java_opts (String)] JVM options passed to +java+, e.g. +"-Dfile.encoding=UTF-8"+. Use this to set +"-D"+ system properties (e.g. +jdk.xml.maxGeneralEntitySizeLimit+) instead of the +JAVA_TOOL_OPTIONS+/_JAVA_OPTIONS+ environment variables, which make the JVM print a +Picked up ...+ banner to stderr on every launch.
|
|
35
37
|
# [:jar (String)] Path to the Jing JAR file. Defaults to the bundled JAR.
|
|
36
38
|
# [:compact (Boolean)] Set to +true+ if the schema uses the RELAX NG compact syntax. Defaults to false, will be set to +true+ is the schema has a +.rnc+ extension.
|
|
37
39
|
# [:encoding (String)] Encoding of the XML document.
|
|
@@ -53,7 +55,8 @@ class Jing
|
|
|
53
55
|
# Optout quirk: true will *include* the switch, which means we *don't* want to check
|
|
54
56
|
@options[:id_check] = !@options[:id_check] if @options.include?(:id_check)
|
|
55
57
|
if @options[:encoding]
|
|
56
|
-
|
|
58
|
+
file_encoding = "-Dfile.encoding=#{@options[:encoding]}"
|
|
59
|
+
@options[:java_opts] = [@options[:java_opts], file_encoding].compact.join(" ")
|
|
57
60
|
end
|
|
58
61
|
end
|
|
59
62
|
|
|
@@ -87,11 +90,10 @@ class Jing
|
|
|
87
90
|
def validate(xml)
|
|
88
91
|
@options[:xmlfile] = xml
|
|
89
92
|
|
|
90
|
-
out = execute(@options)
|
|
91
|
-
return [] if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
errors
|
|
93
|
+
out, status = execute(@options)
|
|
94
|
+
return [] if status.success? and out.empty?
|
|
95
|
+
|
|
96
|
+
parse_output(out)
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
# Validate an XML document against the schema. To receive a list of validation errors use #validate.
|
|
@@ -107,19 +109,26 @@ class Jing
|
|
|
107
109
|
# Same as #validate
|
|
108
110
|
#
|
|
109
111
|
# === Returns
|
|
110
|
-
#
|
|
112
|
+
#
|
|
111
113
|
# [Boolean] +true+ if valid, +false+ if invalid
|
|
112
114
|
#
|
|
113
|
-
|
|
115
|
+
|
|
114
116
|
def valid?(xml)
|
|
115
117
|
errors = validate(xml)
|
|
116
118
|
errors.none?
|
|
117
119
|
end
|
|
118
|
-
|
|
120
|
+
|
|
119
121
|
private
|
|
122
|
+
# Spawn java directly in argv form instead of shelling out via backticks.
|
|
123
|
+
# A shell-form spawn needs /bin/sh, which is not always reachable from the
|
|
124
|
+
# calling process (restricted containers, TruffleRuby processes with a
|
|
125
|
+
# virtual filesystem mounted at /, ...); direct exec needs no shell. It
|
|
126
|
+
# also removes the shell-injection surface of interpolating paths into a
|
|
127
|
+
# command string. Behavior is unchanged: stderr is merged into the
|
|
128
|
+
# captured output and the exit status is returned alongside it.
|
|
120
129
|
def execute(options)
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
argv = @@option_builder.argv(options)
|
|
131
|
+
Open3.capture2e(*argv)
|
|
123
132
|
rescue SystemCallError => e
|
|
124
133
|
raise ExecutionError, "jing execution failed: #{e}"
|
|
125
134
|
rescue Optout::OptionError => e
|
|
@@ -129,13 +138,19 @@ class Jing
|
|
|
129
138
|
def parse_output(output)
|
|
130
139
|
errors = []
|
|
131
140
|
output.split("\n").each do |line|
|
|
132
|
-
|
|
141
|
+
case line
|
|
142
|
+
when /\A(.+):(\d+):(\d+):\s+\w+:\s+(.+)\Z/
|
|
133
143
|
errors << {
|
|
134
144
|
:source => $1,
|
|
135
145
|
:line => $2.to_i,
|
|
136
146
|
:column => $3.to_i,
|
|
137
147
|
:message => $4
|
|
138
148
|
}
|
|
149
|
+
when /Picked up [A-Z_][A-Z0-9_]*: /
|
|
150
|
+
# ignore JVM diagnostic banner printed for env vars like
|
|
151
|
+
# _JAVA_OPTIONS, JAVA_TOOL_OPTIONS and JDK_JAVA_OPTIONS
|
|
152
|
+
else # There must have been a problem that was not schema related
|
|
153
|
+
raise ExecutionError, output
|
|
139
154
|
end
|
|
140
155
|
end
|
|
141
156
|
errors
|
data/test/test_jing.rb
CHANGED
|
@@ -12,7 +12,7 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
12
12
|
|
|
13
13
|
def test_default_jar_file_used
|
|
14
14
|
cmd = fakeshell { Jing.new(RNG_SCHEMA).validate(VALID_XML) }
|
|
15
|
-
assert_match /\
|
|
15
|
+
assert_match /\Ajava\s+ -jar\s+ #{Regexp.escape(Jing::DEFAULT_JAR)} \s+/x, cmd
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def test_jar_file_must_exist
|
|
@@ -24,13 +24,13 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
24
24
|
def test_jar_option
|
|
25
25
|
jar = Tempfile.new "jar"
|
|
26
26
|
cmd = fakeshell { Jing.new(RNG_SCHEMA, :jar => jar.path).validate(VALID_XML) }
|
|
27
|
-
assert_match /\
|
|
27
|
+
assert_match /\Ajava\s+ -jar\s+ #{Regexp.escape(jar.path)} \s+/x, cmd
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def test_java_option
|
|
31
31
|
java = "/usr/alt/java"
|
|
32
32
|
cmd = fakeshell { Jing.new(RNG_SCHEMA, :java => java).validate(VALID_XML) }
|
|
33
|
-
assert_match /\A
|
|
33
|
+
assert_match /\A#{Regexp.escape(java)}\s+/, cmd
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def test_java_must_exist
|
|
@@ -43,12 +43,12 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
43
43
|
def test_encoding_option
|
|
44
44
|
enc = "iso-8859-1"
|
|
45
45
|
cmd = fakeshell { Jing.new(RNG_SCHEMA, :encoding => enc).validate(VALID_XML) }
|
|
46
|
-
assert_match /\
|
|
46
|
+
assert_match /\Ajava\s+ -Dfile\.encoding=#{enc}\s+ -jar\s+ #{Regexp.escape(Jing::DEFAULT_JAR)}\s+ -e\s+ #{enc}/x, cmd
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def test_id_check_option
|
|
50
50
|
cmd = fakeshell { Jing.new(RNG_SCHEMA, :id_check => false).validate(VALID_XML) }
|
|
51
|
-
assert_match /\
|
|
51
|
+
assert_match /\Ajava\s -jar\s+ #{Regexp.escape(Jing::DEFAULT_JAR)}\s+ -i/x, cmd
|
|
52
52
|
|
|
53
53
|
cmd = fakeshell { Jing.new(RNG_SCHEMA, :id_check => true).validate(VALID_XML) }
|
|
54
54
|
refute_match /\b-i\b/x, cmd
|
|
@@ -59,7 +59,7 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
59
59
|
|
|
60
60
|
def test_compact_option
|
|
61
61
|
cmd = fakeshell { Jing.new(RNC_SCHEMA, :compact => true).validate(VALID_XML) }
|
|
62
|
-
assert_match /\
|
|
62
|
+
assert_match /\Ajava\s -jar\s+ #{Regexp.escape(Jing::DEFAULT_JAR)}\s+ -c/x, cmd
|
|
63
63
|
|
|
64
64
|
cmd = fakeshell { Jing.new(RNC_SCHEMA, :compact => false).validate(VALID_XML) }
|
|
65
65
|
refute_match /\b-c\b/, cmd
|
|
@@ -67,7 +67,7 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
67
67
|
|
|
68
68
|
def test_compact_option_when_compact_schema_is_used
|
|
69
69
|
cmd = fakeshell { Jing.new(RNC_SCHEMA).validate(VALID_XML) }
|
|
70
|
-
assert_match /\
|
|
70
|
+
assert_match /\Ajava\s+ -jar\s+ #{Regexp.escape(Jing::DEFAULT_JAR)}\s+ -c/x, cmd
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def test_relaxng_file_must_exist
|
|
@@ -113,28 +113,59 @@ class TestJing < MiniTest::Unit::TestCase
|
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
def test_java_options_env_diagnostic_message
|
|
117
|
+
output = "Picked up _JAVA_OPTIONS: -Djava.io.tmpdir=/tmp"
|
|
118
|
+
fakeshell(:exit => 0, :output => output) {
|
|
119
|
+
errors = Jing.new(RNG_SCHEMA).validate(VALID_XML)
|
|
120
|
+
assert_equal 0, errors.size
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_java_tool_options_env_diagnostic_message
|
|
125
|
+
output = "Picked up JAVA_TOOL_OPTIONS: -Djdk.xml.maxGeneralEntitySizeLimit=200000"
|
|
126
|
+
fakeshell(:exit => 0, :output => output) {
|
|
127
|
+
errors = Jing.new(RNG_SCHEMA).validate(VALID_XML)
|
|
128
|
+
assert_equal 0, errors.size
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_jdk_java_options_env_diagnostic_message
|
|
133
|
+
output = "Picked up JDK_JAVA_OPTIONS: -Dfile.encoding=UTF-8"
|
|
134
|
+
fakeshell(:exit => 0, :output => output) {
|
|
135
|
+
errors = Jing.new(RNG_SCHEMA).validate(VALID_XML)
|
|
136
|
+
assert_equal 0, errors.size
|
|
137
|
+
}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_java_opts_and_encoding_are_combined
|
|
141
|
+
opts = "-Djdk.xml.maxGeneralEntitySizeLimit=200000"
|
|
142
|
+
cmd = fakeshell { Jing.new(RNG_SCHEMA, :java_opts => opts, :encoding => "iso-8859-1").validate(VALID_XML) }
|
|
143
|
+
assert_match(/#{opts} -Dfile\.encoding=iso-8859-1\s+-jar/, cmd)
|
|
144
|
+
assert_match(/-e\s+ iso-8859-1/x, cmd)
|
|
145
|
+
end
|
|
146
|
+
|
|
116
147
|
private
|
|
117
148
|
def fakeshell(options = {})
|
|
118
149
|
output = options.delete(:output) || ""
|
|
119
150
|
exit_code = options.delete(:exit) || 0
|
|
120
151
|
|
|
121
152
|
cmd = nil
|
|
122
|
-
|
|
123
|
-
alias_method "
|
|
124
|
-
define_method("
|
|
125
|
-
cmd =
|
|
126
|
-
|
|
127
|
-
output
|
|
153
|
+
Open3.singleton_class.class_eval do
|
|
154
|
+
alias_method "real_capture2e", "capture2e"
|
|
155
|
+
define_method("capture2e") do |*argv|
|
|
156
|
+
cmd = argv.join(" ")
|
|
157
|
+
`ruby -e"exit #{exit_code}"` # Just to set $?
|
|
158
|
+
[output, $?]
|
|
128
159
|
end
|
|
129
160
|
end
|
|
130
161
|
|
|
131
162
|
yield
|
|
132
|
-
cmd
|
|
163
|
+
cmd
|
|
133
164
|
ensure
|
|
134
|
-
|
|
135
|
-
undef_method "
|
|
136
|
-
alias_method "
|
|
137
|
-
undef_method "
|
|
165
|
+
Open3.singleton_class.class_eval do
|
|
166
|
+
undef_method "capture2e"
|
|
167
|
+
alias_method "capture2e", "real_capture2e"
|
|
168
|
+
undef_method "real_capture2e"
|
|
138
169
|
end
|
|
139
170
|
end
|
|
140
171
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-jing
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Skye Shaw
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2026-09-17 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: optout
|
|
@@ -24,6 +23,20 @@ dependencies:
|
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
25
|
version: 0.0.2
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: bundler
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
27
40
|
- !ruby/object:Gem::Dependency
|
|
28
41
|
name: rake
|
|
29
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -69,8 +82,11 @@ files:
|
|
|
69
82
|
homepage: http://github.com/sshaw/ruby-jing
|
|
70
83
|
licenses:
|
|
71
84
|
- MIT
|
|
72
|
-
metadata:
|
|
73
|
-
|
|
85
|
+
metadata:
|
|
86
|
+
homepage_uri: http://github.com/sshaw/ruby-jing
|
|
87
|
+
source_code_uri: https://github.com/sshaw/ruby-jing
|
|
88
|
+
bug_tracker_uri: https://github.com/sshaw/ruby-jing/issues
|
|
89
|
+
changelog_uri: https://github.com/sshaw/ruby-jing/blob/master/Changes
|
|
74
90
|
rdoc_options: []
|
|
75
91
|
require_paths:
|
|
76
92
|
- lib
|
|
@@ -85,9 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
85
101
|
- !ruby/object:Gem::Version
|
|
86
102
|
version: '0'
|
|
87
103
|
requirements: []
|
|
88
|
-
|
|
89
|
-
rubygems_version: 2.6.14
|
|
90
|
-
signing_key:
|
|
104
|
+
rubygems_version: 3.6.2
|
|
91
105
|
specification_version: 4
|
|
92
106
|
summary: RELAX NG schema validation using the Jing CLI
|
|
93
107
|
test_files:
|