/**
* VMware Continuent Tungsten Replicator
* Copyright (C) 2015 VMware, 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.
*
* Initial developer(s): Ludovic Launer
*/
package com.continuent.tungsten.common.security;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLSocketFactory;
import junit.framework.TestCase;
import org.junit.Assert;
import com.continuent.tungsten.common.config.TungstenProperties;
import com.continuent.tungsten.common.config.cluster.ConfigurationException;
import com.continuent.tungsten.common.jmx.ServerRuntimeException;
import com.continuent.tungsten.common.security.SecurityHelper.TUNGSTEN_APPLICATION_NAME;
/**
* Implements a simple unit test for SecurityHelper
*
* @author <a href="mailto:ludovic.launer@continuent.com">Ludovic Launer</a>
* @version 1.0
*/
public class SecurityHelperTest extends TestCase
{
public static int stopNow = 0;
/**
* Test we can retrieve passwords from the passwords.store file
*
* @throws Exception
*/
public void testLoadPasswordsFromFile() throws Exception
{
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
authenticationInfo.setPasswordFileLocation("sample.passwords.store");
// This should not be null if we retrieve passwords from the file
TungstenProperties tungsteProperties = SecurityHelper
.loadPasswordsFromAuthenticationInfo(authenticationInfo);
assertNotNull(tungsteProperties);
}
/**
* Test we can retrieve authentication information from the
* security.properties file
*
* @throws ConfigurationException
*/
public void testloadAuthenticationInformation()
throws ConfigurationException
{
// Get authInfo from the configuration file on the CLIENT_SIDE
AuthenticationInfo authInfo = SecurityHelper
.loadAuthenticationInformation("sample.security.properties");
assertNotNull(authInfo);
// Get authInfo from the configuration file on the SERVER_SIDE
authInfo = SecurityHelper
.loadAuthenticationInformation("sample.security.properties");
assertNotNull(authInfo);
// Check that an Exception is thrown when the configuration file is not
// found
ConfigurationException configurationException = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"sample.security.properties_DOES_NOT_EXIST");
}
catch (ConfigurationException ce)
{
configurationException = ce;
}
assertNotNull(configurationException);
}
/**
* Confirm that we can retrieve values from the security.properties file
*
* @throws ConfigurationException
*/
public void testRetrieveInformation() throws ConfigurationException
{
// Get authInfo from the configuration file on the SERVER_SIDE
AuthenticationInfo authInfo = SecurityHelper
.loadAuthenticationInformation("sample.security.properties");
assertNotNull(authInfo);
TungstenProperties securityProp = authInfo.getAsTungstenProperties();
assertNotNull(securityProp);
Boolean useJmxAuthentication = securityProp
.getBoolean(SecurityConf.SECURITY_JMX_USE_AUTHENTICATION);
assertNotNull(useJmxAuthentication);
}
/**
* Reset system properties to null value
*/
public static void resetSecuritySystemProperties()
{
System.clearProperty("javax.net.ssl.keyStore");
System.clearProperty("javax.net.ssl.keyStorePassword");
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
System.clearProperty("javax.rmi.ssl.client.enabledCipherSuites");
System.clearProperty(SecurityConf.SYSTEM_PROP_CLIENT_SSLPROTOCOLS);
System.clearProperty(SecurityConf.SYSTEM_PROP_CLIENT_SSLCIPHERS);
System.clearProperty("https.protocols");
}
/**
* Confirm that once we have loaded the security information, it becomes
* available in system properties
*
* @throws ConfigurationException
*/
public void testloadAuthenticationInformation_and_setSystemProperties()
throws ConfigurationException
{
// Reset info
resetSecuritySystemProperties();
// Get authInfo from the configuration file on the SERVER_SIDE
AuthenticationInfo authInfo = SecurityHelper
.loadAuthenticationInformation("sample.security.properties");
assertNotNull(authInfo);
// Check it's available in system wide properties
String systemProperty = null;
systemProperty = System.getProperty("javax.net.ssl.keyStore", null);
assertNotNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.keyStorePassword",
null);
assertNotNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.trustStore", null);
assertNotNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.trustStorePassword",
null);
assertNotNull(systemProperty);
}
/**
* Confirm that once we have loaded the security information, it becomes
* available in system properties Confirm that application specific info is
* used Note: Connector only info for now
*
* @throws ConfigurationException
*/
public void testloadAuthenticationInformation_and_setSystemProperties_4_Connector()
{
// Reset info
resetSecuritySystemProperties();
// Get authInfo from the configuration file on the SERVER_SIDE
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"sample.security.properties", false,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ConfigurationException e)
{
assertFalse("Could not load authentication and securiy information",
true);
}
assertNotNull(authInfo);
// Check it's available in system wide properties
String systemProperty = null;
systemProperty = System.getProperty("javax.net.ssl.keyStore", null);
assertNotNull(systemProperty);
assertTrue(systemProperty.contains("connector"));
systemProperty = System.getProperty("javax.net.ssl.keyStorePassword",
null);
assertNotNull(systemProperty);
assertTrue(systemProperty.contains("connector"));
systemProperty = System.getProperty("javax.net.ssl.trustStore", null);
assertNotNull(systemProperty);
assertTrue(systemProperty.contains("connector"));
systemProperty = System.getProperty("javax.net.ssl.trustStorePassword",
null);
assertNotNull(systemProperty);
assertTrue(systemProperty.contains("connector"));
}
/**
* Confirm that when set to empty in the configuration file, important
* properties are set to null and not ""
*
* @throws ConfigurationException
*/
public void testCrucialEmptyPropertiesAreNull()
{
// Reset info
resetSecuritySystemProperties();
// Get authInfo from the configuration file on the SERVER_SIDE
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ConfigurationException e)
{
assertFalse("Could not load authentication and securiy information",
true);
}
assertNotNull(authInfo);
assertTrue(authInfo.getKeystoreLocation() == null);
assertTrue(authInfo.getTruststoreLocation() == null);
}
/**
* Confirm behavior when connector.security.use.SSL=false
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_false()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that by default connector.security.use.SSL=false
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ConfigurationException e)
{
assertFalse("Could not load authentication and securiy information",
true);
}
assertFalse(authInfo.isConnectorUseSSL());
// Confirm that unnecessary information has been deleted
assertNull(authInfo.getKeystoreLocation());
assertNull(authInfo.getKeystorePassword());
assertNull(authInfo.getTruststoreLocation());
assertNull(authInfo.getTruststorePassword());
// Check it's NOT available in system wide properties
String systemProperty = null;
systemProperty = System.getProperty("javax.net.ssl.keyStore", null);
assertNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.keyStorePassword",
null);
assertNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.trustStore", null);
assertNull(systemProperty);
systemProperty = System.getProperty("javax.net.ssl.trustStorePassword",
null);
assertNull(systemProperty);
}
// Determines whether protocols, cipher suites or both properties is set to empty.
private static enum TEST_ARG {PROTOCOLS, CIPHERS, BOTH};
/**
* check that loading AuthenticationInfo also succeeds with empty protocol
* property
*/
public void testSSLWithEmptyProtocolsProperty()
{
testSSLProtocolsAndCipherSuitesProperties(SecurityHelperTest.TEST_ARG.PROTOCOLS);
}
/**
* check that loading AuthenticationInfo also succeeds with empty cipher
* suites property
*/
public void testSSLWithEmptyCipherSuitesProperty()
{
testSSLProtocolsAndCipherSuitesProperties(SecurityHelperTest.TEST_ARG.CIPHERS);
}
/**
* check that loading AuthenticationInfo also succeeds with empty protocols
* and cipher suites properties
*/
public void testSSLWithEmptyProtocolsAndCipherSuitesProperties()
{
testSSLProtocolsAndCipherSuitesProperties(SecurityHelperTest.TEST_ARG.BOTH);
}
/**
* check that loading AuthenticationInfo also succeeds with empty protocols
* and cipher suites properties
*/
private void testSSLProtocolsAndCipherSuitesProperties(SecurityHelperTest.TEST_ARG arg)
{
// Reset info
resetSecuritySystemProperties();
// Confirm that by default connector.security.use.SSL=false
AuthenticationInfo authInfo = null;
try
{
List <String> emptyList = new ArrayList <String>();
authInfo = SecurityHelper.loadAuthenticationInformation(
"sample.security.properties");
if (arg == SecurityHelperTest.TEST_ARG.PROTOCOLS)
{
// Set empty protocols property
authInfo.setEnabledProtocols(emptyList);
}
else if (arg == SecurityHelperTest.TEST_ARG.CIPHERS)
{
// Set empty cipher suites property
authInfo.setEnabledCipherSuites(emptyList);
}
else if (arg == SecurityHelperTest.TEST_ARG.BOTH)
{
// Set empty protocols property
authInfo.setEnabledProtocols(emptyList);
// Set empty cipher suites property
authInfo.setEnabledCipherSuites(emptyList);
}
// Test
SecurityHelper.testSetSecurityProperties(authInfo, true);
}
catch (ConfigurationException e)
{
assertFalse("Could not load authentication and securiy information",
true);
}
assertTrue(authInfo.isConnectorUseSSL());
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm behavior when connector.security.use.SSL=true
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_true()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that by default connector.security.use.SSL=false
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"sample.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ConfigurationException e)
{
assertFalse("Could not load authentication and securiy information",
true);
}
assertTrue(authInfo.isConnectorUseSSL());
}
/**
* Confirm behavior when connector.security.use.SSL=true
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_errors_true()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when keystore location is not
// specified
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("An exception was thrown, that's expected !", true);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
assertEquals(null, authInfo);
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when trustore location is not
// specified
authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl2.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("An exception was thrown, that's expected !", true);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
assertEquals(null, authInfo);
}
/**
* Confirm behavior when connector.security.use.SSL=true and alias are
* defined
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_alias()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when keystore location is not
// specified
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl.alias.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("There should not be any exception thrown", false);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm behavior when connector.security.use.SSL=true and wrong alias is
* specified
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_alias_error()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when keystore location is not
// specified
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl.alias.wrong.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("An exception was thrown, that's expected !", true);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm behavior when connector.security.use.SSL=true and alias is
* defined + alias is not the first in the list inside the keystore. This
* shows that we can select an alias inside the keystore
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_alias_2()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when keystore location is not
// specified
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl.alias.2.position.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("There should not be any exception thrown", false);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm behavior when connector.security.use.SSL=true and alias are not
* defined This shows that it uses first alias it finds
*
* @throws ConfigurationException
*/
public void testConnectorSecuritySettingsSSL_alias_not_defined()
{
// Reset info
resetSecuritySystemProperties();
// Confirm that exception is thrown when keystore location is not
// specified
AuthenticationInfo authInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.ssl.alias.not.defined.security.properties", true,
TUNGSTEN_APPLICATION_NAME.CONNECTOR);
}
catch (ServerRuntimeException e)
{
assertTrue("There should not be any exception thrown", false);
}
catch (ConfigurationException e)
{
assertFalse(
"That should not be this kind of Exception being thrown",
true);
}
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm that an Exception is thrown when the security.properties files
* does not pass validation. Confirm validation steps
*
* @throws ConfigurationException
*/
public void testValidateSecurityProperties()
throws ConfigurationException, ServerRuntimeException
{
// Reset info
resetSecuritySystemProperties();
// Confirm that initial values are OK
AuthenticationInfo authInfo = null;
AuthenticationInfo badAuthInfo = null;
try
{
authInfo = SecurityHelper.loadAuthenticationInformation(
"test.validation.security.properties", true,
TUNGSTEN_APPLICATION_NAME.REST_API);
badAuthInfo = (AuthenticationInfo) authInfo.clone();
}
catch (ConfigurationException e)
{
assertFalse(
"Initial values should not cause an exception as they are supposed to be OK",
true);
}
// --- Try validations steps one after the other ---
// ###### REST API: If Authentication is on, Encryption can be off
badAuthInfo.setAuthenticationNeeded(true);
try
{
badAuthInfo.setAuthenticationNeeded(true);
assertFalse(badAuthInfo.isEncryptionNeeded()); // Encryption is off
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse(badAuthInfo.isEncryptionNeeded()); // Not Updated to
// true
}
catch (ConfigurationException e)
{
assertTrue(
"That should not throw an exception, just update values.",
false);
}
// ############################## Check password file location ########
badAuthInfo = (AuthenticationInfo) authInfo.clone();
// Feature off + bad value
badAuthInfo.setPasswordFileLocation(
badAuthInfo.getPasswordFileLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("Authentication not needed. No exception was thrown.", true);
// Feature on + good value
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setAuthenticationNeeded(true);
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("File exists, no exception should be thrown !", true);
// Feature on + bad value
try
{
badAuthInfo.setPasswordFileLocation(
badAuthInfo.getPasswordFileLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ServerRuntimeException e)
{
assertTrue("That's expected", true);
}
// ############################## Check keystore for https ###########
badAuthInfo = (AuthenticationInfo) authInfo.clone();
// Feature off + bad value
badAuthInfo.setKeystoreLocation(
badAuthInfo.getKeystoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("Feature off. No exception was thrown.", true);
// Feature on + good value
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setEncryptionNeeded(true);
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("File exists, no exception should be thrown !", true);
// Feature on + bad value
try
{
badAuthInfo.setKeystoreLocation(
badAuthInfo.getKeystoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ServerRuntimeException e)
{
assertTrue("That's expected", true);
}
// ############################## Check trustore for server ###########
badAuthInfo = (AuthenticationInfo) authInfo.clone();
// Feature off + bad value
badAuthInfo.setTruststoreLocation(
badAuthInfo.getTruststoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("Feature off, no exception should be thrown !", true);
// Feature on + good value
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setEncryptionNeeded(true);
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("File exists, no exception should be thrown !", true);
// Feature on + bad value
try
{
badAuthInfo.setTruststoreLocation(
badAuthInfo.getTruststoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (Exception ee)
{
assertTrue("That's expected", true);
}
// ############################## Check keystore for client ###########
badAuthInfo = (AuthenticationInfo) authInfo.clone();
// Feature off + bad value
badAuthInfo.setClientKeystoreLocation(
badAuthInfo.getClientKeystoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("Feature off. No exception was thrown.", true);
// Feature on + good value
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setAuthenticationNeeded(true);
badAuthInfo.setAuthenticationByCertificateNeeded(true);
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("File exists, no exception should be thrown !", true);
// Feature on + bad value
try
{
badAuthInfo.setClientKeystoreLocation(
badAuthInfo.getClientKeystoreLocation() + "_XXX");
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ServerRuntimeException e)
{
assertTrue("That's expected", true);
}
// ######################## Check non empty aliases in Keystore #######
// This also checks that the password can open the keystore
String EMPTY_KEYSTORE = "empty_keystore.jks";
badAuthInfo = (AuthenticationInfo) authInfo.clone();
// Feature off + bad value
badAuthInfo.setKeystoreLocation(EMPTY_KEYSTORE);
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertTrue("Feature off. No exception was thrown.", true);
// Feature on + bad value (empty aliases)
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setEncryptionNeeded(true);
badAuthInfo.setKeystoreLocation(EMPTY_KEYSTORE);
try
{
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ConfigurationException e)
{
assertTrue("That's expected", true);
}
// Feature on + bad value (wrong password)
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setEncryptionNeeded(true);
badAuthInfo.setKeystoreLocation(EMPTY_KEYSTORE);
badAuthInfo.setKeystorePassword("bad_password");
try
{
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ConfigurationException e)
{
assertTrue("That's expected", true);
}
// Check that the trustore is accessible
// Feature on + bad value (empty aliases)
badAuthInfo = (AuthenticationInfo) authInfo.clone();
badAuthInfo.setEncryptionNeeded(true);
badAuthInfo.setTruststorePassword(
badAuthInfo.getTruststorePassword() + "_XXX");
try
{
badAuthInfo.checkAndCleanAuthenticationInfo(
TUNGSTEN_APPLICATION_NAME.REST_API);
assertFalse("Exception should have been thrown !", true);
}
catch (ConfigurationException e)
{
assertTrue("That's expected", true);
}
// Reset info
resetSecuritySystemProperties();
}
/**
* Confirm that the SecurityHelper.getMatchingStrings() method correctly
* computes intersection between two arrays of strings.
*
* @throws ConfigurationException
*/
public void testMatchingStrings()
throws ConfigurationException, ServerRuntimeException
{
String[] s0 = {};
String[] s1 = {"abcd"};
String[] s2 = {"defg", "abcd"};
String[] s3 = {"hijk", "abcd", "defg"};
String[] s4 = {"0123", "defg", "hijl", "abcd"};
String[] s5 = {"0123", "0234"};
// Prove that intersecting with empty array results in empty array.
Assert.assertArrayEquals(s0, SecurityHelper.getMatchingStrings(s0, s1));
Assert.assertArrayEquals(s0, SecurityHelper.getMatchingStrings(s3, s0));
// Prove that intersecting with a single member results in just that
// member.
Assert.assertArrayEquals(s1, SecurityHelper.getMatchingStrings(s1, s1));
Assert.assertArrayEquals(s1, SecurityHelper.getMatchingStrings(s2, s1));
Assert.assertArrayEquals(s1, SecurityHelper.getMatchingStrings(s3, s1));
// Prove that intersection with multiple members results in only common
// members. Sort result to ensure match.
String[] intersection = SecurityHelper.getMatchingStrings(s3, s4);
Arrays.sort(intersection);
Assert.assertArrayEquals(new String[]{"abcd", "defg"}, intersection);
// Prove that disjoint array values result in an empty set.
Assert.assertArrayEquals(s0, SecurityHelper.getMatchingStrings(s3, s5));
}
/**
* Confirm that RealmJMXAuthenticator.getRandomInt(min, max) always returns
* a coherent value
*/
public void testRealmJMXAuthenticatorRandomNumberGenerator()
{
// 0 value -> 0
int randomNumber = SecurityHelper.getRandomInt(0, 0, 0);
assertTrue(randomNumber == 0);
// negative values -> 0
randomNumber = SecurityHelper.getRandomInt(-1, -10, 1);
assertTrue(randomNumber == 0);
// One negative value -> 0 and other value
randomNumber = SecurityHelper.getRandomInt(-10, 2, 1);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
randomNumber >= 0 && randomNumber <= 2);
// inverted min and max -> revert values
randomNumber = SecurityHelper.getRandomInt(5, 2, 1);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
randomNumber <= 5 && randomNumber >= 2);
// steps of 100
randomNumber = SecurityHelper.getRandomInt(500, 3000, 100);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
(randomNumber - 500) % 100 == 0);
// steps of 15
randomNumber = SecurityHelper.getRandomInt(500, 3000, 15);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
(randomNumber - 500) % 15 == 0);
// step of 0 -> step of 1
randomNumber = SecurityHelper.getRandomInt(500, 3000, 0);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
randomNumber >= 500 && randomNumber <= 3000);
// step > max-min
randomNumber = SecurityHelper.getRandomInt(0, 10, 11);
assertTrue(MessageFormat.format("randomNumber={0}", randomNumber),
randomNumber >= 0 && randomNumber <= 10);
}
}