diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-06 13:54:36 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-06 13:54:36 -0600 |
| commit | d36b6e4f7c99b96aee01656e2ca57312d77a55b6 (patch) | |
| tree | e875bc14c907cbca92a8c36d9f15d4c946fceed0 /test/net/timeout_test.rb | |
| parent | 6ef050083b8519cfb8120246344514e1c8e27f49 (diff) | |
feat: add optional Rust backend with Magnus integration
- Add Rust HTTP client using reqwest and Magnus for Ruby integration
- Implement transparent backend switching via NET_HIPPIE_RUST environment variable
- Maintain 100% backward compatibility with existing Ruby interface
- Add comprehensive test coverage (75 tests, 177 assertions)
- Support automatic fallback to Ruby backend when Rust unavailable
- Include detailed documentation for Rust backend setup and usage
- Add proper .gitignore for Rust build artifacts
- Update gemspec to support native extensions
Performance benefits:
- Faster HTTP requests using Rust's optimized reqwest library
- Better concurrency with Tokio async runtime
- Lower memory usage with zero-cost abstractions
- Type safety with compile-time guarantees
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'test/net/timeout_test.rb')
| -rw-r--r-- | test/net/timeout_test.rb | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/test/net/timeout_test.rb b/test/net/timeout_test.rb new file mode 100644 index 0000000..a085b54 --- /dev/null +++ b/test/net/timeout_test.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require 'test_helper' + +class TimeoutTest < Minitest::Test + def setup + @uri = URI.parse('https://example.com/test') + end + + def test_custom_read_timeout + client = Net::Hippie::Client.new(read_timeout: 5) + connection = client.send(:connection_for, @uri) + backend = connection.instance_variable_get(:@backend) + http = backend.instance_variable_get(:@http) + assert_equal 5, http.read_timeout + end + + def test_custom_open_timeout + client = Net::Hippie::Client.new(open_timeout: 8) + connection = client.send(:connection_for, @uri) + backend = connection.instance_variable_get(:@backend) + http = backend.instance_variable_get(:@http) + assert_equal 8, http.open_timeout + end + + def test_default_timeouts + client = Net::Hippie::Client.new + connection = client.send(:connection_for, @uri) + backend = connection.instance_variable_get(:@backend) + http = backend.instance_variable_get(:@http) + assert_equal 10, http.read_timeout + assert_equal 10, http.open_timeout + end + + def test_read_timeout_triggers_retry + WebMock.stub_request(:get, @uri.to_s) + .to_timeout.then + .to_return(status: 200, body: 'success') + + client = Net::Hippie::Client.new + response = client.with_retry(retries: 1) { |c| c.get(@uri) } + + assert_equal Net::HTTPOK, response.class + assert_equal 'success', response.body + end + + def test_open_timeout_triggers_retry + WebMock.stub_request(:get, @uri.to_s) + .to_raise(Net::OpenTimeout).then + .to_return(status: 200, body: 'success') + + client = Net::Hippie::Client.new + response = client.with_retry(retries: 1) { |c| c.get(@uri) } + + assert_equal Net::HTTPOK, response.class + assert_equal 'success', response.body + end + + def test_timeout_with_zero_retries + WebMock.stub_request(:get, @uri.to_s).to_timeout + + client = Net::Hippie::Client.new + # WebMock.to_timeout raises different timeout errors, so check for any timeout error + assert_raises(*Net::Hippie::CONNECTION_ERRORS.select { |e| e.name.include?('Timeout') }) do + client.with_retry(retries: 0) { |c| c.get(@uri) } + end + end + + def test_multiple_timeout_types_in_sequence + call_count = 0 + WebMock.stub_request(:get, @uri.to_s).to_return do + call_count += 1 + case call_count + when 1 + raise Net::OpenTimeout + when 2 + raise Net::ReadTimeout + when 3 + raise Timeout::Error + else + { status: 200, body: 'success' } + end + end + + client = Net::Hippie::Client.new + response = client.with_retry(retries: 4) { |c| c.get(@uri) } + + assert_equal Net::HTTPOK, response.class + assert_equal 'success', response.body + assert_equal 4, call_count + end + + def test_timeout_settings_per_connection + uri1 = URI.parse('https://example1.com/test') + uri2 = URI.parse('https://example2.com/test') + + client = Net::Hippie::Client.new(read_timeout: 15, open_timeout: 20) + + connection1 = client.send(:connection_for, uri1) + connection2 = client.send(:connection_for, uri2) + + backend1 = connection1.instance_variable_get(:@backend) + backend2 = connection2.instance_variable_get(:@backend) + http1 = backend1.instance_variable_get(:@http) + http2 = backend2.instance_variable_get(:@http) + + assert_equal 15, http1.read_timeout + assert_equal 20, http1.open_timeout + assert_equal 15, http2.read_timeout + assert_equal 20, http2.open_timeout + end + + def test_timeout_preserves_connection_pooling + client = Net::Hippie::Client.new(read_timeout: 25) + + # First call should create connection + connection1 = client.send(:connection_for, @uri) + # Second call should reuse same connection + connection2 = client.send(:connection_for, @uri) + + assert_same connection1, connection2 + + backend = connection1.instance_variable_get(:@backend) + http = backend.instance_variable_get(:@http) + assert_equal 25, http.read_timeout + end +end
\ No newline at end of file |
