Skip to content

Commit

Permalink
Don't use #write_byte whenever writing ASCII characters to unknown …
Browse files Browse the repository at this point in the history
…`IO`s (#11124)

Co-authored-by: Johannes Müller <straightshoota@gmail.com>
  • Loading branch information
HertzDevil and straight-shoota authored Sep 24, 2021
1 parent 9e9da00 commit 592470a
Show file tree
Hide file tree
Showing 13 changed files with 283 additions and 306 deletions.
50 changes: 26 additions & 24 deletions spec/std/base64_spec.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
require "spec"
require "base64"
require "crystal/digest/md5"
require "../support/string"

# rearrange parameters for `assert_prints`
{% for method in %w(encode strict_encode urlsafe_encode) %}
private def base64_{{ method.id }}(io : IO, data, *args)
Base64.{{ method.id }}(data, io, *args)
end

private def base64_{{ method.id }}(data, *args)
Base64.{{ method.id }}(data, *args)
end
{% end %}

describe "Base64" do
context "simple test" do
Expand All @@ -9,7 +21,7 @@ describe "Base64" do
"abcdefg" => "YWJjZGVmZw==\n"}
eqs.each do |a, b|
it "encode #{a.inspect} to #{b.inspect}" do
Base64.encode(a).should eq(b)
assert_prints base64_encode(a), b
end
it "decode from #{b.inspect} to #{a.inspect}" do
Base64.decode(b).should eq(a.to_slice)
Expand All @@ -32,15 +44,15 @@ describe "Base64" do

it "encodes byte slice" do
slice = Bytes.new(5) { 1_u8 }
Base64.encode(slice).should eq("AQEBAQE=\n")
Base64.strict_encode(slice).should eq("AQEBAQE=")
assert_prints base64_encode(slice), "AQEBAQE=\n"
assert_prints base64_strict_encode(slice), "AQEBAQE="
end

it "encodes static array" do
array = uninitialized StaticArray(UInt8, 5)
(0...5).each { |i| array[i] = 1_u8 }
Base64.encode(array).should eq("AQEBAQE=\n")
Base64.strict_encode(array).should eq("AQEBAQE=")
assert_prints base64_encode(array), "AQEBAQE=\n"
assert_prints base64_strict_encode(array), "AQEBAQE="
end

describe "base" do
Expand All @@ -50,7 +62,7 @@ describe "Base64" do
"hahah⊙ⓧ⊙" => "aGFoYWjiipnik6fiipk=\n"}
eqs.each do |a, b|
it "encode #{a.inspect} to #{b.inspect}" do
Base64.encode(a).should eq(b)
assert_prints base64_encode(a), b
end
it "decode from #{b.inspect} to #{a.inspect}" do
Base64.decode(b).should eq(a.to_slice)
Expand All @@ -63,20 +75,16 @@ describe "Base64" do
"Now is the time for all good coders\nto learn Crystal")
end

it "encode to stream" do
it "encode to stream returns number of written characters" do
io = IO::Memory.new
count = Base64.encode("Now is the time for all good coders\nto learn Crystal", io)
count.should eq 74
io.rewind
io.gets_to_end.should eq "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nQ3J5c3RhbA==\n"
end

it "decode from stream" do
it "decode from stream returns number of written bytes" do
io = IO::Memory.new
count = Base64.decode("Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gQ3J5c3RhbA==", io)
count.should eq 52
io.rewind
io.gets_to_end.should eq "Now is the time for all good coders\nto learn Crystal"
end

it "big message" do
Expand Down Expand Up @@ -151,39 +159,33 @@ describe "Base64" do

describe "scrict" do
it "encode" do
Base64.strict_encode("Now is the time for all good coders\nto learn Crystal").should eq(
"Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gQ3J5c3RhbA==")
assert_prints base64_strict_encode("Now is the time for all good coders\nto learn Crystal"),
"Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gQ3J5c3RhbA=="
end
it "with spec symbols" do
s = String.build { |b| (160..179).each { |i| b << i.chr } }
se = "wqDCocKiwqPCpMKlwqbCp8KowqnCqsKrwqzCrcKuwq/CsMKxwrLCsw=="
Base64.strict_encode(s).should eq(se)
assert_prints base64_strict_encode(s), se
end

it "encode to stream" do
it "encode to stream returns number of written characters" do
s = String.build { |b| (160..179).each { |i| b << i.chr } }
se = "wqDCocKiwqPCpMKlwqbCp8KowqnCqsKrwqzCrcKuwq/CsMKxwrLCsw=="
io = IO::Memory.new
Base64.strict_encode(s, io).should eq(56)
io.rewind
io.gets_to_end.should eq se
end
end

describe "urlsafe" do
it "work" do
s = String.build { |b| (160..179).each { |i| b << i.chr } }
se = "wqDCocKiwqPCpMKlwqbCp8KowqnCqsKrwqzCrcKuwq_CsMKxwrLCsw=="
Base64.urlsafe_encode(s).should eq(se)
assert_prints base64_urlsafe_encode(s), se
end

it "encode to stream" do
it "encode to stream returns number of written characters" do
s = String.build { |b| (160..179).each { |i| b << i.chr } }
se = "wqDCocKiwqPCpMKlwqbCp8KowqnCqsKrwqzCrcKuwq_CsMKxwrLCsw=="
io = IO::Memory.new
Base64.urlsafe_encode(s, io).should eq(56)
io.rewind
io.gets_to_end.should eq se
end
end
end
91 changes: 37 additions & 54 deletions spec/std/csv/csv_build_spec.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
require "spec"
require "csv"
require "../../support/string"

describe CSV do
describe "build" do
it "builds two rows" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << "one"
row << "two"
Expand All @@ -13,12 +14,11 @@ describe CSV do
row << "three"
row << "four"
end
end
string.should eq("one,two\nthree,four\n")
end, "one,two\nthree,four\n")
end

it "builds with numbers" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << 1
row << 2
Expand All @@ -27,137 +27,120 @@ describe CSV do
row << 3
row << 4
end
end
string.should eq("1,2\n3,4\n")
end, "1,2\n3,4\n")
end

it "builds with commas" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << %(hello,world)
end
end
string.should eq(%("hello,world"\n))
end, %("hello,world"\n))
end

it "builds with custom separator" do
string = CSV.build(separator: ';') do |csv|
assert_prints(CSV.build(separator: ';') do |csv|
csv.row do |row|
row << "one"
row << "two"
row << "thr;ee"
end
end
string.should eq(%(one;two;"thr;ee"\n))
end, %(one;two;"thr;ee"\n))
end

it "builds with quotes" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << %(he said "no")
end
end
string.should eq(%("he said ""no"""\n))
end, %("he said ""no"""\n))
end

it "builds with custom quote character" do
string = CSV.build(quote_char: '\'') do |csv|
assert_prints(CSV.build(quote_char: '\'') do |csv|
csv.row do |row|
row << %(he said 'no')
end
end
string.should eq(%('he said ''no'''\n))
end, %('he said ''no'''\n))
end

it "builds row from enumerable" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row [1, 2, 3]
end
string.should eq("1,2,3\n")
end, "1,2,3\n")
end

it "builds row from splat" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row 1, 2, 3
end
string.should eq("1,2,3\n")
end, "1,2,3\n")
end

it "skips inside row" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << 1
row.skip_cell
row << 2
end
end
string.should eq("1,,2\n")
end, "1,,2\n")
end

it "concats enumerable to row" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << 1
row.concat [2, 3, 4]
row << 5
end
end
string.should eq("1,2,3,4,5\n")
end, "1,2,3,4,5\n")
end

it "concats splat to row" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << 1
row.concat 2, 3, 4
row << 5
end
end
string.should eq("1,2,3,4,5\n")
end, "1,2,3,4,5\n")
end

it "builds with commas" do
string = CSV.build do |csv|
assert_prints(CSV.build do |csv|
csv.row do |row|
row << " , "
row << " , "
end
end
string.should eq(%(" , "," , "\n))
end, %(" , "," , "\n))
end

it "builds with quoting" do
string = CSV.build(quoting: CSV::Builder::Quoting::NONE) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::NONE) do |csv|
csv.row 1, "doesn't", " , ", %(he said "no")
end
string.should eq(%(1,doesn't, , ,he said "no"\n))
end, %(1,doesn't, , ,he said "no"\n))

string = CSV.build(quoting: CSV::Builder::Quoting::RFC) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::RFC) do |csv|
csv.row 1, "doesn't", " , ", %(he said "no")
end
string.should eq(%(1,doesn't," , ","he said ""no"""\n))
end, %(1,doesn't," , ","he said ""no"""\n))

string = CSV.build(quoting: CSV::Builder::Quoting::ALL) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::ALL) do |csv|
csv.row 1, "doesn't", " , ", %(he said "no")
end
string.should eq(%("1","doesn't"," , ","he said ""no"""\n))
end, %("1","doesn't"," , ","he said ""no"""\n))
end

it "builds with inside quoted chars and symbols" do
string = CSV.build(quoting: CSV::Builder::Quoting::NONE) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::NONE) do |csv|
csv.row 'c', '\'', '"', :sym, :"s'm", :"s\"m"
end
string.should eq(%(c,',",sym,s'm,s"m\n))
end, %(c,',",sym,s'm,s"m\n))

string = CSV.build(quoting: CSV::Builder::Quoting::RFC) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::RFC) do |csv|
csv.row 'c', '\'', '"', :sym, :"s'm", :"s\"m"
end
string.should eq(%(c,',"""",sym,s'm,"s""m"\n))
end, %(c,',"""",sym,s'm,"s""m"\n))

string = CSV.build(quoting: CSV::Builder::Quoting::ALL) do |csv|
assert_prints(CSV.build(quoting: CSV::Builder::Quoting::ALL) do |csv|
csv.row 'c', '\'', '"', :sym, :"s'm", :"s\"m"
end
string.should eq(%("c","'","""","sym","s'm","s""m"\n))
end, %("c","'","""","sym","s'm","s""m"\n))
end
end
end
17 changes: 13 additions & 4 deletions spec/std/http/http_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
require "spec"
require "http"
require "../../support/string"

private def http_quote_string(io : IO, string)
HTTP.quote_string(string, io)
end

private def http_quote_string(string)
HTTP.quote_string(string)
end

describe HTTP do
it "parses RFC 1123" do
Expand Down Expand Up @@ -57,10 +66,10 @@ describe HTTP do

describe ".quote_string" do
it "quotes a string" do
HTTP.quote_string("foo!#():;?~").should eq("foo!#():;?~")
HTTP.quote_string(%q(foo"bar\baz)).should eq(%q(foo\"bar\\baz))
HTTP.quote_string("\t ").should eq("\\\t\\ ")
HTTP.quote_string("it works 😂😂😂👌👌👌😂😂😂").should eq("it\\ works\\ 😂😂😂👌👌👌😂😂😂")
assert_prints http_quote_string("foo!#():;?~"), "foo!#():;?~"
assert_prints http_quote_string(%q(foo"bar\baz)), %q(foo\"bar\\baz)
assert_prints http_quote_string("\t "), "\\\t\\ "
assert_prints http_quote_string("it works 😂😂😂👌👌👌😂😂😂"), "it\\ works\\ 😂😂😂👌👌👌😂😂😂"
end

it "raises on invalid characters" do
Expand Down
3 changes: 2 additions & 1 deletion spec/std/mime/media_type_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "../spec_helper"
require "mime/media_type"
require "../../support/string"

private def parse(string)
type = MIME::MediaType.parse(string)
Expand All @@ -8,7 +9,7 @@ private def parse(string)
end

private def assert_format(string, format = string, file = __FILE__, line = __LINE__)
MIME::MediaType.parse(string).to_s.should eq(format), file: file, line: line
assert_prints MIME::MediaType.parse(string).to_s, format, file: file, line: line
end

describe MIME::MediaType do
Expand Down
Loading

0 comments on commit 592470a

Please sign in to comment.