You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

incr.py 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. import os, sys
  2. from org.aspectj.util import FileUtil
  3. from java.io import File
  4. sourcedir = "incr_test_scratch_sources"
  5. outdir = "incr_test_scratch_classes"
  6. errorList = []
  7. VERBOSE = 1
  8. def createEmpty(dir):
  9. if os.path.exists(dir):
  10. FileUtil.deleteContents(File(dir))
  11. else:
  12. os.mkdir(dir)
  13. def makeFile(name, contents):
  14. fullname = os.path.join(sourcedir, name)
  15. dirname = os.path.dirname(fullname)
  16. if not os.path.exists(dirname):
  17. os.makedirs(dirname)
  18. fp = open(fullname, 'w')
  19. fp.write(contents)
  20. fp.close()
  21. def deleteFile(name):
  22. os.remove(os.path.join(sourcedir, name))
  23. def snapshot(dir, map=None):
  24. if map is None: map = {}
  25. for file in os.listdir(dir):
  26. filename = os.path.join(dir, file)
  27. if os.path.isdir(filename):
  28. snapshot(filename, map)
  29. else:
  30. stats = os.stat(filename)
  31. map[filename] = stats[8]
  32. return map
  33. def diffSnapshots(old, new):
  34. unchanged = []
  35. changed = []
  36. for name, mtime in new.items():
  37. if old.has_key(name):
  38. oldTime = old[name]
  39. if oldTime == mtime:
  40. unchanged.append(name)
  41. else:
  42. changed.append(name)
  43. del old[name]
  44. else:
  45. changed.append(name)
  46. deleted = old.keys()
  47. return unchanged, changed, deleted
  48. def error(m):
  49. errorList.append(m)
  50. print m
  51. def suffixInList(suffix, list):
  52. for i in list:
  53. if i.endswith(suffix): return 1
  54. return 0
  55. def checkClasses(kind, filelist, names):
  56. filenames = []
  57. for o in filelist:
  58. name = os.path.basename(o)
  59. filenames.append(name[:-6])
  60. checkSets(names, filenames, kind)
  61. """
  62. #print names, repr(names)
  63. if repr(names).startswith("\'"): names = [names]
  64. for c in names:
  65. classname = c+".class"
  66. if not suffixInList(classname, filelist):
  67. error("%s expected %s not found in %s" % (name, classname, filelist))
  68. """
  69. def findAndRemove(l, item):
  70. for i in range(len(l)):
  71. if l[i] == item:
  72. del l[i]
  73. return 1
  74. return 0
  75. def makeList(l):
  76. if repr(l).startswith("\'"): return [l]
  77. return l
  78. def checkSets(expected, found, kind="error"):
  79. expected = makeList(expected)
  80. for e in expected:
  81. if not findAndRemove(found, e):
  82. error("expected %s %s not found in %s" % (kind, e, found))
  83. for f in found:
  84. error("unexpected %s %s" % (kind, f))
  85. from org.aspectj.ajdt.ajc import AjdtCommand
  86. from org.aspectj.bridge import IMessageHandler, IMessage
  87. def makeSet(errors):
  88. ret = {}
  89. for e in errors:
  90. loc = e.getISourceLocation()
  91. if loc is None: continue #???
  92. s = "%s:%i" % (loc.sourceFile.name[:-5], loc.line)
  93. ret[s] = s
  94. return ret.keys()
  95. class Handler (IMessageHandler):
  96. def __init__(self):
  97. self.errors = []
  98. def handleMessage(self, message):
  99. if message.kind == IMessage.ERROR:
  100. self.errors.append(message)
  101. if VERBOSE: print message
  102. def isIgnoring(self, kind):
  103. return 0
  104. createEmpty(sourcedir)
  105. createEmpty(outdir)
  106. handler = Handler()
  107. cmd = AjdtCommand()
  108. TEMPLATE = """\
  109. %(package)s
  110. %(modifiers)s %(kind)s %(classname)s %(parents)s {
  111. %(body)s
  112. public static void main(String[] args) {
  113. %(stmts)s
  114. }
  115. }
  116. """
  117. import string, time
  118. def splitClassName(className):
  119. dot = className.rfind('.')
  120. if dot == -1:
  121. return None, className, className +".java"
  122. else:
  123. packageName = className[:dot]
  124. className = className[dot+1:]
  125. l = packageName.split('.')
  126. l.append(className + ".java")
  127. path = apply(os.path.join, l)
  128. return packageName, className, path
  129. def makeType(className, stmts="""System.out.println("hello");""", body="", kind="class", parents=""):
  130. packageName, className, path = splitClassName(className)
  131. if packageName is None: packageDecl = ""
  132. else: packageDecl = "package %s;" % packageName
  133. contents = TEMPLATE % {'package':packageDecl, 'modifiers':'public',
  134. 'classname':className, 'body':body,
  135. 'stmts':stmts, 'kind':kind, 'parents':parents}
  136. makeFile(path, contents)
  137. def deleteType(className):
  138. packageName, className, path = splitClassName(className)
  139. deleteFile(path)
  140. def test(batch=0, couldChange=[], changed=[], deleted=[], errors=[]):
  141. print ">>>>test changed=%s, couldChange=%s, deleted=%s, errors=%s<<<<" % (changed, couldChange, deleted, errors)
  142. start = snapshot(outdir)
  143. #print start
  144. handler.errors = []
  145. time.sleep(0.1)
  146. if batch: cmd.runCommand(["-d", outdir, "-sourceroots", sourcedir], handler)
  147. else: cmd.repeatCommand(handler)
  148. checkSets(errors, makeSet(handler.errors))
  149. if len(handler.errors) > 0: return
  150. end = snapshot(outdir)
  151. #print "end", end
  152. u, c, d = diffSnapshots(start, end)
  153. checkClasses("changed", c, makeList(changed) + makeList(couldChange))
  154. checkClasses("deleted", d, deleted)
  155. """
  156. Pure Java tests
  157. """
  158. makeType("p1.Hello")
  159. test(batch=1, changed="Hello")
  160. test()
  161. makeType("p1.Hello", stmts="Target.staticM();")
  162. test(errors="Hello:5")
  163. test(errors="Hello:5")
  164. makeType("p1.Target", body="static void staticM() {}")
  165. test(changed=["Hello", "Target"])
  166. deleteType("p1.Target")
  167. test(errors="Hello:5")
  168. makeType("p1.Target", body="static void staticM() { int x = 2; }")
  169. test(changed=["Target", "Hello"])
  170. makeType("p1.Target", body="""static void staticM() { System.out.println("foo"); }""")
  171. test(changed=["Target"])
  172. makeType("p1.Target", body="static int staticM() { return 2; }")
  173. test(changed=["Hello", "Target"])
  174. makeType("p1.Hello", body="static class Inner {}")
  175. test(changed=["Hello", "Hello$Inner"])
  176. deleteType("p1.Hello")
  177. test(deleted=["Hello", "Hello$Inner"])
  178. makeType("p1.Hello", body="static class NewInner {}")
  179. test(changed=["Hello", "Hello$NewInner"])
  180. makeType("p1.Hello", body="")
  181. test(changed=["Hello"], deleted=["Hello$NewInner"])
  182. print "done", errorList
  183. sys.exit(0)
  184. """
  185. Simple tests with aspects
  186. """
  187. makeType("p1.Hello")
  188. test(batch=1, changed="Hello")
  189. makeType("p1.A", kind="aspect", body="before(): within(String) { }")
  190. test(changed=["A"], couldChange=["Hello"])
  191. makeType("p1.Hello")
  192. makeType("p1.A", kind="aspect", body="before(): execution(* main(..)) { }")
  193. test(changed=["A", "Hello"])
  194. makeType("p1.A", kind="aspect", body="before(): within(Hello) { }")
  195. test(changed=["A", "Hello"])
  196. makeType("p1.Target")
  197. test(changed="Target")
  198. makeType("p1.Hello", stmts="new Target().m();")
  199. test(errors=["Hello:5"])
  200. makeType("p1.ATypes", kind="aspect", body="int Target.m() { return 10; }")
  201. test(changed=["Hello", "ATypes", "Target"], couldChange=["A"])
  202. makeType("p1.ATypes", kind="aspect", body="int Target.m(int x) { return x + 10; }")
  203. test(errors=["Hello:5"])
  204. makeType("p1.Hello", stmts="new Target().m(2);")
  205. test(changed="Hello")
  206. makeType("p1.Hello", stmts="new Target().m(5);")
  207. test(changed="Hello")
  208. makeType("p1.Hello", stmts="new Target().m(42);")
  209. test(changed="Hello")
  210. print "done", errorList
  211. sys.exit(0)
  212. """
  213. Bugzilla Bug 29684
  214. Incremental: Commenting out conflict yeilds NullPointerException
  215. public class SomeClass {
  216. public String toString() {
  217. return "from SomeClass";
  218. }
  219. }
  220. public aspect Conflicter {
  221. public String SomeClass.toString() {
  222. return "from Conflicter";
  223. }
  224. public static void main(String[] args) {
  225. int i = 0;
  226. }
  227. }
  228. However, modifying Conflicter so that it reads:
  229. public aspect Conflicter {
  230. // public String SomeClass.toString() {
  231. // return "from Conflicter";
  232. // }
  233. public static void main(String[] args) {
  234. int i = 0;
  235. }
  236. }
  237. """
  238. makeType("conflict.SomeClass",
  239. body="""public String toString() { return "from SomeClass"; }""")
  240. makeType("conflict.Conflicter", kind="aspect",
  241. body="""public String SomeClass.toString() { return "from Conflicter"; }""")
  242. test(batch=1, errors=["Conflicter:3"])
  243. makeType("conflict.Conflicter", kind="aspect",
  244. body="")
  245. test(changed=["SomeClass", "Conflicter"])
  246. makeType("conflict.Conflicter", kind="aspect",
  247. body="""public String SomeClass.toString() { return "from Conflicter"; }""")
  248. test(errors=["Conflicter:3"])
  249. makeType("conflict.SomeClass",
  250. body="")
  251. test(changed=["SomeClass"])
  252. print "done", errorList
  253. sys.exit(0)
  254. """
  255. Bugzilla Bug 28807
  256. incremental compilation always fails with NullPointerException in 1.1 beta 2
  257. """
  258. makeType("incremental.BasicAspect")
  259. makeType("incremental.Basic")
  260. test(batch=1, changed=["Basic", "BasicAspect"])
  261. makeType("incremental.BasicAspect")
  262. test()
  263. print "done", errorList
  264. sys.exit(0)
  265. """
  266. Stress testing
  267. """
  268. N = 2000
  269. l = []
  270. for i in range(N):
  271. name = "p1.Hello" + str(i)
  272. makeType(name)
  273. l.append("Hello" + str(i))
  274. test(batch=1, changed=l)
  275. print "done", errorList
  276. sys.exit(0)