Back to Repositories

Testing Event Handler Lifecycle Management in LMAX-Disruptor

This test suite validates the lifecycle management functionality of event handlers in the LMAX Disruptor framework, focusing on proper initialization and shutdown behaviors. It ensures event processors correctly notify lifecycle-aware components during startup and termination phases.

Test Coverage Overview

The test suite provides comprehensive coverage of the BatchEventProcessor lifecycle events, specifically verifying:

  • Event handler initialization sequence
  • Proper startup notification
  • Clean shutdown process
  • Accurate lifecycle event counting

Implementation Analysis

The testing approach utilizes JUnit Jupiter to validate lifecycle events through a custom LifecycleAwareEventHandler implementation. The implementation employs CountDownLatch mechanisms to synchronize test execution and verify proper sequencing of lifecycle events.

Key patterns include:
  • Thread synchronization using CountDownLatch
  • Event handler lifecycle tracking
  • Asynchronous processor execution

Technical Details

Testing infrastructure includes:

  • JUnit Jupiter test framework
  • RingBuffer configuration with 16 slots
  • Custom StubEvent implementation
  • BatchEventProcessor with SequenceBarrier
  • Hamcrest matchers for assertions

Best Practices Demonstrated

The test exemplifies several testing best practices:

  • Isolated test scope with clear boundaries
  • Proper thread synchronization
  • Clean separation of concerns
  • Explicit lifecycle state verification
  • Thread-safe counter implementation

lmax-exchange/disruptor

src/test/java/com/lmax/disruptor/LifecycleAwareTest.java

            
/*
 * Copyright 2011 LMAX Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lmax.disruptor;

import com.lmax.disruptor.support.StubEvent;
import org.junit.jupiter.api.Test;

import java.util.concurrent.CountDownLatch;

import static com.lmax.disruptor.RingBuffer.createMultiProducer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public final class LifecycleAwareTest
{
    private final CountDownLatch startLatch = new CountDownLatch(1);
    private final CountDownLatch shutdownLatch = new CountDownLatch(1);


    private final RingBuffer<StubEvent> ringBuffer = createMultiProducer(StubEvent.EVENT_FACTORY, 16);
    private final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
    private final LifecycleAwareEventHandler handler = new LifecycleAwareEventHandler();
    private final BatchEventProcessor<StubEvent> batchEventProcessor =
            new BatchEventProcessorBuilder().build(ringBuffer, sequenceBarrier, handler);

    @Test
    public void shouldNotifyOfBatchProcessorLifecycle() throws Exception
    {
        new Thread(batchEventProcessor).start();

        startLatch.await();
        batchEventProcessor.halt();

        shutdownLatch.await();

        assertThat(Integer.valueOf(handler.startCounter), is(Integer.valueOf(1)));
        assertThat(Integer.valueOf(handler.shutdownCounter), is(Integer.valueOf(1)));
    }

    private final class LifecycleAwareEventHandler implements EventHandler<StubEvent>
    {
        private int startCounter = 0;
        private int shutdownCounter = 0;

        @Override
        public void onEvent(final StubEvent event, final long sequence, final boolean endOfBatch) throws Exception
        {
        }

        @Override
        public void onStart()
        {
            ++startCounter;
            startLatch.countDown();
        }

        @Override
        public void onShutdown()
        {
            ++shutdownCounter;
            shutdownLatch.countDown();
        }
    }
}