Back to Repositories

Testing MessagePack Factory Thread-Local Operations in Fluentd

This test suite validates the MessagePack factory implementation in Fluentd, focusing on thread-local packer and unpacker functionality. It ensures proper caching behavior and buffer management for MessagePack serialization operations.

Test Coverage Overview

The test suite covers critical MessagePack factory operations including:

  • Warning message logging behavior
  • Thread-local packer caching verification
  • Thread-local unpacker caching and buffer reset functionality
  • Edge case handling for incomplete MessagePack data

Implementation Analysis

The testing approach uses Ruby’s Test::Unit framework with mock objects to verify behavior. It implements sub-test cases for organized testing of distinct components and uses assertion patterns to validate object equality and expected outcomes.

Key patterns include mixin testing, thread-local resource management, and buffer state verification.

Technical Details

  • Testing Framework: Test::Unit
  • Mock Framework: Built-in Ruby mocking
  • Key Classes: Fluent::MessagePackFactory
  • Test Dependencies: helper.rb, fluent/msgpack_factory

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolation of test cases using sub_test_case blocks
  • Proper resource cleanup between tests
  • Verification of caching behavior
  • Edge case handling for incomplete data
  • Mock object usage for logging verification

fluent/fluentd

test/test_msgpack_factory.rb

            
require_relative 'helper'
require 'fluent/msgpack_factory'

class MessagePackFactoryTest < Test::Unit::TestCase
  test 'call log.warn only once' do
    klass = Class.new do
      include Fluent::MessagePackFactory::Mixin
    end

    mp = klass.new

    mock.proxy($log).warn(anything).once

    assert mp.msgpack_factory
    assert mp.msgpack_factory
    assert mp.msgpack_factory
  end

  sub_test_case 'thread_local_msgpack_packer' do
    test 'packer is cached' do
      packer1 = Fluent::MessagePackFactory.thread_local_msgpack_packer
      packer2 = Fluent::MessagePackFactory.thread_local_msgpack_packer
      assert_equal packer1, packer2
    end
  end

  sub_test_case 'thread_local_msgpack_unpacker' do
    test 'unpacker is cached' do
      unpacker1 = Fluent::MessagePackFactory.thread_local_msgpack_unpacker
      unpacker2 = Fluent::MessagePackFactory.thread_local_msgpack_unpacker
      assert_equal unpacker1, unpacker2
    end

    # We need to reset the buffer every time so that received incomplete data
    # must not affect data from other senders.
    test 'reset the internal buffer of unpacker every time' do
      unpacker1 = Fluent::MessagePackFactory.thread_local_msgpack_unpacker
      unpacker1.feed_each("\xA6foo") do |result|
        flunk("This callback must not be called since the data is uncomplete.")
      end

      records = []
      unpacker2 = Fluent::MessagePackFactory.thread_local_msgpack_unpacker
      unpacker2.feed_each("\xA3foo") do |result|
        records.append(result)
      end
      assert_equal ["foo"], records
    end
  end
end