Back to Repositories

Testing HTTP Server Request Handling in Fluentd Plugin Helper

This test suite validates the HTTP server application component of the Fluentd plugin helper system. It focuses on testing HTTP request handling, routing functionality, and path management within the Fluent::PluginHelper::HttpServer::App class.

Test Coverage Overview

The test suite provides comprehensive coverage of HTTP request handling and routing functionality.

Key areas tested include:
  • Multiple HTTP method support (GET, POST, DELETE, PUT, PATCH, OPTIONS, CONNECT, TRACE)
  • Path routing and normalization
  • HEAD request handling
  • Response status code verification
  • Response body content validation

Implementation Analysis

The testing approach utilizes Test::Unit with FlexMock for request simulation. The implementation follows a structured pattern using sub_test_cases and data-driven tests to verify different HTTP methods.

Notable patterns include:
  • Mock request objects with FlexMock
  • DummyRouter implementation for controlled routing
  • Consistent response validation structure
  • Path normalization testing

Technical Details

Testing tools and configuration:
  • Test::Unit as the primary testing framework
  • FlexMock for request mocking
  • NULL_LOGGER implementation for test isolation
  • Custom DummyRouter class for routing simulation
  • Conditional test execution based on library availability

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Ruby application development.

Notable practices include:
  • Isolation of external dependencies
  • Comprehensive HTTP method coverage
  • Clean separation of test cases
  • Effective use of mock objects
  • Graceful handling of missing dependencies

fluent/fluentd

test/plugin_helper/http_server/test_app.rb

            
require_relative '../../helper'
require 'flexmock/test_unit'

begin
  require 'fluent/plugin_helper/http_server/app'
  skip = false
rescue LoadError => _
  skip = true
end

unless skip
  class HttpHelperAppTest < Test::Unit::TestCase
    NULL_LOGGER = Logger.new(nil)

    class DummyRounter
      def initialize(table = {})
        @table = table
      end

      def route!(method, path, _req)
        r = @table.fetch(method).fetch(path)
        [200, {}, r]
      end
    end

    sub_test_case '#call' do
      data(
        'GET request' => 'GET',
        'POST request' => 'POST',
        'DELETE request' => 'DELETE',
        'PUT request' => 'PUT',
        'PATCH request' => 'PATCH',
        'OPTION request' => 'OPTIONS',
        'CONNECT request' => 'CONNECT',
        'TRACE request' => 'TRACE',
      )
      test 'dispatch correct path' do |method|
        r = DummyRounter.new(method.downcase.to_sym => { '/path/' => 'hi' })
        app = Fluent::PluginHelper::HttpServer::App.new(r, NULL_LOGGER)
        m = flexmock('request', method: method, path: '/path/')
        r = app.call(m)
        assert_equal(r.body.read, 'hi')
        assert_equal(r.status, 200)
      end

      test 'dispatch correct path for head' do |method|
        r = DummyRounter.new(head: { '/path/' => 'hi' })
        app = Fluent::PluginHelper::HttpServer::App.new(r, NULL_LOGGER)
        m = flexmock('request', method: method, path: '/path')
        r = app.call(m)
        assert_equal(r.body.read, '')
        assert_equal(r.status, 200)
      end

      test 'if path does not end with `/`' do |method|
        r = DummyRounter.new(head: { '/path/' => 'hi' })
        app = Fluent::PluginHelper::HttpServer::App.new(r, NULL_LOGGER)
        m = flexmock('request', method: method, path: '/path')
        r = app.call(m)
        assert_equal(r.body.read, '')
        assert_equal(r.status, 200)
      end
    end
  end
end