/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.itest.control;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.diqube.itest.control.ServerControl.ServerAddr;
import org.diqube.tool.im.IdentityToolFunction;
import org.diqube.tool.merge.Merge;
import org.diqube.tool.transpose.Transpose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
/**
* Controls the execution of diqube-tool in a separate process.
*
* @author Bastian Gloeckle
*/
public class ToolControl {
private static final Logger logger = LoggerFactory.getLogger(ToolControl.class);
public static final String TYPE_JSON = "json";
public static final String TYPE_CSV = "csv";
private File toolJarFile;
public ToolControl(File toolJarFile) {
this.toolJarFile = toolJarFile;
}
/**
* Transpose the given file.
*
* <p>
* This is to be called in tests, as it asserts some expected circumstances after the transposing is done.
*
* <p>
* This method will not return until either there is an error case or the transposing is done.
*
* @param inputFileType
* {@link #TYPE_JSON} or {@link #TYPE_CSV}.
*/
public void transpose(File inputFile, String inputFileType, File outputFile) {
logger.info("Starting to transpose '{}' of type {} to '{}'...", inputFile, inputFileType, outputFile);
executeTool("transpose", Arrays.asList("java", "-jar", toolJarFile.getAbsolutePath(), Transpose.FUNCTION_NAME, "-i",
inputFile.getAbsolutePath(), "-o", outputFile.getAbsolutePath(), "-t", inputFileType), outputFile);
}
/**
* Merge the input .diqube files into a single output .diqube file.
*
* <p>
* This is to be called in tests, as it asserts some expected circumstances after the transposing is done.
*
* <p>
* This method will not return until either there is an error case or the transposing is done.
*
*/
public void merge(List<File> inputFiles, File outputFile) {
logger.info("Starting to merge {} to '{}'...", inputFiles, outputFile);
List<String> cmd = new ArrayList<>();
cmd.addAll(Arrays.asList("java", "-jar", toolJarFile.getAbsolutePath(), Merge.FUNCTION_NAME, "-o",
outputFile.getAbsolutePath(), "-i"));
cmd.addAll(inputFiles.stream().map(f -> f.getAbsolutePath()).collect(Collectors.toList()));
executeTool("merge", cmd, outputFile);
}
/**
* Execute "im" function using diqube-tool.
*/
public void im(ServerAddr serverAddr, String function, String loginUser, String loginPassword, String paramUser,
String paramPassword, String paramEmail, String paramPermission, String paramPermissionObject) {
logger.info(
"Starting im function '{}' with params: loginUser={}, loginPassword={}, paramUser={}, paramPassword={}, "
+ "paramEmail={}, paramPermission={}, paramPermissionObject={} on server={}",
function, loginUser, loginPassword, paramUser, paramPassword, paramEmail, paramPermission,
paramPermissionObject, serverAddr);
List<String> cmd = new ArrayList<>();
cmd.addAll(Arrays.asList("java", "-jar", toolJarFile.getAbsolutePath(), IdentityToolFunction.FUNCTION_NAME, "-s",
serverAddr.toString(), "-f", function));
if (loginUser != null)
cmd.addAll(Arrays.asList("-lu", loginUser));
if (loginPassword != null)
cmd.addAll(Arrays.asList("-lp", loginPassword));
if (paramUser != null)
cmd.addAll(Arrays.asList("-u", paramUser));
if (paramPassword != null)
cmd.addAll(Arrays.asList("-p", paramPassword));
if (paramEmail != null)
cmd.addAll(Arrays.asList("-e", paramEmail));
if (paramPermission != null)
cmd.addAll(Arrays.asList("-a", paramPermission));
if (paramPermissionObject != null)
cmd.addAll(Arrays.asList("-o", paramPermissionObject));
executeTool("im", cmd, null);
}
private void executeTool(String processDescription, List<String> cmd, File outputFile) {
if (outputFile != null)
try {
Files.deleteIfExists(outputFile.toPath());
} catch (IOException e) {
throw new RuntimeException("Could not delete output file before starting the " + processDescription
+ " process: " + outputFile.getAbsolutePath(), e);
}
ProcessBuilder processBuilder = new ProcessBuilder(cmd).inheritIO();
logger.info("====================================================");
Process p;
try {
p = processBuilder.start();
} catch (IOException e) {
throw new RuntimeException("Could not start '" + processDescription + "'", e);
}
try {
boolean stopped = p.waitFor(1, TimeUnit.MINUTES);
if (!stopped) {
logger.error("'" + processDescription + "' did not stop within timeout period, killing it forcibly.");
p.destroyForcibly();
throw new RuntimeException(
"'" + processDescription + "' did not stop within timeout period, killed it forcibly.");
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while waiting for '" + processDescription + "' to complete.", e);
}
logger.info("====================================================");
Assert.assertEquals(p.exitValue(), 0,
"Expected the '" + processDescription + "' sub-process to exit with a non-error exit value.");
if (outputFile != null)
Assert.assertTrue(outputFile.exists(),
"Expected that the '" + processDescription + "' actually created the output file, but it did not.");
}
}