diff --git a/.gitignore b/.gitignore
index a9b2026f25..8a6216b27d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,7 @@ Bundle_*.properties
/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties
+/Testing/script/input/
+/Testing/script/output/
+/Testing/script/gold/
+*~
diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtAction.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtAction.java
index cd134795e3..b0d8b3c7bc 100644
--- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtAction.java
+++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtAction.java
@@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Log;
*/
class HashDbMgmtAction extends CallableSystemAction {
- private static final String ACTION_NAME = "Hash Database Configuration";
+ static final String ACTION_NAME = "Hash Database Configuration";
@Override
public void performAction() {
diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtPanel.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtPanel.java
index 216aa8dcf8..b3bf5254ec 100644
--- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtPanel.java
+++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbMgmtPanel.java
@@ -63,6 +63,7 @@ public class HashDbMgmtPanel extends javax.swing.JPanel {
/** Creates new form HashDbMgmtPanel */
private HashDbMgmtPanel() {
+ setName(HashDbMgmtAction.ACTION_NAME);
notableTableModel = new HashSetTableModel();
initComponents();
customizeComponents();
@@ -293,9 +294,24 @@ public class HashDbMgmtPanel extends javax.swing.JPanel {
JOptionPane.PLAIN_MESSAGE, null, null, derivedName);
if(setName != null && !setName.equals("")) {
- HashDb newDb = new HashDb(setName, Arrays.asList(new String[] {filePath}), false);
- if(IndexStatus.isIngestible(newDb.status()))
- newDb.setUseForIngest(true);
+ HashDb newDb = new HashDb(setName, Arrays.asList(new String[]{filePath}), false);
+ int toIndex = JOptionPane.NO_OPTION;
+ if (IndexStatus.isIngestible(newDb.status())) {
+ newDb.setUseForIngest(true);
+ } else {
+ toIndex = JOptionPane.showConfirmDialog(this,
+ "The database you added has no index.\n"
+ + "It will not be used for ingest until you create one.\n"
+ + "Would you like to do so now?", "No Index Exists", JOptionPane.YES_NO_OPTION);
+ }
+
+ if (toIndex == JOptionPane.YES_OPTION) {
+ try {
+ newDb.createIndex();
+ } catch (TskException ex) {
+ logger.log(Level.WARNING, "Error creating index", ex);
+ }
+ }
notableTableModel.newSet(newDb); // TODO: support multiple file paths
}
diff --git a/Testing/build.xml b/Testing/build.xml
new file mode 100644
index 0000000000..da9b6c050e
--- /dev/null
+++ b/Testing/build.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+ Builds, tests, and runs the project org.sleuthkit.autopsy.testing.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Testing/manifest.mf b/Testing/manifest.mf
new file mode 100644
index 0000000000..a4acafe8e5
--- /dev/null
+++ b/Testing/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.sleuthkit.autopsy.testing
+OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/testing/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/Testing/nbproject/build-impl.xml b/Testing/nbproject/build-impl.xml
new file mode 100644
index 0000000000..50047b6352
--- /dev/null
+++ b/Testing/nbproject/build-impl.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ You must set 'suite.dir' to point to your containing module suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Testing/nbproject/genfiles.properties b/Testing/nbproject/genfiles.properties
new file mode 100644
index 0000000000..b4f5cac4ea
--- /dev/null
+++ b/Testing/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=7c2c586b
+build.xml.script.CRC32=323ed73c
+build.xml.stylesheet.CRC32=a56c6a5b@1.46.2
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=64fc7023
+nbproject/build-impl.xml.script.CRC32=d8a1ea41
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.2
diff --git a/Testing/nbproject/project.properties b/Testing/nbproject/project.properties
new file mode 100644
index 0000000000..17255bac6b
--- /dev/null
+++ b/Testing/nbproject/project.properties
@@ -0,0 +1,2 @@
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml
new file mode 100644
index 0000000000..8511bfbed8
--- /dev/null
+++ b/Testing/nbproject/project.xml
@@ -0,0 +1,56 @@
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ org.sleuthkit.autopsy.testing
+
+
+
+ org.sleuthkit.autopsy.ingest
+
+
+
+ 0-1
+ 1.0
+
+
+
+
+
+ qa-functional
+
+ org.netbeans.libs.junit4
+
+
+
+ org.netbeans.modules.jellytools.platform
+
+
+
+ org.netbeans.modules.jemmy
+
+
+
+ org.netbeans.modules.nbjunit
+
+
+
+
+
+ unit
+
+ org.netbeans.libs.junit4
+
+
+
+ org.netbeans.modules.nbjunit
+
+
+
+
+
+
+
+
+
diff --git a/Testing/nbproject/suite.properties b/Testing/nbproject/suite.properties
new file mode 100644
index 0000000000..29d7cc9bd6
--- /dev/null
+++ b/Testing/nbproject/suite.properties
@@ -0,0 +1 @@
+suite.dir=${basedir}/..
diff --git a/Testing/script/getcounts.py b/Testing/script/getcounts.py
new file mode 100644
index 0000000000..8327923aca
--- /dev/null
+++ b/Testing/script/getcounts.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+import os
+import sys
+import sqlite3
+
+def getNumbers(inFile):
+
+ if not inFile.endswith(".db") or not os.path.exists(inFile):
+ print("Not a database file: " + inFile)
+ return
+ # For now, comparing size of blackboard_artifacts,
+ # blackboard_attributes,
+ # and tsk_objects.
+ inFileConn = sqlite3.connect(inFile)
+ inFileC = inFileConn.cursor()
+ print(inFile)
+ inFileC.execute("select count(*) from tsk_objects")
+ inFileObjects = inFileC.fetchone()[0]
+ print("Objects: %d" % inFileObjects)
+ inFileC.execute("select count(*) from blackboard_artifacts")
+ inFileArtifacts = inFileC.fetchone()[0]
+ print("Artifacts: %d" % inFileArtifacts)
+ inFileC.execute("select count(*) from blackboard_attributes")
+ inFileAttributes = inFileC.fetchone()[0]
+ print("Attributes: %d" % inFileAttributes)
+
+def usage():
+ print("This script queries the databases given as arguments for \n\
+ TSK Object, Blackboard Artifact, and Blackboard Attribute counts.")
+
+if __name__ == "__main__":
+ if len(sys.argv) == 1:
+ usage()
+ argi = 1
+ while argi < len(sys.argv):
+ getNumbers(sys.argv[argi])
+ argi+=1
+
diff --git a/Testing/script/regression.py b/Testing/script/regression.py
new file mode 100644
index 0000000000..5277b44ac9
--- /dev/null
+++ b/Testing/script/regression.py
@@ -0,0 +1,247 @@
+#!/usr/bin/python
+import sys
+import sqlite3
+import re
+import subprocess
+import os.path
+import shutil
+import time
+
+# Usage: ./regression.py [-i FILE] [OPTIONS]
+# Run the RegressionTest.java file, and compare the result with a gold standard
+# When the -i flag is set, this script only tests the image given by FILE.
+# By default, it tests every image in ./input/
+# An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,
+# and an indexed notable hash database at ./input/notablehashes.txt-md5.idx
+# In addition, any keywords to search for must be in ./input/notablekeywords.xml
+# Options:
+# -r, --rebuild Rebuild the gold standards from the test results for each image
+
+hadErrors = False # If any of the tests failed
+results = {} # Dictionary in which to store map ({imgname}->errors)
+goldDir = "gold" # Directory for gold standards (files should be ./gold/{imgname}/standard.db)
+inDir = "input" # Image files, hash dbs, and keywords.
+# Results will be in ./output/{datetime}/{imgname}/
+outDir = os.path.join("output",time.strftime("%Y.%m.%d-%H.%M"))
+
+
+# Run ingest on all the images in 'input', using notablekeywords.xml and notablehashes.txt-md5.idx
+def testAddImageIngest(inFile):
+ print "================================================"
+ print "Ingesting Image: " + inFile
+
+ # Set up case directory path
+ testCaseName = imageName(inFile)
+ if os.path.exists(os.path.join(outDir,testCaseName)):
+ shutil.rmtree(os.path.join(outDir,testCaseName))
+ os.makedirs(os.path.join(outDir,testCaseName))
+
+ cwd = wgetcwd()
+ testInFile = wabspath(inFile)
+ knownBadPath = os.path.join(cwd,inDir,"notablehashes.txt-md5.idx")
+ keywordPath = os.path.join(cwd,inDir,"notablekeywords.xml")
+ nsrlPath = os.path.join(cwd,inDir,"nsrl.txt-md5.idx")
+
+ # set up ant target
+ args = ["ant"]
+ args.append("-q")
+ args.append("-f")
+ args.append(os.path.join("..","build.xml"))
+ args.append("regression-test")
+ args.append("-l")
+ args.append(os.path.join(cwd,outDir,testCaseName,"antlog.txt"))
+ args.append("-Dimg_path=" + testInFile)
+ args.append("-Dknown_bad_path=" + knownBadPath)
+ args.append("-Dkeyword_path=" + keywordPath)
+ args.append("-Dnsrl_path=" + nsrlPath)
+ args.append("-Dgold_path=" + os.path.join(cwd,goldDir))
+ args.append("-Dout_path=" + os.path.join(cwd,outDir,testCaseName))
+
+ # print the ant testing command
+ print "CMD: " + " ".join(args)
+
+ print "Starting test..."
+ #fnull = open(os.devnull, 'w')
+ #subprocess.call(args, stderr=subprocess.STDOUT, stdout=fnull)
+ #fnull.close();
+ subprocess.call(args)
+
+def testCompareToGold(inFile):
+ print "-----------------------------------------------"
+ print "Comparing results for " + inFile + " with gold."
+
+ name = imageName(inFile)
+ cwd = wgetcwd()
+ goldFile = os.path.join(cwd,goldDir,name,"standard.db")
+ testFile = os.path.join(cwd,outDir,name,"AutopsyTestCase","autopsy.db")
+ if os.path.isfile(goldFile) == False:
+ markError("No gold standard exists", inFile)
+ return
+ if os.path.isfile(testFile) == False:
+ markError("No database exists", inFile)
+ return
+
+ # For now, comparing size of blackboard_artifacts,
+ # blackboard_attributes,
+ # and tsk_objects.
+ goldConn = sqlite3.connect(goldFile)
+ goldC = goldConn.cursor()
+ testConn = sqlite3.connect(testFile)
+ testC = testConn.cursor()
+
+ print("Comparing Artifacts: ")
+ goldC.execute("select count(*) from blackboard_artifacts")
+ goldArtifacts = goldC.fetchone()[0]
+ testC.execute("select count(*) from blackboard_artifacts")
+ testArtifacts = testC.fetchone()[0]
+ if(goldArtifacts != testArtifacts):
+ errString = "Artifact counts do not match!: "
+ errString += str("Gold: %d, Test: %d" % (goldArtifacts, testArtifacts))
+ markError(errString, inFile)
+ else:
+ print("Artifact counts match!")
+ print("Comparing Attributes: ")
+ goldC.execute("select count(*) from blackboard_attributes")
+ goldAttributes = goldC.fetchone()[0]
+ testC.execute("select count(*) from blackboard_attributes")
+ testAttributes = testC.fetchone()[0]
+ if(goldAttributes != testAttributes):
+ errString = "Attribute counts do not match!: "
+ errString += str("Gold: %d, Test: %d" % (goldAttributes, testAttributes))
+ markError(errString, inFile)
+ else:
+ print("Attribute counts match!")
+ print("Comparing TSK Objects: ")
+ goldC.execute("select count(*) from tsk_objects")
+ goldObjects = goldC.fetchone()[0]
+ testC.execute("select count(*) from tsk_objects")
+ testObjects = testC.fetchone()[0]
+ if(goldObjects != testObjects):
+ errString = "TSK Object counts do not match!: "
+ errString += str("Gold: %d, Test: %d" % (goldObjects, testObjects))
+ markError(errString, inFile)
+ else:
+ print("Object counts match!")
+
+def copyTestToGold(inFile):
+ print "------------------------------------------------"
+ print "Recreating gold standard from results."
+ inFile = imageName(inFile)
+ cwd = wgetcwd()
+ goldFile = os.path.join(cwd,goldDir,inFile,"standard.db")
+ testFile = os.path.join(cwd,outDir,inFile,"AutopsyTestCase","autopsy.db")
+ if os.path.exists(os.path.join(cwd,goldDir,inFile)):
+ shutil.rmtree(os.path.join(cwd,goldDir,inFile))
+ os.makedirs(os.path.join(cwd,goldDir,inFile))
+ shutil.copy(testFile, goldFile)
+
+class ImgType:
+ RAW, ENCASE, SPLIT, UNKNOWN = range(4)
+
+def imageType(inFile):
+ extStart = inFile.rfind(".")
+ if (extStart == -1):
+ return ImgType.UNKNOWN
+ ext = inFile[extStart:].lower()
+ if (ext == ".img" or ext == ".dd"):
+ return ImgType.RAW
+ elif (ext == ".e01"):
+ return ImgType.ENCASE
+ elif (ext == ".aa" or ext == ".001"):
+ return ImgType.SPLIT
+ else:
+ return ImgType.UNKNOWN
+
+def imageName(inFile):
+ pathEnd = inFile.rfind("/")
+ extStart = inFile.rfind(".")
+ if(extStart == -1 and extStart == -1):
+ return inFile
+ elif(extStart == -1):
+ return inFile[pathEnd+1:]
+ elif(pathEnd == -1):
+ return inFile[:extStart]
+ else:
+ return inFile[pathEnd+1:extStart]
+
+def markError(errString, inFile):
+ global hadErrors
+ hadErrors = True
+ errors = results.get(inFile, [])
+ errors.append(errString)
+ results[inFile] = errors
+ print errString
+
+def wgetcwd():
+ proc = subprocess.Popen(("cygpath", "-m", os.getcwd()), stdout=subprocess.PIPE)
+ out,err = proc.communicate()
+ return out.rstrip()
+
+def wabspath(inFile):
+ proc = subprocess.Popen(("cygpath", "-m", os.path.abspath(inFile)), stdout=subprocess.PIPE)
+ out,err = proc.communicate()
+ return out.rstrip()
+
+def copyLogs(inFile):
+ logDir = os.path.join("..","build","test","qa-functional","work","userdir0","var","log")
+ shutil.copytree(logDir,os.path.join(outDir,imageName(inFile),"logs"))
+
+def testFile(image, rebuild):
+ if imageType(image) != ImgType.UNKNOWN:
+ testAddImageIngest(image)
+ #print imageName(image)
+ copyLogs(image)
+ if rebuild:
+ copyTestToGold(image)
+ else:
+ testCompareToGold(image)
+
+def usage() :
+ usage = "\
+ Usage: ./regression.py [-i FILE] [OPTIONS] \n\n\
+ Run the RegressionTest.java file, and compare the result with a gold standard \n\n\
+ When the -i flag is set, this script only tests the image given by FILE.\n\
+ By default, it tests every image in ./input/\n\n\
+ An indexed NSRL database is expected at ./input/nsrl.txt-md5.idx,\n\
+ and an indexed notable hash database at ./input/notablehashes.txt-md5.idx\n\
+ In addition, any keywords to search for must be in ./input/notablekeywords.xml\n\n\
+ Options:\n\n\
+ -r, --rebuild\t\tRebuild the gold standards from the test results for each image"
+ return usage
+
+def main():
+ rebuild = False
+ single = False
+ test = True
+ argi = 1
+ while argi < len(sys.argv):
+ arg = sys.argv[argi]
+ if arg == "-i" and argi+1 < len(sys.argv):
+ single = True
+ argi+=1
+ image = sys.argv[argi]
+ print "Running on single image: " + image
+ elif (arg == "--rebuild") or (arg == "-r"):
+ rebuild = True
+ print "Running in REBUILD mode"
+ else:
+ test = False
+ print usage()
+ argi+=1
+ if single:
+ testFile(image, rebuild)
+ elif test:
+ for inFile in os.listdir(inDir):
+ testFile(os.path.join(inDir,inFile), rebuild)
+
+ if hadErrors == True:
+ print "**********************************************"
+ print "Tests complete: There were errors"
+
+ for k,v in results.items():
+ print k
+ for errString in v:
+ print("\t%s" % errString)
+
+if __name__ == "__main__":
+ main()
diff --git a/Testing/src/org/sleuthkit/autopsy/testing/Bundle.properties b/Testing/src/org/sleuthkit/autopsy/testing/Bundle.properties
new file mode 100644
index 0000000000..125ec1c485
--- /dev/null
+++ b/Testing/src/org/sleuthkit/autopsy/testing/Bundle.properties
@@ -0,0 +1 @@
+OpenIDE-Module-Name=Testing
diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java
new file mode 100644
index 0000000000..7e1708603b
--- /dev/null
+++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java
@@ -0,0 +1,215 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011 Basis Technology Corp.
+ * Contact: carrier sleuthkit 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.testing;
+
+import java.util.logging.Logger;
+import javax.swing.JDialog;
+import javax.swing.JTextField;
+import junit.framework.Test;
+import org.netbeans.jellytools.JellyTestCase;
+import org.netbeans.jellytools.NbDialogOperator;
+import org.netbeans.jellytools.WizardOperator;
+import org.netbeans.jemmy.Timeout;
+import org.netbeans.jemmy.operators.JButtonOperator;
+import org.netbeans.jemmy.operators.JCheckBoxOperator;
+import org.netbeans.jemmy.operators.JDialogOperator;
+import org.netbeans.jemmy.operators.JFileChooserOperator;
+import org.netbeans.jemmy.operators.JTableOperator;
+import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.netbeans.junit.NbModuleSuite;
+import org.sleuthkit.autopsy.ingest.IngestManager;
+import org.sleuthkit.autopsy.ingest.IngestServiceAbstract;
+/**
+ * This test expects the following system properties to be set:
+ * img_path: The fully qualified path to the image file (if split, the first file)
+ * out_path: The location where the case will be stored
+ * nsrl_path: Path to the nsrl database
+ * known_bad_path: Path to a database of known bad hashes
+ * keyword_path: Path to a keyword list xml file
+ *
+ * Without these properties set, the test will fail to run correctly.
+ * To run this test correctly, you should use the script 'regression.py'
+ * located in the 'script' directory of the Testing module.
+ */
+public class RegressionTest extends JellyTestCase{
+
+ private static final Logger logger = Logger.getLogger(RegressionTest.class.getName());
+
+ /** Constructor required by JUnit */
+ public RegressionTest(String name) {
+ super(name);
+ }
+
+
+ /** Creates suite from particular test cases. */
+ public static Test suite() {
+
+ // run tests with specific configuration
+ NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(RegressionTest.class).
+ clusters(".*").
+ enableModules(".*");
+ conf = conf.addTest("testNewCaseWizardOpen",
+ "testNewCaseWizard",
+ "testAddImageWizard1",
+ "testConfigureIngest1",
+ "testConfigureHash",
+ "testConfigureIngest2",
+ "testConfigureSearch",
+ "testIngest");
+ return NbModuleSuite.create(conf);
+ }
+
+ /** Method called before each test case. */
+ @Override
+ public void setUp() {
+ logger.info("######## " + System.getProperty("img_path") + " #######");
+ }
+
+ /** Method called after each test case. */
+ @Override
+ public void tearDown() {
+ }
+
+ public void testNewCaseWizardOpen() {
+ logger.info("New Case");
+ NbDialogOperator nbdo = new NbDialogOperator("Welcome");
+ JButtonOperator jbo = new JButtonOperator(nbdo, 0); // the "New Case" button
+ jbo.clickMouse();
+ }
+
+ public void testNewCaseWizard() {
+ logger.info("New Case Wizard");
+ WizardOperator wo = new WizardOperator("New Case Information");
+ JTextFieldOperator jtfo1 = new JTextFieldOperator(wo, 1);
+ jtfo1.typeText("AutopsyTestCase"); // Name the case "AutopsyTestCase"
+ JTextFieldOperator jtfo0 = new JTextFieldOperator(wo, 0);
+ jtfo0.typeText(System.getProperty("out_path"));
+ wo.btNext().clickMouse();
+ JTextFieldOperator jtfo2 = new JTextFieldOperator(wo, 0);
+ jtfo2.typeText("000"); // Set the case number
+ JTextFieldOperator jtfo3 = new JTextFieldOperator(wo, 1);
+ jtfo3.typeText("Examiner 1"); // Set the case examiner
+ wo.btFinish().clickMouse();
+ }
+
+ public void testAddImageWizard1() {
+ logger.info("AddImageWizard 1");
+ WizardOperator wo = new WizardOperator("Add Image");
+ JTextFieldOperator jtfo0 = new JTextFieldOperator(wo, 0);
+ String imageDir = System.getProperty("img_path");
+ ((JTextField)jtfo0.getSource()).setText(imageDir);
+ wo.btNext().clickMouse();
+ long start = System.currentTimeMillis();
+ while(!wo.btNext().isEnabled()) {
+ new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process
+ }
+ logger.info("Add image took " + (System.currentTimeMillis()-start) + "ms");
+ wo.btNext().clickMouse();
+ }
+
+ public void testConfigureIngest1() {
+ logger.info("Ingest 1");
+ WizardOperator wo = new WizardOperator("Add Image");
+ JTableOperator jto = new JTableOperator(wo, 0);
+ int row = jto.findCellRow("Hash Lookup", 1, 0);
+ jto.clickOnCell(row, 1);
+ JButtonOperator jbo1 = new JButtonOperator(wo, "Advanced");
+ jbo1.pushNoBlock();
+ }
+
+ public void testConfigureHash() {
+ logger.info("Hash Configure");
+ JDialog jd = JDialogOperator.waitJDialog("Hash Database Configuration", false, false);
+ JDialogOperator jdo = new JDialogOperator(jd);
+ String databaseDir = System.getProperty("nsrl_path");
+ String badDir = System.getProperty("known_bad_path");
+ JButtonOperator jbo0 = new JButtonOperator(jdo, "Change");
+ jbo0.pushNoBlock();
+ JFileChooserOperator jfco0 = new JFileChooserOperator();
+ jfco0.chooseFile(databaseDir);
+ JButtonOperator jbo1 = new JButtonOperator(jdo, "Add Notable Database");
+ jbo1.pushNoBlock();
+ JFileChooserOperator jfco1 = new JFileChooserOperator();
+ jfco1.chooseFile(badDir);
+ JDialog jd2 = JDialogOperator.waitJDialog("New Hash Set", false, false);
+ JDialogOperator jdo2 = new JDialogOperator(jd2);
+ JButtonOperator jbo2 = new JButtonOperator(jdo2, "OK", 0);
+ jbo2.pushNoBlock();
+ // Used if the database has no index
+ //JDialog jd3 = JDialogOperator.waitJDialog("No Index Exists", false, false);
+ //JDialogOperator jdo3 = new JDialogOperator(jd3);
+ //JButtonOperator jbo3 = new JButtonOperator(jdo3, "Yes", 0);
+ //new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process
+ //jbo3.pushNoBlock();
+ JButtonOperator jbo4 = new JButtonOperator(jdo, "OK", 0);
+ jbo4.pushNoBlock();
+ }
+
+ public void testConfigureIngest2() {
+ logger.info("Ingest 2");
+ WizardOperator wo = new WizardOperator("Add Image");
+ JTableOperator jto = new JTableOperator(wo, 0);
+ int row = jto.findCellRow("Keyword Search", 1, 0);
+ jto.clickOnCell(row, 1);
+ JButtonOperator jbo1 = new JButtonOperator(wo, "Advanced");
+ jbo1.pushNoBlock();
+ }
+
+ public void testConfigureSearch() {
+ logger.info("Search Configure");
+ JDialog jd = JDialogOperator.waitJDialog("Keyword List Configuration", false, false);
+ JDialogOperator jdo = new JDialogOperator(jd);
+ String words = System.getProperty("keyword_path");
+ JButtonOperator jbo0 = new JButtonOperator(jdo, "Import List", 0);
+ jbo0.pushNoBlock();
+ JFileChooserOperator jfco0 = new JFileChooserOperator();
+ jfco0.chooseFile(words);
+ JCheckBoxOperator jcbo = new JCheckBoxOperator(jdo, "Use during triage / ingest", 0);
+ jcbo.doClick();
+ JButtonOperator jbo2 = new JButtonOperator(jdo, "OK", 0);
+ jbo2.pushNoBlock();
+ WizardOperator wo = new WizardOperator("Add Image");
+ wo.btNext().clickMouse();
+ wo.btFinish().clickMouse();
+ }
+
+ public void testIngest() {
+ logger.info("Ingest 3");
+ long start = System.currentTimeMillis();
+ IngestManager man = IngestManager.getDefault();
+ while(man.isEnqueueRunning()) {
+ new Timeout("pausing", 5000).sleep(); // give it a second (or five) to process
+ }
+ logger.info("Enqueue took " + (System.currentTimeMillis()-start) + "ms");
+ while(man.isIngestRunning()) {
+ new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process
+ }
+ new Timeout("pausing", 15000).sleep(); // give it a second (or fifteen) to process
+ boolean sleep = true;
+ while (sleep) {
+ new Timeout("pausing", 5000).sleep(); // give it a second (or five) to process
+ sleep = false;
+ for (IngestServiceAbstract serv : IngestManager.enumerateFsContentServices()) {
+ sleep = sleep || serv.hasBackgroundJobsRunning();
+ }
+ }
+ logger.info("Ingest (including enqueue) took " + (System.currentTimeMillis()-start) + "ms");
+ new Timeout("pausing", 5000).sleep(); // allow keyword search to finish saving artifacts, just in case
+ }
+}
\ No newline at end of file
diff --git a/nbproject/platform.properties b/nbproject/platform.properties
index 38ecd5a92e..95295edd72 100644
--- a/nbproject/platform.properties
+++ b/nbproject/platform.properties
@@ -1,4 +1,5 @@
cluster.path=\
+ ${nbplatform.active.dir}/harness:\
${nbplatform.active.dir}/java:\
${nbplatform.active.dir}/platform
disabled.modules=\
diff --git a/nbproject/project.properties b/nbproject/project.properties
index 103f5f1935..e499096b46 100644
--- a/nbproject/project.properties
+++ b/nbproject/project.properties
@@ -29,7 +29,8 @@ modules=\
${project.org.sleuthkit.autopsy.hashdatabase}:\
${project.org.gnu.trove}:\
${project.org.sleuthkit.autopsy.recentactivity}:\
- ${project.org.sleuthkit.autopsy.report}
+ ${project.org.sleuthkit.autopsy.report}:\
+ ${project.org.sleuthkit.autopsy.testing}
project.org.gnu.trove=trove
project.org.sleuthkit.autopsy.casemodule=Case
project.org.sleuthkit.autopsy.corecomponentinterfaces=CoreComponentInterfaces
@@ -43,4 +44,5 @@ project.org.sleuthkit.autopsy.keywordsearch=KeywordSearch
project.org.sleuthkit.autopsy.menuactions=MenuActions
project.org.sleuthkit.autopsy.datamodel=DataModel
project.org.sleuthkit.autopsy.recentactivity=RecentActivity
-project.org.sleuthkit.autopsy.report=Report
\ No newline at end of file
+project.org.sleuthkit.autopsy.report=Report
+project.org.sleuthkit.autopsy.testing=Testing