Home | History | Annotate | Download | only in java
      1 #!/usr/bin/env python
      2 
      3 import sys, os, re
      4 
      5 classes_ignore_list = (
      6     'OpenCV(Test)?Case',
      7     'OpenCV(Test)?Runner',
      8     'CvException',
      9 )
     10 
     11 funcs_ignore_list = (
     12     '\w+--HashCode',
     13     'Mat--MatLong',
     14     '\w+--Equals',
     15     'Core--MinMaxLocResult',
     16 )
     17 
     18 class 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 
    149 if __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