예제 #1
0
def run():
    
    
    print("LiSiCA initialiser program")
    if not os.path.isdir(os.path.join(HOME_DIRECTORY,"LiSiCA")):
        configure=Configuration()
        exe_filename=configure.exe_File()
        
        upgrader=Upgrader()
        jsonData=upgrader.findLatestVersion()
        url=jsonData['zipball_url']
        installer_Object=Installer()
        installer_Object.downloadInstall(url)
        installer_Object.extractInstall()
    else :
        
    
        lisica_Folder=os.path.join(HOME_DIRECTORY,"LiSiCA")
        import FileStructure
        file_StructureObj=FileStructure.Directory_Structure(lisica_Folder)
        if file_StructureObj.check()==True:
            pass
        else:
            tkMessageBox.showerror("Missing Files", """LiSiCA Directory is corrupted.
            Missing files or folders. Try reinstalling the plugin """)  
            
        #modify this
        exe_path="so"   
        import License
        if License.checkLicenseStatus()==None:
            License.activate(exe_path)
        else:
            import Plugin_GUI
            Plugin_GUI.main()
예제 #2
0
 def upgrade(self):
     print "upgrading lisicagui to the latest version = ", self.latestVersionGUI
     self.downloadInstall()
     self.extractInstall()
     sys.path.append(os.path.normpath(os.path.join(LISICA_DIRECTORY,"modules")))
     import License
     License.writeToInsilabTxt(self.latestVersionGUI)
     print "Upgrade finished successfully!"
예제 #3
0
 def findCurrentVersion(self):
     import License
     #for GUI
     license_details=License.checkVersionGUI()
     self.licenseCodeGUI = license_details['Key']
     self.currentVersionGUI = license_details['Version']
     #for lisica program
     license_details=License.checkLicenseStatus()
     self.licenseCodeLisica = license_details['Key']
     self.currentVersionLisica = license_details['Version']
예제 #4
0
def run():
    
    print("Initialising LiSiCA...")
    try:
        sys.path.remove('')
    except:
        pass

    upgraderObj = UpgraderGitlab()

    if upgraderObj.firstUpgrade():
        upgraderObj.findLatestVersionGUI()
        upgraderObj.upgrade()
        
    sys.path.append(os.path.normpath(os.path.join(LISICA_DIRECTORY,"modules")))
    import License
    if License.checkVersionGUI()==None:
        upgraderObj.findLatestVersionGUI()
        upgraderObj.upgrade()

    del upgraderObj

    configure=Configuration()
    exe_filename=configure.exe_File()
    exe_path=os.path.normpath(os.path.join(LISICA_DIRECTORY,"bin",exe_filename))
    st = os.stat(exe_path)
    os.chmod(exe_path, st.st_mode | stat.S_IEXEC)
            

    import LisicaGUI
    LisicaGUI.main()
예제 #5
0
 def findCurrentVersion(self):
     import License
     #for GUI
     self.currentVersionGUI = License.checkVersionGUI()['Version']
예제 #6
0
def main(argv):
    print """
    __     _  __   __   __       ____                          _
   / /    (_)/ /_ / /_ / /___   / __ \ ____ _ _____ _      __ (_)____
  / /    / // __// __// // _ \ / / / // __ `// ___/| | /| / // // __ \\
 / /___ / // /_ / /_ / //  __// /_/ // /_/ // /    | |/ |/ // // / / /
/_____//_/ \__/ \__//_/ \___//_____/ \__,_//_/     |__/|__//_//_/ /_/

      _                     _                 ___
     /_|  /|/|  _/__/'     /_|   _ /   _ ' _ (_  _ _ _  _      _ /
    (  | /   |(//(///()/) (  |/)(/((/_) /_)  /  / (///)(-((/()/ /(
                                  /


    LittleDarwin version %s Copyright (C) 2014 Ali Parsai

    LittleDarwin comes with ABSOLUTELY NO WARRANTY.
    This is free software, and you are welcome to redistribute it
    under certain conditions; run LittleDarwin --license for details.


    """ % littleDarwinVersion

    # let's caution the user that we are using the alternative method.
    # if not timeoutSupport:
    #     print "!!! CAUTION !!!\nmodule subprocess32 not found. using alternative method. build procedure may hang in an infinite loop.\n\n"

    # parsing input options
    optionParser = OptionParser()

    optionParser.add_option("-m", "--mutate", action="store_true", dest="isMutationActive", default=False,
                            help="Activate the mutation phase.")
    optionParser.add_option("-b", "--build", action="store_true", dest="isBuildActive", default=False,
                            help="Activate the build phase.")
    optionParser.add_option("-v", "--verbose", action="store_true", dest="isVerboseActive", default=False,
                            help="Verbose output.")
    optionParser.add_option("-p", "--path", action="store", dest="sourcePath",
                            default=os.path.dirname(os.path.realpath(__file__)), help="Path to source files.")
    optionParser.add_option("-t", "--build-path", action="store", dest="buildPath",
                            default=os.path.dirname(os.path.realpath(__file__)), help="Path to build system working directory.")
    optionParser.add_option("-c", "--build-command", action="store", dest="buildCommand", default="mvn,test",
                            help="Command to run the build system. If it includes more than a single argument, they should be seperated by comma. For example: mvn,install")
    optionParser.add_option("--test-path", action="store", dest="testPath",
                            default="***dummy***", help="path to test project build system working directory")
    optionParser.add_option("--test-command", action="store", dest="testCommand", default="***dummy***",
                            help="Command to run the test-suite. If it includes more than a single argument, they should be seperated by comma. For example: mvn,test")
    optionParser.add_option("--initial-build-command", action="store", dest="initialBuildCommand",
                            default="***dummy***", help="Command to run the initial build.")
    optionParser.add_option("--timeout", type="int", action="store", dest="timeout", default=60,
                            help="Timeout value for the build process.")
    optionParser.add_option("--cleanup", action="store", dest="cleanUp", default="***dummy***",
                            help="Commands to run after each build.")
    optionParser.add_option("--use-alternate-database", action="store", dest="alternateDb", default="***dummy***",
                            help="Path to alternative database.")
    optionParser.add_option("--license", action="store_true", dest="isLicenseActive", default=False,
                            help="Output the license and exit.")
    optionParser.add_option("--higher-order", type="int", action="store", dest="higherOrder", default=1,
                            help="Define order of mutation. Use -1 to dynamically adjust per class.")
    optionParser.add_option("--null-check", action="store_true", dest="isNullCheck", default=False,
                            help="Use null check mutation operators.")

    optionParser.add_option("--all", action="store_true", dest="isAll", default=False,
                            help="Use all mutation operators.")

    (options, args) = optionParser.parse_args()

    if options.isLicenseActive:
        License.outputLicense()
        sys.exit(0)

    if options.higherOrder <= 1 and options.higherOrder != -1:
        higherOrder = 1
    else:
        higherOrder = options.higherOrder

    # there is an upside in not running two phases together. we may include the ability to edit some mutants later.
    if options.isBuildActive and options.isMutationActive:
        print "it is strongly recommended to do the analysis in two different phases.\n\n"


    #*****************************************************************************************************************
    #---------------------------------------- mutant generation phase ------------------------------------------------
    #*****************************************************************************************************************

    if options.isMutationActive:
        assert options.isVerboseActive is not None
        # creating our module objects.
        javaRead = JavaRead(options.isVerboseActive)
        javaParse = JavaParse(options.isVerboseActive)
        javaMutate = JavaMutate(javaParse, options.isVerboseActive)

        totalMutantCount = 0


        try:
            assert os.path.isdir(options.sourcePath)
        except AssertionError as exception:
            print "source path must be a directory."
            sys.exit(1)


        # getting the list of files.
        javaRead.listFiles(os.path.abspath(options.sourcePath))
        fileCounter = 0
        fileCount = len(javaRead.fileList)

        # creating a database for generated mutants. the format of this database is different on different platforms,
        # so it cannot be simply copied from a platform to another.
        databasePath = os.path.join(javaRead.targetDirectory, "mutationdatabase")

        print "source dir: ", javaRead.sourceDirectory
        print "target dir: ", javaRead.targetDirectory
        print "creating mutation database: ", databasePath

        mutationDatabase = shelve.open(databasePath, "c")
        mutantTypeDatabase = dict()

        # go through each file, parse it, calculate all mutations, and generate files accordingly.
        for srcFile in javaRead.fileList:
            print "(" + str(fileCounter + 1) + "/" + str(fileCount) + ") source file: ", srcFile
            targetList = list()

            try:
                # parsing the source file into a tree.
                tree = javaParse.parse(javaRead.getFileContent(srcFile))

                # assigning a number to each node to be able to identify it uniquely.
                javaParse.numerify(tree)
                # javaParse.tree2DOT(tree)

            except Exception as e:
                # Java 8 problem
                print "Error in parsing, skipping the file."
                sys.stderr.write(e.message)
                continue

            fileCounter += 1

            if options.isAll:
                enabledMutators = "all"
            elif options.isNullCheck:
                enabledMutators = "null-check"
            else:
                enabledMutators = "classical"

            # apply mutations on the tree and receive the resulting mutants as a list of strings, and a detailed
            # list of which operators created how many mutants.
            mutated, mutantTypes = javaMutate.applyMutators(tree, higherOrder, enabledMutators)

            print "--> mutations found: ", len(mutated)

            # go through all mutant types, and add them in total. also output the info to the user.
            for mutantType in mutantTypes.keys():
                if mutantTypes[mutantType] > 0:
                    print "---->", mutantType, ":", mutantTypes[mutantType]
                mutantTypeDatabase[mutantType] = mutantTypes[mutantType] + mutantTypeDatabase.get(mutantType, 0)
            totalMutantCount += len(mutated)

            # for each mutant, generate the file, and add it to the list.
            for mutatedFile in mutated:
                targetList.append(javaRead.generateNewFile(srcFile, mutatedFile))

            # if the list is not empty (some mutants were found), put the data in the database.
            if len(targetList) != 0:
                mutationDatabase[os.path.relpath(srcFile, javaRead.sourceDirectory)] = targetList

        mutationDatabase.close()

        print "total mutations found: ", totalMutantCount
        for mutantType in mutantTypeDatabase.keys():
            if mutantTypeDatabase[mutantType] > 0:
                print "-->", mutantType, ":", mutantTypeDatabase[mutantType]


    #*****************************************************************************************************************
    #---------------------------------------- test suite running phase -----------------------------------------------
    #*****************************************************************************************************************

    if options.isBuildActive:

        # let's tell the user upfront that this may corrupt the source code.
        print "\n\n!!! CAUTION !!!"
        print "code can be changed accidentally. use a backup version.\n"

        reportGenerator = ReportGenerator()

        if options.alternateDb == "***dummy***":
            databasePath = os.path.abspath(os.path.join(options.sourcePath, os.path.pardir, "mutated", "mutationdatabase"))
        else:
            databasePath = options.alternateDb

        resultsDatabasePath = databasePath + "-results"
        reportGenerator.initiateDatabase(resultsDatabasePath)

        try:
            if os.path.basename(options.buildPath) == "pom.xml":
                assert os.path.isfile(options.buildPath)
                buildDir = os.path.abspath(os.path.dirname(options.buildPath))
            else:
                assert os.path.isdir(options.buildPath)
                buildDir = os.path.abspath(options.buildPath)

        except AssertionError as exception:
            print "build system working directory should be a directory."



        # check if we have separate test-suite
        if options.testCommand != "***dummy***":
            separateTestSuite = True
            if options.testPath == "***dummy***":
                testDir = buildDir
            else:
                try:
                    if os.path.basename(options.buildPath) == "pom.xml":
                        assert os.path.isfile(options.buildPath)
                        testDir = os.path.abspath(os.path.dirname(options.testPath))
                    else:
                        assert os.path.isdir(options.buildPath)
                        testDir = os.path.abspath(options.testPath)

                except AssertionError as exception:
                    print "test project build system working directory should be a directory."

        else:
            separateTestSuite = False

        # try to open the database. if it can't be opened, it means that it does not exist or it is corrupt.
        try:
            mutationDatabase = shelve.open(databasePath, "r")
        except:
            print "cannot open mutation database. it may be corrupted or unavailable. delete all generated files and run the mutant generation phase again."
            sys.exit(1)

        databaseKeys = mutationDatabase.keys()
        assert isinstance(databaseKeys, list)

        # let's sort the mutants by name to create the possibility of following the flow of the process by user.
        databaseKeys.sort()

        # only here for debugging purposes
        # for desired in databaseKeys:
        #     if "PluginMap.java" in desired:
        #         desiredIndex = databaseKeys.index(desired)
        #         break
        #
        # databaseKeys.insert(0, databaseKeys.pop(desiredIndex))
        #


        mutationDatabaseLength = len(databaseKeys)
        textReportData = list()
        htmlReportData = list()
        fileCounter = 0




        # initial build check to avoid false results. the system must be able to build cleanly without errors.

        # use build command for the initial build unless it is explicitly provided.
        if options.initialBuildCommand == "***dummy***":
            commandString = options.buildCommand.split(',')
        else:
            commandString = options.initialBuildCommand.split(',')

        print "Initial build... ",

        try:
            processKilled, processExitCode, initialOutput = timeoutAlternative(commandString,
                                                                           workingDirectory=buildDir,
                                                                           timeout=int(options.timeout))

            # initialOutput = subprocess.check_output(commandString, stderr=subprocess.STDOUT, cwd=buildDir)
            # workaround for older python versions
            if processKilled or processExitCode:
                raise subprocess.CalledProcessError(1 if processKilled else processExitCode, commandString, initialOutput)


            with open(os.path.abspath(os.path.join(options.sourcePath, os.path.pardir, "mutated", "initialbuild.txt")),
                      'w') as content_file:
                content_file.write(initialOutput)
            print "done.\n\n"

        except subprocess.CalledProcessError as exception:
            initialOutput = exception.output
            with open(os.path.abspath(os.path.join(options.sourcePath, os.path.pardir, "mutated", "initialbuild.txt")),
                      'w') as content_file:
                content_file.write(initialOutput)
            print "failed.\n\nInitial build failed. Try building the system manually first to make sure it can be built."
            sys.exit(1)

        totalMutantCount = 0
        totalMutantCounter = 0


        for key in databaseKeys:
            totalMutantCount += len(mutationDatabase[key])

        startTime = time.time()

        # running the build system for each mutant.
        for key in databaseKeys:

            fileCounter += 1

            print "(" + str(fileCounter) + "/" + str(mutationDatabaseLength) + ") collecting results for ", key

            mutantCount = len(mutationDatabase[key])
            mutantCounter = 0

            successList = list()
            failureList = list()

            # for each mutant, replace the original file, run the build, store the results
            for replacementFileRel in mutationDatabase[key]:
                replacementFile = os.path.join(options.sourcePath, os.path.pardir, "mutated", replacementFileRel)
                mutantCounter += 1
                totalMutantCounter += 1

                # let's make sure that runOutput is empty, and not None to begin with.
                runOutput = ""
                runOutputTest = ""

                # replace the original file with the mutant
                shutil.copyfile(replacementFile, os.path.join(options.sourcePath, key))

                commandString = options.buildCommand.split(',')
                if separateTestSuite:
                    testCommandString = options.testCommand.split(',')

                try:
                    # if we have timeout support, simply run the command with timeout support from subprocess32
                    # if timeoutSupport:
                    #     runOutput = subprocess.check_output(commandString, stderr=subprocess.STDOUT, cwd=buildDir,
                    #                                         timeout=int(options.timeout))
                    #     if separateTestSuite:
                    #         runOutput += subprocess.check_output(testCommandString, stderr=subprocess.STDOUT, cwd=testDir,
                    #                                         timeout=int(options.timeout))

                    # else, run our alternative method
                    # else:
                    processKilled, processExitCode, runOutput = timeoutAlternative(commandString,
                                                                              workingDirectory=buildDir,
                                                                              timeout=int(options.timeout))

                    # raise the same exception as the original check_output.
                    if processKilled or processExitCode:
                        raise subprocess.CalledProcessError(1 if processKilled else processExitCode, commandString,
                                                                runOutput)

                    if separateTestSuite:
                        processKilled, processExitCode, runOutputTest = timeoutAlternative(testCommandString,
                                                              workingDirectory=testDir, timeout=int(options.timeout))

                            # raise the same exception as the original check_output.
                        if processKilled or processExitCode:
                            raise subprocess.CalledProcessError(1 if processKilled else processExitCode,
                                                              commandString, "\n".join([runOutput, runOutputTest]))


                    # if we are here, it means no exceptions happened, so lets add this to our success list.
                    runOutput += "\n" + runOutputTest
                    successList.append(os.path.basename(replacementFile))

                # putting two exceptions in one except clause, specially when one of them is not defined on some
                # platforms does not look like a good idea; even though both of them do exactly the same thing.
                except subprocess.CalledProcessError as exception:
                    runOutput = exception.output
                    # oops, error. let's add this to failure list.
                    failureList.append(os.path.basename(replacementFile))

                # except subprocess.TimeoutExpired as exception:
                #     runOutput = exception.output
                #     failureList.append(os.path.basename(replacementFile))

                targetTextOutputFile = os.path.splitext(replacementFile)[0] + ".txt"


                # we can't use print, since we like to write on the same line again.
                sys.stdout.write(
                    "elapsed: " + str(datetime.timedelta(seconds=int(time.time() - startTime))) + " remaining: " + str(
                        datetime.timedelta(seconds=int((float(time.time() - startTime) / totalMutantCounter) * float(
                            totalMutantCount - totalMutantCounter)))) + " total: " + str(
                        totalMutantCounter) + "/" + str(totalMutantCount) + " current: " + str(
                        mutantCounter) + "/" + str(mutantCount) + " *** survived: " + str(
                        len(successList)) + " - killed: " + str(len(failureList)) + "         \r")
                sys.stdout.flush()

                # writing the build output to disk.
                with open(targetTextOutputFile, 'w') as content_file:
                    content_file.write(runOutput)

                # if there's a cleanup option, execute it. the results will be ignored because we don't want our process
                #  to be interrupted if there's nothing to clean up.
                if options.cleanUp != "***dummy***":
                    subprocess.call(options.cleanUp.split(","), cwd=buildDir)
                    if separateTestSuite:
                        subprocess.call(options.cleanUp.split(","), cwd=testDir)

                #workaround:
                #shutil.rmtree(os.path.join(testDir,"VolumetryLoggerTest"),ignore_errors=True)


            # all mutants must be checked by now, so we should have a complete divide between success and failure.
            assert len(successList) + len(failureList) == mutantCount

            # append the information for this file to the reports.
            textReportData.append(key + ": survived (" + str(len(successList)) + "/" + str(mutantCount) + ") -> " + str(
                successList) + " - killed (" + str(len(failureList)) + "/" + str(mutantCount) + ") -> " + str(
                failureList) + "\r\n")
            htmlReportData.append([key, len(successList), mutantCount])

            # we are done with the file. let's return it to the original state.
            shutil.copyfile(os.path.join(os.path.dirname(replacementFile), "original.java"), os.path.join(options.sourcePath, key))

            # generate an HTML report for the file.

            targetHTMLOutputFile = os.path.join(os.path.dirname(replacementFile), "results.html")
            with open(targetHTMLOutputFile, 'w') as content_file:
                content_file.write(
                    reportGenerator.generateHTMLReportPerFile(key, targetHTMLOutputFile, successList, failureList))

            print "\n\n"

        # write final text report.
        with open(os.path.abspath(os.path.join(options.sourcePath, os.path.pardir, "mutated", "report.txt")),
                  'w') as textReportFile:
            textReportFile.writelines(textReportData)

        # write final HTML report.
        targetHTMLReportFile = os.path.abspath(
            os.path.join(options.sourcePath, os.path.pardir, "mutated", "report.html"))
        with open(targetHTMLReportFile, 'w') as htmlReportFile:
            htmlReportFile.writelines(reportGenerator.generateHTMLFinalReport(htmlReportData, targetHTMLReportFile))

    # if neither build nor mutation phase is active, let's help the user.
    if not (options.isBuildActive or options.isMutationActive):
        optionParser.print_help()
예제 #7
0
파일: Asset.py 프로젝트: manolodd/activae
    def _compile_tags (self):
        # Versions & Source
        version_of = None
        version    = self._db.get('version', None)
        versions   = [x['id'] for x in self._versions if x['id']!=self['id']]
        source     = self._parent_id
        if self['version'] != 1:
            version_of = self._replacements.get('replaces')

        # Formats
        has_formats  = None
        is_format_of = None
        if self._formats:
            format_list  =[x['format'] for x in self._formats if x['id']!=self['id']]
            has_formats  = dict.fromkeys(format_list).keys()
            for f in self._formats:
                if f['source'] == None and f['id'] != self['id']:
                    is_format_of = f['id']

        self._tags = {
            'Creator':          self._db.get('creator_id'),
            'Date':             max(self._db.get('date_modified'), self._db.get('date_edited'), self._db.get('date_created')),
            'Date Created':     self._db.get('date_created'),
            'Date (Modified)':  self._db.get('date_modified'),
            'Date Available':   self._db.get('date_available'),
            'Description':      self._db.get('description'),
            'Extent':           self._file.get('extent'),
            'Format':           self._file.get('formats_id'),
            'Has Format':       has_formats,
            'Has Part':         self._parts.get('has_parts_of'),
            'Has Version':      versions,
            'Identifier':       self._db.get('id'),
            'Is Format Of':     is_format_of,
            'Is Part Of':       self._parts.get('is_part_of'),
            'Is Referenced By': self._db.get('collections_id'),
            'Is Replaced By':   self._replacements.get('replaced_by'),
            'Is Version Of':    version_of,
            'Language':         self._db.get('language'),
            'Publisher':        self._db.get('publisher_id'),
            'Relation':         self._collection,
            'Replaces':         self._replacements.get('replaces'),
            'Source':           source,
            'Subject':          self._db.get('subject'),
            'Title':            self._db.get('title'),
            'Type':             self._db.get('asset_types_id'),
            'Rights':           self._db.get('licenses_id'),
            }

        if self['Creator']:
            self._tags['Creator'] = Auth.get_user_name (self['tags']['Creator'])
        if self['Publisher']:
            self._tags['Publisher'] = Auth.get_user_name (self['tags']['Publisher'])
        if self['Rights']:
            self._tags['Rights']    = License.get_license_name(self['tags']['Rights'])
        if self['Format']:
            self._tags['Format']    = Format.get_format_name (self['tags']['Format'])
        if self['Type']:
            self._tags['Type']      = Type.get_type_name (self['tags']['Type'])

        for key in self._tags.keys():
            if key.startswith('Date') and self._tags[key] == '0000-00-00 00:00:00':
                self._tags[key] = None
예제 #8
0
def main(argv):
    print """
    __     _  __   __   __       ____                          _
   / /    (_)/ /_ / /_ / /___   / __ \ ____ _ _____ _      __ (_)____
  / /    / // __// __// // _ \ / / / // __ `// ___/| | /| / // // __ \\
 / /___ / // /_ / /_ / //  __// /_/ // /_/ // /    | |/ |/ // // / / /
/_____//_/ \__/ \__//_/ \___//_____/ \__,_//_/     |__/|__//_//_/ /_/

      _                     _                 ___
     /_|  /|/|  _/__/'     /_|   _ /   _ ' _ (_  _ _ _  _      _ /
    (  | /   |(//(///()/) (  |/)(/((/_) /_)  /  / (///)(-((/()/ /(
                                  /


    LittleDarwin version %s Copyright (C) 2014 Ali Parsai

    LittleDarwin comes with ABSOLUTELY NO WARRANTY.
    This is free software, and you are welcome to redistribute it
    under certain conditions; run LittleDarwin --license for details.


    """ % littleDarwinVersion

    # let's caution the user that we are using the alternative method.
    # if not timeoutSupport:
    #     print "!!! CAUTION !!!\nmodule subprocess32 not found. using alternative method. build procedure may hang in an infinite loop.\n\n"

    # parsing input options
    optionParser = OptionParser()

    optionParser.add_option("-m",
                            "--mutate",
                            action="store_true",
                            dest="isMutationActive",
                            default=False,
                            help="Activate the mutation phase.")
    optionParser.add_option("-b",
                            "--build",
                            action="store_true",
                            dest="isBuildActive",
                            default=False,
                            help="Activate the build phase.")
    optionParser.add_option("-v",
                            "--verbose",
                            action="store_true",
                            dest="isVerboseActive",
                            default=False,
                            help="Verbose output.")
    optionParser.add_option("-p",
                            "--path",
                            action="store",
                            dest="sourcePath",
                            default=os.path.dirname(
                                os.path.realpath(__file__)),
                            help="Path to source files.")
    optionParser.add_option("-t",
                            "--build-path",
                            action="store",
                            dest="buildPath",
                            default=os.path.dirname(
                                os.path.realpath(__file__)),
                            help="Path to build system working directory.")
    optionParser.add_option(
        "-c",
        "--build-command",
        action="store",
        dest="buildCommand",
        default="mvn,test",
        help=
        "Command to run the build system. If it includes more than a single argument, they should be seperated by comma. For example: mvn,install"
    )
    optionParser.add_option(
        "--test-path",
        action="store",
        dest="testPath",
        default="***dummy***",
        help="path to test project build system working directory")
    optionParser.add_option(
        "--test-command",
        action="store",
        dest="testCommand",
        default="***dummy***",
        help=
        "Command to run the test-suite. If it includes more than a single argument, they should be seperated by comma. For example: mvn,test"
    )
    optionParser.add_option("--initial-build-command",
                            action="store",
                            dest="initialBuildCommand",
                            default="***dummy***",
                            help="Command to run the initial build.")
    optionParser.add_option("--timeout",
                            type="int",
                            action="store",
                            dest="timeout",
                            default=60,
                            help="Timeout value for the build process.")
    optionParser.add_option("--cleanup",
                            action="store",
                            dest="cleanUp",
                            default="***dummy***",
                            help="Commands to run after each build.")
    optionParser.add_option("--use-alternate-database",
                            action="store",
                            dest="alternateDb",
                            default="***dummy***",
                            help="Path to alternative database.")
    optionParser.add_option("--license",
                            action="store_true",
                            dest="isLicenseActive",
                            default=False,
                            help="Output the license and exit.")
    optionParser.add_option(
        "--higher-order",
        type="int",
        action="store",
        dest="higherOrder",
        default=1,
        help="Define order of mutation. Use -1 to dynamically adjust per class."
    )
    optionParser.add_option("--null-check",
                            action="store_true",
                            dest="isNullCheck",
                            default=False,
                            help="Use null check mutation operators.")

    optionParser.add_option("--all",
                            action="store_true",
                            dest="isAll",
                            default=False,
                            help="Use all mutation operators.")

    (options, args) = optionParser.parse_args()

    if options.isLicenseActive:
        License.outputLicense()
        sys.exit(0)

    if options.higherOrder <= 1 and options.higherOrder != -1:
        higherOrder = 1
    else:
        higherOrder = options.higherOrder

    # there is an upside in not running two phases together. we may include the ability to edit some mutants later.
    if options.isBuildActive and options.isMutationActive:
        print "it is strongly recommended to do the analysis in two different phases.\n\n"

    #*****************************************************************************************************************
    #---------------------------------------- mutant generation phase ------------------------------------------------
    #*****************************************************************************************************************

    if options.isMutationActive:
        assert options.isVerboseActive is not None
        # creating our module objects.
        javaRead = JavaRead(options.isVerboseActive)
        javaParse = JavaParse(options.isVerboseActive)
        javaMutate = JavaMutate(javaParse, options.isVerboseActive)

        totalMutantCount = 0

        try:
            assert os.path.isdir(options.sourcePath)
        except AssertionError as exception:
            print "source path must be a directory."
            sys.exit(1)

        # getting the list of files.
        javaRead.listFiles(os.path.abspath(options.sourcePath))
        fileCounter = 0
        fileCount = len(javaRead.fileList)

        # creating a database for generated mutants. the format of this database is different on different platforms,
        # so it cannot be simply copied from a platform to another.
        databasePath = os.path.join(javaRead.targetDirectory,
                                    "mutationdatabase")

        print "source dir: ", javaRead.sourceDirectory
        print "target dir: ", javaRead.targetDirectory
        print "creating mutation database: ", databasePath

        mutationDatabase = shelve.open(databasePath, "c")
        mutantTypeDatabase = dict()

        # go through each file, parse it, calculate all mutations, and generate files accordingly.
        for srcFile in javaRead.fileList:
            print "(" + str(fileCounter + 1) + "/" + str(
                fileCount) + ") source file: ", srcFile
            targetList = list()

            try:
                # parsing the source file into a tree.
                tree = javaParse.parse(javaRead.getFileContent(srcFile))

                # assigning a number to each node to be able to identify it uniquely.
                javaParse.numerify(tree)
                # javaParse.tree2DOT(tree)

            except Exception as e:
                # Java 8 problem
                print "Error in parsing, skipping the file."
                sys.stderr.write(e.message)
                continue

            fileCounter += 1

            if options.isAll:
                enabledMutators = "all"
            elif options.isNullCheck:
                enabledMutators = "null-check"
            else:
                enabledMutators = "classical"

            # apply mutations on the tree and receive the resulting mutants as a list of strings, and a detailed
            # list of which operators created how many mutants.
            mutated, mutantTypes = javaMutate.applyMutators(
                tree, higherOrder, enabledMutators)

            print "--> mutations found: ", len(mutated)

            # go through all mutant types, and add them in total. also output the info to the user.
            for mutantType in mutantTypes.keys():
                if mutantTypes[mutantType] > 0:
                    print "---->", mutantType, ":", mutantTypes[mutantType]
                mutantTypeDatabase[mutantType] = mutantTypes[
                    mutantType] + mutantTypeDatabase.get(mutantType, 0)
            totalMutantCount += len(mutated)

            # for each mutant, generate the file, and add it to the list.
            for mutatedFile in mutated:
                targetList.append(
                    javaRead.generateNewFile(srcFile, mutatedFile))

            # if the list is not empty (some mutants were found), put the data in the database.
            if len(targetList) != 0:
                mutationDatabase[os.path.relpath(
                    srcFile, javaRead.sourceDirectory)] = targetList

        mutationDatabase.close()

        print "total mutations found: ", totalMutantCount
        for mutantType in mutantTypeDatabase.keys():
            if mutantTypeDatabase[mutantType] > 0:
                print "-->", mutantType, ":", mutantTypeDatabase[mutantType]

    #*****************************************************************************************************************
    #---------------------------------------- test suite running phase -----------------------------------------------
    #*****************************************************************************************************************

    if options.isBuildActive:

        # let's tell the user upfront that this may corrupt the source code.
        print "\n\n!!! CAUTION !!!"
        print "code can be changed accidentally. use a backup version.\n"

        reportGenerator = ReportGenerator()

        if options.alternateDb == "***dummy***":
            databasePath = os.path.abspath(
                os.path.join(options.sourcePath, os.path.pardir, "mutated",
                             "mutationdatabase"))
        else:
            databasePath = options.alternateDb

        resultsDatabasePath = databasePath + "-results"
        reportGenerator.initiateDatabase(resultsDatabasePath)

        try:
            if os.path.basename(options.buildPath) == "pom.xml":
                assert os.path.isfile(options.buildPath)
                buildDir = os.path.abspath(os.path.dirname(options.buildPath))
            else:
                assert os.path.isdir(options.buildPath)
                buildDir = os.path.abspath(options.buildPath)

        except AssertionError as exception:
            print "build system working directory should be a directory."

        # check if we have separate test-suite
        if options.testCommand != "***dummy***":
            separateTestSuite = True
            if options.testPath == "***dummy***":
                testDir = buildDir
            else:
                try:
                    if os.path.basename(options.buildPath) == "pom.xml":
                        assert os.path.isfile(options.buildPath)
                        testDir = os.path.abspath(
                            os.path.dirname(options.testPath))
                    else:
                        assert os.path.isdir(options.buildPath)
                        testDir = os.path.abspath(options.testPath)

                except AssertionError as exception:
                    print "test project build system working directory should be a directory."

        else:
            separateTestSuite = False

        # try to open the database. if it can't be opened, it means that it does not exist or it is corrupt.
        try:
            mutationDatabase = shelve.open(databasePath, "r")
        except:
            print "cannot open mutation database. it may be corrupted or unavailable. delete all generated files and run the mutant generation phase again."
            sys.exit(1)

        databaseKeys = mutationDatabase.keys()
        assert isinstance(databaseKeys, list)

        # let's sort the mutants by name to create the possibility of following the flow of the process by user.
        databaseKeys.sort()

        # only here for debugging purposes
        # for desired in databaseKeys:
        #     if "PluginMap.java" in desired:
        #         desiredIndex = databaseKeys.index(desired)
        #         break
        #
        # databaseKeys.insert(0, databaseKeys.pop(desiredIndex))
        #

        mutationDatabaseLength = len(databaseKeys)
        textReportData = list()
        htmlReportData = list()
        fileCounter = 0

        # initial build check to avoid false results. the system must be able to build cleanly without errors.

        # use build command for the initial build unless it is explicitly provided.
        if options.initialBuildCommand == "***dummy***":
            commandString = options.buildCommand.split(',')
        else:
            commandString = options.initialBuildCommand.split(',')

        print "Initial build... ",

        try:
            processKilled, processExitCode, initialOutput = timeoutAlternative(
                commandString,
                workingDirectory=buildDir,
                timeout=int(options.timeout))

            # initialOutput = subprocess.check_output(commandString, stderr=subprocess.STDOUT, cwd=buildDir)
            # workaround for older python versions
            if processKilled or processExitCode:
                raise subprocess.CalledProcessError(
                    1 if processKilled else processExitCode, commandString,
                    initialOutput)

            with open(
                    os.path.abspath(
                        os.path.join(options.sourcePath, os.path.pardir,
                                     "mutated", "initialbuild.txt")),
                    'w') as content_file:
                content_file.write(initialOutput)
            print "done.\n\n"

        except subprocess.CalledProcessError as exception:
            initialOutput = exception.output
            with open(
                    os.path.abspath(
                        os.path.join(options.sourcePath, os.path.pardir,
                                     "mutated", "initialbuild.txt")),
                    'w') as content_file:
                content_file.write(initialOutput)
            print "failed.\n\nInitial build failed. Try building the system manually first to make sure it can be built."
            sys.exit(1)

        totalMutantCount = 0
        totalMutantCounter = 0

        for key in databaseKeys:
            totalMutantCount += len(mutationDatabase[key])

        startTime = time.time()

        # running the build system for each mutant.
        for key in databaseKeys:

            fileCounter += 1

            print "(" + str(fileCounter) + "/" + str(
                mutationDatabaseLength) + ") collecting results for ", key

            mutantCount = len(mutationDatabase[key])
            mutantCounter = 0

            successList = list()
            failureList = list()

            # for each mutant, replace the original file, run the build, store the results
            for replacementFileRel in mutationDatabase[key]:
                replacementFile = os.path.join(options.sourcePath,
                                               os.path.pardir, "mutated",
                                               replacementFileRel)
                mutantCounter += 1
                totalMutantCounter += 1

                # let's make sure that runOutput is empty, and not None to begin with.
                runOutput = ""
                runOutputTest = ""

                # replace the original file with the mutant
                shutil.copyfile(replacementFile,
                                os.path.join(options.sourcePath, key))

                commandString = options.buildCommand.split(',')
                if separateTestSuite:
                    testCommandString = options.testCommand.split(',')

                try:
                    # if we have timeout support, simply run the command with timeout support from subprocess32
                    # if timeoutSupport:
                    #     runOutput = subprocess.check_output(commandString, stderr=subprocess.STDOUT, cwd=buildDir,
                    #                                         timeout=int(options.timeout))
                    #     if separateTestSuite:
                    #         runOutput += subprocess.check_output(testCommandString, stderr=subprocess.STDOUT, cwd=testDir,
                    #                                         timeout=int(options.timeout))

                    # else, run our alternative method
                    # else:
                    processKilled, processExitCode, runOutput = timeoutAlternative(
                        commandString,
                        workingDirectory=buildDir,
                        timeout=int(options.timeout))

                    # raise the same exception as the original check_output.
                    if processKilled or processExitCode:
                        raise subprocess.CalledProcessError(
                            1 if processKilled else processExitCode,
                            commandString, runOutput)

                    if separateTestSuite:
                        processKilled, processExitCode, runOutputTest = timeoutAlternative(
                            testCommandString,
                            workingDirectory=testDir,
                            timeout=int(options.timeout))

                        # raise the same exception as the original check_output.
                        if processKilled or processExitCode:
                            raise subprocess.CalledProcessError(
                                1 if processKilled else processExitCode,
                                commandString,
                                "\n".join([runOutput, runOutputTest]))

                    # if we are here, it means no exceptions happened, so lets add this to our success list.
                    runOutput += "\n" + runOutputTest
                    successList.append(os.path.basename(replacementFile))

                # putting two exceptions in one except clause, specially when one of them is not defined on some
                # platforms does not look like a good idea; even though both of them do exactly the same thing.
                except subprocess.CalledProcessError as exception:
                    runOutput = exception.output
                    # oops, error. let's add this to failure list.
                    failureList.append(os.path.basename(replacementFile))

                # except subprocess.TimeoutExpired as exception:
                #     runOutput = exception.output
                #     failureList.append(os.path.basename(replacementFile))

                targetTextOutputFile = os.path.splitext(
                    replacementFile)[0] + ".txt"

                # we can't use print, since we like to write on the same line again.
                sys.stdout.write("elapsed: " + str(
                    datetime.timedelta(seconds=int(time.time() - startTime))
                ) + " remaining: " + str(
                    datetime.timedelta(seconds=int(
                        (float(time.time() - startTime) / totalMutantCounter) *
                        float(totalMutantCount - totalMutantCounter)))) +
                                 " total: " + str(totalMutantCounter) + "/" +
                                 str(totalMutantCount) + " current: " +
                                 str(mutantCounter) + "/" + str(mutantCount) +
                                 " *** survived: " + str(len(successList)) +
                                 " - killed: " + str(len(failureList)) +
                                 "         \r")
                sys.stdout.flush()

                # writing the build output to disk.
                with open(targetTextOutputFile, 'w') as content_file:
                    content_file.write(runOutput)

                # if there's a cleanup option, execute it. the results will be ignored because we don't want our process
                #  to be interrupted if there's nothing to clean up.
                if options.cleanUp != "***dummy***":
                    subprocess.call(options.cleanUp.split(","), cwd=buildDir)
                    if separateTestSuite:
                        subprocess.call(options.cleanUp.split(","),
                                        cwd=testDir)

                #workaround:
                #shutil.rmtree(os.path.join(testDir,"VolumetryLoggerTest"),ignore_errors=True)

            # all mutants must be checked by now, so we should have a complete divide between success and failure.
            assert len(successList) + len(failureList) == mutantCount

            # append the information for this file to the reports.
            textReportData.append(key + ": survived (" +
                                  str(len(successList)) + "/" +
                                  str(mutantCount) + ") -> " +
                                  str(successList) + " - killed (" +
                                  str(len(failureList)) + "/" +
                                  str(mutantCount) + ") -> " +
                                  str(failureList) + "\r\n")
            htmlReportData.append([key, len(successList), mutantCount])

            # we are done with the file. let's return it to the original state.
            shutil.copyfile(
                os.path.join(os.path.dirname(replacementFile),
                             "original.java"),
                os.path.join(options.sourcePath, key))

            # generate an HTML report for the file.

            targetHTMLOutputFile = os.path.join(
                os.path.dirname(replacementFile), "results.html")
            with open(targetHTMLOutputFile, 'w') as content_file:
                content_file.write(
                    reportGenerator.generateHTMLReportPerFile(
                        key, targetHTMLOutputFile, successList, failureList))

            print "\n\n"

        # write final text report.
        with open(
                os.path.abspath(
                    os.path.join(options.sourcePath, os.path.pardir, "mutated",
                                 "report.txt")), 'w') as textReportFile:
            textReportFile.writelines(textReportData)

        # write final HTML report.
        targetHTMLReportFile = os.path.abspath(
            os.path.join(options.sourcePath, os.path.pardir, "mutated",
                         "report.html"))
        with open(targetHTMLReportFile, 'w') as htmlReportFile:
            htmlReportFile.writelines(
                reportGenerator.generateHTMLFinalReport(
                    htmlReportData, targetHTMLReportFile))

    # if neither build nor mutation phase is active, let's help the user.
    if not (options.isBuildActive or options.isMutationActive):
        optionParser.print_help()