All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.simulator.tests.topic.ITopicTest Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.hazelcast.simulator.tests.topic;

import com.hazelcast.cp.IAtomicLong;
import com.hazelcast.simulator.hz.HazelcastTest;
import com.hazelcast.simulator.test.BaseThreadState;
import com.hazelcast.simulator.test.annotations.AfterRun;
import com.hazelcast.simulator.test.annotations.Setup;
import com.hazelcast.simulator.test.annotations.Teardown;
import com.hazelcast.simulator.test.annotations.TimeStep;
import com.hazelcast.simulator.test.annotations.Verify;
import com.hazelcast.topic.ITopic;
import com.hazelcast.topic.Message;
import com.hazelcast.topic.MessageListener;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import static com.hazelcast.simulator.utils.CommonUtils.sleepRandomNanos;
import static com.hazelcast.simulator.utils.TestUtils.assertTrueEventually;
import static org.junit.Assert.assertEquals;

/**
 * Creates a number of {@link ITopic} and a number of listeners per topic. Each member publishes messages to every topic.
 *
 * This test is inherently unreliable because the {@link ITopic} relies on the event system which is unreliable.
 * When messages are published with a too high rate, eventually the event system will ignore incoming events.
 */
public class ITopicTest extends HazelcastTest {

    // properties
    public int topicCount = 1000;
    public int listenersPerTopic = 1;
    public int maxProcessingDelayNanos = 0;
    public int maxPublicationDelayNanos = 1000;
    // the maximum period the verification process is going to wait till the correct number of messags
    // have been received. A negative value indicates that no verification should be done.
    public int maxVerificationTimeSeconds = 60;

    private IAtomicLong totalExpectedCounter;
    private IAtomicLong totalFoundCounter;
    private ITopic[] topics;
    private List listeners;

    @Setup
    public void setup() {
        totalExpectedCounter = getAtomicLong(name + ":TotalExpectedCounter");
        totalFoundCounter = getAtomicLong(name + ":TotalFoundCounter");

        topics = new ITopic[topicCount];
        listeners = new LinkedList<>();
        for (int topicIndex = 0; topicIndex < topics.length; topicIndex++) {
            ITopic topic = targetInstance.getTopic(name + topicIndex);
            topics[topicIndex] = topic;

            for (int listenerIndex = 0; listenerIndex < listenersPerTopic; listenerIndex++) {
                TopicListener topicListener = new TopicListener();
                topic.addMessageListener(topicListener);
                listeners.add(topicListener);
            }
        }
    }

    @TimeStep
    public void timeStep(ThreadState state) {
        sleepRandomNanos(state.random, maxPublicationDelayNanos);

        long msg = state.nextMessage();
        state.count += msg;

        ITopic topic = state.getRandomTopic();
        topic.publish(msg);
    }

    @AfterRun
    public void afterRun(ThreadState state) {
        totalExpectedCounter.addAndGet(state.count);
    }

    public class ThreadState extends BaseThreadState {

        private long count;

        @SuppressWarnings("unchecked")
        private ITopic getRandomTopic() {
            int index = randomInt(topics.length);
            return (ITopic) topics[index];
        }

        private long nextMessage() {
            long msg = randomLong() % 1000;
            return (msg < 0) ? -msg : msg;
        }
    }

    private class TopicListener implements MessageListener {

        private final Random random = new Random();

        private volatile long count;

        @Override
        public void onMessage(Message message) {
            sleepRandomNanos(random, maxProcessingDelayNanos);
            count += message.getMessageObject();
        }
    }

    @Verify(global = true)
    public void verify() {
        if (maxVerificationTimeSeconds < 0) {
            return;
        }

        final long expectedCount = totalExpectedCounter.get();
        assertTrueEventually(() -> {
            long actualCount = 0;
            for (TopicListener topicListener : listeners) {
                actualCount += topicListener.count;
            }
            assertEquals("published messages don't match received messages", expectedCount, actualCount);
        }, maxVerificationTimeSeconds);
    }

    @Teardown
    public void teardown() {
        for (ITopic topic : topics) {
            topic.destroy();
        }
        totalExpectedCounter.destroy();
        totalFoundCounter.destroy();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy