working through classpath issues

This commit is contained in:
Greg DiCristofaro
2020-10-13 16:47:22 -04:00
parent 9d38d08aba
commit 292dbc4b53
39 changed files with 238 additions and 949 deletions
-105
View File
@@ -196,109 +196,4 @@
</copy>
</target>
<!-- INTEGRATION TEST ITEMS START HERE (based heavily on Testing NBM build.xml) -->
<!-- use manifestclasspath (http://ant.apache.org/manual/Tasks/manifestclasspath.html) to put all the jar files that we need for junit/regression test
to a single jar file: allJarsInUse.jar. Then we put this new jar to classpath for testing program to avoid command line Java classpath too long problem.
Note: Started from ant 1.10, maxParentLevels are enforced. If you get error from manifestclasspath complaines 'No suitable relative path from ...' then it's time to
increase your maxParentLevels -->
<target name="manifest-classpath">
<manifestclasspath property="tem.classpath" jarfile="allJarsInUse.jar" maxParentLevels="5">
<classpath refid="test.${regression}.run.cp"/>
</manifestclasspath>
<jar destfile="allJarsInUse.jar" basedir="build/classes">
<manifest>
<attribute name="Class-Path" value="${tem.classpath}"/>
</manifest>
</jar>
<path id="test.classpath">
<pathelement path="allJarsInUse.jar"/>
</path>
</target>
<target name="integration-test-check-args">
<fail message="Missing required argument: configPath" unless="configPath"/>
</target>
<target name="regression-test" depends="integration-test-check-args,init,test-init,test-build, manifest-classpath" if="exists.test.qa-functional.src.dir">
<test test.type="${regression}"/>
<delete file="allJarsInUse.jar"/>
</target>
<macrodef name="test">
<attribute name="test.type"/>
<attribute name="disable.apple.ui" default="false"/>
<sequential>
<property name="test.config" value="default"/>
<property name="test.config.default.includes" value="**/*Test.class"/>
<property name="test.config.${test.config}.includes" value="NOTHING"/>
<metaproperty name="test.includes" value="test.config.${test.config}.includes"/>
<property name="test.config.${test.config}.excludes" value=""/>
<metaproperty name="test.excludes" value="test.config.${test.config}.excludes"/>
<mkdir dir="${build.test.@{test.type}.results.dir}"/>
<junit fork="true" failureproperty="tests.failed" errorproperty="tests.failed" filtertrace="${test.filter.trace}" tempdir="${build.test.@{test.type}.results.dir}">
<batchtest todir="${build.test.@{test.type}.results.dir}">
<fileset dir="${build.test.@{test.type}.classes.dir}">
<filename name="**/org/sleuthkit/autopsy/integrationtesting.MainTestRunner.class" />
</fileset>
</batchtest>
<classpath refid="test.classpath"/>
<syspropertyset refid="test.@{test.type}.properties"/>
<jvmarg line="${test.bootclasspath.prepend.args}"/>
<jvmarg line="${test.run.args}"/>
<!-- should be in sync with project.properties and build.xml of autopsy main project -->
<!-- disable for now, causes issues with Java 7 -->
<!-- <jvmarg line="-J-Xms24m -J-Xmx512m -J-XX:MaxPermSize=128M -J-Xverify:none"/> -->
<sysproperty key="configPath" value="configPath"/>
<!--needed to have tests NOT to steal focus when running, works in latest apple jdk update only.-->
<sysproperty key="apple.awt.UIElement" value="@{disable.apple.ui}"/>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
</junit>
<fail message="Some tests failed; see details above.">
<condition>
<and>
<isset property="tests.failed"/>
<isfalse value="${continue.after.failing.tests}"/>
</and>
</condition>
</fail>
</sequential>
</macrodef>
</project>
-5
View File
@@ -27,12 +27,7 @@
<dependency conf="core->default" org="org.jsoup" name="jsoup" rev="1.10.3"/>
<!-- for yaml reading/writing (these two should likely have the same rev) -->
<dependency conf="core->default" org="com.fasterxml.jackson.dataformat" name="jackson-dataformat-yaml" rev="2.9.7"/>
<dependency conf="core->default" org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.9.7"/>
<dependency conf="core->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.9.7"/>
<dependency conf="core->default" org="com.fasterxml.jackson.core" name="jackson-annotations" rev="2.9.7"/>
<dependency conf="core->default" org="com.drewnoakes" name="metadata-extractor" rev="2.11.0"/>
<dependency conf="core->default" org="com.google.cloud" name="google-cloud-translate" rev="1.70.0"/>
+8 -12
View File
@@ -391,18 +391,6 @@
<runtime-relative-path>ext/jackson-databind-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-databind-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-dataformat-yaml-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-dataformat-yaml-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-annotations-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-annotations-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-core-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-core-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/okhttp-2.7.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\okhttp-2.7.5.jar</binary-origin>
@@ -623,10 +611,18 @@
<runtime-relative-path>ext/curator-recipes-2.8.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\curator-recipes-2.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-annotations-2.9.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-annotations-2.9.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/objenesis-3.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\objenesis-3.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-core-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-core-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-lang3-3.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-lang3-3.5.jar</binary-origin>
@@ -1,68 +1,68 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.datasourcesummary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult;
import org.sleuthkit.autopsy.integrationtesting.IntegrationTest;
import org.sleuthkit.autopsy.integrationtesting.IntegrationTests;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskCoreException;
import org.openide.util.lookup.ServiceProvider;
/**
* Tests for the UserActivitySummary class.
*/
@ServiceProvider(service = IntegrationTests.class)
public class UserActivitySummaryTests implements IntegrationTests {
/**
* Runs UserActivitySummary.getRecentDomains for all data sources found in
* the current case.
*
* @return A map where the key is the data source name and the value are the
* results of that method.
*/
@IntegrationTest
public Map<String, List<TopDomainsResult>> getRecentDomainsTest()
throws NoCurrentCaseException, TskCoreException, SleuthkitCaseProviderException {
UserActivitySummary userActivitySummary = new UserActivitySummary();
Map<String, List<TopDomainsResult>> toRet = new HashMap<>();
for (Content c : Case.getCurrentCaseThrows().getDataSources()) {
if (c instanceof DataSource) {
DataSource ds = (DataSource) c;
List<TopDomainsResult> thisResult = userActivitySummary.getRecentDomains(ds, 10);
toRet.put(ds.getName(), thisResult);
}
}
return toRet;
}
//...other tests for other methods in the class...
}
///*
// * Autopsy Forensic Browser
// *
// * Copyright 2020 Basis Technology Corp.
// * Contact: carrier <at> sleuthkit <dot> org
// *
// * 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 org.sleuthkit.autopsy.datasourcesummary;
//
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import org.sleuthkit.autopsy.casemodule.Case;
//import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
//import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
//import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary;
//import org.sleuthkit.autopsy.datasourcesummary.datamodel.UserActivitySummary.TopDomainsResult;
//import org.sleuthkit.autopsy.integrationtesting.IntegrationTest;
//import org.sleuthkit.autopsy.integrationtesting.IntegrationTests;
//import org.sleuthkit.datamodel.Content;
//import org.sleuthkit.datamodel.DataSource;
//import org.sleuthkit.datamodel.TskCoreException;
//import org.openide.util.lookup.ServiceProvider;
//
///**
// * Tests for the UserActivitySummary class.
// */
//@ServiceProvider(service = IntegrationTests.class)
//public class UserActivitySummaryTests implements IntegrationTests {
//
// /**
// * Runs UserActivitySummary.getRecentDomains for all data sources found in
// * the current case.
// *
// * @return A map where the key is the data source name and the value are the
// * results of that method.
// */
// @IntegrationTest
// public Map<String, List<TopDomainsResult>> getRecentDomainsTest()
// throws NoCurrentCaseException, TskCoreException, SleuthkitCaseProviderException {
//
// UserActivitySummary userActivitySummary = new UserActivitySummary();
// Map<String, List<TopDomainsResult>> toRet = new HashMap<>();
// for (Content c : Case.getCurrentCaseThrows().getDataSources()) {
// if (c instanceof DataSource) {
// DataSource ds = (DataSource) c;
// List<TopDomainsResult> thisResult = userActivitySummary.getRecentDomains(ds, 10);
// toRet.put(ds.getName(), thisResult);
// }
// }
// return toRet;
//
// }
//
// //...other tests for other methods in the class...
//}
@@ -1,30 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.ingest;
import java.util.List;
/**
* Service for obtaining all Ingest Module Factories
*/
public class IngestModuleFactoryService {
public List<IngestModuleFactory> getFactories() {
return IngestModuleFactoryLoader.getIngestModuleFactories();
}
}
@@ -1,33 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation similar to Junit's @Test for outputing results as a part of an
* integration test.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface IntegrationTest {
}
@@ -1,45 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting;
/**
* Basic interface for integration test suite.
*/
public interface IntegrationTests {
/**
* Allows for a test to perform any necessary setup.
*/
default void setup() {}
/**
* Allows for a test to perform any necessary disposing of resources.
*/
default void tearDown() {}
/**
* Allows for this suite of tests to perform any necessary setup.
*/
default void setupClass() {}
/**
* Allows for this suite of tests to dispose of resources.
*/
default void tearDownClass() {}
}
@@ -1,312 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.sleuthkit.autopsy.integrationtesting.config.IntegrationTestConfig;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import junit.framework.Test;
import junit.framework.TestCase;
import org.apache.cxf.common.util.CollectionUtils;
import org.netbeans.junit.NbModuleSuite;
import org.openide.util.Lookup;
import org.openide.util.io.NbObjectInputStream;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.datasourceprocessors.DataSourceProcessorUtility;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryService;
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleTemplate;
import org.sleuthkit.autopsy.integrationtesting.config.CaseConfig;
import org.sleuthkit.autopsy.integrationtesting.config.IntegrationCaseType;
import org.sleuthkit.autopsy.python.FactoryClassNameNormalizer;
import org.sleuthkit.autopsy.testutils.CaseUtils;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Main entry point for running integration tests. Handles processing
* parameters, ingesting data sources for cases, and running items implementing
* IntegrationTests.
*/
public class MainTestRunner extends TestCase {
private static final Logger logger = Logger.getLogger(MainTestRunner.class.getName()); // DO NOT USE AUTOPSY LOGGER
private static final String CONFIG_FILE_KEY = "CONFIG_FILE_KEY";
private static final IngestModuleFactoryService ingestFactoryService = new IngestModuleFactoryService();
private static final IngestType DEFAULT_INGEST_TYPE = IngestType.ALL_MODULES;
/**
* Constructor required by JUnit
*/
public MainTestRunner(String name) {
super(name);
}
/**
* Creates suite from particular test cases.
*/
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(MainTestRunner.class).
clusters(".*").
enableModules(".*");
return NbModuleSuite.create(conf.addTest("runIntegrationTests"));
}
public void runIntegrationTests() {
String configFile = System.getProperty(CONFIG_FILE_KEY);
IntegrationTestConfig config;
try {
config = getConfigFromFile(configFile);
} catch (IOException ex) {
logger.log(Level.WARNING, "There was an error processing integration test config at " + configFile, ex);
return;
}
if (config == null) {
logger.log(Level.WARNING, "No properly formatted config found at " + configFile);
}
if (!CollectionUtils.isEmpty(config.getCases())) {
for (CaseConfig caseConfig : config.getCases()) {
for (CaseType caseType : IntegrationCaseType.getCaseTypes(caseConfig.getCaseTypes())) {
Case autopsyCase = runIngest(caseConfig, caseType);
if (autopsyCase == null || autopsyCase != Case.getCurrentCase()) {
logger.log(Level.WARNING,
String.format("Case was not properly ingested or setup correctly for environment. Case is %s and current case is %s.",
autopsyCase, Case.getCurrentCase()));
return;
}
String caseName = autopsyCase.getName();
runIntegrationTests(config, caseConfig, caseType);
try {
Case.closeCurrentCase();
} catch (CaseActionException ex) {
logger.log(Level.WARNING, "There was an error while trying to close current case: {0}", caseName);
return;
}
}
}
}
}
private Case runIngest(CaseConfig caseConfig, CaseType caseType) {
Case openCase = null;
switch (caseType) {
case SINGLE_USER_CASE:
openCase = CaseUtils.createAsCurrentCase(caseConfig.getCaseName());
break;
case MULTI_USER_CASE:
// TODO
default:
throw new IllegalArgumentException("Unknown case type: " + caseType);
}
if (openCase == null) {
logger.log(Level.WARNING, String.format("No case could be created for %s of type %s.", caseConfig.getCaseName(), caseType));
return null;
}
addDataSourcesToCase(caseConfig.getDataSourceResources(), caseConfig.getCaseName());
try {
IngestJobSettings ingestJobSettings = getIngestSettings(caseConfig.getCaseName(),
DEFAULT_INGEST_TYPE,
caseConfig.getIngestModules(), caseConfig.getIngestModuleSettingsPath());
IngestUtils.runIngestJob(openCase.getDataSources(), ingestJobSettings);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("There was an error while ingesting datasources for case %s", caseConfig.getCaseName()), ex);
}
return openCase;
}
private IngestJobSettings getIngestSettings(String profileName, IngestType ingestType, List<String> enabledFactoryClasses, String pathToIngestModuleSettings) {
Map<String, IngestModuleFactory> classToFactoryMap = ingestFactoryService.getFactories().stream()
.collect(Collectors.toMap(factory -> factory.getClass().getCanonicalName(), factory -> factory, (f1, f2) -> f1));
List<IngestModuleTemplate> ingestModuleTemplates = enabledFactoryClasses.stream()
.map(className -> {
IngestModuleFactory factory = classToFactoryMap.get(className);
if (factory == null) {
logger.log(Level.WARNING, "Could not find ingest module factory: " + className);
}
return factory;
})
.filter(factory -> factory != null)
.map(factory -> getTemplate(pathToIngestModuleSettings, factory))
.collect(Collectors.toList());
return new IngestJobSettings(profileName, ingestType, ingestModuleTemplates);
}
private IngestModuleTemplate getTemplate(String pathToIngestModuleSettings, IngestModuleFactory factory) {
String fileName = FactoryClassNameNormalizer.normalize(factory.getClass().getCanonicalName()) + ".settings";
File settingsFile = Paths.get(pathToIngestModuleSettings, fileName).toFile();
if (settingsFile.exists()) {
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) {
IngestModuleIngestJobSettings settings = (IngestModuleIngestJobSettings) in.readObject();
return new IngestModuleTemplate(factory, settings);
} catch (IOException | ClassNotFoundException ex) {
logger.log(Level.WARNING, String.format("Unable to open %s as IngestModuleIngestJobSettings", settingsFile), ex);
}
}
return new IngestModuleTemplate(factory, factory.getDefaultIngestJobSettings());
}
private void addDataSourcesToCase(List<String> pathStrings, String caseName) {
for (String strPath : pathStrings) {
Path path = Paths.get(strPath);
List<AutoIngestDataSourceProcessor> processors = null;
try {
processors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(path);
} catch (AutoIngestDataSourceProcessorException ex) {
logger.log(Level.WARNING, String.format("There was an error while adding data source: %s to case %s", strPath, caseName));
}
if (CollectionUtils.isEmpty(processors)) {
continue;
}
IngestUtils.addDataSource(processors.get(0), path);
}
}
private IntegrationTestConfig getConfigFromFile(String filePath) throws IOException {
ObjectMapper om = new ObjectMapper();
try (FileInputStream jsonSrc = new FileInputStream(filePath)) {
return om.readValue(jsonSrc, IntegrationTestConfig.class);
}
}
private void runIntegrationTests(IntegrationTestConfig config, CaseConfig caseConfig, CaseType caseType) {
// this will capture output results
OutputResults results = new OutputResults();
// run through each ConsumerIntegrationTest
for (IntegrationTests testGroup : Lookup.getDefault().lookupAll(IntegrationTests.class)) {
// if test should not be included in results, skip it.
if (!caseConfig.getTestConfig().hasIncludedTest(testGroup.getClass().getCanonicalName())) {
continue;
}
List<Method> testMethods = getIntegrationTestMethods(testGroup);
if (CollectionUtils.isEmpty(testMethods)) {
continue;
}
testGroup.setupClass();
for (Method testMethod : testMethods) {
runIntegrationTestMethod(results, testGroup, testMethod);
}
testGroup.tearDownClass();
}
// write the results for the case to a file
serializeFile(results, config.getRootTestOutputPath(), caseConfig.getCaseName(), getCaseTypeId(caseType));
}
private String getCaseTypeId(CaseType caseType) {
if (caseType == null) {
return "";
}
switch (caseType) {
case SINGLE_USER_CASE:
return "singleUser";
case MULTI_USER_CASE:
return "multiUser";
default:
throw new IllegalArgumentException("Unknown case type: " + caseType);
}
}
private void runIntegrationTestMethod(OutputResults results, IntegrationTests testGroup, Method testMethod) {
testGroup.setup();
// run the test method and get the results
Object serializableResult = null;
try {
serializableResult = testMethod.invoke(testGroup);
} catch (IllegalAccessException | IllegalArgumentException ex) {
logger.log(Level.WARNING,
String.format("test method %s in %s could not be properly invoked",
testMethod.getName(), testGroup.getClass().getCanonicalName()),
ex);
serializableResult = ex;
} catch (InvocationTargetException ex) {
serializableResult = ex.getCause();
}
testGroup.tearDown();
// add the results and capture the package, class,
// and method of the test for easy location of failed tests
results.addResult(
testGroup.getClass().getPackage().getName(),
testGroup.getClass().getSimpleName(),
testMethod.getName(),
serializableResult);
}
private List<Method> getIntegrationTestMethods(IntegrationTests testGroup) {
return Stream.of(testGroup.getClass().getMethods())
.filter((method) -> method.getAnnotation(IntegrationTest.class) != null)
.collect(Collectors.toList());
}
private void serializeFile(OutputResults results, String outputFolder, String caseName, String caseType) {
String outputExtension = ".yml";
Path outputPath = Paths.get(outputFolder, String.format("%s-%s%s", caseName, caseType, outputExtension));
ObjectMapper om = new ObjectMapper(new YAMLFactory());
try {
om.writeValue(outputPath.toFile(), results.getSerializableData());
} catch (IOException ex) {
logger.log(Level.WARNING, "There was an error writing results to outputPath: " + outputPath, ex);
}
}
}
@@ -1,78 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import org.apache.commons.lang.exception.ExceptionUtils;
/**
* Integration Test results for a case to be written to disk in a text format.
*/
public class OutputResults {
private static class ExceptionObject {
private final String message;
private final String stackTrace;
private final ExceptionObject innerException;
ExceptionObject(Throwable t) {
this.message = t.getMessage();
this.stackTrace = ExceptionUtils.getStackTrace(t);
this.innerException = (t.getCause() == null) ? null : new ExceptionObject(t.getCause());
}
String getMessage() {
return message;
}
String getStackTrace() {
return stackTrace;
}
ExceptionObject getInnerException() {
return innerException;
}
}
private final Map<String, Map<String, Map<String, Object>>> data = new HashMap<>();
private static <K, V> V getOrCreate(Map<K, V> map, K key, Supplier<V> onNotPresent) {
V curValue = map.get(key);
if (curValue == null) {
curValue = onNotPresent.get();
map.put(key, curValue);
}
return curValue;
}
public void addResult(String pkgName, String className, String methodName, Object result) {
Map<String, Map<String, Object>> packageClasses = getOrCreate(data, pkgName, () -> new HashMap<>());
Map<String, Object> classMethods = getOrCreate(packageClasses, className, () -> new HashMap<>());
Object toWrite = result instanceof Throwable ? new ExceptionObject((Throwable) result) : result;
classMethods.put(methodName, toWrite);
}
public Object getSerializableData() {
return Collections.unmodifiableMap(data);
}
}
@@ -1,70 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting.config;
import java.util.List;
/**
* Configuration in IntegrationTests per case.
*/
public class CaseConfig {
private final String caseName;
private final List<String> dataSourceResources;
private final List<String> ingestModules;
private final String ingestModuleSettingsPath;
private final IntegrationCaseType caseTypes;
private final TestingConfig testConfig;
public CaseConfig(String caseName, List<String> dataSourceResources,
List<String> ingestModules, String ingestModuleSettingsPath,
IntegrationCaseType caseTypes, TestingConfig testConfig) {
this.caseName = caseName;
this.dataSourceResources = dataSourceResources;
this.ingestModules = ingestModules;
this.ingestModuleSettingsPath = ingestModuleSettingsPath;
this.caseTypes = caseTypes;
this.testConfig = testConfig;
}
public String getCaseName() {
return caseName;
}
public List<String> getDataSourceResources() {
return dataSourceResources;
}
public String getIngestModuleSettingsPath() {
return ingestModuleSettingsPath;
}
public IntegrationCaseType getCaseTypes() {
return caseTypes;
}
public TestingConfig getTestConfig() {
return testConfig;
}
public List<String> getIngestModules() {
return ingestModules;
}
}
@@ -1,44 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting.config;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
/**
* The case types to create for this case.
*/
public enum IntegrationCaseType {
multiUser, singleUser, both;
public static List<CaseType> getCaseTypes(IntegrationCaseType integrationCaseType) {
if (integrationCaseType == null) {
return Collections.emptyList();
}
switch (integrationCaseType) {
case multiUser: return Arrays.asList(CaseType.MULTI_USER_CASE);
case singleUser: return Arrays.asList(CaseType.SINGLE_USER_CASE);
case both: return Arrays.asList(CaseType.MULTI_USER_CASE, CaseType.SINGLE_USER_CASE);
default: throw new IllegalArgumentException("Unknown integration case type: " + integrationCaseType);
}
}
}
@@ -1,50 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting.config;
import java.util.List;
/**
* Configuration for running Integration Tests including things like ingest
* parameters, datasource locations, cases to create, tests to run, etc.
*/
public class IntegrationTestConfig {
private final String rootCaseOutputPath;
private final String rootTestOutputPath;
private final List<CaseConfig> cases;
public IntegrationTestConfig(String rootCaseOutputPath,
String rootTestOutputPath, List<CaseConfig> cases) {
this.rootCaseOutputPath = rootCaseOutputPath;
this.rootTestOutputPath = rootTestOutputPath;
this.cases = cases;
}
public String getRootCaseOutputPath() {
return rootCaseOutputPath;
}
public String getRootTestOutputPath() {
return rootTestOutputPath;
}
public List<CaseConfig> getCases() {
return cases;
}
}
@@ -1,77 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 org.sleuthkit.autopsy.integrationtesting.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
/**
* Configuration for which integration test suites to run.
*/
public class TestingConfig {
private final Set<String> excludeAllExcept;
private final Set<String> includeAllExcept;
private static Set<String> convert(List<String> orig) {
if (orig == null) {
return Collections.emptySet();
}
return orig.stream()
.map((item) -> item.toUpperCase())
.collect(Collectors.toSet());
}
@JsonCreator
public TestingConfig(@JsonProperty() List<String> excludeAllExcept, @JsonProperty() List<String> includeAllExcept) {
this.excludeAllExcept = convert(excludeAllExcept);
this.includeAllExcept = convert(includeAllExcept);
}
public Set<String> getExcludeAllExcept() {
return excludeAllExcept;
}
public Set<String> getIncludeAllExcept() {
return includeAllExcept;
}
public boolean hasIncludedTest(String itemType) {
if (itemType == null) {
return false;
}
if (!CollectionUtils.isEmpty(includeAllExcept)) {
if (includeAllExcept.contains(itemType.toUpperCase())) {
return false;
}
}
if (!CollectionUtils.isEmpty(excludeAllExcept)) {
return excludeAllExcept.contains(itemType.toUpperCase());
}
return true;
}
}