Skip to content

Commit

Permalink
tests for base64 encoding and line-ending canonicalization
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Dean committed Feb 14, 2024
1 parent d1cb2ec commit 3291210
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 10 deletions.
10 changes: 6 additions & 4 deletions lib/as2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def self.generate_message_id(server_info)

def self.valid_base64_schemes
[
'rfc2045', # https://www.rfc-editor.org/rfc/rfc2045#section-6.8
'rfc4648' # https://www.rfc-editor.org/rfc/rfc4648#section-4
'rfc2045',
'rfc4648'
]
end

Expand All @@ -36,17 +36,19 @@ def self.valid_base64_schemes
# @param [String] scheme one of As2.valid_base64_schemes
# @return [String]
def self.base64_encode(content, scheme: 'rfc4648')
case scheme
case scheme.to_s
when 'rfc2045'
# "This method complies with RFC 2045."
# https://ruby-doc.org/stdlib-3.0.4/libdoc/base64/rdoc/Base64.html#method-i-encode64
# https://www.rfc-editor.org/rfc/rfc2045#section-6.8
then Base64.encode64(content)
when 'rfc4648'
# "This method complies with RFC 4648."
# https://ruby-doc.org/stdlib-3.0.4/libdoc/base64/rdoc/Base64.html#method-i-strict_encode64
# https://www.rfc-editor.org/rfc/rfc4648#section-4
then Base64.strict_encode64(content)
else
raise "unsupported base64_scheme '#{@partner.base64_scheme}'"
raise ArgumentError, "unsupported scheme '#{scheme}'. choose one of: #{valid_base64_schemes}"
end
end

Expand Down
101 changes: 95 additions & 6 deletions test/as2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,104 @@
end

describe '.base64_encode' do
it 'can encode according to RFC-2045'
it 'can encode according to RFC-4648'
it 'raises if the given encoding scheme is not recognized'
it 'defaults to RFC-4648 for backwards-compatibility'
before(:all) do
@ascii = (32..126).map(&:chr).join.freeze
@binary = File.open('test/fixtures/white-box.png', 'rb').read.freeze
@utf8 = "こんにちは".freeze
end

describe 'with rfc2045 rules' do
it 'can encode all printable ascii characters' do
encoded = As2.base64_encode(@ascii, scheme: 'rfc2045')
decoded = Base64.decode64(encoded)
assert_equal @ascii, decoded
end

it 'can encode arbitrary binary data' do
encoded = As2.base64_encode(@binary, scheme: 'rfc2045')
decoded = Base64.decode64(encoded)
assert_equal @binary, decoded
end

it 'can encode UTF-8' do
encoded = As2.base64_encode(@utf8, scheme: 'rfc2045')
decoded = Base64.decode64(encoded)
decoded.force_encoding('UTF-8')
assert_equal @utf8, decoded
end
end

describe 'with rfc4648 rules' do
it 'can encode all printable ascii characters' do
encoded = As2.base64_encode(@ascii, scheme: 'rfc4648')
decoded = Base64.strict_decode64(encoded)
assert_equal @ascii, decoded
end

it 'can encode arbitrary binary data' do
encoded = As2.base64_encode(@binary, scheme: 'rfc4648')
decoded = Base64.strict_decode64(encoded)
assert_equal @binary, decoded
end

it 'can encode UTF-8' do
encoded = As2.base64_encode(@utf8, scheme: 'rfc4648')
decoded = Base64.decode64(encoded)
decoded.force_encoding('UTF-8')
assert_equal @utf8, decoded
end
end

it 'raises if the given encoding scheme is not recognized' do
error = assert_raises(ArgumentError) do
As2.base64_encode(@binary, scheme: 'blah')
end
assert_equal "unsupported scheme 'blah'. choose one of: [\"rfc2045\", \"rfc4648\"]", error.message
end

it 'defaults to RFC-4648 for backwards-compatibility' do
expected = As2.base64_encode(@ascii, scheme: 'rfc4648')
assert_equal expected, As2.base64_encode(@ascii)
end
end

describe '.canonicalize_line_endings' do
it 'replaces \n with \r\n'
it 'does not alter existing \r\n sequences'
it 'replaces \n with \r\n' do
input = "a\nb\nc\n"
expected = "a\r\nb\r\nc\r\n"
assert_equal expected, As2.canonicalize_line_endings(input)
end

it 'does not alter existing \r\n sequences' do
input = "a\r\nb\nc\n"
expected = "a\r\nb\r\nc\r\n"
assert_equal expected, As2.canonicalize_line_endings(input)
end

it 'does not add trailing newlines if string does not end with a newline' do
input = "a"
expected = "a"
assert_equal expected, As2.canonicalize_line_endings(input)
end

it 'is compatible with all base64_encode schemes' do
ascii = (32..126).map(&:chr).join.freeze
input = ascii * 10 # long enough to be split onto multiple lines in rfc2045

# if a new scheme is added, this assertion will remind us to test it here also.
valid_schemes = As2.valid_base64_schemes
assert_equal(['rfc2045', 'rfc4648'], valid_schemes)

encoded = As2.base64_encode(input, scheme: 'rfc2045')
canonicalized = As2.canonicalize_line_endings(encoded)
decoded = Base64.decode64(encoded)
assert_equal input, decoded

encoded = As2.base64_encode(input, scheme: 'rfc4648')
canonicalized = As2.canonicalize_line_endings(encoded)
decoded = Base64.strict_decode64(encoded)
assert_equal input, decoded
end
end

describe '.choose_mic_algorithm' do
Expand Down
Binary file added test/fixtures/white-box.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3291210

Please sign in to comment.