/*
* 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.client.config;
import com.hazelcast.config.EntryListenerConfig;
import com.hazelcast.config.EvictionConfig;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.GlobalSerializerConfig;
import com.hazelcast.config.GroupConfig;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.InvalidConfigurationException;
import com.hazelcast.config.ListenerConfig;
import com.hazelcast.config.MapIndexConfig;
import com.hazelcast.config.NearCacheConfig;
import com.hazelcast.config.QueryCacheConfig;
import com.hazelcast.config.SerializationConfig;
import com.hazelcast.config.SerializerConfig;
import com.hazelcast.config.SocketInterceptorConfig;
import com.hazelcast.config.XMLConfigBuilderTest;
import com.hazelcast.core.HazelcastException;
import com.hazelcast.test.HazelcastSerialClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.ByteOrder;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import static com.hazelcast.nio.IOUtil.delete;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* This class tests the usage of {@link XmlClientConfigBuilder}
*/
// tests need to be executed sequentially because of system properties being set/unset
@RunWith(HazelcastSerialClassRunner.class)
@Category(QuickTest.class)
public class XmlClientConfigBuilderTest extends HazelcastTestSupport {
static final String HAZELCAST_CLIENT_START_TAG =
"<hazelcast-client xmlns=\"http://www.hazelcast.com/schema/client-config\">\n";
static final String HAZELCAST_CLIENT_END_TAG = "</hazelcast-client>";
private ClientConfig clientConfig;
@Before
public void init() throws Exception {
URL schemaResource = XMLConfigBuilderTest.class.getClassLoader().getResource("hazelcast-client-full.xml");
clientConfig = new XmlClientConfigBuilder(schemaResource).build();
}
@After
@Before
public void after() {
System.clearProperty("hazelcast.client.config");
}
@Test(expected = InvalidConfigurationException.class)
public void testInvalidRootElement() {
String xml = "<hazelcast>"
+ "<group>"
+ "<name>dev</name>"
+ "<password>clusterpass</password>"
+ "</group>"
+ "</hazelcast>";
buildConfig(xml);
}
@Test(expected = HazelcastException.class)
public void loadingThroughSystemProperty_nonExistingFile() throws IOException {
File file = File.createTempFile("foo", "bar");
delete(file);
System.setProperty("hazelcast.client.config", file.getAbsolutePath());
new XmlClientConfigBuilder();
}
@Test
public void loadingThroughSystemProperty_existingFile() throws IOException {
String xml = HAZELCAST_CLIENT_START_TAG
+ " <group>\n"
+ " <name>foobar</name>\n"
+ " <password>dev-pass</password>\n"
+ " </group>\n"
+ "</hazelcast-client>";
File file = File.createTempFile("foo", "bar");
file.deleteOnExit();
PrintWriter writer = new PrintWriter(file, "UTF-8");
writer.println(xml);
writer.close();
System.setProperty("hazelcast.client.config", file.getAbsolutePath());
XmlClientConfigBuilder configBuilder = new XmlClientConfigBuilder();
ClientConfig config = configBuilder.build();
assertEquals("foobar", config.getGroupConfig().getName());
}
@Test(expected = HazelcastException.class)
public void loadingThroughSystemProperty_nonExistingClasspathResource() throws IOException {
System.setProperty("hazelcast.client.config", "classpath:idontexist");
new XmlClientConfigBuilder();
}
@Test
public void loadingThroughSystemProperty_existingClasspathResource() throws IOException {
System.setProperty("hazelcast.client.config", "classpath:test-hazelcast-client.xml");
XmlClientConfigBuilder configBuilder = new XmlClientConfigBuilder();
ClientConfig config = configBuilder.build();
assertEquals("foobar", config.getGroupConfig().getName());
assertEquals("com.hazelcast.nio.ssl.BasicSSLContextFactory", config.getNetworkConfig().getSSLConfig().getFactoryClassName());
assertEquals(128, config.getNetworkConfig().getSocketOptions().getBufferSize());
assertFalse(config.getNetworkConfig().getSocketOptions().isKeepAlive());
assertFalse(config.getNetworkConfig().getSocketOptions().isTcpNoDelay());
assertEquals(3, config.getNetworkConfig().getSocketOptions().getLingerSeconds());
}
@Test
public void testGroupConfig() {
final GroupConfig groupConfig = clientConfig.getGroupConfig();
assertEquals("dev", groupConfig.getName());
assertEquals("dev-pass", groupConfig.getPassword());
}
@Test
public void testProperties() {
assertEquals(6, clientConfig.getProperties().size());
assertEquals("60000", clientConfig.getProperty("hazelcast.client.heartbeat.timeout"));
}
@Test
public void testNetworkConfig() {
final ClientNetworkConfig networkConfig = clientConfig.getNetworkConfig();
assertEquals(2, networkConfig.getConnectionAttemptLimit());
assertEquals(2, networkConfig.getAddresses().size());
assertContains(networkConfig.getAddresses(), "127.0.0.1");
assertContains(networkConfig.getAddresses(), "127.0.0.2");
assertTrue(networkConfig.isSmartRouting());
assertTrue(networkConfig.isRedoOperation());
final SocketInterceptorConfig socketInterceptorConfig = networkConfig.getSocketInterceptorConfig();
assertTrue(socketInterceptorConfig.isEnabled());
assertEquals("com.hazelcast.examples.MySocketInterceptor", socketInterceptorConfig.getClassName());
assertEquals("bar", socketInterceptorConfig.getProperty("foo"));
final ClientAwsConfig awsConfig = networkConfig.getAwsConfig();
assertTrue(awsConfig.isEnabled());
assertTrue(awsConfig.isInsideAws());
assertEquals("TEST_ACCESS_KEY", awsConfig.getAccessKey());
assertEquals("TEST_ACCESS_KEY", awsConfig.getAccessKey());
assertEquals("TEST_SECRET_KEY", awsConfig.getSecretKey());
assertEquals("us-east-1", awsConfig.getRegion());
assertEquals("ec2.amazonaws.com", awsConfig.getHostHeader());
assertEquals("type", awsConfig.getTagKey());
assertEquals("hz-nodes", awsConfig.getTagValue());
assertEquals(11, awsConfig.getConnectionTimeoutSeconds());
}
@Test
public void testSerializationConfig() {
final SerializationConfig serializationConfig = clientConfig.getSerializationConfig();
assertEquals(3, serializationConfig.getPortableVersion());
final Map<Integer, String> dsClasses = serializationConfig.getDataSerializableFactoryClasses();
assertEquals(1, dsClasses.size());
assertEquals("com.hazelcast.examples.DataSerializableFactory", dsClasses.get(1));
final Map<Integer, String> pfClasses = serializationConfig.getPortableFactoryClasses();
assertEquals(1, pfClasses.size());
assertEquals("com.hazelcast.examples.PortableFactory", pfClasses.get(2));
final Collection<SerializerConfig> serializerConfigs = serializationConfig.getSerializerConfigs();
assertEquals(1, serializerConfigs.size());
final SerializerConfig serializerConfig = serializerConfigs.iterator().next();
assertEquals("com.hazelcast.examples.DummyType", serializerConfig.getTypeClassName());
assertEquals("com.hazelcast.examples.SerializerFactory", serializerConfig.getClassName());
final GlobalSerializerConfig globalSerializerConfig = serializationConfig.getGlobalSerializerConfig();
assertEquals("com.hazelcast.examples.GlobalSerializerFactory", globalSerializerConfig.getClassName());
assertEquals(ByteOrder.BIG_ENDIAN, serializationConfig.getByteOrder());
assertTrue(serializationConfig.isCheckClassDefErrors());
assertFalse(serializationConfig.isAllowUnsafe());
assertFalse(serializationConfig.isEnableCompression());
assertTrue(serializationConfig.isEnableSharedObject());
assertTrue(serializationConfig.isUseNativeByteOrder());
}
@Test
public void testProxyFactories() {
final List<ProxyFactoryConfig> pfc = clientConfig.getProxyFactoryConfigs();
assertEquals(3, pfc.size());
assertContains(pfc, new ProxyFactoryConfig("com.hazelcast.examples.ProxyXYZ1", "sampleService1"));
assertContains(pfc, new ProxyFactoryConfig("com.hazelcast.examples.ProxyXYZ2", "sampleService1"));
assertContains(pfc, new ProxyFactoryConfig("com.hazelcast.examples.ProxyXYZ3", "sampleService3"));
}
@Test
public void testNearCacheConfigs() {
assertEquals(1, clientConfig.getNearCacheConfigMap().size());
final NearCacheConfig nearCacheConfig = clientConfig.getNearCacheConfig("asd");
assertEquals(2000, nearCacheConfig.getMaxSize());
assertEquals(2000, nearCacheConfig.getEvictionConfig().getSize());
assertEquals(90, nearCacheConfig.getTimeToLiveSeconds());
assertEquals(100, nearCacheConfig.getMaxIdleSeconds());
assertEquals("LFU", nearCacheConfig.getEvictionPolicy());
assertEquals(EvictionPolicy.LFU, nearCacheConfig.getEvictionConfig().getEvictionPolicy());
assertTrue(nearCacheConfig.isInvalidateOnChange());
assertEquals(InMemoryFormat.OBJECT, nearCacheConfig.getInMemoryFormat());
}
@Test
public void testNearCacheConfig_withEvictionConfig_withPreloaderConfig() throws IOException {
URL schemaResource = XMLConfigBuilderTest.class.getClassLoader().getResource("hazelcast-client-test.xml");
ClientConfig clientConfig = new XmlClientConfigBuilder(schemaResource).build();
assertEquals("MyInstanceName", clientConfig.getInstanceName());
NearCacheConfig nearCacheConfig = clientConfig.getNearCacheConfig("nearCacheWithEvictionAndPreloader");
assertEquals(10000, nearCacheConfig.getTimeToLiveSeconds());
assertEquals(5000, nearCacheConfig.getMaxIdleSeconds());
assertFalse(nearCacheConfig.isInvalidateOnChange());
assertEquals(InMemoryFormat.OBJECT, nearCacheConfig.getInMemoryFormat());
assertTrue(nearCacheConfig.isCacheLocalEntries());
assertNotNull(nearCacheConfig.getEvictionConfig());
assertEquals(100, nearCacheConfig.getEvictionConfig().getSize());
assertEquals(EvictionConfig.MaxSizePolicy.ENTRY_COUNT, nearCacheConfig.getEvictionConfig().getMaximumSizePolicy());
assertEquals(EvictionPolicy.LFU, nearCacheConfig.getEvictionConfig().getEvictionPolicy());
assertNotNull(nearCacheConfig.getPreloaderConfig());
assertTrue(nearCacheConfig.getPreloaderConfig().isEnabled());
assertEquals("/tmp/myNearCache", nearCacheConfig.getPreloaderConfig().getDirectory());
assertEquals(2342, nearCacheConfig.getPreloaderConfig().getStoreInitialDelaySeconds());
assertEquals(4223, nearCacheConfig.getPreloaderConfig().getStoreIntervalSeconds());
}
@Test
public void testQueryCacheFullConfig() throws Exception {
QueryCacheConfig queryCacheConfig = clientConfig.getQueryCacheConfigs().get("map-name").get("query-cache-name");
EntryListenerConfig entryListenerConfig = queryCacheConfig.getEntryListenerConfigs().get(0);
assertEquals("query-cache-name", queryCacheConfig.getName());
assertTrue(entryListenerConfig.isIncludeValue());
assertFalse(entryListenerConfig.isLocal());
assertEquals("com.hazelcast.examples.EntryListener", entryListenerConfig.getClassName());
assertTrue(queryCacheConfig.isIncludeValue());
assertEquals(1, queryCacheConfig.getBatchSize());
assertEquals(16, queryCacheConfig.getBufferSize());
assertEquals(0, queryCacheConfig.getDelaySeconds());
assertEquals(EvictionPolicy.LRU, queryCacheConfig.getEvictionConfig().getEvictionPolicy());
assertEquals(EvictionConfig.MaxSizePolicy.ENTRY_COUNT, queryCacheConfig.getEvictionConfig().getMaximumSizePolicy());
assertEquals(10000, queryCacheConfig.getEvictionConfig().getSize());
assertEquals(InMemoryFormat.BINARY, queryCacheConfig.getInMemoryFormat());
assertFalse(queryCacheConfig.isCoalesce());
assertTrue(queryCacheConfig.isPopulate());
for (MapIndexConfig mapIndexConfig : queryCacheConfig.getIndexConfigs()) {
assertEquals("name", mapIndexConfig.getAttribute());
assertFalse(mapIndexConfig.isOrdered());
}
assertEquals("com.hazelcast.examples.ExamplePredicate", queryCacheConfig.getPredicateConfig().getClassName());
}
@Test
public void testLeftovers() {
assertEquals(40, clientConfig.getExecutorPoolSize());
assertEquals("com.hazelcast.security.UsernamePasswordCredentials",
clientConfig.getSecurityConfig().getCredentialsClassname());
assertEquals(40, clientConfig.getExecutorPoolSize());
assertEquals("com.hazelcast.client.util.RandomLB", clientConfig.getLoadBalancer().getClass().getName());
final List<ListenerConfig> listenerConfigs = clientConfig.getListenerConfigs();
assertEquals(3, listenerConfigs.size());
assertContains(listenerConfigs, new ListenerConfig("com.hazelcast.examples.MembershipListener"));
assertContains(listenerConfigs, new ListenerConfig("com.hazelcast.examples.InstanceListener"));
assertContains(listenerConfigs, new ListenerConfig("com.hazelcast.examples.MigrationListener"));
}
@Test
public void testXSDDefaultXML() throws SAXException, IOException {
testXSDConfigXML("hazelcast-client-default.xml");
}
@Test
public void testFullConfigXML() throws SAXException, IOException {
testXSDConfigXML("hazelcast-client-full.xml");
}
@Test(expected = InvalidConfigurationException.class)
public void testMissingNamespace() {
String xml = "<hazelcast-client/>";
buildConfig(xml);
}
@Test(expected = InvalidConfigurationException.class)
public void testInvalidNamespace() {
String xml = "<hazelcast-client xmlns=\"http://foo.bar\"/>";
buildConfig(xml);
}
@Test
public void testValidNamespace() {
String xml = HAZELCAST_CLIENT_START_TAG + "</hazelcast-client>";
buildConfig(xml);
}
@Test(expected = InvalidConfigurationException.class)
public void testHazelcastClientTagAppearsTwice() {
String xml = HAZELCAST_CLIENT_START_TAG + "<hazelcast-client/></<hazelcast-client>";
buildConfig(xml);
}
@Test
public void testNearCacheEvictionPolicy() {
String xml = HAZELCAST_CLIENT_START_TAG
+ "<near-cache name=\"lfu\">"
+ " <eviction eviction-policy=\"LFU\"/>"
+ "</near-cache>"
+ "<near-cache name=\"lru\">"
+ " <eviction eviction-policy=\"LRU\"/>"
+ "</near-cache>"
+ "<near-cache name=\"none\">"
+ " <eviction eviction-policy=\"NONE\"/>"
+ "</near-cache>"
+ "<near-cache name=\"random\">"
+ " <eviction eviction-policy=\"RANDOM\"/>"
+ "</near-cache>"
+ HAZELCAST_CLIENT_END_TAG;
ClientConfig clientConfig = buildConfig(xml);
assertEquals(EvictionPolicy.LFU, getNearCacheEvictionPolicy("lfu", clientConfig));
assertEquals(EvictionPolicy.LRU, getNearCacheEvictionPolicy("lru", clientConfig));
assertEquals(EvictionPolicy.NONE, getNearCacheEvictionPolicy("none", clientConfig));
assertEquals(EvictionPolicy.RANDOM, getNearCacheEvictionPolicy("random", clientConfig));
}
private EvictionPolicy getNearCacheEvictionPolicy(String mapName, ClientConfig clientConfig) {
return clientConfig.getNearCacheConfig(mapName).getEvictionConfig().getEvictionPolicy();
}
static ClientConfig buildConfig(String xml, Properties properties) {
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes());
XmlClientConfigBuilder configBuilder = new XmlClientConfigBuilder(bis);
configBuilder.setProperties(properties);
return configBuilder.build();
}
static ClientConfig buildConfig(String xml, String key, String value) {
Properties properties = new Properties();
properties.setProperty(key, value);
return buildConfig(xml, properties);
}
public static ClientConfig buildConfig(String xml) {
return buildConfig(xml, null);
}
private void testXSDConfigXML(String xmlFileName) throws SAXException, IOException {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
URL schemaResource = XMLConfigBuilderTest.class.getClassLoader().getResource("hazelcast-client-config-3.9.xsd");
InputStream xmlResource = XMLConfigBuilderTest.class.getClassLoader().getResourceAsStream(xmlFileName);
Schema schema = factory.newSchema(schemaResource);
Source source = new StreamSource(xmlResource);
Validator validator = schema.newValidator();
try {
validator.validate(source);
} catch (SAXException ex) {
fail(xmlFileName + " is not valid because: " + ex.toString());
}
}
}