Regression test changes

Added email support to the regression test, documentation coming soon
This commit is contained in:
Sean-M 2013-02-20 17:48:56 -05:00
parent 90b1a49d29
commit 0a84f38902
4 changed files with 1451 additions and 1340 deletions

34
.gitignore vendored
View File

@ -6,14 +6,34 @@
/Core/release/modules/lib/ /Core/release/modules/lib/
/Core/release/modules/ext/ /Core/release/modules/ext/
/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties /Core/src/org/sleuthkit/autopsy/coreutils/Version.properties
/Core/build/
/Core/dist/
/Core/nbproject/*
!/Core/nbproject/project.xml
!/Core/nbproject/project.properties
/CoreLibs/release/modules/lib/ /CoreLibs/release/modules/lib/
/CoreLibs/release/modules/ext/ /CoreLibs/release/modules/ext/
/CoreLibs/build/
/CoreLibs/dist/
/CoreLibs/nbproject/*
!/CoreLibs/nbproject/project.xml
!/CoreLibs/nbproject/project.properties
/KeywordSearch/release/modules/ext/ /KeywordSearch/release/modules/ext/
/KeywordSearch/release/solr/lib/ /KeywordSearch/release/solr/lib/
/KeywordSearch/release/solr/solr/lib/ /KeywordSearch/release/solr/solr/lib/
/KeywordSearch/release/solr/start.jar /KeywordSearch/release/solr/start.jar
/KeywordSearch/release/solr/webapps/solr.war /KeywordSearch/release/solr/webapps/solr.war
/KeywordSearch/build/
/KeywordSearch/dist/
/KeywordSearch/nbproject/*
!/KeywordSearch/nbproject/project.xml
!/KeywordSearch/nbproject/project.properties
/Ingest/release/modules/ext/ /Ingest/release/modules/ext/
/Ingest/build/
/Ingest/dist/
/Ingest/nbproject/*
!/Ingest/nbproject/project.xml
!/Ingest/nbproject/project.properties
/branding_spear /branding_spear
/installer_spear /installer_spear
Bundle_*.properties Bundle_*.properties
@ -21,9 +41,19 @@ Bundle_*.properties
genfiles.properties genfiles.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
/branding/build/
/branding/dist/
/branding/nbproject/*
!/branding/nbproject/project.xml
!/branding/nbproject/project.properties
/Testing/script/input/ /Testing/script/input/
/Testing/script/output/ /Testing/script/output/
/Testing/script/gold/ /Testing/script/gold/
/Testing/build/
/Testing/dist/
/Testing/nbproject/*
!/Testing/nbproject/project.xml
!/Testing/nbproject/project.properties
*~ *~
/netbeans-plat /netbeans-plat
/docs/doxygen/doxygen_docs /docs/doxygen/doxygen_docs
@ -31,4 +61,6 @@ genfiles.properties
/jdiff-logs/* /jdiff-logs/*
/gen_version.txt /gen_version.txt
hs_err_pid*.log hs_err_pid*.log
Core/src/org/sleuthkit/autopsy/casemodule/docs/QuickStart.html
Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
/Testing/script/myconfig.xml

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=dee5be43
build.xml.script.CRC32=1308cb72
build.xml.stylesheet.CRC32=a56c6a5b@2.50.1
# 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=dee5be43
nbproject/build-impl.xml.script.CRC32=a7a0d07a
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.50.1

View File

@ -1,8 +0,0 @@
build.xml.data.CRC32=11199bf7
build.xml.script.CRC32=d323407a
build.xml.stylesheet.CRC32=a56c6a5b@2.50.1
# 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=11199bf7
nbproject/build-impl.xml.script.CRC32=aef16a21
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.50.1

View File

@ -16,6 +16,14 @@ import traceback
import xml import xml
from time import localtime, strftime from time import localtime, strftime
from xml.dom.minidom import parse, parseString from xml.dom.minidom import parse, parseString
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.MIMEBase import MIMEBase
from email import Encoders
import urllib2
# #
# Please read me... # Please read me...
@ -57,13 +65,16 @@ class Args:
self.verbose = False self.verbose = False
self.exception = False self.exception = False
self.exception_string = "" self.exception_string = ""
self.mugen = False
self.contin = False self.contin = False
def parse(self): def parse(self):
sys.argv.pop(0) global nxtproc
nxtproc = []
nxtproc.append("python")
nxtproc.append(sys.argv.pop(0))
while sys.argv: while sys.argv:
arg = sys.argv.pop(0) arg = sys.argv.pop(0)
nxtproc.append(arg)
if(arg == "-f"): if(arg == "-f"):
try: try:
arg = sys.argv.pop(0) arg = sys.argv.pop(0)
@ -80,6 +91,7 @@ class Args:
elif(arg == "-l" or arg == "--list"): elif(arg == "-l" or arg == "--list"):
try: try:
arg = sys.argv.pop(0) arg = sys.argv.pop(0)
nxtproc.append(arg)
printout("Running from configuration file:") printout("Running from configuration file:")
printout(arg + "\n") printout(arg + "\n")
self.list = True self.list = True
@ -103,15 +115,13 @@ class Args:
elif(arg == "-e" or arg == "--exception"): elif(arg == "-e" or arg == "--exception"):
try: try:
arg = sys.argv.pop(0) arg = sys.argv.pop(0)
nxtproc.append(arg)
printout("Running in exception mode: ") printout("Running in exception mode: ")
printout("Printing all exceptions with the string '" + arg + "'\n") printout("Printing all exceptions with the string '" + arg + "'\n")
self.exception = True self.exception = True
self.exception_string = arg self.exception_string = arg
except: except:
printerror("Error: No exception string given.") printerror("Error: No exception string given.")
elif(arg == "-m" or arg == "--mugen"):
printout("Running in mugen mode. Will loop through config file until interrupted.")
self.mugen = True
elif arg == "-h" or arg == "--help": elif arg == "-h" or arg == "--help":
printout(usage()) printout(usage())
return False return False
@ -267,11 +277,19 @@ class Database:
if not self.artifact_comparison: if not self.artifact_comparison:
return "All counts matched" return "All counts matched"
else: else:
global failedbool
global errorem
failedbool = True
errorem += "There was a difference in the number of artifacts.\n"
return "; ".join(self.artifact_comparison) return "; ".join(self.artifact_comparison)
def get_attribute_comparison(self): def get_attribute_comparison(self):
if not self.attribute_comparison: if not self.attribute_comparison:
return "All counts matched" return "All counts matched"
global failedbool
global errorem
failedbool = True
errorem += "There was a difference in the number of attributes.\n"
list = [] list = []
for error in self.attribute_comparison: for error in self.attribute_comparison:
list.append(error) list.append(error)
@ -347,6 +365,7 @@ class Database:
# Iterates through an XML configuration file to find all given elements # Iterates through an XML configuration file to find all given elements
def run_config_test(config_file): def run_config_test(config_file):
try: try:
global parsed
parsed = parse(config_file) parsed = parse(config_file)
counts = {} counts = {}
if parsed.getElementsByTagName("indir"): if parsed.getElementsByTagName("indir"):
@ -355,36 +374,37 @@ def run_config_test(config_file):
case.global_csv = parsed.getElementsByTagName("global_csv")[0].getAttribute("value").encode().decode("utf-8") case.global_csv = parsed.getElementsByTagName("global_csv")[0].getAttribute("value").encode().decode("utf-8")
# Generate the top navbar of the HTML for easy access to all images # Generate the top navbar of the HTML for easy access to all images
case.global_csv = make_local_path(case.global_csv)
values = [] values = []
for element in parsed.getElementsByTagName("image"): for element in parsed.getElementsByTagName("image"):
value = element.getAttribute("value").encode().decode("utf-8") value = element.getAttribute("value").encode().decode("utf-8")
if file_exists(value): if file_exists(value):
values.append(value) values.append(value)
html_add_images(values) html_add_images(values)
# Run the test for each file in the configuration # Run the test for each file in the configuration
global args global args
if(args.mugen): if(args.contin):
#set all times an image has been processed to 0 #set all times an image has been processed to 0
for element in parsed.getElementsByTagName("image"): for element in parsed.getElementsByTagName("image"):
value = element.getAttribute("value").encode().decode("utf-8") value = element.getAttribute("value").encode().decode("utf-8")
counts[value] = 0 counts[value] = 0
#Begin infiniloop #Begin infiniloop
while(True): if(True):
for elem in counts.keys(): global daycount
if(newDay()): global nxtproc
if (daycount==1):
print("starting process")
pid = subprocess.Popen(nxtproc,
stdout=subprocess.PIPE).pid
sys.exit()
else:
daycount = 1
setDay() setDay()
gitPull("sleuthkit") gitPull("sleuthkit")
vsBuild() vsBuild()
gitPull("autopsy") gitPull("autopsy")
antBuild("datamodel", False) antBuild("datamodel", False)
antBuild("autopsy", True) antBuild("autopsy", True)
if file_exists(elem):
counts[elem]+=1
run_test(elem, counts[elem])
else:
printerror("Warning: Image file listed in the configuration does not exist:")
printerror(elem + "\n")
else: else:
for img in values: for img in values:
if file_exists(img): if file_exists(img):
@ -397,7 +417,6 @@ def run_config_test(config_file):
printerror("Error: There was an error running with the configuration file.") printerror("Error: There was an error running with the configuration file.")
printerror(str(e) + "\n") printerror(str(e) + "\n")
logging.critical(traceback.format_exc()) logging.critical(traceback.format_exc())
# Runs the test on the single given file. # Runs the test on the single given file.
# The path must be guarenteed to be a correct path. # The path must be guarenteed to be a correct path.
def run_test(image_file, count): def run_test(image_file, count):
@ -429,10 +448,6 @@ def run_test(image_file, count):
printerror("Error: Unknown fatal error when filling case data.") printerror("Error: Unknown fatal error when filling case data.")
printerror(str(e) + "\n") printerror(str(e) + "\n")
logging.critical(traceback.format_exc()) logging.critical(traceback.format_exc())
# If running in rebuild mode (-r)
if args.rebuild:
rebuild()
# If NOT keeping Solr index (-k) # If NOT keeping Solr index (-k)
if not args.keep: if not args.keep:
solr_index = make_local_path(case.output_dir, case.image_name, "AutopsyTestCase", "KeywordSearch") solr_index = make_local_path(case.output_dir, case.image_name, "AutopsyTestCase", "KeywordSearch")
@ -460,7 +475,9 @@ def run_test(image_file, count):
if case.global_csv: if case.global_csv:
generate_csv(case.global_csv) generate_csv(case.global_csv)
generate_html() generate_html()
# If running in rebuild mode (-r)
if args.rebuild:
rebuild()
# Reset the case and return the tests sucessfully finished # Reset the case and return the tests sucessfully finished
case.reset() case.reset()
return True return True
@ -489,14 +506,16 @@ def run_ant():
case.ant.append("-Dgold_path=" + make_local_path(case.gold)) case.ant.append("-Dgold_path=" + make_local_path(case.gold))
case.ant.append("-Dout_path=" + make_local_path(case.output_dir, case.image_name)) case.ant.append("-Dout_path=" + make_local_path(case.output_dir, case.image_name))
case.ant.append("-Dignore_unalloc=" + "%s" % args.unallocated) case.ant.append("-Dignore_unalloc=" + "%s" % args.unallocated)
case.ant.append("-Dmugen_mode" + str(args.mugen)) case.ant.append("-Dcontin_mode=" + str(args.contin))
case.ant.append("-Dtest.timeout=" + str(case.timeout)) case.ant.append("-Dtest.timeout=" + str(case.timeout))
printout("Ingesting Image:\n" + case.image_file + "\n") printout("Ingesting Image:\n" + case.image_file + "\n")
printout("CMD: " + " ".join(case.ant)) printout("CMD: " + " ".join(case.ant))
printout("Starting test...\n") printout("Starting test...\n")
antoutpth = make_local_path(case.output_dir, "antRunOutput.txt")
antout = open(antoutpth, "a")
if SYS is OS.CYGWIN: if SYS is OS.CYGWIN:
subprocess.call(case.ant) subprocess.call(case.ant, stdout=antout)
elif SYS is OS.WIN: elif SYS is OS.WIN:
theproc = subprocess.Popen(case.ant, shell = True) theproc = subprocess.Popen(case.ant, shell = True)
theproc.communicate() theproc.communicate()
@ -542,10 +561,10 @@ def rebuild():
copy_file(gold_from, gold_to) copy_file(gold_from, gold_to)
except FileNotFoundException as e: except FileNotFoundException as e:
errors.append(e.error) errors.append(e.error)
print(str(e))
except Exception as e: except Exception as e:
errors.append("Error: Unknown fatal error when rebuilding the gold database.") errors.append("Error: Unknown fatal error when rebuilding the gold database.")
errors.append(str(e) + "\n") errors.append(str(e) + "\n")
# Rebuild the HTML report # Rebuild the HTML report
htmlfolder = "" htmlfolder = ""
for fs in os.listdir(os.path.join(os.getcwd(),case.output_dir, case.image_name, "AutopsyTestCase", "Reports")): for fs in os.listdir(os.path.join(os.getcwd(),case.output_dir, case.image_name, "AutopsyTestCase", "Reports")):
@ -553,20 +572,18 @@ def rebuild():
htmlfolder = fs htmlfolder = fs
autopsy_html_path = make_local_path(case.output_dir, case.image_name, "AutopsyTestCase", "Reports", htmlfolder) autopsy_html_path = make_local_path(case.output_dir, case.image_name, "AutopsyTestCase", "Reports", htmlfolder)
html_path = make_local_path(case.output_dir, case.image_name,
#html_path = make_local_path(case.output_dir, case.image_name, "AutopsyTestCase", "Reports")
# "AutopsyTestCase", "Reports")
try: try:
os.makedirs(os.path.join(os.getcwd(), case.gold, case.image_name, htmlfolder)) os.makedirs(os.path.join(os.getcwd(), case.gold, case.image_name, htmlfolder))
for file in os.listdir(autopsy_html_path): for file in os.listdir(autopsy_html_path):
html_to = make_local_path(case.gold, case.image_name, file) html_to = make_local_path(case.gold, case.image_name, file.replace("HTML Report", "Report"))
copy_file(get_file_in_dir(autopsy_html_path, file), html_to) copy_dir(get_file_in_dir(autopsy_html_path, file), html_to)
except FileNotFoundException as e: except FileNotFoundException as e:
errors.append(e.error) errors.append(e.error)
except Exception as e: except Exception as e:
errors.append("Error: Unknown fatal error when rebuilding the gold html report.") errors.append("Error: Unknown fatal error when rebuilding the gold html report.")
errors.append(str(e) + "\n") errors.append(str(e) + "\n")
okay = "Sucessfully rebuilt all gold standards." okay = "Sucessfully rebuilt all gold standards."
print_report(errors, "REBUILDING", okay) print_report(errors, "REBUILDING", okay)
@ -700,6 +717,10 @@ def compare_bb_artifacts():
(database.gold_artifacts[type_id], (database.gold_artifacts[type_id],
database.autopsy_artifacts[type_id])) database.autopsy_artifacts[type_id]))
exceptions.append(error) exceptions.append(error)
global failedbool
global errorem
failedbool = True
errorem += "There was a difference in the number of artifacts.\n"
return exceptions return exceptions
except Exception as e: except Exception as e:
exceptions.append("Error: Unable to compare blackboard_artifacts.\n") exceptions.append("Error: Unable to compare blackboard_artifacts.\n")
@ -714,6 +735,10 @@ def compare_bb_attributes():
error = "Attribute counts do not match. " error = "Attribute counts do not match. "
error += str("Gold: %d, Test: %d" % (database.gold_attributes, database.autopsy_attributes)) error += str("Gold: %d, Test: %d" % (database.gold_attributes, database.autopsy_attributes))
exceptions.append(error) exceptions.append(error)
global failedbool
global errorem
failedbool = True
errorem += "There was a difference in the number of attributes.\n"
return exceptions return exceptions
except Exception as e: except Exception as e:
exceptions.append("Error: Unable to compare blackboard_attributes.\n") exceptions.append("Error: Unable to compare blackboard_attributes.\n")
@ -728,6 +753,10 @@ def compare_tsk_objects():
error = "TSK Object counts do not match. " error = "TSK Object counts do not match. "
error += str("Gold: %d, Test: %d" % (database.gold_objects, database.autopsy_objects)) error += str("Gold: %d, Test: %d" % (database.gold_objects, database.autopsy_objects))
exceptions.append(error) exceptions.append(error)
global failedbool
global errorem
failedbool = True
errorem += "There was a difference between the tsk object counts.\n"
return exceptions return exceptions
except Exception as e: except Exception as e:
exceptions.append("Error: Unable to compare tsk_objects.\n") exceptions.append("Error: Unable to compare tsk_objects.\n")
@ -762,7 +791,7 @@ def generate_common_log():
common_log.close() common_log.close()
except Exception as e: except Exception as e:
printerror("Error: Unable to generate the common log.") printerror("Error: Unable to generate the common log.")
printerror(str(e)) printerror(str(e) + "\n")
logging.critical(traceback.format_exc()) logging.critical(traceback.format_exc())
# Fill in the global case's variables that require the log files # Fill in the global case's variables that require the log files
@ -782,7 +811,6 @@ def fill_case_data():
printerror("Error: Unable to open autopsy.log.0.") printerror("Error: Unable to open autopsy.log.0.")
printerror(str(e) + "\n") printerror(str(e) + "\n")
logging.warning(traceback.format_exc()) logging.warning(traceback.format_exc())
# Set the case total test time # Set the case total test time
# Start date must look like: "Jul 16, 2012 12:57:53 PM" # Start date must look like: "Jul 16, 2012 12:57:53 PM"
# End date must look like: "Mon Jul 16 13:02:42 2012" # End date must look like: "Mon Jul 16 13:02:42 2012"
@ -1044,7 +1072,7 @@ def print_report(errors, name, okay):
if errors: if errors:
printerror("--------< " + name + " >----------") printerror("--------< " + name + " >----------")
for error in errors: for error in errors:
printerror(error) printerror(str(error))
printerror("--------< / " + name + " >--------\n") printerror("--------< / " + name + " >--------\n")
else: else:
printout("-----------------------------------------------------------------") printout("-----------------------------------------------------------------")
@ -1068,6 +1096,7 @@ def generate_html():
if not file_exists(case.html_log): if not file_exists(case.html_log):
write_html_head() write_html_head()
try: try:
global html
html = open(case.html_log, "a") html = open(case.html_log, "a")
# The image title # The image title
title = "<h1><a name='" + case.image_name + "'>" + case.image_name + " \ title = "<h1><a name='" + case.image_name + "'>" + case.image_name + " \
@ -1248,25 +1277,40 @@ def newDay():
def gitPull(TskOrAutopsy): def gitPull(TskOrAutopsy):
global SYS global SYS
ccwd = "" ccwd = ""
gppth = make_local_path(case.output_dir, "GitPullOutput" + TskOrAutopsy + ".txt")
gpout = open(gppth, 'a')
toPull = "http://www.github.com/sleuthkit/" + TskOrAutopsy toPull = "http://www.github.com/sleuthkit/" + TskOrAutopsy
call = ["git", "pull", toPull] call = ["git", "pull", toPull]
if TskOrAutopsy == "sleuthkit": if TskOrAutopsy == "sleuthkit":
ccwd = os.path.join("..", "..", "..", "TSK") ccwd = os.path.join("..", "..", "..", "sleuthkit")
else: else:
ccwd = os.path.join("..", "..") ccwd = os.path.join("..", "..")
subprocess.call(call, stdout=subprocess.PIPE, cwd=ccwd) subprocess.call(call, stdout=gpout, cwd=ccwd)
#Builds TSK as a win32 applicatiion #Builds TSK as a win32 applicatiion
def vsBuild(): def vsBuild():
#Please ensure that the current working directory is $autopsy/testing/script #Please ensure that the current working directory is $autopsy/testing/script
vs = [] vs = []
vs.append("/cygdrive/c/windows/microsoft.NET/framework/v4.0.30319/MSBuild.exe") vs.append("/cygdrive/c/windows/microsoft.NET/framework/v4.0.30319/MSBuild.exe")
vs.append(os.path.join("..", "..", "..","TSK", "win32", "Tsk-win.sln")) vs.append(os.path.join("..", "..", "..","sleuthkit", "win32", "Tsk-win.sln"))
vs.append("/p:configuration=release") vs.append("/p:configuration=release")
vs.append("/p:platform=win32") vs.append("/p:platform=win32")
vs.append("/t:rebuild") vs.append("/t:rebuild")
print(vs) print(vs)
subprocess.call(vs) VSpth = make_local_path(case.output_dir, "VSOutput.txt")
VSout = open(VSpth, 'a')
subprocess.call(vs, stdout=VSout)
chk = os.path.join("..", "..", "..","sleuthkit", "win32", "Release", "libtsk_jni.dll")
try:
open(chk)
except IOError as e:
global errorem
global attachl
errorem += "LIBTSK C++ failed to build.\n"
attachl.append(VSpth)
send_email()
sys.exit()
#Builds Autopsy or the Datamodel #Builds Autopsy or the Datamodel
@ -1274,7 +1318,7 @@ def antBuild(which, Build):
directory = os.path.join("..", "..") directory = os.path.join("..", "..")
ant = [] ant = []
if which == "datamodel": if which == "datamodel":
directory = os.path.join("..", "TSK", "bindings", "java") directory = os.path.join("..", "..", "..", "sleuthkit", "bindings", "java")
ant.append("ant") ant.append("ant")
ant.append("-f") ant.append("-f")
ant.append(directory) ant.append(directory)
@ -1283,7 +1327,21 @@ def antBuild(which, Build):
ant.append("build") ant.append("build")
else: else:
ant.append("dist") ant.append("dist")
subprocess.call(ant) antpth = make_local_path(case.output_dir, "ant" + which + "Output.txt")
antout = open(antpth, 'a')
subprocess.call(ant, stdout=antout)
if which == "datamodel":
chk = os.path.join("..", "..", "..","sleuthkit", "bindings", "java", "dist", "TSK_DataModel.jar")
try:
open(chk)
except IOError as e:
global errorem
global attachl
errorem += "DataModel Java build failed.\n"
attachl.append(antpth)
send_email()
sys.exit()
#Watches clock and waits for current ingest to be done #Watches clock and waits for current ingest to be done
@ -1340,7 +1398,6 @@ def copy_logs():
printerror("Error: Failed to copy the logs.") printerror("Error: Failed to copy the logs.")
printerror(str(e) + "\n") printerror(str(e) + "\n")
logging.warning(traceback.format_exc()) logging.warning(traceback.format_exc())
# Clears all the files from a directory and remakes it # Clears all the files from a directory and remakes it
def clear_dir(dir): def clear_dir(dir):
try: try:
@ -1362,6 +1419,14 @@ def copy_file(ffrom, to):
except: except:
raise FileNotFoundException(to) raise FileNotFoundException(to)
# Copies a directory file from "ffrom" to "to"
def copy_dir(ffrom, to):
try :
if not os.path.isdir(ffrom):
raise FileNotFoundException(ffrom)
shutil.copytree(ffrom, to)
except:
raise FileNotFoundException(to)
# Returns the first file in the given directory with the given extension # Returns the first file in the given directory with the given extension
def get_file_in_dir(dir, ext): def get_file_in_dir(dir, ext):
try: try:
@ -1472,7 +1537,6 @@ class FileNotFoundException(Exception):
def print_error(self): def print_error(self):
printerror("Error: File could not be found at:") printerror("Error: File could not be found at:")
printerror(self.file + "\n") printerror(self.file + "\n")
def error(self): def error(self):
error = "Error: File could not be found at:\n" + self.file + "\n" error = "Error: File could not be found at:\n" + self.file + "\n"
return error return error
@ -1487,13 +1551,99 @@ class DirNotFoundException(Exception):
def print_error(self): def print_error(self):
printerror("Error: Directory could not be found at:") printerror("Error: Directory could not be found at:")
printerror(self.dir + "\n") printerror(self.dir + "\n")
def error(self): def error(self):
error = "Error: Directory could not be found at:\n" + self.dir + "\n" error = "Error: Directory could not be found at:\n" + self.dir + "\n"
return error return error
#Executes the tests, makes continuous testing easier
def execute_test():
global failedbool
global html
global attachl
case.output_dir = make_path("output", time.strftime("%Y.%m.%d-%H.%M.%S"))
os.makedirs(case.output_dir)
case.common_log = make_local_path(case.output_dir, "AutopsyErrors.txt")
case.csv = make_local_path(case.output_dir, "CSV.txt")
case.html_log = make_local_path(case.output_dir, "AutopsyTestCase.html")
log_name = case.output_dir + "\\regression.log"
logging.basicConfig(filename=log_name, level=logging.DEBUG)
# If user wants to do a single file and a list (contradictory?)
if args.single and args.list:
printerror("Error: Cannot run both from config file and on a single file.")
return
# If working from a configuration file
if args.list:
if not file_exists(args.config_file):
printerror("Error: Configuration file does not exist at:")
printerror(args.config_file)
return
run_config_test(args.config_file)
# Else if working on a single file
elif args.single:
if not file_exists(args.single_file):
printerror("Error: Image file does not exist at:")
printerror(args.single_file)
return
run_test(args.single_file, 0)
# If user has not selected a single file, and does not want to ignore
# the input directory, continue on to parsing ./input
if (not args.single) and (not args.ignore):
for file in os.listdir(case.input_dir):
# Make sure it's not a required hash/keyword file or dir
if (not required_input_file(file) and
not os.path.isdir(make_path(case.input_dir, file))):
run_test(make_path(case.input_dir, file), 0)
write_html_foot()
html.close()
if failedbool:
htmll = html.name.split('\\')
ainsert = html.name
attachl.insert(0, ainsert)
send_email()
html.close()
#email_send(HTML_email, None)
def send_email():
global parsed
global errorem
global attachl
global html
element = parsed.getElementsByTagName("email")[0]
toval = element.getAttribute("value").encode().decode("utf-8")
element = parsed.getElementsByTagName("mail_server")[0]
serverval = element.getAttribute("value").encode().decode("utf-8")
# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Email Test'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = 'AutopsyContinuousTest'
msg['To'] = toval
msg.preamble = 'This is a test'
container = MIMEText(errorem, 'plain')
msg.attach(container)
Build_email(msg)
s = smtplib.SMTP(serverval)
s.sendmail(msg['From'], msg['To'], msg.as_string())
s.quit()
def Build_email(msg):
global attachl
for file in attachl:
part = MIMEBase('application', "octet-stream")
atach = open(file, "rb")
attch = atach.read()
noml = file.split("\\")
nom = noml[len(noml)-1]
part.set_payload(attch)
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="' + nom + '"')
msg.attach(part)
#----------------------# #----------------------#
# Main # # Main #
#----------------------# #----------------------#
@ -1502,90 +1652,35 @@ def main():
global args global args
global case global case
global database global database
global failedbool
global inform
global fl
global errorem
global attachl
global daycount
setDay()
daycount = 0
failedbool = False
errorem = "The test standard didn't match the gold standard.\n"
case = TestAutopsy() case = TestAutopsy()
database = Database() database = Database()
printout("") printout("")
args = Args() args = Args()
attachl = []
# The arguments were given wrong: # The arguments were given wrong:
if not args.parse(): if not args.parse():
case.reset() case.reset()
pass pass
# Otherwise test away! # Otherwise test away!
else: else:
case.output_dir = make_path("output", time.strftime("%Y.%m.%d-%H.%M.%S")) execute_test()
os.makedirs(case.output_dir)
case.common_log = make_local_path(case.output_dir, "AutopsyErrors.txt")
case.csv = make_local_path(case.output_dir, "CSV.txt")
case.html_log = make_local_path(case.output_dir, "AutopsyTestCase.html")
log_name = case.output_dir + "\\regression.log"
logging.basicConfig(filename=log_name, level=logging.DEBUG)
# If user wants to do a single file and a list (contradictory?)
if args.single and args.list:
printerror("Error: Cannot run both from config file and on a single file.")
return
# If working from a configuration file
if args.list:
if not file_exists(args.config_file):
printerror("Error: Configuration file does not exist at:")
printerror(args.config_file)
return
run_config_test(args.config_file)
# Else if working on a single file
elif args.single:
if not file_exists(args.single_file):
printerror("Error: Image file does not exist at:")
printerror(args.single_file)
return
run_test(args.single_file, 0)
# If user has not selected a single file, and does not want to ignore
# the input directory, continue on to parsing ./input
if (not args.single) and (not args.ignore):
for file in os.listdir(case.input_dir):
# Make sure it's not a required hash/keyword file or dir
if (not required_input_file(file) and
not os.path.isdir(make_path(case.input_dir, file))):
run_test(make_path(case.input_dir, file), 0)
write_html_foot()
while args.contin: while args.contin:
case.output_dir = make_path("output", time.strftime("%Y.%m.%d-%H.%M.%S")) attachl = []
os.makedirs(case.output_dir) errorem = "The test standard didn't match the gold standard.\n"
case.common_log = make_local_path(case.output_dir, "AutopsyErrors.txt") failedbool = False
case.csv = make_local_path(case.output_dir, "CSV.txt") execute_test()
case.html_log = make_local_path(case.output_dir, "AutopsyTestCase.html")
log_name = case.output_dir + "\\regression.log"
logging.basicConfig(filename=log_name, level=logging.DEBUG)
# If user wants to do a single file and a list (contradictory?)
if args.single and args.list:
printerror("Error: Cannot run both from config file and on a single file.")
return
# If working from a configuration file
if args.list:
if not file_exists(args.config_file):
printerror("Error: Configuration file does not exist at:")
printerror(args.config_file)
return
run_config_test(args.config_file)
# Else if working on a single file
elif args.single:
if not file_exists(args.single_file):
printerror("Error: Image file does not exist at:")
printerror(args.single_file)
return
run_test(args.single_file, 0)
# If user has not selected a single file, and does not want to ignore
# the input directory, continue on to parsing ./input
if (not args.single) and (not args.ignore):
for file in os.listdir(case.input_dir):
# Make sure it's not a required hash/keyword file or dir
if (not required_input_file(file) and
not os.path.isdir(make_path(case.input_dir, file))):
run_test(make_path(case.input_dir, file), 0)
write_html_foot()
class OS: class OS:
LINUX, MAC, WIN, CYGWIN = range(4) LINUX, MAC, WIN, CYGWIN = range(4)