hexapdf 1.9.1 → 1.11.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 +4 -4
- data/CHANGELOG.md +55 -0
- data/lib/hexapdf/cli/command.rb +1 -2
- data/lib/hexapdf/configuration.rb +2 -2
- data/lib/hexapdf/content/canvas.rb +2 -2
- data/lib/hexapdf/content/smart_text_extractor.rb +3 -2
- data/lib/hexapdf/dictionary_fields.rb +7 -0
- data/lib/hexapdf/digital_signature/cms_handler.rb +27 -2
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +5 -0
- data/lib/hexapdf/digital_signature/signatures.rb +105 -0
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +0 -2
- data/lib/hexapdf/document.rb +2 -2
- data/lib/hexapdf/encryption/security_handler.rb +3 -1
- data/lib/hexapdf/layout/style.rb +2 -2
- data/lib/hexapdf/layout/text_fragment.rb +5 -1
- data/lib/hexapdf/layout/text_shaper.rb +1 -57
- data/lib/hexapdf/parser.rb +1 -2
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/task/import_pages.rb +41 -9
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +3 -1
- data/lib/hexapdf/type/acro_form/field.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +8 -1
- data/lib/hexapdf/type/document_security_store.rb +81 -13
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/content/test_canvas.rb +3 -3
- data/test/hexapdf/content/test_smart_text_extractor.rb +7 -0
- data/test/hexapdf/digital_signature/common.rb +209 -2
- data/test/hexapdf/digital_signature/test_cms_handler.rb +4 -2
- data/test/hexapdf/digital_signature/test_pkcs1_handler.rb +4 -0
- data/test/hexapdf/digital_signature/test_signatures.rb +131 -0
- data/test/hexapdf/encryption/test_security_handler.rb +12 -0
- data/test/hexapdf/layout/test_style.rb +3 -1
- data/test/hexapdf/layout/test_text_fragment.rb +11 -4
- data/test/hexapdf/task/test_import_pages.rb +42 -1
- data/test/hexapdf/test_dictionary_fields.rb +8 -0
- data/test/hexapdf/test_parser.rb +25 -9
- data/test/hexapdf/test_serializer.rb +7 -1
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +1 -1
- data/test/hexapdf/type/acro_form/test_choice_field.rb +5 -0
- data/test/hexapdf/type/acro_form/test_field.rb +3 -1
- data/test/hexapdf/type/test_catalog.rb +10 -0
- data/test/hexapdf/type/test_document_security_store.rb +120 -0
- data/test/test_helper.rb +7 -3
- metadata +939 -904
|
@@ -43,10 +43,18 @@ describe HexaPDF::Layout::TextFragment do
|
|
|
43
43
|
|
|
44
44
|
it "allows using a style object instead of directly specifying style properties" do
|
|
45
45
|
style = HexaPDF::Layout::Style.new(font: @font, font_size: 20)
|
|
46
|
-
frags = HexaPDF::Layout::TextFragment.create_with_fallback_glyphs("Tom", style)
|
|
46
|
+
frags = HexaPDF::Layout::TextFragment.create_with_fallback_glyphs("Tom", style) {}
|
|
47
47
|
assert_equal(37.78, frags[0].width)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
it "handles control characters separately by not running them through the text shaper" do
|
|
51
|
+
frags = HexaPDF::Layout::TextFragment.create_with_fallback_glyphs("\tA\nB\rC\r\nD", font: @font) {}
|
|
52
|
+
assert_equal(5, frags.size)
|
|
53
|
+
assert_equal("\t", frags[0].text)
|
|
54
|
+
assert_equal("A\n", frags[1].text)
|
|
55
|
+
assert_equal("C\r\n", frags[3].text)
|
|
56
|
+
end
|
|
57
|
+
|
|
50
58
|
it "replaces invalid glyphs with the result of the block" do
|
|
51
59
|
zapf_dingbats = @doc.fonts.add('ZapfDingbats')
|
|
52
60
|
i = 0
|
|
@@ -62,7 +70,7 @@ describe HexaPDF::Layout::TextFragment do
|
|
|
62
70
|
|
|
63
71
|
frags = HexaPDF::Layout::TextFragment.create_with_fallback_glyphs("✂Tom✂Tom✂Tom✂Tom\u{ad}",
|
|
64
72
|
style, &fallback)
|
|
65
|
-
assert_equal(
|
|
73
|
+
assert_equal(7, frags.size)
|
|
66
74
|
assert_equal(zapf_dingbats, frags[0].style.font)
|
|
67
75
|
assert_equal(:a2, frags[0].items[0].name)
|
|
68
76
|
assert_equal("Tom", frags[1].text)
|
|
@@ -71,8 +79,7 @@ describe HexaPDF::Layout::TextFragment do
|
|
|
71
79
|
assert_equal("Tom", frags[3].text)
|
|
72
80
|
assert_equal(:'.notdef', frags[4].items[0].name)
|
|
73
81
|
assert_equal("Tom", frags[5].text)
|
|
74
|
-
assert_equal("Tom", frags[6].text)
|
|
75
|
-
assert_equal("\u{ad}", frags[7].text)
|
|
82
|
+
assert_equal("Tom\u{ad}", frags[6].text)
|
|
76
83
|
end
|
|
77
84
|
end
|
|
78
85
|
|
|
@@ -99,9 +99,10 @@ describe HexaPDF::Task::ImportPages do
|
|
|
99
99
|
canvas = @doc.pages[0].canvas
|
|
100
100
|
form = canvas.form
|
|
101
101
|
form[:OC] = @ocg1
|
|
102
|
+
form.canvas.optional_content(@ocmd)
|
|
102
103
|
canvas.xobject(form, at: [0, 0])
|
|
103
104
|
@target.task(:import_pages, source: @doc)
|
|
104
|
-
assert_equal(['OCG'], @target.optional_content.ocgs.map(&:name))
|
|
105
|
+
assert_equal(['OCG', 'OCMD'], @target.optional_content.ocgs.map(&:name))
|
|
105
106
|
end
|
|
106
107
|
|
|
107
108
|
it "preserves OCGs/OCMDs associated with annotations" do
|
|
@@ -123,4 +124,44 @@ describe HexaPDF::Task::ImportPages do
|
|
|
123
124
|
assert_equal(['OCG'], rb_groups[0].map(&:name))
|
|
124
125
|
end
|
|
125
126
|
end
|
|
127
|
+
|
|
128
|
+
describe "resize_to argument" do
|
|
129
|
+
before do
|
|
130
|
+
@doc.annotations.create_line(@pages[0], start_point: [10, 10], end_point: [100, 100]).
|
|
131
|
+
regenerate_appearance
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "works when given a symbolic page size" do
|
|
135
|
+
@target.task(:import_pages, source: @doc, resize_to: :A4)
|
|
136
|
+
assert_equal(2, @doc.each.select {|obj| obj.type == :Page }.size)
|
|
137
|
+
assert_operators(@target.pages[0].contents, [[:paint_xobject, [:XO1]]])
|
|
138
|
+
assert_operators(@target.pages[1].contents, [[:paint_xobject, [:XO1]]])
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "works when given a media box directly" do
|
|
142
|
+
@target.task(:import_pages, source: @doc, pages: 0, resize_to: [5, 5, 100, 100])
|
|
143
|
+
assert_equal(1, @target.each.select {|obj| obj.type == :Page }.size)
|
|
144
|
+
assert_operators(@target.pages[0].contents,
|
|
145
|
+
[[:concatenate_matrix, [1, 0, 0, 1, 5, 5]],
|
|
146
|
+
[:save_graphics_state],
|
|
147
|
+
[:concatenate_matrix, [0.15959, 0, 0, 0.112841, 0.0, 0.0]],
|
|
148
|
+
[:paint_xobject, [:XO1]],
|
|
149
|
+
[:restore_graphics_state]])
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "flattens the annotations" do
|
|
153
|
+
@target.task(:import_pages, source: @doc, pages: 0, resize_to: [5, 5, 100, 100])
|
|
154
|
+
assert_operators(@target.pages[0].resources.xobject(:XO1).contents,
|
|
155
|
+
[[:save_graphics_state],
|
|
156
|
+
[:restore_graphics_state],
|
|
157
|
+
[:save_graphics_state],
|
|
158
|
+
[:restore_graphics_state],
|
|
159
|
+
[:save_graphics_state],
|
|
160
|
+
[:save_graphics_state],
|
|
161
|
+
[:concatenate_matrix, [1.0, 0, 0, 1.0, 0.0, 0.0]],
|
|
162
|
+
[:paint_xobject, [:XO1]],
|
|
163
|
+
[:restore_graphics_state],
|
|
164
|
+
[:restore_graphics_state]])
|
|
165
|
+
end
|
|
166
|
+
end
|
|
126
167
|
end
|
|
@@ -129,6 +129,11 @@ describe HexaPDF::DictionaryFields do
|
|
|
129
129
|
str = @field.convert("\xfe\xff\x00t\x00e\x00s\x00t".b, self)
|
|
130
130
|
assert_equal('test', str)
|
|
131
131
|
assert_equal(Encoding::UTF_8, str.encoding)
|
|
132
|
+
|
|
133
|
+
str = @field.convert("\xef\xbb\xbfHall\xC3\xB6".b, self)
|
|
134
|
+
assert_equal('Hallö', str)
|
|
135
|
+
assert_equal(Encoding::UTF_8, str.encoding)
|
|
136
|
+
|
|
132
137
|
str = @field.convert("Testing\x9c\x92".b, self)
|
|
133
138
|
assert_equal("Testing\u0153\u2122", str)
|
|
134
139
|
assert_equal(Encoding::UTF_8, str.encoding)
|
|
@@ -141,6 +146,9 @@ describe HexaPDF::DictionaryFields do
|
|
|
141
146
|
it "calls document.on_invalid_string if the provided string is invalid" do
|
|
142
147
|
str = "\xfe\xff\xD8\x00\x00s\x00t".b
|
|
143
148
|
assert_equal("st", @field.convert(str, self))
|
|
149
|
+
|
|
150
|
+
str = "\xef\xbb\xbfHall\xFF\xC3".b
|
|
151
|
+
assert_equal("Hall", @field.convert(str, self))
|
|
144
152
|
end
|
|
145
153
|
end
|
|
146
154
|
|
data/test/hexapdf/test_parser.rb
CHANGED
|
@@ -702,15 +702,6 @@ describe HexaPDF::Parser do
|
|
|
702
702
|
assert_equal(6, @parser.load_object(@xref).value)
|
|
703
703
|
end
|
|
704
704
|
|
|
705
|
-
it "uses a security handler for decrypting indirect objects if necessary" do
|
|
706
|
-
handler = Minitest::Mock.new
|
|
707
|
-
handler.expect(:decrypt, HexaPDF::Object.new(:result, oid: 1), [HexaPDF::Object])
|
|
708
|
-
@document.instance_variable_set(:@security_handler, handler)
|
|
709
|
-
create_parser("1 0 obj\n6\nendobj\ntrailer\n<</Size 1>>")
|
|
710
|
-
assert_equal(:result, @parser.load_object(@xref).value)
|
|
711
|
-
assert(handler.verify)
|
|
712
|
-
end
|
|
713
|
-
|
|
714
705
|
it "ignores parts where the starting line is split across lines" do
|
|
715
706
|
create_parser("1 0 obj\n5\nendobj\n1 0\nobj\n6\nendobj\ntrailer\n<</Size 1>>")
|
|
716
707
|
assert_equal(5, @parser.load_object(@xref).value)
|
|
@@ -774,6 +765,31 @@ describe HexaPDF::Parser do
|
|
|
774
765
|
assert_equal({Root: HexaPDF::Reference.new(1, 0)}, @parser.reconstructed_revision.trailer.value)
|
|
775
766
|
end
|
|
776
767
|
|
|
768
|
+
it "decrypts strings and streams correctly in case of whole/part document recovery" do
|
|
769
|
+
io = StringIO.new
|
|
770
|
+
doc = HexaPDF::Document.new
|
|
771
|
+
doc.catalog[:XXTest] = doc.add({Data: "string"}, stream: "stream")
|
|
772
|
+
doc.encrypt
|
|
773
|
+
xref_section = doc.write(io)[1]
|
|
774
|
+
test_oid = doc.catalog[:XXTest].oid
|
|
775
|
+
|
|
776
|
+
# whole document corruption
|
|
777
|
+
invalid_doc = io.string.sub(/xref\n0 #{xref_section.max_oid + 1}/, "xref\n0 1")
|
|
778
|
+
doc = HexaPDF::Document.new(io: StringIO.new(invalid_doc))
|
|
779
|
+
assert(doc.revisions.parser.reconstructed?)
|
|
780
|
+
assert_equal('string', doc.catalog[:XXTest][:Data])
|
|
781
|
+
assert_equal('stream', doc.catalog[:XXTest].stream)
|
|
782
|
+
|
|
783
|
+
# part document corruption
|
|
784
|
+
invalid_doc = io.string.sub(xref_section[test_oid].pos.to_s.rjust(10, '0'),
|
|
785
|
+
(xref_section[test_oid].pos + 5).to_s.rjust(10, '0'))
|
|
786
|
+
doc = HexaPDF::Document.new(io: StringIO.new(invalid_doc))
|
|
787
|
+
refute(doc.revisions.parser.reconstructed?)
|
|
788
|
+
assert_equal('string', doc.catalog[:XXTest][:Data])
|
|
789
|
+
assert_equal('stream', doc.catalog[:XXTest].stream)
|
|
790
|
+
assert(doc.revisions.parser.reconstructed?)
|
|
791
|
+
end
|
|
792
|
+
|
|
777
793
|
it "fails if no valid trailer is found and couldn't be constructed" do
|
|
778
794
|
create_parser("1 0 obj\n5\nendobj\nquack trailer <</Size 1>>\nstartxref\n22\n%%EOF")
|
|
779
795
|
assert_raises(HexaPDF::MalformedPDFError) { @parser.reconstructed_revision.trailer }
|
|
@@ -58,7 +58,7 @@ describe HexaPDF::Serializer do
|
|
|
58
58
|
assert_serialized("1208925819614629174706176", 1_208_925_819_614_629_174_706_176)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
it "serializes floats with a precision of
|
|
61
|
+
it "serializes floats with a precision of 6" do
|
|
62
62
|
assert_serialized("1.5", 1.5)
|
|
63
63
|
assert_serialized("-1.5", -1.5)
|
|
64
64
|
assert_serialized("9.123456", 9.123456)
|
|
@@ -66,6 +66,12 @@ describe HexaPDF::Serializer do
|
|
|
66
66
|
assert_serialized("0.000005", 0.000005)
|
|
67
67
|
assert_serialized("-0.000005", -0.000005)
|
|
68
68
|
assert_serialized("0.0", 0.0)
|
|
69
|
+
assert_serialized("123456789012345.0", 1.23456789012345e14)
|
|
70
|
+
assert_serialized("123456789012345.34", 1.2345678901234534e14)
|
|
71
|
+
assert_serialized("-123456789012345.0", -1.23456789012345e14)
|
|
72
|
+
assert_serialized("-123456789012345.34", -1.2345678901234534e14)
|
|
73
|
+
assert_serialized("999999999999999", 1.23456789012345e15)
|
|
74
|
+
assert_serialized("-999999999999999", -1.23456789012345e15)
|
|
69
75
|
assert_raises(HexaPDF::Error) { @serializer.serialize(0.0 / 0) }
|
|
70
76
|
assert_raises(HexaPDF::Error) { @serializer.serialize(1.0 / 0) }
|
|
71
77
|
assert_raises(HexaPDF::Error) { @serializer.serialize(-1.0 / 0) }
|
|
@@ -928,7 +928,7 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
|
|
|
928
928
|
|
|
929
929
|
it "creates the /N appearance stream" do
|
|
930
930
|
@field[:I] = [1, 2]
|
|
931
|
-
@field[:V] = ['b', 'c']
|
|
931
|
+
@field[:V] = ['b', 'c', 'd']
|
|
932
932
|
@field.set_default_appearance_string(font_size: 12, font_color: "red")
|
|
933
933
|
@generator.create_appearances
|
|
934
934
|
assert_operators(@widget[:AP][:N].stream,
|
|
@@ -103,6 +103,11 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
|
103
103
|
@field.option_items = [1, 2, 3, 4]
|
|
104
104
|
@field.list_box_top_index = 2
|
|
105
105
|
assert_equal(2, @field.list_box_top_index)
|
|
106
|
+
|
|
107
|
+
@field[:TI] = 100
|
|
108
|
+
assert_equal(0, @field.list_box_top_index)
|
|
109
|
+
@field[:TI] = "other"
|
|
110
|
+
assert_equal(0, @field.list_box_top_index)
|
|
106
111
|
end
|
|
107
112
|
|
|
108
113
|
it "fails if mulitple values are provided but the list box is not a multi-select" do
|
|
@@ -113,7 +113,9 @@ describe HexaPDF::Type::AcroForm::Field do
|
|
|
113
113
|
|
|
114
114
|
it "can check whether a widget is embedded in the field" do
|
|
115
115
|
refute(@field.embedded_widget?)
|
|
116
|
-
@field[:Subtype] = :
|
|
116
|
+
@field[:Subtype] = :Link
|
|
117
|
+
refute(@field.embedded_widget?)
|
|
118
|
+
@field[:Subtype] = :Widget
|
|
117
119
|
assert(@field.embedded_widget?)
|
|
118
120
|
end
|
|
119
121
|
|
|
@@ -50,6 +50,16 @@ describe HexaPDF::Type::Catalog do
|
|
|
50
50
|
assert_equal(:XXOCConfiguration, oc[:D].type)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
it "uses or creates the document security store on access" do
|
|
54
|
+
@catalog[:DSS] = {}
|
|
55
|
+
assert_equal(:DSS, @catalog.dss.type)
|
|
56
|
+
|
|
57
|
+
@catalog.delete(:DSS)
|
|
58
|
+
dss = @catalog.dss
|
|
59
|
+
assert_equal(:DSS, dss.type)
|
|
60
|
+
assert_same(dss, @catalog.dss)
|
|
61
|
+
end
|
|
62
|
+
|
|
53
63
|
describe "acro_form" do
|
|
54
64
|
it "returns an existing form object" do
|
|
55
65
|
@catalog[:AcroForm] = :test
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require_relative '../digital_signature/common'
|
|
5
|
+
require 'hexapdf/document'
|
|
6
|
+
require 'hexapdf/type/document_security_store'
|
|
7
|
+
|
|
8
|
+
describe HexaPDF::Type::DocumentSecurityStore do
|
|
9
|
+
before do
|
|
10
|
+
@doc = HexaPDF::Document.new
|
|
11
|
+
@dss = @doc.add({Type: :DSS})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
[[:add_cert, :Certs], [:add_ocsp, :OCSPs], [:add_crl, :CRLs]].each do |method, field|
|
|
15
|
+
describe method do
|
|
16
|
+
it "adds a #{field[0..-2]} as an indirect stream object" do
|
|
17
|
+
result = @dss.send(method, "der_data")
|
|
18
|
+
assert_kind_of(HexaPDF::Stream, result)
|
|
19
|
+
assert_equal(:FlateDecode, result[:Filter])
|
|
20
|
+
assert_equal("der_data", result.stream)
|
|
21
|
+
assert_equal(1, @dss[field].size)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "returns the same stream object for duplicate #{field[0..-2]} data" do
|
|
25
|
+
result1 = @dss.send(method, "der_data")
|
|
26
|
+
result2 = @dss.send(method, "der_data")
|
|
27
|
+
assert_same(result1, result2)
|
|
28
|
+
assert_equal(1, @dss[field].size)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "adds distinct stream objects for different #{field[0..-2]} data" do
|
|
32
|
+
@dss.send(method, "data_one")
|
|
33
|
+
@dss.send(method, "data_two")
|
|
34
|
+
assert_equal(2, @dss[field].size)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "add_vri" do
|
|
40
|
+
before do
|
|
41
|
+
@signature_contents = 'signature bytes'
|
|
42
|
+
@signature = @doc.add({Type: :Sig, Contents: @signature_contents})
|
|
43
|
+
@vri_key = OpenSSL::Digest::SHA1.hexdigest(@signature_contents).upcase.to_sym
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "returns the VRI entry" do
|
|
47
|
+
vri = @dss.add_vri(@signature)
|
|
48
|
+
assert_equal(:VRI, vri.type)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "creates the /VRI dictionary with an entry for the signature" do
|
|
52
|
+
vri = @dss.add_vri(@signature)
|
|
53
|
+
assert(@dss.key?(:VRI))
|
|
54
|
+
assert_same(vri, @dss[:VRI][@vri_key])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "populates /Cert in the VRI entry and the DSS /Certs array" do
|
|
58
|
+
@dss.add_vri(@signature, certs: ["cert1", "cert2"])
|
|
59
|
+
assert_equal(2, @dss[:VRI][@vri_key][:Cert].size)
|
|
60
|
+
assert_equal(2, @dss[:Certs].size)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "populates /OCSP in the VRI entry and the DSS /OCSPs array" do
|
|
64
|
+
@dss.add_vri(@signature, ocsps: ["ocsp1", "ocsp2"])
|
|
65
|
+
assert_equal(2, @dss[:VRI][@vri_key][:OCSP].size)
|
|
66
|
+
assert_equal(2, @dss[:OCSPs].size)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "populates /CRL in the VRI entry and the DSS /CRLs array" do
|
|
70
|
+
@dss.add_vri(@signature, crls: ["crl1"])
|
|
71
|
+
assert_equal(1, @dss[:VRI][@vri_key][:CRL].size)
|
|
72
|
+
assert_equal(1, @dss[:CRLs].size)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "de-duplicates DER streams shared across multiple VRI entries" do
|
|
76
|
+
@dss.add_vri(@signature, certs: ["shared_cert", "cert_a"])
|
|
77
|
+
@dss.add_vri(@doc.add({Type: :Sig, Contents: 'new'}), certs: ["shared_cert", "cert_b"])
|
|
78
|
+
# shared_cert added once despite appearing in both VRI entries
|
|
79
|
+
assert_equal(2, @dss[:VRI].value.size)
|
|
80
|
+
assert_equal(3, @dss[:Certs].size)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "creates a VRI entry with no optional arrays when all inputs are empty" do
|
|
84
|
+
@dss.add_vri(@signature)
|
|
85
|
+
vri = @dss[:VRI][@vri_key]
|
|
86
|
+
refute(vri.key?(:Cert))
|
|
87
|
+
refute(vri.key?(:OCSP))
|
|
88
|
+
refute(vri.key?(:CRL))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "vri_for" do
|
|
93
|
+
before do
|
|
94
|
+
@signature = @doc.add({Type: :Sig, Contents: 'signature bytes'})
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "returns nil if no /VRI entry exists" do
|
|
98
|
+
assert_nil(@dss.vri_for(@signature))
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "returns the VRI entry for the signature if it exists" do
|
|
102
|
+
@dss[:VRI] = {}
|
|
103
|
+
assert_nil(@dss.vri_for(@signature))
|
|
104
|
+
@dss.add_vri(@signature)
|
|
105
|
+
assert_equal(@dss[:VRI].value.first[1], @dss.vri_for(@signature))
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe "certificates" do
|
|
110
|
+
it "returns an empty array if no /Certs entry exists" do
|
|
111
|
+
assert_equal([], @dss.certificates)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "returns an array with certificate instances" do
|
|
115
|
+
cert = CERTIFICATES.signer_certificate
|
|
116
|
+
@dss[:Certs] = [@doc.add({}, stream: cert.to_der)]
|
|
117
|
+
assert_equal([cert], @dss.certificates)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
begin
|
|
4
4
|
require 'simplecov'
|
|
5
5
|
SimpleCov.start do
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
enable_coverage(:method)
|
|
7
|
+
unless ENV['NO_SIMPLECOV']
|
|
8
|
+
coverage(:line) { minimum 100 }
|
|
9
|
+
coverage(:method) { minimum 100 }
|
|
10
|
+
end
|
|
11
|
+
skip '/test/'
|
|
12
|
+
skip '/fast_arc4.rb'
|
|
9
13
|
end
|
|
10
14
|
rescue LoadError
|
|
11
15
|
end
|