|
| 1 | +# Due to the way that specs are handled this file cannot be run |
| 2 | +# together with everything else without causing a compile time error |
| 3 | +# |
| 4 | +# TODO: Allow running different isolated spec through make |
| 5 | +# |
| 6 | +# For now run this with `crystal spec -p spec/helpers/networking/connection_pool_spec.cr -Drunning_by_self` |
| 7 | +{% skip_file unless flag?(:running_by_self) %} |
| 8 | + |
| 9 | +# Based on https://github.com/jgaskins/http_client/blob/958cf56064c0d31264a117467022b90397eb65d7/spec/http_client_spec.cr |
| 10 | +require "wait_group" |
| 11 | +require "uri" |
| 12 | +require "http" |
| 13 | +require "http/server" |
| 14 | +require "http_proxy" |
| 15 | + |
| 16 | +require "db" |
| 17 | +require "pg" |
| 18 | +require "spectator" |
| 19 | + |
| 20 | +require "../../load_config" |
| 21 | +require "../../../src/invidious/helpers/crystal_class_overrides" |
| 22 | +require "../../../src/invidious/connection/*" |
| 23 | + |
| 24 | +server = HTTP::Server.new do |context| |
| 25 | + request = context.request |
| 26 | + response = context.response |
| 27 | + |
| 28 | + case {request.method, request.path} |
| 29 | + when {"GET", "/get"} |
| 30 | + response << "get" |
| 31 | + when {"POST", "/post"} |
| 32 | + response.status = :created |
| 33 | + response << "post" |
| 34 | + when {"GET", "/sleep"} |
| 35 | + duration = request.query_params["duration_sec"].to_i.seconds |
| 36 | + sleep duration |
| 37 | + end |
| 38 | +end |
| 39 | + |
| 40 | +spawn server.listen 12345 |
| 41 | + |
| 42 | +Fiber.yield |
| 43 | + |
| 44 | +Spectator.describe Invidious::ConnectionPool do |
| 45 | + describe "Pool" do |
| 46 | + it "Can make a requests through standard HTTP methods" do |
| 47 | + pool = Invidious::ConnectionPool::Pool.new(URI.parse("http://localhost:12345"), max_capacity: 100) |
| 48 | + |
| 49 | + expect(pool.get("/get").body).to eq("get") |
| 50 | + expect(pool.post("/post").body).to eq("post") |
| 51 | + end |
| 52 | + |
| 53 | + it "Can make streaming requests" do |
| 54 | + pool = Invidious::ConnectionPool::Pool.new(URI.parse("http://localhost:12345"), max_capacity: 100) |
| 55 | + |
| 56 | + expect(pool.get("/get") { |r| r.body_io.gets_to_end }).to eq("get") |
| 57 | + expect(pool.get("/post") { |r| r.body }).to eq("") |
| 58 | + expect(pool.post("/post") { |r| r.body_io.gets_to_end }).to eq("post") |
| 59 | + end |
| 60 | + |
| 61 | + # it "Can checkout a client" do |
| 62 | + # end |
| 63 | + |
| 64 | + it "Allows concurrent requests" do |
| 65 | + pool = Invidious::ConnectionPool::Pool.new(URI.parse("http://localhost:12345"), max_capacity: 100) |
| 66 | + responses = [] of HTTP::Client::Response |
| 67 | + |
| 68 | + WaitGroup.wait do |wg| |
| 69 | + 100.times do |
| 70 | + wg.spawn { responses << pool.get("/get") } |
| 71 | + end |
| 72 | + end |
| 73 | + |
| 74 | + expect(responses.map(&.body)).to eq(["get"] * 100) |
| 75 | + end |
| 76 | + |
| 77 | + it "Raises on checkout timeout" do |
| 78 | + pool = Invidious::ConnectionPool::Pool.new(URI.parse("http://localhost:12345"), max_capacity: 2, timeout: 0.01) |
| 79 | + |
| 80 | + # Long running requests |
| 81 | + 2.times do |
| 82 | + spawn { pool.get("/sleep?duration_sec=2") } |
| 83 | + end |
| 84 | + |
| 85 | + Fiber.yield |
| 86 | + |
| 87 | + expect { pool.get("/get") }.to raise_error(Invidious::ConnectionPool::Error) |
| 88 | + end |
| 89 | + |
| 90 | + it "Raises when an error is encounter" do |
| 91 | + pool = Invidious::ConnectionPool::Pool.new(URI.parse("http://localhost:12345"), max_capacity: 100, timeout: 0.01) |
| 92 | + expect { pool.get("/get") { raise IO::Error.new } }.to raise_error(Invidious::ConnectionPool::Error) |
| 93 | + end |
| 94 | + end |
| 95 | +end |
0 commit comments