TEST (atomicBufferTests, checkBounds)
{
    clearBuffer();
    AtomicBuffer ab (&testBuffer[0], testBuffer.size());
    std::string testString ("hello world!");

    ASSERT_NO_THROW({
        ab.putInt32(0, -1);
    });
    void verifyPayload(AtomicBuffer& buffer, util::index_t offset, util::index_t length)
    {
        std::uint8_t* ptr = buffer.buffer() + offset;

        for (int i = 0; i < length; i++)
        {
            ASSERT_EQ(*(ptr + i), i % 256);
        }
    }
ControlledPollAction RecordingSubscriptionDescriptorPoller::onFragment(
    AtomicBuffer& buffer, util::index_t offset, util::index_t length, Header& header)
{
    MessageHeader msgHeader(
        buffer.sbeData() + offset,
        static_cast<std::uint64_t>(length),
        MessageHeader::sbeSchemaVersion());

    const std::int16_t schemaId = msgHeader.schemaId();
    if (schemaId != MessageHeader::sbeSchemaId())
    {
        throw ArchiveException(
            "expected schemaId=" + std::to_string(MessageHeader::sbeSchemaId()) +
                ", actual=" + std::to_string(schemaId),
            SOURCEINFO);
    }

    const std::uint16_t templateId = msgHeader.templateId();
    switch (templateId)
    {
        case ControlResponse::sbeTemplateId():
        {
            ControlResponse response(
                buffer.sbeData() + offset + MessageHeader::encodedLength(),
                static_cast<std::uint64_t>(length) - MessageHeader::encodedLength(),
                msgHeader.blockLength(),
                msgHeader.version());

            if (response.controlSessionId() == m_controlSessionId)
            {
                const ControlResponseCode::Value code = response.code();
                const std::int64_t correlationId = response.correlationId();

                if (ControlResponseCode::Value::SUBSCRIPTION_UNKNOWN == code && correlationId == m_correlationId)
                {
                    m_isDispatchComplete = true;
                    return ControlledPollAction::BREAK;
                }

                if (ControlResponseCode::Value::ERROR == code)
                {
                    ArchiveException ex(
                        static_cast<std::int32_t>(response.relevantId()),
                        "response for correlationId=" + std::to_string(m_correlationId) +
                            ", error: " + response.errorMessage(),
                        SOURCEINFO);

                    if (correlationId == m_correlationId)
                    {
                        throw ArchiveException(ex);
                    }
                    else if (nullptr != m_errorHandler)
                    {
                        m_errorHandler(ex);
                    }
                }
            }
        }
        break;

        case RecordingSubscriptionDescriptor::sbeTemplateId():
        {
            RecordingSubscriptionDescriptor descriptor(
                buffer.sbeData() + offset + MessageHeader::encodedLength(),
                static_cast<std::uint64_t>(length) - MessageHeader::encodedLength(),
                msgHeader.blockLength(),
                msgHeader.version());

            const std::int64_t correlationId = descriptor.correlationId();
            if (descriptor.controlSessionId() == m_controlSessionId && correlationId == m_correlationId)
            {
                m_consumer(
                    m_controlSessionId,
                    correlationId,
                    descriptor.subscriptionId(),
                    descriptor.streamId(),
                    descriptor.strippedChannel());

                if (0 == --m_remainingSubscriptionCount)
                {
                    m_isDispatchComplete = true;
                    return ControlledPollAction::BREAK;
                }
            }
        }
            break;

        default:
            break;
    }

    return ControlledPollAction::CONTINUE;
}
void ControlResponseAdapter::onFragment(
    AtomicBuffer& buffer, util::index_t offset, util::index_t length, Header& header)
{
    MessageHeader msgHeader(
        buffer.sbeData() + offset,
        static_cast<std::uint64_t>(length),
        MessageHeader::sbeSchemaVersion());

    const std::int16_t schemaId = msgHeader.schemaId();
    if (schemaId != MessageHeader::sbeSchemaId())
    {
        throw ArchiveException(
            "expected schemaId=" + std::to_string(MessageHeader::sbeSchemaId()) +
                ", actual=" + std::to_string(schemaId),
            SOURCEINFO);
    }

    const std::uint16_t templateId = msgHeader.templateId();
    switch (templateId)
    {
        case ControlResponse::sbeTemplateId():
        {
            ControlResponse response(
                buffer.sbeData() + offset + MessageHeader::encodedLength(),
                static_cast<std::uint64_t>(length) - MessageHeader::encodedLength(),
                msgHeader.blockLength(),
                msgHeader.version());

            m_onResponse(
                response.controlSessionId(),
                response.correlationId(),
                response.relevantId(),
                response.code(),
                response.errorMessage());
            break;
        }

        case RecordingDescriptor::sbeTemplateId():
        {
            RecordingDescriptor descriptor(
                buffer.sbeData() + offset + MessageHeader::encodedLength(),
                static_cast<std::uint64_t>(length) - MessageHeader::encodedLength(),
                msgHeader.blockLength(),
                msgHeader.version());

            m_onRecordingDescriptor(
                descriptor.controlSessionId(),
                descriptor.correlationId(),
                descriptor.recordingId(),
                descriptor.startTimestamp(),
                descriptor.stopTimestamp(),
                descriptor.startPosition(),
                descriptor.stopPosition(),
                descriptor.initialTermId(),
                descriptor.segmentFileLength(),
                descriptor.termBufferLength(),
                descriptor.mtuLength(),
                descriptor.sessionId(),
                descriptor.streamId(),
                descriptor.strippedChannel(),
                descriptor.originalChannel(),
                descriptor.sourceIdentity());
            break;
        }

        default:
            break;
    }
}