Skip to content

Commit 8c8b349

Browse files
authored
Merge pull request #160 from delphaber/replace-external-test-dependencies
Replace external Wikipedia dependency in tests with local servers
2 parents 7b615ae + 59ad39b commit 8c8b349

4 files changed

Lines changed: 121 additions & 27 deletions

File tree

fastimage.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
2525
s.add_development_dependency('rake', ">= 10.5")
2626
s.add_development_dependency('rdoc')
2727
s.add_development_dependency('test-unit')
28+
s.add_development_dependency('webrick')
2829

2930
s.licenses = ['MIT']
3031
end

test/https_server.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
require 'webrick'
3+
require 'webrick/https'
4+
require 'openssl'
5+
6+
# A local HTTPS server with a self-signed certificate.
7+
# Used to verify that FastImage handles SSL connections.
8+
class HTTPSServer
9+
def initialize(replies)
10+
@replies = replies
11+
end
12+
13+
def open
14+
key = OpenSSL::PKey::RSA.new(2048)
15+
cert = OpenSSL::X509::Certificate.new
16+
cert.subject = cert.issuer = OpenSSL::X509::Name.parse("/CN=localhost")
17+
cert.not_before = Time.now
18+
cert.not_after = Time.now + 600
19+
cert.public_key = key.public_key
20+
cert.serial = 1
21+
cert.sign(key, OpenSSL::Digest::SHA256.new)
22+
23+
server = WEBrick::HTTPServer.new(
24+
Port: 0,
25+
SSLEnable: true,
26+
SSLCertificate: cert,
27+
SSLPrivateKey: key,
28+
Logger: WEBrick::Log.new("/dev/null"),
29+
AccessLog: []
30+
)
31+
32+
@replies.each do |path, (content_type, body)|
33+
server.mount_proc(path) do |_req, res|
34+
res['Content-Type'] = content_type
35+
res.body = body
36+
end
37+
end
38+
39+
thread = Thread.new { server.start }
40+
41+
begin
42+
yield server.config[:Port]
43+
ensure
44+
server.shutdown
45+
thread.join
46+
end
47+
end
48+
end

test/slow_server.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# frozen_string_literal: true
2+
require 'socket'
3+
4+
# A raw TCP server that sends an image immediately, then drip-feeds
5+
# padding bytes with long delays. Used to verify that FastImage reads
6+
# only the minimum bytes needed from the response.
7+
class SlowServer
8+
def initialize(image_path)
9+
@image_data = File.binread(image_path)
10+
end
11+
12+
def open
13+
tcp_server = TCPServer.new("127.0.0.1", 0)
14+
15+
thread = Thread.new do
16+
loop do
17+
client = tcp_server.accept rescue break
18+
Thread.new(client) do |c|
19+
begin
20+
c.gets("\r\n\r\n")
21+
total_size = @image_data.bytesize + 5_000_000
22+
c.write "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: #{total_size}\r\n\r\n"
23+
c.write @image_data
24+
100.times do
25+
sleep 0.5
26+
c.write("\x00" * 1024)
27+
end
28+
rescue
29+
ensure
30+
c.close
31+
end
32+
end
33+
end
34+
end
35+
36+
begin
37+
yield tcp_server.addr[1]
38+
ensure
39+
tcp_server.close
40+
thread.join(1)
41+
end
42+
end
43+
end

test/test.rb

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
require 'fastimage'
77
require 'fakeweb'
8+
require_relative 'slow_server'
9+
require_relative 'https_server'
810

911
FixturePath = File.join(PathHere, "fixtures")
1012

@@ -78,15 +80,6 @@
7880

7981
TestUrl = "http://example.nowhere/"
8082

81-
# this image fetch allows me to really test that fastimage is truly fast
82-
# but it's not ideal relying on external resources and connectivity speed
83-
LargeImage = "https://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg"
84-
LargeImageInfo = [:jpeg, [9545, 6623]]
85-
LargeImageFetchLimit = 2 # seconds
86-
87-
HTTPSImage = "https://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg"
88-
HTTPSImageInfo = [:jpeg, [9545, 6623]]
89-
9083
DataUriImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAAD0lEQVR42mNk+M9QzwAEAAmGAYCF+yOnAAAAAElFTkSuQmCC"
9184
DataUriImageInfo = [:png, [2, 1]]
9285
DataUriImageContentLength = 72
@@ -352,16 +345,19 @@ def register_redirect(from, to)
352345
end
353346

354347
def test_should_fetch_info_of_large_image_faster_than_downloading_the_whole_thing
355-
time = Time.now
356-
size = FastImage.size(LargeImage)
357-
size_time = Time.now
358-
assert size_time - time < LargeImageFetchLimit
359-
assert_equal LargeImageInfo[1], size
360-
time = Time.now
361-
type = FastImage.type(LargeImage)
362-
type_time = Time.now
363-
assert type_time - time < LargeImageFetchLimit
364-
assert_equal LargeImageInfo[0], type
348+
SlowServer.new(File.join(FixturePath, "test.jpg")).open do |port|
349+
url = "http://127.0.0.1:#{port}/large.jpg"
350+
351+
time = Time.now
352+
size = FastImage.size(url)
353+
assert Time.now - time < 2, "FastImage.size took too long, likely reading the entire body"
354+
assert_equal GoodFixtures["test.jpg"][1], size
355+
356+
time = Time.now
357+
type = FastImage.type(url)
358+
assert Time.now - time < 2, "FastImage.type took too long, likely reading the entire body"
359+
assert_equal GoodFixtures["test.jpg"][0], type
360+
end
365361
end
366362

367363
# This test doesn't actually test the proxy function, but at least
@@ -384,8 +380,14 @@ def test_should_fetch_via_proxy_option
384380
end
385381

386382
def test_should_handle_https_image
387-
size = FastImage.size(HTTPSImage)
388-
assert_equal HTTPSImageInfo[1], size
383+
replies = {
384+
"/test.jpg" => ["image/jpeg", File.binread(File.join(FixturePath, "test.jpg"))]
385+
}
386+
387+
HTTPSServer.new(replies).open do |port|
388+
size = FastImage.size("https://localhost:#{port}/test.jpg")
389+
assert_equal GoodFixtures["test.jpg"][1], size
390+
end
389391
end
390392

391393
require 'pathname'
@@ -446,7 +448,7 @@ def test_content_length
446448
FakeWeb.register_uri(:get, url, :body => File.join(FixturePath, "test.jpg"), :content_length => 52)
447449

448450
assert_equal 52, FastImage.new(url).content_length
449-
451+
450452
assert_equal 322, FastImage.new(File.join(FixturePath, "test.png")).content_length
451453
assert_equal 322, FastImage.new(Pathname.new(File.join(FixturePath, "test.png"))).content_length
452454

@@ -510,17 +512,17 @@ def test_canon_raw_formats_are_not_recognised_as_tiff
510512
FastImage.size(TestUrl + "a.CRW", :raise_on_failure=>true)
511513
end
512514
end
513-
515+
514516
def test_returns_nil_when_uri_is_nil
515517
assert_equal nil, FastImage.size(nil)
516518
end
517-
519+
518520
def test_raises_when_uri_is_nil_and_raise_on_failure_is_set
519521
assert_raises(FastImage::BadImageURI) do
520522
FastImage.size(nil, :raise_on_failure => true)
521523
end
522524
end
523-
525+
524526
def test_width
525527
assert_equal 30, FastImage.new(TestUrl + "test.png").width
526528
assert_equal nil, FastImage.new(TestUrl + "does_not_exist").width
@@ -530,13 +532,13 @@ def test_height
530532
assert_equal 20, FastImage.new(TestUrl + "test.png").height
531533
assert_equal nil, FastImage.new(TestUrl + "does_not_exist").height
532534
end
533-
535+
534536
def test_content_length_after_size
535537
fi = FastImage.new(File.join(FixturePath, "test.png"))
536538
fi.size
537539
assert_equal 322, fi.content_length
538540
end
539-
541+
540542
def test_unknown_protocol
541543
FakeWeb.register_uri(:get, "http://example.com/test", body: "", location: "hhttp://example.com", :status => 301)
542544
assert_nil FastImage.size("http://example.com/test")

0 commit comments

Comments
 (0)