コード例 #1
0
    def testExtractCodeWithEmptyDiffBetweenTwoCommits(self):
        gp = gitprovider.GitProvider(config.getRepoDir())
        commits = gp.getAllVersions('trainDbScriptTest')
        commit1 = commits[-2]
        commit2 = commits[-2]
        file1 = gp.getFileContents('bugcode2.cpp', commit1)
        file2 = gp.getFileContents('bugcode2.cpp', commit2)
        diff = LinuxDiffer().diff(file1, file2)
        usedDiffs = []
        bugData = self.getBugData()
        extractor = CodeExtractor(bugData)
        extractor.loadCodeFromText(file1, '\r\n', '\n')
        extractor.extractBugCode()
        extractor.loadDiff(diff)
        with self.assertRaises(ValueError):
            extractor.extractFixCode()
        bugCode = extractor.getBugCodeFragment()
        fixCode = extractor.getFixCodeFragment()
        usedDiffs = extractor.getUsedDiffs()
        expectedOutputFix = ''
        expectedOutputBug = """int main(void)
{
    int a;
    a = 3;
    a = 0;
    if (a == 0)
    {
"""
        self.assertEqual(expectedOutputBug, bugCode)
        self.assertEqual(expectedOutputFix, fixCode)
        self.assertEqual(0, len(usedDiffs))
コード例 #2
0
 def testCheckout(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     gp.checkout('e46f62cbdcd7447dc6c796d917fece54426c782f'
                 )  #'bde8d75eb1133703b93a5110ed01c635d6d886ac')
     #self.assertEqual(3, len(gp.getTree().blobs))
     self.assertEqual(2, len(gp.getTree().blobs))
     gp.checkout('955fa1826edfc9a0936201675029492669a3ec81'
                 )  #'52a7d8e413686e54d23dbf002f68f6c9baeaa313')
     #self.assertEqual(4, len(gp.getTree().blobs))
     self.assertEqual(3, len(gp.getTree().blobs))
コード例 #3
0
    def testDiffBetweenTwoCommits(self):
        gp = gitprovider.GitProvider(config.getRepoDir())
        commits = gp.getAllVersions('trainDbScriptTest')
        commit1 = commits[-2]
        commit2 = commits[-3]
        file1 = gp.getFileContents('bugcode2.cpp', commit1)
        file2 = gp.getFileContents('bugcode2.cpp', commit2)
        diff = LinuxDiffer().diff(file1, file2)
        expectedOutput = """8d7
<     a = 3;"""
        self.assertEqual(expectedOutput, diff)
コード例 #4
0
 def testDatabaseStoreAndClean(self):
     dbPath = config.getRepoDir() + "/testtmp.sqlite"
     dbFile = Path(dbPath)
     db = CFDatabase(dbPath)
     self.assertEqual(len(db.getAllFixData()), 0)
     db.store('', '', 'a')
     self.assertEqual(len(db.getAllFixData()), 1)
     self.assertEqual(len(db.getFixDataForChecker('a')), 1)
     self.assertEqual(len(db.getFixDataForChecker('b')), 0)
     db.clean()
     self.assertEqual(len(db.getAllFixData()), 0)
     del db
     dbFile.unlink()
コード例 #5
0
 def testDatabaseOpenCreateSuccess(self):
     dbPath = config.getRepoDir() + "/testtmp.sqlite"
     dbFile = Path(dbPath)
     if dbFile.is_file():
         dbFile.unlink()
     db = CFDatabase(dbPath)
     dbFile = Path(dbPath)
     self.assertTrue(dbFile.is_file())
     del db
     db = CFDatabase(dbPath)
     self.assertEqual(len(db.getAllFixData()), 0)
     del db
     dbFile.unlink()
コード例 #6
0
    def testFileContents(self):
        gp = gitprovider.GitProvider(config.getRepoDir())
        contents = gp.getFileContents(
            'bugcode2.cpp', 'bbe7c95cbbbe1ce8871a5e1fad674ee245e52314'
        )  #'3242a5e8d56da17553feee2b61fa424963148c82')
        expectedContent = """#include <iostream>

using namespace std;

int main(void)
{
    int a;
    a = 3;
    a = 0;
    if (a == 0)
    {
        int b = 1 / a;
        cout << b << endl;
    }
    return 0;
}"""
        self.assertEqual(expectedContent.split('\n'), contents.split('\r\n'))
        contents = gp.getFileContents(
            'bugcode2.cpp', 'c1b5543440eb2e671018736d79f9a8a4e96f4855'
        )  #'f9aac9d2cb840744f64ce8882fd4202884139680')
        expectedContent = """#include <iostream>

using namespace std;

int main(void)
{
    int a;
    a = 0;
    if (a == 0)
    {
        int b = 1 / a;
        cout << b << endl;
    }
    return 0;
}"""
        self.assertEqual(expectedContent.split('\n'), contents.split('\r\n'))
コード例 #7
0
    def testExtractCodeWithDiffBetweenTwoCommitsMultiDiffInFragment(self):
        gp = gitprovider.GitProvider(config.getRepoDir())
        commits = gp.getAllVersions('trainDbScriptTest')
        commit1 = commits[-6]
        commit2 = commits[-7]
        file1 = gp.getFileContents('bugcode3.cpp', commit1)
        file2 = gp.getFileContents('bugcode3.cpp', commit2)
        diff = LinuxDiffer().diff(file1, file2)
        usedDiffs = []
        bugData = self.getBugData3()
        extractor = CodeExtractor(bugData)
        extractor.loadCodeFromText(file1, '\r\n', '\n')
        extractor.extractBugCode()
        extractor.loadDiff(diff)
        extractor.extractFixCode()
        bugCode = extractor.getBugCodeFragment()
        fixCode = extractor.getFixCodeFragment()
        usedDiffs = extractor.getUsedDiffs()
        expectedOutputFix = """{;
    int a;
    a = 0;
    a = 2;
    if (a != 0)
    {;
        int b = 1 / a;
"""
        expectedOutputBug = """{
    int a;
    a = 0;
    a = 2;
    if (a != 0)
    {
        int b = 1 / a;
"""
        self.assertEqual(expectedOutputBug, bugCode)
        self.assertEqual(expectedOutputFix, fixCode)
        self.assertEqual(2, len(usedDiffs))
コード例 #8
0
 def getIncorrectBugDataFileNotExist(self):
     bugStartLine = 8
     bugEndLine = 8
     filepath = config.getRepoDir() + '/bugcode_notexists.cpp'
     return BugData(bugStartLine, bugEndLine, filepath, '', '')
コード例 #9
0
 def getCorrectBugDataFileBegin(self):
     bugStartLine = 1
     bugEndLine = 1
     filepath = config.getRepoDir() + '/bugcode.cpp'
     return BugData(bugStartLine, bugEndLine, filepath, '', '')
コード例 #10
0
 def getCorrectBugDataFileMultiLine(self):
     bugStartLine = 7
     bugEndLine = 9
     filepath = config.getRepoDir() + '/bugcode.cpp'
     return BugData(bugStartLine, bugEndLine, filepath, '', '')
コード例 #11
0
 def __init__(self):
     self.vcs = GitProvider(config.getRepoDir())
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
コード例 #12
0
 def testDatabaseOpenNonExistingFailure(self):
     dbPath = config.getRepoDir() + "/testtmp.sqlite"
     with self.assertRaises(FileNotFoundError):
         db = CCDatabase(dbPath)
コード例 #13
0
 def testGetFileContentsNotExistingCommitFailure(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     with self.assertRaises(ValueError):
         gp.getFileContents('bugcode.cpp',
                            '0000000000000000000000000000000000000002')
コード例 #14
0
ファイル: hook.py プロジェクト: Nieobliczalny/CodeFixer
    def main(self):
        # Do analysis
        shutil.rmtree(config.getTmpDir())
        self.codeChecker.check(True)

        # Diff new
        newBugs = self.getDiffNew()

        if len(newBugs) < 1:
            print('No new bugs introduced, commit is accepted!')
            return
        
        print("New bugs found! Count: {0}. Attempting repairs...".format(len(newBugs)))

        # Load models
        models = {}
        for checker in globals.availableCheckers:
            models[checker] = load_model(config.cfModelFilenameFormat.format(checker))

        # Load all content from files having new
        files = set([self.convertFilePathToRepoRelativePath(x.getFile()) for x in newBugs])
        fileContents = {}
        for f in files:
            fn = config.getRepoDir() + f
            with open(fn, 'r') as fh:
                fileContents[f] = ''.join(fh.readlines())

        # For each file sort by bug line desc
        suggestions = []
        validSuggestions = 0
        for f in files:
            bugs = [x for x in newBugs if self.convertFilePathToRepoRelativePath(x.getFile()) == f]
            bugs.sort(key=lambda x: x.getLine(), reverse=True)
            print("=== File: {0} ===".format(f))
            # For each bug get a suggestion and test it
            for b in bugs:
                print("L{0}, Type: {1}".format(b.getLine(), b.getChecker()))
                # Prepare useful data
                dictionary = Dictionary(b.getChecker())
                coder = Coder(dictionary)
                totalDictionaryLength = dictionary.length()
                # Prepare and extract bug fragment
                checkerInfo = self.checkers.extractTokensForChecker(b.getChecker(), b.getMessage())
                extractor = CodeExtractor(b)
                extractor.loadCodeFromText(fileContents[f])
                extractor.extractBugCode()
                bugCodeFragment = extractor.getBugCodeFragment()
                fixCodeFragment = ''
                # Encode it
                encodedBugData, initialUnkList = coder.encode(bugCodeFragment, checkerData = checkerInfo)
                # Convert to one-hot
                MODEL_X_MAX_LEN = models[b.getChecker()].get_layer(index = 0).input_shape[1]

                if len(encodedBugData) > MODEL_X_MAX_LEN:
                    print("Ignored: Code too big for model")
                    continue

                noZerosToPad = MODEL_X_MAX_LEN - len(encodedBugData)
                if noZerosToPad > 0:
                    encodedBugData = coder.applyPadding(encodedBugData, noZerosToPad)
                X = np.zeros((1, MODEL_X_MAX_LEN, totalDictionaryLength))
                X[0] = coder.convertToOneHot(encodedBugData, np.zeros((MODEL_X_MAX_LEN, totalDictionaryLength)))
                # Predict and convert from one-hot
                Y = coder.convertFromOneHot(models[b.getChecker()].predict(X)[0])
                Y = coder.removePadding(Y)
                # Decode
                fixCodeFragment = coder.decode(Y, initialUnkList)[:-1]
                
                #Verify?
                vStatus = 2
                if config.cfVerifyPrediction:
                    # Apply fix in source code file
                    extractor.applyFix(fixCodeFragment)
                    extractor.saveToFile(b.getFile())
                    # Run CodeChecker and analyze code
                    shutil.rmtree(config.getTmpDir())
                    compilationLog = self.codeChecker.check(True)
                    newBugsAfterFix = self.getDiffNew()
                    # Check if ID is resolved in tmp folder
                    isFixed = 'Build failed' not in compilationLog
                    for nb in newBugsAfterFix:
                        if self.isBugDataEqual(b, nb):
                            isFixed = False
                    # Set vStatus accordingly
                    if isFixed:
                        vStatus = 1
                    else:
                        vStatus = 0
                    # Revert file
                    extractor.loadCodeFromText(fileContents[f])
                    extractor.saveToFile(b.getFile())
                if vStatus == 0:
                    print("Verification: Negative, cannot be applied")
                elif vStatus == 1:
                    print("Verification: Positive, can be applied")
                    validSuggestions += 1
                elif vStatus == 2:
                    print("Verification: Skipped")
                    validSuggestions += 1
                sugg = SuggestionData(f, b, bugCodeFragment, fixCodeFragment, vStatus)
                suggestions.append(sugg)
        print("Valid suggestions prepared for {0} / {1} bugs.".format(validSuggestions, len(newBugs)))

        if validSuggestions > 0:
            print("Apply valid suggestions (a), display them (d), ignore them (i) or abort commit (q)?")
            apply = False
            choice = True
            while choice:
                c = sys.stdin.read(1)
                if c == 'a':
                    apply = True
                    choice = False
                    print("Applying fixes...")
                elif c == 'i':
                    choice = False
                    print("Fixes ignored...")
                elif c == 'd':
                    self.displaySuggestions(suggestions)
                    print("Apply valid suggestions (a), ignore them (i) or abort commit (q)?")
                elif c == 'q':
                    print("Aborting commit...")
                    sys.exit(1)
            if apply:
                self.applyValidFixes(suggestions, files)
                print("Fixes applied!")
        if validSuggestions != len(newBugs):
            print("Unable to fix all bugs, continue with commit (c) or abort (q)?")
            choice = True
            while choice:
                c = sys.stdin.read(1)
                if c == 'c':
                    choice = False
                    print("Continuing...")
                elif c == 'q':
                    print("Aborting commit...")
                    sys.exit(1)
        else:
            print("Bugs corrected, commit is good to go!")
コード例 #15
0
 def __init__(self):
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
     self.code = []
     self.checkers = Checkers()
コード例 #16
0
    if bugData.getChecker() == 'clang-diagnostic-unused-parameter':
        return fixUnusedParam(code, bugData)
    if bugData.getChecker() == 'clang-diagnostic-constant-conversion':
        return fixConstConv(code, bugData)
    return None


ccdb = CCDatabase(config.getCcDbFile())
db = sqlite3.connect('../Results/db.sqlite')
cursor = db.cursor()
cursor.execute('SELECT * FROM bugs')
dataFromDb = cursor.fetchall()
bugs = []
bugsPerFile = {}
BUG_NOT_PROCESSED = 0
vcs = GitProvider(config.getRepoDir())
checkers = Checkers()
currentCommit = vcs.getAllVersions(config.getBranch())[0]
bugDataList = {}
fileContents = {}
codechecker = CodeChecker(config.getRepoDir())

if len(dataFromDb) > 0:
    print("Skipping steps 1-2, DB already filled with data")
    for bug in dataFromDb:
        if bug[2] not in bugsPerFile:
            bugsPerFile[bug[2]] = []
        if bug[3] == BUG_NOT_PROCESSED:
            bugDataList[bug[0]] = ccdb.getNotResolvedBugData(bug[0])
            bugsPerFile[bug[2]].append(bug[0])
else:
コード例 #17
0
 def __init__(self):
     self.vcs = GitProvider(config.getRepoDir())
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
     self.checkers = Checkers()
     self.loadCommitList()
コード例 #18
0
 def testCheckoutNonExistingCommitFailure(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     with self.assertRaises(ValueError):
         gp.checkout('0000000000000000000000000000000000000002')
コード例 #19
0
 def testLoadRootCommit(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     commits = gp.getAllVersions(config.getBranch())
     self.assertEqual(
         'e46f62cbdcd7447dc6c796d917fece54426c782f', commits[-1]
     )  #'bde8d75eb1133703b93a5110ed01c635d6d886ac', commits[-1])
コード例 #20
0
 def testDatabaseOpenExistingSuccess(self):
     dbPath = config.getRepoDir() + "/test.sqlite"
     db = CFDatabase(dbPath)
     self.assertGreater(len(db.getAllFixData()), 0)
     del db
コード例 #21
0
 def tearDownClass(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     gp.checkout('master')
コード例 #22
0
 def getIncorrectBugDataLineOutOfRange(self):
     bugStartLine = 20
     bugEndLine = 21
     filepath = config.getRepoDir() + '/bugcode.cpp'
     return BugData(bugStartLine, bugEndLine, filepath, '', '')
コード例 #23
0
def ProcessBugsInFile(fileName):
    # 5.1.
    # 5.2.
    for bug in bugsPerFile[fileName]:
        bugData = bugDataList[bug]
        cleanFn = fileName[:-4]
        fn = '../Results/Analysis/{0}_{1}_{2}.txt'.format(
            cleanFn, bug, bugData.getChecker())
        repoFn = os.fsdecode(
            os.path.join(os.fsencode(config.getRepoDir()),
                         os.fsencode(fileName)))
        if os.path.isfile(fn):
            continue
        model = None
        if bugData.getChecker() == 'deadcode.DeadStores':
            model = model1
            coder = coder1
            totalDictionaryLength = totalDictionaryLength1
        if bugData.getChecker(
        ) == 'clang-diagnostic-tautological-constant-out-of-range-compare':
            model = model2
            coder = coder2
            totalDictionaryLength = totalDictionaryLength2
        if bugData.getChecker() == 'clang-diagnostic-unused-parameter':
            model = model3
            coder = coder3
            totalDictionaryLength = totalDictionaryLength3
        if bugData.getChecker() == 'clang-diagnostic-constant-conversion':
            model = model4
            coder = coder4
            totalDictionaryLength = totalDictionaryLength4
        MODEL_X_MAX_LEN = model.get_layer(index=0).input_shape[1]

        # 5.2.1.
        fullCodeWithBug = fileContents[fileName]
        extractor = CodeExtractor(bugData)
        extractor.loadCodeFromText(fullCodeWithBug)
        extractor.extractBugCode()
        bugCodeFragment = extractor.getBugCodeFragment()

        # 5.2.2.
        fullCodeWithoutBug = ''.join(fix(extractor.code, bugData))
        diff = POSIXDiffer().diff(fullCodeWithBug, fullCodeWithoutBug)
        extractor.loadDiff(diff)
        try:
            extractor.extractFixCode()
        except ValueError as ve:
            print(
                "Unable to generate expected fix for bug #{0} ({1}), checker = {2}"
                .format(bug, fileName, bugData.getChecker()))
            continue
        expectedFixCodeFragment = extractor.getFixCodeFragment()

        # 5.2.3.
        checkerInfo = checkers.extractTokensForChecker(bugData.getChecker(),
                                                       bugData.getMessage())
        encodedBugData, initialUnkList = coder.encode(bugCodeFragment,
                                                      checkerData=checkerInfo)
        noZerosToPad = MODEL_X_MAX_LEN - len(encodedBugData)
        if noZerosToPad > 0:
            encodedBugData = coder.applyPadding(encodedBugData, noZerosToPad)
        X = np.zeros((1, MODEL_X_MAX_LEN, totalDictionaryLength))
        X[0] = coder.convertToOneHot(
            encodedBugData, np.zeros((MODEL_X_MAX_LEN, totalDictionaryLength)))
        Y = coder.convertFromOneHot(model.predict(X)[0])
        while (Y[-1] == 0):
            Y.pop()
        fixCodeFragment = coder.decode(Y, initialUnkList)

        # 5.2.4.
        isCompiling = False
        f1 = os.fsdecode(
            os.path.join(os.fsencode(config.getRepoDir()),
                         os.fsencode(cleanFn)))
        f2 = os.fsdecode(
            os.path.join(os.fsencode(config.getRepoDir()),
                         os.fsencode('{0}.o'.format(cleanFn))))
        if os.path.isfile(f1):
            os.remove(f1)
        if os.path.isfile(f2):
            os.remove(f2)
        extractor.loadCodeFromText(fullCodeWithBug)
        extractor.applyFix(fixCodeFragment)
        with open(repoFn, 'wt') as f:
            f.writelines(extractor.code)
        log = codechecker.runCmd(
            'CodeChecker check -e all -b "cd {0} && make {1}" -o /tmp/codefixer_{1}'
            .format(config.getRepoDir(), cleanFn))
        if os.path.isfile(f1):
            isCompiling = True

        # 5.2.5.
        isFixed = False
        ids = []
        if isCompiling:
            resolved = codechecker.diffResolved(
                config.getCcRunName(), '/tmp/codefixer_{0}'.format(cleanFn),
                ccdb)
            for bugInfo in resolved:
                ids.append(bugInfo['reportId'])
            if bug in ids:
                isFixed = True

        # 5.2.6.
        isExpected = False
        if fixCodeFragment == expectedFixCodeFragment:
            isExpected = True

        # 5.2.7.
        encodedExpFix, finalUnkList = coder.encode(expectedFixCodeFragment,
                                                   unkList=initialUnkList,
                                                   reverse=False)
        noXTokens = len(encodedExpFix)
        noYTokens = len(Y)
        noAllTokens = max(noXTokens, noYTokens)
        noCorrectTokens = 0
        #print(encodedExpFix)
        #print(Y)
        for i in range(min(noXTokens, noYTokens)):
            if encodedExpFix[i] == Y[i]:
                noCorrectTokens += 1

        # 5.2.8.
        with open(fn, 'wt') as f:
            f.write(
                '#BUG#\n{0}\n#EXP#\n{1}\n#FIX#\n{2}\n#STATS#\n{3},{4},{5},{6},{7},{8},{9}\n{10}\n{11}'
                .format(bugCodeFragment, expectedFixCodeFragment,
                        fixCodeFragment, isCompiling, isFixed, isExpected,
                        noXTokens, noYTokens, noAllTokens, noCorrectTokens,
                        log, ids))

        # 5.2.9.
        with open(repoFn, 'wt') as f:
            f.write(fileContents[fileName])

        # 5.2.10.
        # Not used due to multithreading issues, will be done on file-by-file basis after closing pool
    # 5.3.
    return fileName
コード例 #24
0
 def getIncorrectBugDataLineBoundariesSwap(self):
     bugStartLine = 9
     bugEndLine = 7
     filepath = config.getRepoDir() + '/bugcode.cpp'
     return BugData(bugStartLine, bugEndLine, filepath, '', '')
コード例 #25
0
 def testGetFileContentsNotExistingFileFailure(self):
     gp = gitprovider.GitProvider(config.getRepoDir())
     with self.assertRaises(KeyError):
         gp.getFileContents('bugcode2.cpp',
                            'e46f62cbdcd7447dc6c796d917fece54426c782f'
                            )  #'bde8d75eb1133703b93a5110ed01c635d6d886ac')
コード例 #26
0
 def convertFilePathToRepoRelativePath(self, path):
     return os.path.relpath(path, config.getRepoDir())
コード例 #27
0
 def __init__(self, repo=None):
     if repo is None:
         self.repo = config.getRepoDir()
     else:
         self.repo = repo