Back to Repositories

Testing Compression Module Implementation in Fluentd

This test suite validates the compression and decompression functionality in Fluentd’s Compressable plugin. It ensures reliable data compression operations while handling various input/output scenarios and edge cases.

Test Coverage Overview

The test suite provides comprehensive coverage of the Compressable plugin’s core functionality:

  • Compression of text data with size verification
  • Decompression accuracy validation
  • IO stream handling for both compression and decompression
  • Multiple compressed data concatenation and processing
  • Edge case handling for empty/nil inputs

Implementation Analysis

The testing approach utilizes Test::Unit framework with modular test organization:

The implementation employs sub_test_cases for logical grouping of compression and decompression tests. It uses StringIO for simulating IO operations and Zlib::GzipReader for verification. The tests demonstrate both direct string manipulation and IO-based processing patterns.

Technical Details

  • Testing Framework: Test::Unit
  • Core Libraries: Zlib, StringIO
  • Custom Helpers: compress_assert_equal method
  • Test Organization: Hierarchical structure with sub_test_cases
  • Setup blocks for test data preparation

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases with clear setup blocks
  • Comprehensive edge case coverage
  • Consistent assertion patterns
  • Helper methods for repeated validations
  • Clear test naming conventions

fluent/fluentd

test/plugin/test_compressable.rb

            
require_relative '../helper'
require 'fluent/plugin/compressable'

class CompressableTest < Test::Unit::TestCase
  include Fluent::Plugin::Compressable

  def compress_assert_equal(expected, actual)
    e = Zlib::GzipReader.new(StringIO.new(expected)).read
    a = Zlib::GzipReader.new(StringIO.new(actual)).read
    assert_equal(e, a)
  end

  sub_test_case '#compress' do
    setup do
      @src = 'text data for compressing' * 5
      @gzipped_src = compress(@src)
    end

    test 'compress data' do
      assert compress(@src).size < @src.size
      assert_not_equal @gzipped_src, @src
    end

    test 'write compressed data to IO with output_io option' do
      io = StringIO.new
      compress(@src, output_io: io)
      compress_assert_equal @gzipped_src, io.string
    end
  end

  sub_test_case '#decompress' do
    setup do
      @src = 'text data for compressing' * 5
      @gzipped_src = compress(@src)
    end

    test 'decompress compressed data' do
      assert_equal @src, decompress(@gzipped_src)
    end

    test 'write decompressed data to IO with output_io option' do
      io = StringIO.new
      decompress(@gzipped_src, output_io: io)
      assert_equal @src, io.string
    end

    test 'return decompressed string with output_io option' do
      io = StringIO.new(@gzipped_src)
      assert_equal @src, decompress(input_io: io)
    end

    test 'decompress multiple compressed data' do
      src1 = 'text data'
      src2 = 'text data2'
      gzipped_src = compress(src1) + compress(src2)

      assert_equal src1 + src2, decompress(gzipped_src)
    end

    test 'decompress with input_io and output_io' do
      input_io = StringIO.new(@gzipped_src)
      output_io = StringIO.new

      decompress(input_io: input_io, output_io: output_io)
      assert_equal @src, output_io.string
    end

    test 'decompress multiple compressed data with input_io and output_io' do
      src1 = 'text data'
      src2 = 'text data2'
      gzipped_src = compress(src1) + compress(src2)

      input_io = StringIO.new(gzipped_src)
      output_io = StringIO.new

      decompress(input_io: input_io, output_io: output_io)
      assert_equal src1 + src2, output_io.string
    end

    test 'return the received value as it is with empty string or nil' do
      assert_equal nil, decompress
      assert_equal nil, decompress(nil)
      assert_equal '', decompress('')
      assert_equal '', decompress('', output_io: StringIO.new)
    end
  end
end