19package org.sleuthkit.autopsy.integrationtesting;
22import org.sleuthkit.autopsy.integrationtesting.config.TestSuiteConfig;
23import org.sleuthkit.autopsy.integrationtesting.config.IntegrationTestConfig;
24import org.sleuthkit.autopsy.integrationtesting.config.IntegrationCaseType;
25import java.io.IOException;
26import java.lang.reflect.InvocationTargetException;
27import java.lang.reflect.Method;
28import java.nio.file.Path;
29import java.nio.file.Paths;
32import java.util.logging.Level;
33import java.util.stream.Collectors;
34import java.util.stream.Stream;
35import org.apache.commons.io.FileUtils;
36import org.apache.commons.lang.StringUtils;
37import org.apache.commons.collections.CollectionUtils;
38import org.openide.util.Exceptions;
39import org.openide.util.Lookup;
40import org.openide.util.Pair;
41import org.sleuthkit.autopsy.casemodule.Case;
42import org.sleuthkit.autopsy.casemodule.Case.CaseType;
43import org.sleuthkit.autopsy.casemodule.CaseActionException;
44import org.sleuthkit.autopsy.casemodule.CaseDetails;
45import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
46import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbChoice;
47import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager;
48import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
49import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings;
50import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresConnectionSettings;
51import org.sleuthkit.autopsy.core.UserPreferences;
52import org.sleuthkit.autopsy.core.UserPreferencesException;
53import org.sleuthkit.autopsy.coreutils.Logger;
54import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
55import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
56import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
57import org.sleuthkit.autopsy.datasourceprocessors.DataSourceProcessorUtility;
58import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
59import org.sleuthkit.autopsy.ingest.IngestJobSettings;
60import org.sleuthkit.autopsy.integrationtesting.DiffService.DiffServiceException;
61import org.sleuthkit.autopsy.integrationtesting.config.ConfigDeserializer;
62import org.sleuthkit.autopsy.integrationtesting.config.ConnectionConfig;
63import org.sleuthkit.autopsy.integrationtesting.config.EnvConfig;
64import org.sleuthkit.autopsy.integrationtesting.config.TestingConfig;
65import org.sleuthkit.autopsy.testutils.IngestUtils;
66import org.sleuthkit.autopsy.testutils.TestUtilsException;
67import org.sleuthkit.datamodel.CaseDbConnectionInfo;
68import org.sleuthkit.datamodel.TskCoreException;
69import org.sleuthkit.datamodel.TskData.DbType;
119 super(message, exception);
145 }
catch (IOException ex) {
152 boolean hasCrSettings =
false;
159 hasCrSettings = oldSettings.getCrConnection() !=
null;
162 logger.log(Level.SEVERE,
"There was an error while trying to set up multi user connection information.", ex);
167 if (CollectionUtils.isEmpty(
config.getTestSuites())) {
168 logger.log(Level.WARNING,
"No test suites discovered. No tests will be run.");
176 logger.log(Level.SEVERE, String.format(
"Unable to set cr settings to %s for test suite %s.", caseType.name(), testSuiteConfig.getName()));
183 logger.log(Level.SEVERE,
"There was an error working with current case: " + testSuiteConfig.getName(), ex);
194 if (
writeDiff(outputPath, goldPath, diffPath)) {
197 +
"and the current iteration output data: %s. Diff file created at %s.",
198 goldPath, outputPath, diffPath));
205 if (oldSettings !=
null) {
209 }
catch (Exception ex) {
210 logger.log(Level.WARNING,
"There was an error reverting database settings", ex);
214 if (oldCrChoice !=
null) {
218 logger.log(Level.WARNING,
"There was an error reverting cr settings", ex);
227 private static class AllConnectionInfo {
271 ConnectionConfig getSolrConnection() {
278 ConnectionConfig getZkConnection() {
285 ConnectionConfig getCrConnection() {
316 case MULTI_USER_CASE:
319 case SINGLE_USER_CASE:
322 default:
throw new IllegalArgumentException(
"No known case type: " + caseType);
337 if (connectionInfo ==
null) {
349 return new AllConnectionInfo(oldPostgresSettings, oldActiveMqSettings, oldSolrSettings, oldZkSettings, oldCrSettings);
363 if (connectionInfo ==
null) {
368 String username = connectionInfo.getUserName();
369 String host = connectionInfo.getHostName();
370 String password = connectionInfo.getPassword();
374 if (StringUtils.isBlank(username) || StringUtils.isBlank(password) || StringUtils.isBlank(host)) {
375 logger.log(Level.WARNING,
"Username, password, or host are not present. Not setting multi user connection info.");
385 oldInfo.getUserName(),
386 oldInfo.getPassword());
389 return oldConnectionInfo;
403 if (connectionInfo ==
null) {
408 String host = connectionInfo.getHostName();
409 String username = connectionInfo.getUserName() ==
null ?
"" : connectionInfo.getUserName();
410 String password = connectionInfo.getPassword() ==
null ?
"" : connectionInfo.getPassword();
414 if (StringUtils.isBlank(host)) {
415 logger.log(Level.WARNING,
"Host is not present. Not setting active mq connection info.");
424 return oldConnectionInfo;
437 if (connectionInfo ==
null) {
446 if (StringUtils.isBlank(host)) {
447 logger.log(Level.WARNING,
"Host is not present. Not setting solr info.");
468 if (connectionInfo ==
null) {
474 if (StringUtils.isBlank(host)) {
499 if (connectionInfo ==
null) {
504 String username = connectionInfo.getUserName();
505 String host = connectionInfo.getHostName();
506 String password = connectionInfo.getPassword();
510 if (StringUtils.isBlank(username) || StringUtils.isBlank(password) || StringUtils.isBlank(host)) {
511 logger.log(Level.WARNING,
"Username, password, or host are not present. Not setting central repo connection info.");
531 return oldConnectionInfo;
543 if (toBeParsed ==
null) {
548 return Integer.parseInt(toBeParsed);
549 }
catch (NumberFormatException ex) {
563 String caseName = testSuiteConfig.getName();
568 envConfig.getWorkingDirectory(),
569 envConfig.getRootCaseOutputPath(),
572 testSuiteConfig.getDataSources());
574 throw new IllegalStateException(
575 String.format(
"Case was not properly ingested or setup correctly for environment. Returned case is %s and current case is %s.",
579 Pair<IngestJobSettings, List<ConfigurationModule<?>>> configurationResult
582 List<ConfigurationModule<?>> configModules = configurationResult.second();
584 runIngest(autopsyCase, ingestSettings, caseName);
589 String outputFolder =
PathUtil.
getAbsolutePath(envConfig.getWorkingDirectory(), envConfig.getRootTestOutputPath());
591 results.serializeToFile(
592 envConfig.getUseRelativeOutput() ==
true
593 ? Paths.get(outputFolder, testSuiteConfig.getRelativeOutputPath()).toString()
595 testSuiteConfig.getName(),
617 Case openCase =
null;
620 String caseOutputFolder = Paths.get(outputFolder, uniqueCaseName).toString();
621 File caseOutputFolderFile =
new File(caseOutputFolder);
622 if (!caseOutputFolderFile.exists()) {
623 caseOutputFolderFile.mkdirs();
643 for (String strPath : pathStrings) {
644 Path path = Paths.get(strPath);
645 List<AutoIngestDataSourceProcessor> processors =
null;
649 logger.log(Level.WARNING, String.format(
"There was an error while adding data source: %s to case %s", strPath, caseName));
652 if (CollectionUtils.isEmpty(processors)) {
659 logger.log(Level.WARNING, String.format(
"There was an error adding datasource at path: " + strPath), ex);
674 logger.log(Level.WARNING, String.format(
"No datasources provided in %s. Not running ingest.", caseName));
679 logger.log(Level.WARNING, String.format(
"There was an error while ingesting datasources for case %s", caseName), ex);
690 OutputResults results =
new OutputResults();
696 if (!testSuiteConfig.
hasIncludedTest(testGroup.getClass().getCanonicalName())) {
700 List<Method> testMethods = Stream.of(testGroup.getClass().getMethods())
701 .filter((method) -> method.getAnnotation(
IntegrationTest.class) !=
null)
702 .collect(Collectors.toList());
704 if (CollectionUtils.isEmpty(testMethods)) {
708 testGroup.setupClass();
709 Map<String, Object> parametersMap = testSuiteConfig.
getParameters(testGroup.getClass().getCanonicalName());
711 for (Method testMethod : testMethods) {
712 Object[] parameters =
new Object[0];
714 if (testMethod.getParameters().length > 1) {
715 logger.log(Level.WARNING, String.format(
"Could not call method %s in class %s. Multiple parameters cannot be handled.",
716 testMethod.getName(), testGroup.getClass().getCanonicalName()));
719 }
else if (testMethod.getParameters().length > 0) {
720 parameters =
new Object[]{
configDeserializer.convertToObj(parametersMap, testMethod.getParameterTypes()[0])};
727 testGroup.getClass().getPackage().getName(),
728 testGroup.getClass().getSimpleName(),
729 testMethod.getName(),
733 testGroup.tearDownClass();
752 Object serializableResult =
null;
755 serializableResult = testMethod.invoke(testGroup, parameters ==
null ?
new Object[0] : parameters);
756 }
catch (InvocationTargetException ex) {
758 serializableResult = ex.getCause();
759 }
catch (Exception ex) {
762 String.format(
"test method %s in %s could not be properly invoked",
763 testMethod.getName(), testGroup.getClass().getCanonicalName()),
766 serializableResult = ex;
771 return serializableResult;
785 if (StringUtils.isBlank(goldPath) || StringUtils.isBlank(diffPath)) {
786 logger.log(Level.INFO,
"gold path or diff output path not specified. Not creating diff.");
789 File goldDir =
new File(goldPath);
790 if (!goldDir.exists()) {
791 logger.log(Level.WARNING, String.format(
"Gold does not exist at location: %s. Not creating diff.", goldDir.toString()));
794 File outputDir =
new File(outputPath);
795 if (!outputDir.exists()) {
796 logger.log(Level.WARNING, String.format(
"Output path does not exist at location: %s. Not creating diff.", outputDir.toString()));
799 String diff =
diffService.diffFilesOrDirs(goldDir, outputDir);
800 if (StringUtils.isNotBlank(diff)) {
802 FileUtils.writeStringToFile(
new File(diffPath), diff,
"UTF-8");
803 }
catch (IOException ex) {
804 logger.log(Level.SEVERE,
"Unable to write diff file to {0}", diffPath);
static void closeCurrentCase()
List< Content > getDataSources()
static Case getCurrentCaseThrows()
static Case getCurrentCase()
static void createAsCurrentCase(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
PostgresCentralRepoSettings getDbSettingsPostgres()
void saveNewCentralRepo()
CentralRepoDbChoice getSelectedDbChoice()
void setSelctedDbChoice(CentralRepoDbChoice newSelected)
void setHost(String host)
void setUserName(String userName)
void setPassword(String password)
static final int DEFAULT_PORT
static String getIndexingServerPort()
static void setDatabaseConnectionInfo(CaseDbConnectionInfo connectionInfo)
static String getZkServerHost()
static CaseDbConnectionInfo getDatabaseConnectionInfo()
static void setMessageServiceConnectionInfo(MessageServiceConnectionInfo info)
static String getIndexingServerHost()
static String getZkServerPort()
static void setZkServerPort(String port)
static void setIndexingServerPort(int port)
static void setZkServerHost(String hostName)
static MessageServiceConnectionInfo getMessageServiceConnectionInfo()
static void setIndexingServerHost(String hostName)
synchronized static Logger getLogger(String name)
static String createTimeStamp()
static List< AutoIngestDataSourceProcessor > getOrderedListOfDataSourceProcessors(Path dataSourcePath)
final ConnectionConfig zkConnection
final ConnectionConfig mqConnection
final ConnectionConfig crConnection
final ConnectionConfig dbConnection
final ConnectionConfig solrConnection
IntegrationTestDiffException(String message)
static final long serialVersionUID
static final long serialVersionUID
IntegrationTestServiceException(String message, Throwable exception)
IntegrationTestServiceException(String message)
Case createCaseWithDataSources(String workingDirectory, String caseOutputPath, String caseName, CaseType caseType, List< String > dataSourcePaths)
void runIntegrationTestSuite(EnvConfig envConfig, CaseType caseType, TestSuiteConfig testSuiteConfig)
int parseIntOrDefault(String toBeParsed, int defaultVal)
static final Logger logger
void addDataSourcesToCase(List< String > pathStrings, String caseName)
static final int DEFAULT_ZOOKEEPER_PORT
ConnectionConfig pushZookeeperSettings(ConnectionConfig connectionInfo)
static final int DEFAULT_POSTGRES_PORT
AllConnectionInfo pushNewMultiUserSettings(AllConnectionInfo connectionInfo)
Object runIntegrationTestMethod(IntegrationTestGroup testGroup, Method testMethod, Object[] parameters)
boolean writeDiff(String outputPath, String goldPath, String diffPath)
static final int DEFAULT_ACTIVEMQ_PORT
void setCurrentChoice(CaseType caseType)
ConnectionConfig pushCentralRepoSettings(ConnectionConfig connectionInfo)
CentralRepoDbChoice getCurrentChoice()
ConnectionConfig pushActiveMqSettings(ConnectionConfig connectionInfo)
static final ConfigurationModuleManager configurationModuleManager
ConnectionConfig pushPostgresSettings(ConnectionConfig connectionInfo)
void runIntegrationTests()
static final ConfigDeserializer configDeserializer
CentralRepoDbChoice pushCurrentCrChoice(CentralRepoDbChoice curChoice)
ConnectionConfig pushSolrSettings(ConnectionConfig connectionInfo)
static final int DEFAULT_SOLR_PORT
static final DiffService diffService
OutputResults runIntegrationTests(TestingConfig testSuiteConfig)
void runIngest(Case openCase, IngestJobSettings ingestJobSettings, String caseName)
static List< String > getAbsolutePaths(String workingDirectory, List< String > relPaths)
static String getAbsolutePath(String workingDirectory, String relPath)
String getRootTestOutputPath()
ConnectionConfig getSolrConnection()
String getDiffOutputPath()
ConnectionConfig getZkConnection()
ConnectionConfig getMqConnection()
String getWorkingDirectory()
ConnectionConfig getDbConnection()
ConnectionConfig getCrConnection()
boolean hasIncludedTest(String itemType)
Map< String, Object > getParameters(String itemType)
static void addDataSource(AutoIngestDataSourceProcessor dataSourceProcessor, Path dataSourcePath)
static void runIngestJob(List< Content > datasources, IngestJobSettings ingestJobSettings)
static List< CaseType > getCaseTypes(IntegrationCaseType integrationCaseType)