/*
* Copyright (c) 2008-2017, 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.config;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import static com.hazelcast.config.XMLConfigBuilderTest.HAZELCAST_START_TAG;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class InvalidConfigurationTest {
@Rule
public ExpectedException rule = ExpectedException.none();
@Test
public void testWhenTwoJoinMethodEnabled() {
expectInvalid();
String xml = getDraftXml();
Properties properties = getDraftProperties();
properties.setProperty("multicast-enabled", "true");
properties.setProperty("tcp-ip-enabled", "true");
buildConfig(xml, properties);
}
@Test
public void testWhenXmlValid() {
String xml = getDraftXml();
buildConfig(xml);
}
@Test
public void testWhenXmlValidAndPropertiesAreResolved() {
String xml = getDraftXml();
Properties properties = getDraftProperties();
buildConfig(xml, properties);
}
@Test
public void testWhenInvalid_QueueBackupCount() {
expectInvalid();
buildConfig("queue-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_QueueBackupCount() {
buildConfig("queue-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_AsyncQueueBackupCount() {
expectInvalid();
buildConfig("queue-async-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_AsyncQueueBackupCount() {
buildConfig("queue-async-backup-count", getValidBackupCount());
}
@Test
public void testWhenValid_QueueTTL() {
buildConfig("empty-queue-ttl", "10");
}
@Test
public void testWhenInValid_QueueTTL() {
expectInvalid();
buildConfig("empty-queue-ttl", "a");
}
@Test
public void testWhenInvalid_MapMemoryFormat() {
expectInvalid();
buildConfig("map-in-memory-format", "binary");
}
@Test
public void testWhenInvalid_MapBackupCount() {
expectInvalid();
buildConfig("map-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_MapBackupCount() {
buildConfig("map-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_MapTTL() {
expectInvalid();
buildConfig("map-time-to-live-seconds", "-1");
}
@Test
public void testWhenInvalid_MapMaxIdleSeconds() {
expectInvalid();
buildConfig("map-max-idle-seconds", "-1");
}
@Test
public void testWhenValid_MapEvictionPolicy() {
buildConfig("map-eviction-policy", "NONE");
}
@Test
public void testWhenInvalid_MapEvictionPercentage() {
expectInvalid();
buildConfig("map-eviction-percentage", "101");
}
@Test
public void testWhenInvalid_MultiMapBackupCount() {
expectInvalid();
buildConfig("multimap-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_MultiMapStats() {
buildConfig("multimap-statistics-enabled", "false");
}
@Test
public void testWhenValid_MultiMapBinary() {
buildConfig("multimap-binary", "false");
}
@Test
public void testWhenValid_MultiMapBackupCount() {
buildConfig("multimap-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalidValid_MultiMapCollectionType() {
expectInvalid();
buildConfig("multimap-value-collection-type", "set");
}
@Test
public void testWhenInvalid_ListBackupCount() {
expectInvalid();
buildConfig("list-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_ListBackupCount() {
buildConfig("list-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_SetBackupCount() {
expectInvalid();
buildConfig("list-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_SetBackupCount() {
buildConfig("list-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_SemaphoreInitialPermits() {
expectInvalid();
buildConfig("semaphore-initial-permits", "-1");
}
@Test
public void testWhenInvalid_SemaphoreBackupCount() {
expectInvalid();
buildConfig("semaphore-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_SemaphoreBackupCount() {
buildConfig("semaphore-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_AsyncSemaphoreBackupCount() {
expectInvalid();
buildConfig("semaphore-async-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_AsyncSemaphoreBackupCount() {
buildConfig("semaphore-async-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalidTcpIpConfiguration() {
expectInvalid();
buildConfig(HAZELCAST_START_TAG +
"<network\n>" +
"<join>\n" +
"<tcp-ip enabled=\"true\">\n" +
"<required-member>127.0.0.1</required-member>\n" +
"<required-member>128.0.0.1</required-member>\n" +
"</tcp-ip>\n" +
"</join>\n" +
"</network>\n" +
"</hazelcast>\n");
}
@Test
public void invalidConfigurationTest_WhenOrderIsDifferent() {
buildConfig(HAZELCAST_START_TAG +
"<list name=\"default\">\n" +
"<statistics-enabled>false</statistics-enabled>\n" +
"<max-size>0</max-size>\n" +
"<backup-count>1</backup-count>\n" +
"<async-backup-count>0</async-backup-count>\n" +
"</list>\n" +
"</hazelcast>\n");
buildConfig(HAZELCAST_START_TAG +
"<list name=\"default\">\n" +
"<backup-count>1</backup-count>\n" +
"<async-backup-count>0</async-backup-count>\n" +
"<statistics-enabled>false</statistics-enabled>\n" +
"<max-size>0</max-size>\n" +
"</list>\n" +
"</hazelcast>\n");
}
@Test
public void testWhenDoctypeAddedToXml() {
// expectInvalid("DOCTYPE is disallowed when the feature " +
// "\"http://apache.org/xml/features/disallow-doctype-decl\" set to true.");
rule.expect(InvalidConfigurationException.class);
buildConfig("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE hazelcast [ <!ENTITY e1 \"0123456789\"> ] >\n" +
HAZELCAST_START_TAG + "</hazelcast>");
}
public void testWhenInvalid_CacheBackupCount() {
buildConfig("cache-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_CacheBackupCount() {
buildConfig("cache-backup-count", getValidBackupCount());
}
@Test
public void testWhenInvalid_CacheAsyncBackupCount() {
expectInvalid();
buildConfig("cache-async-backup-count", getInvalidBackupCount());
}
@Test
public void testWhenValid_CacheAsyncBackupCount() {
buildConfig("cache-async-backup-count", getValidBackupCount());
}
@Test
public void testWhenValid_CacheInMemoryFormat() {
buildConfig("cache-in-memory-format", "OBJECT");
}
@Test
public void testWhenInvalid_CacheInMemoryFormat() {
expectInvalid();
buildConfig("cache-in-memory-format", "binaryyy");
}
@Test
public void testWhenInvalid_EmptyDurationTime() {
expectInvalid();
buildConfig("cache-expiry-policy-duration-amount", "");
}
@Test
public void testWhenInvalid_InvalidDurationTime() {
expectInvalid();
buildConfig("cache-expiry-policy-duration-amount", "asd");
}
@Test
public void testWhenInvalid_NegativeDurationTime() {
expectInvalid();
buildConfig("cache-expiry-policy-duration-amount", "-1");
}
@Test
public void testWhenInvalid_EmptyTimeUnit() {
expectInvalid();
buildConfig("cache-expiry-policy-time-unit", "");
}
@Test
public void testWhenInvalid_InvalidTimeUnit() {
expectInvalid();
buildConfig("cache-expiry-policy-time-unit", "asd");
}
@Test
public void testWhenInvalid_CacheEvictionSize() {
expectInvalid();
buildConfig("cache-eviction-size", "-100");
}
@Test
public void testWhenValid_CacheEvictionSize() {
buildConfig("cache-eviction-size", "100");
}
@Test
public void testWhenInvalid_CacheEvictionPolicy() {
expectInvalid();
buildConfig("cache-eviction-policy", "NONE");
}
@Test
public void testWhenInvalid_BothOfEvictionPolicyAndComparatorClassNameConfigured() {
expectInvalid();
Map<String, String> props = new HashMap<String, String>() {{
put("cache-eviction-policy", "LFU");
put("cache-eviction-policy-comparator-class-name", "my-comparator");
}};
buildConfig(props);
}
private static Config buildConfig(String xml) {
return buildConfig(xml, getDraftProperties());
}
private static Config buildConfig(String propertyKey, String propertyValue) {
String xml = getDraftXml();
Properties properties = getDraftProperties();
properties.setProperty(propertyKey, propertyValue);
return buildConfig(xml, properties);
}
private static Config buildConfig(Map<String, String> props) {
String xml = getDraftXml();
Properties properties = getDraftProperties();
for (Map.Entry<String, String> prop : props.entrySet()) {
properties.setProperty(prop.getKey(), prop.getValue());
}
return buildConfig(xml, properties);
}
private void expectInvalid() {
expectInvalid(rule);
}
private static Config buildConfig(String xml, Properties properties) {
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes());
XmlConfigBuilder configBuilder = new XmlConfigBuilder(bis);
configBuilder.setProperties(properties);
return configBuilder.build();
}
static void expectInvalid(ExpectedException rule) {
rule.expect(InvalidConfigurationException.class);
}
private static String getValidBackupCount() {
final Random random = new Random();
return String.valueOf(random.nextInt(7));
}
private static String getInvalidBackupCount() {
final Random random = new Random();
return String.valueOf(random.nextInt(1000) + 7);
}
private static Properties getDraftProperties() {
Properties properties = new Properties();
properties.setProperty("queue-backup-count", "0");
properties.setProperty("queue-async-backup-count", "0");
properties.setProperty("empty-queue-ttl", "-1");
properties.setProperty("map-in-memory-format", "BINARY");
properties.setProperty("map-backup-count", "0");
properties.setProperty("map-async-backup-count", "0");
properties.setProperty("map-time-to-live-seconds", "0");
properties.setProperty("map-max-idle-seconds", "0");
properties.setProperty("map-eviction-policy", "NONE");
properties.setProperty("map-eviction-percentage", "25");
properties.setProperty("cache-in-memory-format", "BINARY");
properties.setProperty("cache-backup-count", "0");
properties.setProperty("cache-async-backup-count", "0");
properties.setProperty("cache-statistics-enabled", "true");
properties.setProperty("cache-management-enabled", "true");
properties.setProperty("cache-read-through", "true");
properties.setProperty("cache-write-through", "true");
properties.setProperty("cache-eviction-size", "100");
properties.setProperty("cache-eviction-max-size-policy", "ENTRY_COUNT");
properties.setProperty("cache-eviction-policy", "LRU");
properties.setProperty("cache-eviction-policy-comparator-class-name", "");
properties.setProperty("cache-expiry-policy-type", "CREATED");
properties.setProperty("cache-expiry-policy-duration-amount", "1");
properties.setProperty("cache-expiry-policy-time-unit", "DAYS");
properties.setProperty("multimap-backup-count", "0");
properties.setProperty("multimap-value-collection-type", "SET");
properties.setProperty("multimap-statistics-enabled", "false");
properties.setProperty("multimap-binary", "false");
properties.setProperty("list-backup-count", "0");
properties.setProperty("set-backup-count", "1");
properties.setProperty("semaphore-initial-permits", "0");
properties.setProperty("semaphore-backup-count", "0");
properties.setProperty("semaphore-async-backup-count", "0");
properties.setProperty("multicast-enabled", "false");
properties.setProperty("tcp-ip-enabled", "false");
return properties;
}
private static String getDraftXml() {
return HAZELCAST_START_TAG +
" <network>\n" +
"<join>\n" +
"<multicast enabled=\"${multicast-enabled}\">\n" +
"</multicast>\n" +
"<tcp-ip enabled=\"${tcp-ip-enabled}\">\n" +
"</tcp-ip>\n" +
"</join>\n" +
"</network>\n" +
"<queue name=\"default\">\n" +
"<quorum-ref>quorumRuleWithThreeMembers</quorum-ref>" +
"<max-size>0</max-size>\n" +
"<backup-count>${queue-backup-count}</backup-count>\n" +
"<async-backup-count>${queue-async-backup-count}</async-backup-count>\n" +
"<empty-queue-ttl>${empty-queue-ttl}</empty-queue-ttl>\n" +
"</queue>\n" +
"<map name=\"default\">\n" +
"<in-memory-format>${map-in-memory-format}</in-memory-format>\n" +
"<backup-count>${map-backup-count}</backup-count>\n" +
"<async-backup-count>${map-async-backup-count}</async-backup-count>\n" +
"<time-to-live-seconds>${map-time-to-live-seconds}</time-to-live-seconds>\n" +
"<max-idle-seconds>${map-max-idle-seconds}</max-idle-seconds>\n" +
"<eviction-policy>${map-eviction-policy}</eviction-policy>\n" +
"<eviction-percentage>${map-eviction-percentage}</eviction-percentage>\n" +
"</map>\n" +
"<cache name=\"default\">\n" +
"<key-type class-name=\"${cache-key-type-class-name}\"/>\n" +
"<value-type class-name=\"${cache-value-type-class-name}\"/>\n" +
"<in-memory-format>${cache-in-memory-format}</in-memory-format>\n" +
"<statistics-enabled>${cache-statistics-enabled}</statistics-enabled>\n" +
"<management-enabled>${cache-management-enabled}</management-enabled>\n" +
"<backup-count>${cache-backup-count}</backup-count>\n" +
"<async-backup-count>${cache-async-backup-count}</async-backup-count>\n" +
"<read-through>${cache-read-through}</read-through>\n" +
"<write-through>${cache-write-through}</write-through>\n" +
"<cache-loader-factory class-name=\"${cache-loader-factory-class-name}\"/>\n" +
"<cache-writer-factory class-name=\"${cache-writer-factory-class-name}\"/>\n" +
"<expiry-policy-factory class-name=\"${expiry-policy-factory-class-name}\"/>\n" +
"<eviction size=\"${cache-eviction-size}\"" +
" max-size-policy=\"${cache-eviction-max-size-policy}\"" +
" eviction-policy=\"${cache-eviction-policy}\"" +
" comparator-class-name=\"${cache-eviction-policy-comparator-class-name}\"/>\n" +
"</cache>\n" +
"<cache name=\"cacheWithTimedExpiryPolicyFactory\">\n" +
"<expiry-policy-factory>\n" +
"<timed-expiry-policy-factory" +
" expiry-policy-type=\"${cache-expiry-policy-type}\"" +
" duration-amount=\"${cache-expiry-policy-duration-amount}\"" +
" time-unit=\"${cache-expiry-policy-time-unit}\"/>" +
"</expiry-policy-factory>\n" +
"</cache>\n" +
"<multimap name=\"default\">\n" +
"<backup-count>${multimap-backup-count}</backup-count>\n" +
"<value-collection-type>${multimap-value-collection-type}</value-collection-type>\n" +
"<statistics-enabled>${multimap-statistics-enabled}</statistics-enabled>\n" +
"<binary>${multimap-binary}</binary>\n" +
"</multimap>\n" +
"<list name=\"default\">\n" +
"<backup-count>${list-backup-count}</backup-count>\n" +
"</list>\n" +
"<set name=\"default\">\n" +
"<backup-count>${set-backup-count}</backup-count>\n" +
"</set>\n" +
"<semaphore name=\"default\">\n" +
"<initial-permits>${semaphore-initial-permits}</initial-permits>\n" +
"<backup-count>${semaphore-backup-count}</backup-count>\n" +
"<async-backup-count>${semaphore-async-backup-count}</async-backup-count>\n" +
"</semaphore>\n" +
"<lock name=\"default\">\n" +
"<quorum-ref>quorumRuleWithThreeMembers</quorum-ref>\n" +
"</lock>" +
" <ringbuffer name=\"default\">\n" +
" <capacity>10000</capacity>\n" +
" <time-to-live-seconds>30</time-to-live-seconds>\n" +
" <backup-count>1</backup-count>\n" +
" <async-backup-count>0</async-backup-count>\n" +
" <in-memory-format>BINARY</in-memory-format>\n" +
" <ringbuffer-store enabled=\"true\">\n" +
" <class-name>com.hazelcast.RingbufferStoreImpl</class-name>\n" +
" </ringbuffer-store>\n" +
" </ringbuffer>" +
"</hazelcast>\n";
}
}