org.sonar.ce.cluster.HazelcastClientWrapperImplTest.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.ce.cluster.HazelcastClientWrapperImplTest.java

Source

/*
 * SonarQube
 * Copyright (C) 2009-2017 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package org.sonar.ce.cluster;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import com.google.common.collect.ImmutableSet;
import com.hazelcast.client.impl.HazelcastClientInstanceImpl;
import com.hazelcast.client.impl.HazelcastClientProxy;
import com.hazelcast.core.HazelcastInstance;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
import org.slf4j.LoggerFactory;
import org.sonar.api.config.MapSettings;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
import org.sonar.process.NetworkUtils;
import org.sonar.process.ProcessProperties;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.MapEntry.entry;

public class HazelcastClientWrapperImplTest {
    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Rule
    public TestRule safeguardTimeout = new DisableOnDebug(Timeout.seconds(60));

    private static HazelcastInstance hzCluster;
    private static HazelcastClientWrapperImpl hzClient;

    @BeforeClass
    public static void setupHazelcastClusterAndHazelcastClient() {
        int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
        hzCluster = HazelcastTestHelper.createHazelcastCluster("cluster_with_client", port);

        Settings settings = createClusterSettings("cluster_with_client", "localhost:" + port);
        hzClient = new HazelcastClientWrapperImpl(settings);
    }

    @AfterClass
    public static void stopHazelcastClusterAndHazelcastClient() {
        try {
            hzClient.stop();
        } catch (Exception e) {
            // Ignore it
        }
        try {
            hzCluster.shutdown();
        } catch (Exception e) {
            // Ignore it
        }
    }

    @Test
    public void start_throws_ISE_if_LOCALENDPOINT_is_incorrect() {
        Settings settings = createClusterSettings("sonarqube", "\u4563\u1432\u1564");
        HazelcastClientWrapperImpl hzClient = new HazelcastClientWrapperImpl(settings);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage(
                "Unable to connect to any address in the config! The following addresses were tried:");

        hzClient.start();
    }

    @Test
    public void constructor_throws_ISE_if_LOCALENDPOINT_is_empty() {
        Settings settings = createClusterSettings("sonarqube", "");

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("LocalEndPoint have not been set");

        new HazelcastClientWrapperImpl(settings);
    }

    @Test
    public void constructor_throws_ISE_if_CLUSTER_ENABLED_is_false() {
        Settings settings = createClusterSettings("sonarqube", "localhost:9003");
        settings.setProperty(ProcessProperties.CLUSTER_ENABLED, false);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("Cluster is not enabled");

        new HazelcastClientWrapperImpl(settings);
    }

    @Test
    public void constructor_throws_ISE_if_missing_CLUSTER_ENABLED() {
        Settings settings = createClusterSettings("sonarqube", "localhost:9003");
        settings.removeProperty(ProcessProperties.CLUSTER_ENABLED);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("Cluster is not enabled");

        new HazelcastClientWrapperImpl(settings);
    }

    @Test
    public void constructor_throws_ISE_if_missing_CLUSTER_NAME() {
        Settings settings = createClusterSettings("sonarqube", "localhost:9003");
        settings.removeProperty(ProcessProperties.CLUSTER_NAME);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("sonar.cluster.name is missing");

        new HazelcastClientWrapperImpl(settings);
    }

    @Test
    public void constructor_throws_ISE_if_missing_CLUSTER_LOCALENDPOINT() {
        Settings settings = createClusterSettings("sonarqube", "localhost:9003");
        settings.removeProperty(ProcessProperties.CLUSTER_LOCALENDPOINT);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("LocalEndPoint have not been set");

        new HazelcastClientWrapperImpl(settings);
    }

    @Test
    public void client_must_connect_to_hazelcast() {
        int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
        // Launch a fake Hazelcast instance
        HazelcastInstance hzInstance = HazelcastTestHelper
                .createHazelcastCluster("client_must_connect_to_hazelcast", port);
        Settings settings = createClusterSettings("client_must_connect_to_hazelcast", "localhost:" + port);

        HazelcastClientWrapperImpl hazelcastClientWrapperImpl = new HazelcastClientWrapperImpl(settings);
        try {
            hazelcastClientWrapperImpl.start();
            assertThat(hazelcastClientWrapperImpl.getConnectedClients()).hasSize(1);
            assertThat(hazelcastClientWrapperImpl.getClientUUID()).isNotEmpty();
        } finally {
            hazelcastClientWrapperImpl.stop();
        }
    }

    @Test
    public void client_must_be_able_to_set_ReplicatedMap_objects() throws InterruptedException {
        try {
            hzClient.start();

            Set<String> setTest = new HashSet<>();
            setTest.addAll(Arrays.asList(RandomStringUtils.randomAlphanumeric(10),
                    RandomStringUtils.randomAlphanumeric(10)));
            Map<String, Set<String>> replicatedMap = hzClient.getReplicatedMap("TEST1");
            replicatedMap.put("KEY1", ImmutableSet.copyOf(setTest));
            assertThat(hzCluster.getReplicatedMap("TEST1")).containsOnlyKeys("KEY1");
            assertThat(hzCluster.getReplicatedMap("TEST1").get("KEY1")).isEqualTo(setTest);
        } finally {
            hzClient.stop();
        }
    }

    @Test
    public void client_must_be_able_to_retrieve_Set_objects() {
        try {
            hzClient.start();

            // Set
            Set<String> setTest = new HashSet<>();
            setTest.addAll(Arrays.asList("8", "9"));
            hzCluster.getSet("TEST1").addAll(setTest);
            assertThat(hzClient.getSet("TEST1")).containsAll(setTest);
        } finally {
            hzClient.stop();
        }
    }

    @Test
    public void client_must_be_able_to_retrieve_List_objects() {
        try {
            hzClient.start();

            // List
            List<String> listTest = Arrays.asList("1", "2");
            hzCluster.getList("TEST2").addAll(listTest);
            assertThat(hzClient.getList("TEST2")).containsAll(listTest);
        } finally {
            hzClient.stop();
        }
    }

    @Test
    public void client_must_be_able_to_retrieve_Map_objects() {
        try {
            hzClient.start();

            Map mapTest = new HashMap<>();
            mapTest.put("a", Arrays.asList("123", "456"));
            hzCluster.getMap("TEST3").putAll(mapTest);
            assertThat(hzClient.getMap("TEST3")).containsExactly(entry("a", Arrays.asList("123", "456")));
        } finally {
            hzClient.stop();
        }
    }

    @Test
    public void configuration_tweaks_of_hazelcast_must_be_present() {
        try {
            hzClient.start();
            HazelcastClientInstanceImpl realClient = ((HazelcastClientProxy) hzClient.hzInstance).client;
            assertThat(realClient.getClientConfig().getProperty("hazelcast.tcp.join.port.try.count"))
                    .isEqualTo("10");
            assertThat(realClient.getClientConfig().getProperty("hazelcast.phone.home.enabled")).isEqualTo("false");
            assertThat(realClient.getClientConfig().getProperty("hazelcast.logging.type")).isEqualTo("slf4j");
        } finally {
            hzClient.stop();
        }
    }

    @Test
    public void hazelcast_client_must_log_through_sl4fj() {
        MemoryAppender<ILoggingEvent> memoryAppender = new MemoryAppender<>();
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        lc.reset();
        memoryAppender.setContext(lc);
        memoryAppender.start();
        lc.getLogger("com.hazelcast").addAppender(memoryAppender);

        try {
            hzClient.start();
        } finally {
            hzClient.stop();
            memoryAppender.stop();
        }
        assertThat(memoryAppender.events).isNotEmpty();
        memoryAppender.events.stream().forEach(e -> assertThat(e.getLoggerName()).startsWith("com.hazelcast"));
    }

    private static Settings createClusterSettings(String name, String localEndPoint) {
        Properties properties = new Properties();
        properties.setProperty(ProcessProperties.CLUSTER_NAME, name);
        properties.setProperty(ProcessProperties.CLUSTER_LOCALENDPOINT, localEndPoint);
        properties.setProperty(ProcessProperties.CLUSTER_ENABLED, "true");
        return new MapSettings(new PropertyDefinitions()).addProperties(properties);
    }

    private class MemoryAppender<E> extends AppenderBase<E> {
        private final List<E> events = new ArrayList();

        @Override
        protected void append(E eventObject) {
            events.add(eventObject);
        }
    }
}