rs
  1# frozen_string_literal: true
  2
  3require 'test_helper'
  4
  5class TimeoutTest < Minitest::Test
  6  def setup
  7    @uri = URI.parse('https://example.com/test')
  8  end
  9
 10  def test_custom_read_timeout
 11    client = Net::Hippie::Client.new(read_timeout: 5)
 12    connection = client.send(:connection_for, @uri)
 13    backend = connection.instance_variable_get(:@backend)
 14    http = backend.instance_variable_get(:@http)
 15    assert_equal 5, http.read_timeout
 16  end
 17
 18  def test_custom_open_timeout
 19    client = Net::Hippie::Client.new(open_timeout: 8)
 20    connection = client.send(:connection_for, @uri)
 21    backend = connection.instance_variable_get(:@backend)
 22    http = backend.instance_variable_get(:@http)
 23    assert_equal 8, http.open_timeout
 24  end
 25
 26  def test_default_timeouts
 27    client = Net::Hippie::Client.new
 28    connection = client.send(:connection_for, @uri)
 29    backend = connection.instance_variable_get(:@backend)
 30    http = backend.instance_variable_get(:@http)
 31    assert_equal 10, http.read_timeout
 32    assert_equal 10, http.open_timeout
 33  end
 34
 35  def test_read_timeout_triggers_retry
 36    WebMock.stub_request(:get, @uri.to_s)
 37           .to_timeout.then
 38           .to_return(status: 200, body: 'success')
 39
 40    client = Net::Hippie::Client.new
 41    response = client.with_retry(retries: 1) { |c| c.get(@uri) }
 42    
 43    assert_equal Net::HTTPOK, response.class
 44    assert_equal 'success', response.body
 45  end
 46
 47  def test_open_timeout_triggers_retry
 48    WebMock.stub_request(:get, @uri.to_s)
 49           .to_raise(Net::OpenTimeout).then
 50           .to_return(status: 200, body: 'success')
 51
 52    client = Net::Hippie::Client.new
 53    response = client.with_retry(retries: 1) { |c| c.get(@uri) }
 54    
 55    assert_equal Net::HTTPOK, response.class
 56    assert_equal 'success', response.body
 57  end
 58
 59  def test_timeout_with_zero_retries
 60    WebMock.stub_request(:get, @uri.to_s).to_timeout
 61
 62    client = Net::Hippie::Client.new
 63    # WebMock.to_timeout raises different timeout errors, so check for any timeout error
 64    assert_raises(*Net::Hippie::CONNECTION_ERRORS.select { |e| e.name.include?('Timeout') }) do
 65      client.with_retry(retries: 0) { |c| c.get(@uri) }
 66    end
 67  end
 68
 69  def test_multiple_timeout_types_in_sequence
 70    call_count = 0
 71    WebMock.stub_request(:get, @uri.to_s).to_return do
 72      call_count += 1
 73      case call_count
 74      when 1
 75        raise Net::OpenTimeout
 76      when 2
 77        raise Net::ReadTimeout
 78      when 3
 79        raise Timeout::Error
 80      else
 81        { status: 200, body: 'success' }
 82      end
 83    end
 84
 85    client = Net::Hippie::Client.new
 86    response = client.with_retry(retries: 4) { |c| c.get(@uri) }
 87    
 88    assert_equal Net::HTTPOK, response.class
 89    assert_equal 'success', response.body
 90    assert_equal 4, call_count
 91  end
 92
 93  def test_timeout_settings_per_connection
 94    uri1 = URI.parse('https://example1.com/test')
 95    uri2 = URI.parse('https://example2.com/test')
 96
 97    client = Net::Hippie::Client.new(read_timeout: 15, open_timeout: 20)
 98    
 99    connection1 = client.send(:connection_for, uri1)
100    connection2 = client.send(:connection_for, uri2)
101    
102    backend1 = connection1.instance_variable_get(:@backend)
103    backend2 = connection2.instance_variable_get(:@backend)
104    http1 = backend1.instance_variable_get(:@http)
105    http2 = backend2.instance_variable_get(:@http)
106    
107    assert_equal 15, http1.read_timeout
108    assert_equal 20, http1.open_timeout
109    assert_equal 15, http2.read_timeout
110    assert_equal 20, http2.open_timeout
111  end
112
113  def test_timeout_preserves_connection_pooling
114    client = Net::Hippie::Client.new(read_timeout: 25)
115    
116    # First call should create connection
117    connection1 = client.send(:connection_for, @uri)
118    # Second call should reuse same connection
119    connection2 = client.send(:connection_for, @uri)
120    
121    assert_same connection1, connection2
122    
123    backend = connection1.instance_variable_get(:@backend)
124    http = backend.instance_variable_get(:@http)
125    assert_equal 25, http.read_timeout
126  end
127end