/**
* Copyright 2013-2015 Seagate Technology LLC.
*
* This Source Code Form is subject to the terms of the Mozilla
* Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at
* https://mozilla.org/MP:/2.0/.
*
* This program is distributed in the hope that it will be useful,
* but is provided AS-IS, WITHOUT ANY WARRANTY; including without
* the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or
* FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public
* License for more details.
*
* See www.openkinetic.org for more project information
*/
package com.seagate.kinetic;
import static com.seagate.kinetic.KineticTestHelpers.toByteArray;
import static org.testng.AssertJUnit.assertEquals;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import kinetic.admin.AdminClientConfiguration;
import kinetic.admin.KineticAdminClient;
import kinetic.admin.KineticAdminClientFactory;
import kinetic.client.ClientConfiguration;
import kinetic.client.Entry;
import kinetic.client.KineticClient;
import kinetic.client.KineticException;
import kinetic.client.p2p.KineticP2PClientFactory;
import kinetic.client.p2p.KineticP2pClient;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import com.google.protobuf.ByteString;
import com.jcraft.jsch.JSchException;
import com.seagate.kinetic.client.internal.MessageFactory;
import com.seagate.kinetic.common.lib.KineticMessage;
import com.seagate.kinetic.proto.Kinetic;
import com.seagate.kinetic.proto.Kinetic.Command;
import com.seagate.kinetic.proto.Kinetic.Command.Header;
import com.seagate.kinetic.proto.Kinetic.Command.Security.ACL.Permission;
/**
* Kinetic client integration test case.
* <p>
* The methods are used before and after every kinetic client test case.
* <p>
*
*
*/
public class IntegrationTestCase {
protected static final String NONNIO_NONSSL_CLIENT = "nonNio_nonSsl";
protected static final String NIO_NONSSL_CLIENT = "nio_nonSsl";
protected static final String NONNIO_SSL_CLIENT = "nonNio_ssl";
protected Map<String, KineticP2pClient> kineticClients = new HashMap<String, KineticP2pClient>();
protected Map<String, ClientConfiguration> kineticClientConfigutations = new HashMap<String, ClientConfiguration>();
private KineticAdminClient adminClient;
private AbstractIntegrationTestTarget testTarget;
/**
* Initialize a test server and a Kinetic client.
* <p>
*
* @throws KineticException
* if any internal error occurred.
* @throws IOException
* if any IO error occurred
* @throws InterruptedException
* if any Interrupt error occurred
*/
@BeforeClass(alwaysRun = true)
public void startTestServer() throws InterruptedException,
KineticException, IOException, JSchException, ExecutionException {
createKineticClientConfigurations();
testTarget = IntegrationTestTargetFactory.createTestTarget(true);
kineticClients.clear();
for (String clientName : kineticClientConfigutations.keySet()) {
kineticClients.put(clientName, KineticP2PClientFactory
.createP2pClient(kineticClientConfigutations
.get(clientName)));
}
adminClient = KineticAdminClientFactory
.createInstance(getAdminClientConfig());
}
/**
* Stop a test server and a Kinetic client.
* <p>
*
* @throws KineticException
* if any internal error occurred.
* @throws IOException
* if any IO error occurred.
*/
@AfterClass(alwaysRun = true)
public void stopTestServer() throws Exception {
closeKineticClients();
if (null != adminClient) {
adminClient.close();
}
testTarget.shutdown();
}
@BeforeSuite(alwaysRun = true)
protected void securityEraseTarget() throws KineticException {
if (Boolean.parseBoolean(System.getProperty("RUN_AGAINST_EXTERNAL"))) {
AdminClientConfiguration acc = new AdminClientConfiguration();
acc.setHost(System.getProperty("KINETIC_HOST", "127.0.0.1"));
acc.setPort(Integer.parseInt(System.getProperty("KINETIC_SSL_PORT",
"8443")));
KineticAdminClient kac = KineticAdminClientFactory
.createInstance(acc);
String oldErasePin = System.getProperty("OLD_PIN", "");
String newErasePin = System.getProperty("NEW_PIN", "123");
kac.setErasePin(toByteArray(oldErasePin), toByteArray(newErasePin));
kac.instantErase(toByteArray(newErasePin));
kac.close();
}
}
/**
* Get a Kinetic client.
* <p>
*/
protected KineticP2pClient getClient(String clientName) {
return kineticClients.get(clientName);
}
protected KineticAdminClient getAdminClient() {
return adminClient;
}
/**
* Get a Kinetic client configuration with default setting.
* <p>
*/
protected ClientConfiguration getClientConfig() {
ClientConfiguration clientConfiguration = IntegrationTestTargetFactory
.createDefaultClientConfig();
return clientConfiguration;
}
/**
* Get a Kinetic client configuration with setting userId and key flexible.
* <p>
*/
protected ClientConfiguration getClientConfig(int userId, String key) {
ClientConfiguration clientConfiguration = getClientConfig();
clientConfiguration.setUserId(userId);
clientConfiguration.setKey(key);
return clientConfiguration;
}
/**
* Get a Kinetic client configuration with setting cluster version flexible.
* <p>
*/
protected ClientConfiguration getClientConfig(long clusterVersion) {
ClientConfiguration clientConfiguration = getClientConfig();
clientConfiguration.setClusterVersion(clusterVersion);
return clientConfiguration;
}
/**
* Get a Kinetic client configuration with default setting.
* <p>
*/
protected AdminClientConfiguration getAdminClientConfig() {
AdminClientConfiguration adminClientConfiguration = testTarget
.getAdminClientConfig();
return adminClientConfiguration;
}
/**
* Get a Kinetic client configuration with setting cluster version flexible.
* <p>
*/
protected AdminClientConfiguration getAdminClientConfig(long clusterVersion) {
AdminClientConfiguration adminClientConfiguration = testTarget
.getAdminClientConfig();
adminClientConfiguration.setClusterVersion(clusterVersion);
return adminClientConfiguration;
}
/**
* Get a Kinetic admin client configuration with setting userId and key
* flexible.
* <p>
*/
protected AdminClientConfiguration getAdminClientConfig(int userId,
String key) {
AdminClientConfiguration adminClientConfiguration = getAdminClientConfig();
adminClientConfiguration.setUserId(userId);
adminClientConfiguration.setKey(key);
return adminClientConfiguration;
}
/**
* Restart the server and the Kinetic client.
* <p>
*/
protected void restartServer() throws Exception {
closeKineticClients();
adminClient.close();
testTarget.shutdown();
testTarget = IntegrationTestTargetFactory.createTestTarget(false);
kineticClients.clear();
for (String clientName : kineticClientConfigutations.keySet()) {
kineticClients.put(clientName, KineticP2PClientFactory
.createP2pClient(kineticClientConfigutations
.get(clientName)));
}
adminClient = KineticAdminClientFactory
.createInstance(getAdminClientConfig());
}
/**
* Test case begin log info.
* <p>
*/
protected String testBeginInfo() {
String className = Thread.currentThread().getStackTrace()[2]
.getClassName();
String methodName = Thread.currentThread().getStackTrace()[2]
.getMethodName();
return (className + "#" + methodName + " test starting...");
}
/**
* Test case end log info.
* <p>
*/
protected String testEndInfo() {
return ("status=success");
}
/**
* Useful for writing tests which exercise permissions corner cases. Creates
* a new client and adds the given roles to the client's ACL
*
* @param clientId
* @param clientKeyString
* @param roles
* @throws KineticException
*/
public void createClientAclWithRoles(String clientName, int clientId,
String clientKeyString,
List<Kinetic.Command.Security.ACL.Permission> roles)
throws KineticException {
Kinetic.Command.Security.ACL.Scope.Builder domain = Kinetic.Command.Security.ACL.Scope
.newBuilder();
for (Kinetic.Command.Security.ACL.Permission role : roles) {
domain.addPermission(role);
}
createClientAclWithDomains(clientName, clientId, clientKeyString,
Collections.singletonList(domain.build()));
// create a admin clientId with all permission to avoid user nor found.
List<Kinetic.Command.Security.ACL.Permission> rolesAll = new ArrayList<Kinetic.Command.Security.ACL.Permission>();
rolesAll.add(Permission.DELETE);
rolesAll.add(Permission.GETLOG);
rolesAll.add(Permission.P2POP);
rolesAll.add(Permission.RANGE);
rolesAll.add(Permission.READ);
rolesAll.add(Permission.SECURITY);
rolesAll.add(Permission.SETUP);
rolesAll.add(Permission.WRITE);
int clientIdAdmin = 1;
String clientIdAdminKey = "asdfasdf";
Kinetic.Command.Security.ACL.Scope.Builder domainAll = Kinetic.Command.Security.ACL.Scope
.newBuilder();
for (Kinetic.Command.Security.ACL.Permission role : rolesAll) {
domainAll.addPermission(role);
}
createClientAclWithDomains(clientName, clientIdAdmin, clientIdAdminKey,
Collections.singletonList(domainAll.build()));
}
/**
* Useful for writing tests which exercise permissions corner cases. Creates
* a new client and adds the given domains to the client's ACL
*
* @param clientId
* @param clientKeyString
* @param domains
* @throws KineticException
*/
public void createClientAclWithDomains(String clientName, int clientId,
String clientKeyString,
List<Kinetic.Command.Security.ACL.Scope> domains)
throws KineticException {
KineticMessage km = MessageFactory.createKineticMessageWithBuilder();
// Kinetic.Message.Builder request = (Kinetic.Message.Builder)
// km.getMessage();
Kinetic.Command.Builder commandBuilder = (Kinetic.Command.Builder) km
.getCommand();
Header.Builder header = commandBuilder.getHeaderBuilder();
header.setMessageType(Command.MessageType.SECURITY);
Kinetic.Command.Security.Builder security = commandBuilder
.getBodyBuilder().getSecurityBuilder();
Kinetic.Command.Security.ACL.Builder acl = Kinetic.Command.Security.ACL
.newBuilder();
acl.setIdentity(clientId);
acl.setKey(ByteString.copyFromUtf8(clientKeyString));
acl.setHmacAlgorithm(Kinetic.Command.Security.ACL.HMACAlgorithm.HmacSHA1);
for (Kinetic.Command.Security.ACL.Scope domain : domains) {
acl.addScope(domain);
}
security.addAcl(acl);
// KineticMessage response = getClient(clientName).request(km);
KineticMessage response = getAdminClient().request(km);
// Ensure setup succeeded, or else fail the calling test.
assertEquals(Kinetic.Command.Status.StatusCode.SUCCESS, response
.getCommand().getStatus().getCode());
}
/**
* Utility method to reduce duplicated test code. Creates a new entry for
* the given key/value pair, and executes a PUT using the given client.
*
* @param key
* The string representation of the key to put
* @param value
* The string representation of the value to put
* @param client
* The client used to put
* @return The entry created from the key/value pair
* @throws kinetic.client.KineticException
*/
protected Entry buildAndPutEntry(String key, String value,
KineticClient client) throws KineticException {
Entry entry = new Entry(toByteArray(key), toByteArray(value));
client.put(entry, null);
return entry;
}
@DataProvider(name = "transportProtocolOptions")
public Object[][] createObjectsBasedOnProtocolOptions()
throws KineticException {
Object[][] objects = new Object[kineticClientConfigutations.size()][];
int i = 0;
for (String clientName : kineticClientConfigutations.keySet()) {
objects[i++] = new Object[] { clientName };
}
return objects;
}
private void createKineticClientConfigurations() throws KineticException {
kineticClientConfigutations.clear();
ClientConfiguration clientConfiguration;
if (Boolean.parseBoolean(System.getProperty("RUN_TCP_TEST"))) {
clientConfiguration = getClientConfig();
clientConfiguration.setUseSsl(false);
clientConfiguration.setUseNio(false);
kineticClientConfigutations.put(NONNIO_NONSSL_CLIENT,
clientConfiguration);
}
if (Boolean.parseBoolean(System.getProperty("RUN_NIO_TEST"))) {
clientConfiguration = getClientConfig();
clientConfiguration.setUseSsl(false);
clientConfiguration.setUseNio(true);
kineticClientConfigutations.put(NIO_NONSSL_CLIENT,
clientConfiguration);
}
if (Boolean.parseBoolean(System.getProperty("RUN_SSL_TEST"))) {
clientConfiguration = getClientConfig();
clientConfiguration.setUseSsl(true);
clientConfiguration.setUseNio(false);
clientConfiguration
.setPort(clientConfiguration.getSSLDefaultPort());
kineticClientConfigutations.put(NONNIO_SSL_CLIENT,
clientConfiguration);
}
if (kineticClientConfigutations.size() == 0) {
clientConfiguration = getClientConfig();
clientConfiguration.setUseSsl(false);
clientConfiguration.setUseNio(true);
kineticClientConfigutations.put(NIO_NONSSL_CLIENT,
clientConfiguration);
}
}
private void closeKineticClients() throws KineticException {
for (KineticP2pClient client : kineticClients.values()) {
if (null != client) {
client.close();
}
}
}
}