1#!/usr/bin/env python 2 3import sys, os, re 4 5classes_ignore_list = ( 6 'OpenCV(Test)?Case', 7 'OpenCV(Test)?Runner', 8 'CvException', 9) 10 11funcs_ignore_list = ( 12 '\w+--HashCode', 13 'Mat--MatLong', 14 '\w+--Equals', 15 'Core--MinMaxLocResult', 16) 17 18class JavaParser: 19 def __init__(self): 20 self.clear() 21 22 def clear(self): 23 self.mdict = {} 24 self.tdict = {} 25 self.mwhere = {} 26 self.twhere = {} 27 self.empty_stubs_cnt = 0 28 self.r1 = re.compile("\s*public\s+(?:static\s+)?(\w+)\(([^)]*)\)") # c-tor 29 self.r2 = re.compile("\s*(?:(?:public|static|final)\s+){1,3}\S+\s+(\w+)\(([^)]*)\)") 30 self.r3 = re.compile('\s*fail\("Not yet implemented"\);') # empty test stub 31 32 33 def dict2set(self, d): 34 s = set() 35 for f in d.keys(): 36 if len(d[f]) == 1: 37 s.add(f) 38 else: 39 s |= set(d[f]) 40 return s 41 42 43 def get_tests_count(self): 44 return len(self.tdict) 45 46 def get_empty_stubs_count(self): 47 return self.empty_stubs_cnt 48 49 def get_funcs_count(self): 50 return len(self.dict2set(self.mdict)), len(self.mdict) 51 52 def get_not_tested(self): 53 mset = self.dict2set(self.mdict) 54 tset = self.dict2set(self.tdict) 55 nottested = mset - tset 56 out = set() 57 58 for name in nottested: 59 out.add(name + " " + self.mwhere[name]) 60 61 return out 62 63 64 def parse(self, path): 65 if ".svn" in path: 66 return 67 if os.path.isfile(path): 68 if path.endswith("FeatureDetector.java"): 69 for prefix1 in ("", "Grid", "Pyramid", "Dynamic"): 70 for prefix2 in ("FAST", "STAR", "MSER", "ORB", "SIFT", "SURF", "GFTT", "HARRIS", "SIMPLEBLOB", "DENSE"): 71 parser.parse_file(path,prefix1+prefix2) 72 elif path.endswith("DescriptorExtractor.java"): 73 for prefix1 in ("", "Opponent"): 74 for prefix2 in ("BRIEF", "ORB", "SIFT", "SURF"): 75 parser.parse_file(path,prefix1+prefix2) 76 elif path.endswith("GenericDescriptorMatcher.java"): 77 for prefix in ("OneWay", "Fern"): 78 parser.parse_file(path,prefix) 79 elif path.endswith("DescriptorMatcher.java"): 80 for prefix in ("BruteForce", "BruteForceHamming", "BruteForceHammingLUT", "BruteForceL1", "FlannBased", "BruteForceSL2"): 81 parser.parse_file(path,prefix) 82 else: 83 parser.parse_file(path) 84 elif os.path.isdir(path): 85 for x in os.listdir(path): 86 self.parse(path + "/" + x) 87 return 88 89 90 def parse_file(self, fname, prefix = ""): 91 istest = fname.endswith("Test.java") 92 clsname = os.path.basename(fname).replace("Test", "").replace(".java", "") 93 clsname = prefix + clsname[0].upper() + clsname[1:] 94 for cls in classes_ignore_list: 95 if re.match(cls, clsname): 96 return 97 f = open(fname, "rt") 98 linenum = 0 99 for line in f: 100 linenum += 1 101 m1 = self.r1.match(line) 102 m2 = self.r2.match(line) 103 m3 = self.r3.match(line) 104 func = '' 105 args_str = '' 106 if m1: 107 func = m1.group(1) 108 args_str = m1.group(2) 109 elif m2: 110 if "public" not in line: 111 continue 112 func = m2.group(1) 113 args_str = m2.group(2) 114 elif m3: 115 self.empty_stubs_cnt += 1 116 continue 117 else: 118 #if "public" in line: 119 #print "UNRECOGNIZED: " + line 120 continue 121 d = (self.mdict, self.tdict)[istest] 122 w = (self.mwhere, self.twhere)[istest] 123 func = re.sub(r"^test", "", func) 124 func = clsname + "--" + func[0].upper() + func[1:] 125 args_str = args_str.replace("[]", "Array").replace("...", "Array ") 126 args_str = re.sub(r"List<(\w+)>", "ListOf\g<1>", args_str) 127 args_str = re.sub(r"List<(\w+)>", "ListOf\g<1>", args_str) 128 args = [a.split()[0] for a in args_str.split(",") if a] 129 func_ex = func + "".join([a[0].upper() + a[1:] for a in args]) 130 func_loc = fname + " (line: " + str(linenum) + ")" 131 skip = False 132 for fi in funcs_ignore_list: 133 if re.match(fi, func_ex): 134 skip = True 135 break 136 if skip: 137 continue 138 if func in d: 139 d[func].append(func_ex) 140 else: 141 d[func] = [func_ex] 142 w[func_ex] = func_loc 143 w[func] = func_loc 144 145 f.close() 146 return 147 148 149if __name__ == '__main__': 150 if len(sys.argv) < 2: 151 print "Usage:\n", \ 152 os.path.basename(sys.argv[0]), \ 153 "<Classes/Tests dir1/file1> [<Classes/Tests dir2/file2> ...]\n", "Not tested methods are loggedto stdout." 154 exit(0) 155 parser = JavaParser() 156 for x in sys.argv[1:]: 157 parser.parse(x) 158 funcs = parser.get_not_tested() 159 if funcs: 160 print "NOT TESTED methods:\n\t", "\n\t".join(sorted(funcs)) 161 print "Total methods found: %i (%i)" % parser.get_funcs_count() 162 print "Not tested methods found:", len(funcs) 163 print "Total tests found:", parser.get_tests_count() 164 print "Empty test stubs found:", parser.get_empty_stubs_count() 165