mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-08 22:29:33 +00:00
Initial test script commit.
This commit is contained in:
parent
4de3ae81f2
commit
5d4dc02634
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,3 +22,7 @@ Bundle_*.properties
|
|||||||
/branding/core/core.jar/org/netbeans/core/startup/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
|
/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
|
||||||
/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties
|
/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties
|
||||||
|
/Testing/script/input/
|
||||||
|
/Testing/script/output/
|
||||||
|
/Testing/script/gold/
|
||||||
|
*~
|
||||||
|
@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Log;
|
|||||||
*/
|
*/
|
||||||
class HashDbMgmtAction extends CallableSystemAction {
|
class HashDbMgmtAction extends CallableSystemAction {
|
||||||
|
|
||||||
private static final String ACTION_NAME = "Hash Database Configuration";
|
static final String ACTION_NAME = "Hash Database Configuration";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void performAction() {
|
public void performAction() {
|
||||||
|
@ -63,6 +63,7 @@ public class HashDbMgmtPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
/** Creates new form HashDbMgmtPanel */
|
/** Creates new form HashDbMgmtPanel */
|
||||||
private HashDbMgmtPanel() {
|
private HashDbMgmtPanel() {
|
||||||
|
setName(HashDbMgmtAction.ACTION_NAME);
|
||||||
notableTableModel = new HashSetTableModel();
|
notableTableModel = new HashSetTableModel();
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
@ -294,8 +295,23 @@ public class HashDbMgmtPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
if(setName != null && !setName.equals("")) {
|
if(setName != null && !setName.equals("")) {
|
||||||
HashDb newDb = new HashDb(setName, Arrays.asList(new String[]{filePath}), false);
|
HashDb newDb = new HashDb(setName, Arrays.asList(new String[]{filePath}), false);
|
||||||
if(IndexStatus.isIngestible(newDb.status()))
|
int toIndex = JOptionPane.NO_OPTION;
|
||||||
|
if (IndexStatus.isIngestible(newDb.status())) {
|
||||||
newDb.setUseForIngest(true);
|
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
|
notableTableModel.newSet(newDb); // TODO: support multiple file paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
71
Testing/build.xml
Normal file
71
Testing/build.xml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
|
||||||
|
<!-- for some information on what you could do (e.g. targets to override). -->
|
||||||
|
<!-- If you delete this file and reopen the project it will be recreated. -->
|
||||||
|
<project name="org.sleuthkit.autopsy.testing" default="netbeans" basedir=".">
|
||||||
|
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.testing.</description>
|
||||||
|
<import file="nbproject/build-impl.xml"/>
|
||||||
|
|
||||||
|
<target name="set-args">
|
||||||
|
<property name="img_path" value="C:\Users\dfickling\Desktop\test-data\64mb2.img"/>
|
||||||
|
<property name="known_bad_path" value="C:\Users\dfickling\Desktop\test-data\notable_files.txt"/>
|
||||||
|
<property name="nsrl_path" value="C:\Users\dfickling\Desktop\NSRLComplete.txt-md5.idx"/>
|
||||||
|
<property name="keyword_path" value="C:\Users\dfickling\Desktop\test-data\notable_words.xml"/>
|
||||||
|
<property name="gold_path" value="C:\Users\dfickling\Desktop\test-data\win7-ren.txt"/>
|
||||||
|
<property name="out_path" value="C:\Users\dfickling\Desktop\test-data"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="check-args"> <!-- remove dependency on set-args to get from script -->
|
||||||
|
<fail message="Missing required argument: img_path" unless="img_path"/>
|
||||||
|
<fail message="Missing required argument: gold_path" unless="gold_path"/>
|
||||||
|
<fail message="Missing required argument: out_path" unless="out_path"/>
|
||||||
|
<fail message="Missing required argument: known_bad_path" unless="known_bad_path"/>
|
||||||
|
<fail message="Missing required argument: nsrl_path" unless="nsrl_path"/>
|
||||||
|
<fail message="Missing required argument: keyword_path" unless="keyword_path"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="regression-test" depends="check-args,init,test-init,test-build" if="exists.test.qa-functional.src.dir">
|
||||||
|
<test test.type="qa-functional"/>
|
||||||
|
</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}" includes="${test.includes}" excludes="${test.excludes}"/>
|
||||||
|
</batchtest>
|
||||||
|
<classpath refid="test.@{test.type}.run.cp"/>
|
||||||
|
<syspropertyset refid="test.@{test.type}.properties"/>
|
||||||
|
<jvmarg line="${test.bootclasspath.prepend.args}"/>
|
||||||
|
<jvmarg line="${test.run.args}"/>
|
||||||
|
<sysproperty key="img_path" value="${img_path}"/>
|
||||||
|
<sysproperty key="gold_path" value="${gold_path}"/>
|
||||||
|
<sysproperty key="out_path" value="${out_path}"/>
|
||||||
|
<sysproperty key="known_bad_path" value="${known_bad_path}"/>
|
||||||
|
<sysproperty key="nsrl_path" value="${nsrl_path}"/>
|
||||||
|
<sysproperty key="keyword_path" value="${keyword_path}"/>
|
||||||
|
<!--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
Testing/manifest.mf
Normal file
5
Testing/manifest.mf
Normal file
@ -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
|
||||||
|
|
45
Testing/nbproject/build-impl.xml
Normal file
45
Testing/nbproject/build-impl.xml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||||
|
*** EDIT ../build.xml INSTEAD ***
|
||||||
|
-->
|
||||||
|
<project name="org.sleuthkit.autopsy.testing-impl" basedir="..">
|
||||||
|
<fail message="Please build using Ant 1.7.1 or higher.">
|
||||||
|
<condition>
|
||||||
|
<not>
|
||||||
|
<antversion atleast="1.7.1"/>
|
||||||
|
</not>
|
||||||
|
</condition>
|
||||||
|
</fail>
|
||||||
|
<property file="nbproject/private/suite-private.properties"/>
|
||||||
|
<property file="nbproject/suite.properties"/>
|
||||||
|
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
|
||||||
|
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
|
||||||
|
<property file="${suite.dir}/nbproject/platform.properties"/>
|
||||||
|
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
|
||||||
|
<attribute name="name"/>
|
||||||
|
<attribute name="value"/>
|
||||||
|
<sequential>
|
||||||
|
<property name="@{name}" value="${@{value}}"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
|
||||||
|
<attribute name="property"/>
|
||||||
|
<attribute name="value"/>
|
||||||
|
<sequential>
|
||||||
|
<property name="@{property}" value="@{value}"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
<property file="${user.properties.file}"/>
|
||||||
|
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||||
|
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||||
|
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||||
|
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
|
||||||
|
<condition>
|
||||||
|
<not>
|
||||||
|
<contains string="${cluster.path.evaluated}" substring="platform"/>
|
||||||
|
</not>
|
||||||
|
</condition>
|
||||||
|
</fail>
|
||||||
|
<import file="${harness.dir}/build.xml"/>
|
||||||
|
</project>
|
8
Testing/nbproject/genfiles.properties
Normal file
8
Testing/nbproject/genfiles.properties
Normal file
@ -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
|
2
Testing/nbproject/project.properties
Normal file
2
Testing/nbproject/project.properties
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
javac.source=1.6
|
||||||
|
javac.compilerargs=-Xlint -Xlint:-serial
|
56
Testing/nbproject/project.xml
Normal file
56
Testing/nbproject/project.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||||
|
<type>org.netbeans.modules.apisupport.project</type>
|
||||||
|
<configuration>
|
||||||
|
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
|
||||||
|
<code-name-base>org.sleuthkit.autopsy.testing</code-name-base>
|
||||||
|
<suite-component/>
|
||||||
|
<module-dependencies>
|
||||||
|
<dependency>
|
||||||
|
<code-name-base>org.sleuthkit.autopsy.ingest</code-name-base>
|
||||||
|
<build-prerequisite/>
|
||||||
|
<compile-dependency/>
|
||||||
|
<run-dependency>
|
||||||
|
<release-version>0-1</release-version>
|
||||||
|
<specification-version>1.0</specification-version>
|
||||||
|
</run-dependency>
|
||||||
|
</dependency>
|
||||||
|
</module-dependencies>
|
||||||
|
<test-dependencies>
|
||||||
|
<test-type>
|
||||||
|
<name>qa-functional</name>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.libs.junit4</code-name-base>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.modules.jellytools.platform</code-name-base>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.modules.jemmy</code-name-base>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
|
||||||
|
<recursive/>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
</test-type>
|
||||||
|
<test-type>
|
||||||
|
<name>unit</name>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.libs.junit4</code-name-base>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
<test-dependency>
|
||||||
|
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
|
||||||
|
<recursive/>
|
||||||
|
<compile-dependency/>
|
||||||
|
</test-dependency>
|
||||||
|
</test-type>
|
||||||
|
</test-dependencies>
|
||||||
|
<public-packages/>
|
||||||
|
</data>
|
||||||
|
</configuration>
|
||||||
|
</project>
|
1
Testing/nbproject/suite.properties
Normal file
1
Testing/nbproject/suite.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
suite.dir=${basedir}/..
|
38
Testing/script/getcounts.py
Normal file
38
Testing/script/getcounts.py
Normal file
@ -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
|
||||||
|
|
247
Testing/script/regression.py
Normal file
247
Testing/script/regression.py
Normal file
@ -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()
|
@ -0,0 +1 @@
|
|||||||
|
OpenIDE-Module-Name=Testing
|
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011 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.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
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
cluster.path=\
|
cluster.path=\
|
||||||
|
${nbplatform.active.dir}/harness:\
|
||||||
${nbplatform.active.dir}/java:\
|
${nbplatform.active.dir}/java:\
|
||||||
${nbplatform.active.dir}/platform
|
${nbplatform.active.dir}/platform
|
||||||
disabled.modules=\
|
disabled.modules=\
|
||||||
|
@ -29,7 +29,8 @@ modules=\
|
|||||||
${project.org.sleuthkit.autopsy.hashdatabase}:\
|
${project.org.sleuthkit.autopsy.hashdatabase}:\
|
||||||
${project.org.gnu.trove}:\
|
${project.org.gnu.trove}:\
|
||||||
${project.org.sleuthkit.autopsy.recentactivity}:\
|
${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.gnu.trove=trove
|
||||||
project.org.sleuthkit.autopsy.casemodule=Case
|
project.org.sleuthkit.autopsy.casemodule=Case
|
||||||
project.org.sleuthkit.autopsy.corecomponentinterfaces=CoreComponentInterfaces
|
project.org.sleuthkit.autopsy.corecomponentinterfaces=CoreComponentInterfaces
|
||||||
@ -44,3 +45,4 @@ project.org.sleuthkit.autopsy.menuactions=MenuActions
|
|||||||
project.org.sleuthkit.autopsy.datamodel=DataModel
|
project.org.sleuthkit.autopsy.datamodel=DataModel
|
||||||
project.org.sleuthkit.autopsy.recentactivity=RecentActivity
|
project.org.sleuthkit.autopsy.recentactivity=RecentActivity
|
||||||
project.org.sleuthkit.autopsy.report=Report
|
project.org.sleuthkit.autopsy.report=Report
|
||||||
|
project.org.sleuthkit.autopsy.testing=Testing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user