rs
  1# frozen_string_literal: true
  2
  3require 'test_helper'
  4
  5class ErrorHandlingTest < Minitest::Test
  6  def setup
  7    @client = Net::Hippie::Client.new
  8    @uri = URI.parse('https://example.com/test')
  9  end
 10
 11  def test_handles_eof_error
 12    WebMock.stub_request(:get, @uri.to_s).to_raise(EOFError)
 13    
 14    assert_raises EOFError do
 15      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 16    end
 17  end
 18
 19  def test_handles_connection_refused
 20    WebMock.stub_request(:get, @uri.to_s).to_raise(Errno::ECONNREFUSED)
 21    
 22    assert_raises Errno::ECONNREFUSED do
 23      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 24    end
 25  end
 26
 27  def test_handles_connection_reset
 28    WebMock.stub_request(:get, @uri.to_s).to_raise(Errno::ECONNRESET)
 29    
 30    assert_raises Errno::ECONNRESET do
 31      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 32    end
 33  end
 34
 35  def test_handles_host_unreachable
 36    WebMock.stub_request(:get, @uri.to_s).to_raise(Errno::EHOSTUNREACH)
 37    
 38    assert_raises Errno::EHOSTUNREACH do
 39      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 40    end
 41  end
 42
 43  def test_handles_invalid_argument
 44    WebMock.stub_request(:get, @uri.to_s).to_raise(Errno::EINVAL)
 45    
 46    assert_raises Errno::EINVAL do
 47      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 48    end
 49  end
 50
 51  def test_handles_net_open_timeout
 52    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::OpenTimeout)
 53    
 54    assert_raises Net::OpenTimeout do
 55      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 56    end
 57  end
 58
 59  def test_handles_net_protocol_error
 60    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::ProtocolError)
 61    
 62    assert_raises Net::ProtocolError do
 63      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 64    end
 65  end
 66
 67  def test_handles_net_read_timeout
 68    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::ReadTimeout)
 69    
 70    assert_raises Net::ReadTimeout do
 71      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 72    end
 73  end
 74
 75  def test_handles_openssl_error
 76    WebMock.stub_request(:get, @uri.to_s).to_raise(OpenSSL::OpenSSLError)
 77    
 78    assert_raises OpenSSL::OpenSSLError do
 79      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 80    end
 81  end
 82
 83  def test_handles_ssl_error
 84    WebMock.stub_request(:get, @uri.to_s).to_raise(OpenSSL::SSL::SSLError)
 85    
 86    assert_raises OpenSSL::SSL::SSLError do
 87      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 88    end
 89  end
 90
 91  def test_handles_socket_error
 92    WebMock.stub_request(:get, @uri.to_s).to_raise(SocketError)
 93    
 94    assert_raises SocketError do
 95      @client.with_retry(retries: 0) { |client| client.get(@uri) }
 96    end
 97  end
 98
 99  def test_handles_timeout_error
100    WebMock.stub_request(:get, @uri.to_s).to_raise(Timeout::Error)
101    
102    assert_raises Timeout::Error do
103      @client.with_retry(retries: 0) { |client| client.get(@uri) }
104    end
105  end
106
107  def test_retry_with_exponential_backoff
108    call_count = 0
109    WebMock.stub_request(:get, @uri.to_s).to_return do
110      call_count += 1
111      if call_count < 3
112        raise Net::ReadTimeout
113      else
114        { status: 200, body: 'success' }
115      end
116    end
117
118    start_time = Time.now
119    response = @client.with_retry(retries: 3) { |client| client.get(@uri) }
120    end_time = Time.now
121
122    assert_equal Net::HTTPOK, response.class
123    assert_equal 'success', response.body
124    assert_equal 3, call_count
125    # Should have some delay due to exponential backoff
126    assert_operator end_time - start_time, :>, 0.3
127  end
128
129  def test_retry_eventually_fails_after_max_retries
130    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::ReadTimeout)
131    
132    start_time = Time.now
133    
134    assert_raises Net::ReadTimeout do
135      @client.with_retry(retries: 2) { |client| client.get(@uri) }
136    end
137    
138    end_time = Time.now
139    # Should have attempted 3 times (initial + 2 retries) with delays
140    assert_operator end_time - start_time, :>, 0.3
141  end
142
143  def test_retry_with_nil_retries
144    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::ReadTimeout)
145    
146    assert_raises Net::ReadTimeout do
147      @client.with_retry(retries: nil) { |client| client.get(@uri) }
148    end
149  end
150
151  def test_retry_with_negative_retries
152    WebMock.stub_request(:get, @uri.to_s).to_raise(Net::ReadTimeout)
153    
154    assert_raises Net::ReadTimeout do
155      @client.with_retry(retries: -1) { |client| client.get(@uri) }
156    end
157  end
158
159  def test_connection_errors_constant_includes_all_expected_errors
160    expected_errors = [
161      EOFError,
162      Errno::ECONNREFUSED,
163      Errno::ECONNRESET,
164      Errno::ECONNRESET,  # Listed twice in original
165      Errno::EHOSTUNREACH,
166      Errno::EINVAL,
167      Net::OpenTimeout,
168      Net::ProtocolError,
169      Net::ReadTimeout,
170      OpenSSL::OpenSSLError,
171      OpenSSL::SSL::SSLError,
172      SocketError,
173      Timeout::Error
174    ]
175    
176    expected_errors.each do |error_class|
177      assert_includes Net::Hippie::CONNECTION_ERRORS, error_class
178    end
179  end
180end