treeCompTest.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. _accu_ = 0
  3. _iList_ = [1,2,3,4]
  4. for _item_ in _iList_:
  5. _accu_ = _accu_ + _item_
  6. print(_accu_)
  7. */
  8. /**
  9. parses code and returns a new EasyNode that is the root of the student
  10. **/
  11. function parseCode(studentCode){
  12. var stdAST;
  13. try{
  14. Sk.python3 = true;
  15. var filename = '__main__'
  16. var studentParse = Sk.parse(filename,studentCode);
  17. stdAST = Sk.astFromParse(studentParse.cst, filename, studentParse.flags);
  18. stdAST = new EasyNode(stdAST, "none");
  19. } catch (studentError){
  20. console.log(studentParse);
  21. console.log(stdAST);
  22. stdAST = null;
  23. }
  24. return stdAST;
  25. }
  26. function testShallowMatch(){
  27. console.log("TESTING VAR MATCH");
  28. var failCount = 0;
  29. var successCount = 0;
  30. //tests whether variables are stored correctly
  31. var testTree = new StretchyTreeMatcher("_accu_ = 0");
  32. //extracting instrutor name node
  33. var insAST = testTree.rootNode;
  34. var insNameNode = insAST.children[0].children[0];
  35. //creating student code
  36. var studentCode = "accumulator = 0";
  37. var stdAST = parseCode(studentCode);
  38. //extracting student name node
  39. var stdNameNode = stdAST.children[0].children[0];
  40. var mapping = testTree.shallowMatch(insNameNode, stdNameNode)[0];
  41. var debugPrint = false;
  42. if(!(mapping.mappings.keys[0] == insNameNode.astNode)){
  43. console.error("ins node match not correct in _var_ case");
  44. debugPrint = true;
  45. failCount++;
  46. }else
  47. successCount++;
  48. if(!(mapping.mappings.values[0] == stdNameNode.astNode)){
  49. console.error("std node match not correct in _var_ case");
  50. debugPrint = true;
  51. failCount++;
  52. }else
  53. successCount++;
  54. if(debugPrint){
  55. console.log(testTree);
  56. console.log(insNameNode);
  57. console.log(stdNameNode);
  58. console.log(mapping);
  59. }
  60. //tests whether expressions are stored correctly
  61. console.log("TESTING EXPRESSION MATCH");
  62. testTree = new StretchyTreeMatcher("__exp__ = 0");
  63. //extracting instrutor name node
  64. insAST = testTree.rootNode;
  65. insNameNode = insAST.children[0].children[0];
  66. //creating student code
  67. studentCode += "\nfor item in myList:\n accumulator += item";
  68. stdAST = parseCode(studentCode);
  69. //extracting body node
  70. var stdForLoop = stdAST.children[1];
  71. mapping = testTree.shallowMatch(insNameNode, stdForLoop)[0];
  72. debugPrint = false;
  73. if(mapping){
  74. if(!(mapping.expTable.keys[0] == "__exp__")){
  75. debugPrint = true;
  76. failCount++;
  77. console.error("symbol match not found");
  78. }else
  79. successCount++;
  80. if(!(mapping.expTable.values[0] == stdForLoop.astNode)){
  81. debugPrint = true;
  82. failCount++;
  83. console.error("did not match to correct ast node");
  84. }else
  85. successCount++;
  86. }else{
  87. debugPrint = true;
  88. console.error("no mapping found");
  89. failCount++;
  90. }
  91. if(debugPrint){
  92. console.log(testTree);
  93. console.log(insNameNode);
  94. console.log(stdForLoop);
  95. console.log(mapping);
  96. }
  97. //tests whether Wild matches are stored correctly
  98. console.log("TESTING WILD CARD MATCH");
  99. testTree = new StretchyTreeMatcher("___ = 0");
  100. //extracting instrutor name node
  101. insAST = testTree.rootNode;
  102. insNameNode = insAST.children[0].children[0];
  103. //creating student code
  104. studentCode += "\nfor item in myList:\n accumulator += item";
  105. stdAST = parseCode(studentCode);
  106. //extracting body node
  107. var stdForLoop = stdAST.children[1];
  108. debugPrint = false;
  109. mapping = testTree.shallowMatch(insNameNode, stdForLoop)[0];
  110. if(!mapping || (mapping.mappings.keys[0] != insNameNode.astNode &&
  111. mapping.mappings.values[0] != stdForLoop.astNode)){
  112. console.error("wild card match didn't match");
  113. debugPrint = true;
  114. failCount++;
  115. }else
  116. successCount++;
  117. if(debugPrint){
  118. console.log(testTree);
  119. console.log(insNameNode);
  120. console.log(stdForLoop);
  121. console.log(mapping);
  122. }
  123. console.log("TESTING MATCH ALL");
  124. testTree = new StretchyTreeMatcher("___ = 0");
  125. var insNumNode = insAST.children[0].children[1];
  126. //creating student code
  127. studentCode = "billy = 0";
  128. stdAST = parseCode(studentCode);
  129. //extracting body node
  130. var stdNumNode = stdAST.children[0].children[1];
  131. mapping = testTree.shallowMatch(insNumNode, stdNumNode)[0];
  132. debugPrint = false;
  133. if(mapping){
  134. if(mapping.mappings.keys[0] != insNumNode.astNode){
  135. console.error("ins node not matched correctly");
  136. debugPrint = true;
  137. failCount++;
  138. }else
  139. successCount++;
  140. if(mapping.mappings.values[0] != stdNumNode.astNode){
  141. console.error("student node not matched correctly");
  142. debugPrint = true;
  143. failCount++;
  144. }else
  145. successCount++;
  146. successCount++;
  147. }else{
  148. console.error("Match not found");
  149. debugPrint = true;
  150. failCount++;
  151. }
  152. if(debugPrint){
  153. console.log(testTree);
  154. console.log(stdNumNode);
  155. console.log(mapping);
  156. }
  157. return [failCount, successCount];
  158. }
  159. function testGenericMatch(){
  160. console.log("TESTING SAME ORDER");
  161. var failCount = 0;
  162. var successCount = 0;
  163. var stdCode = "_sum = 0\nlist = [1,2,3,4]\nfor item in list:\n _sum = _sum + item\nprint(_sum)";
  164. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu_ + _item_\nprint(_accu_)";
  165. //var stdCode = "_sum = 12 + 13";
  166. //var insCode = "_accu_ = 12 + 11";
  167. var insTree = new StretchyTreeMatcher(insCode);
  168. var insAST = insTree.rootNode;
  169. var stdAST = parseCode(stdCode);
  170. var mappingsArray = insTree.findMatches(stdAST.astNode);
  171. var mappings = mappingsArray[0];
  172. var debugPrint = false;
  173. if(!mappingsArray || mappings.mappings.size() != 19){
  174. debugPrint = true;
  175. failCount++;
  176. console.error("incorrect number of mappings found");
  177. }else
  178. successCount++;
  179. if(mappingsArray){
  180. if(mappings.symbolTable.size() != 3 ||
  181. mappings.symbolTable.values[0].length != 4 ||
  182. mappings.symbolTable.values[1].length != 2 ||
  183. mappings.symbolTable.values[2].length != 2){
  184. debugPrint = true;
  185. failCount++;
  186. console.error("inconsistent symbol matching");
  187. }else
  188. successCount++;
  189. }
  190. if(debugPrint){
  191. console.log(mappings);
  192. console.log(insAST.astNode);
  193. console.log(stdAST.astNode);
  194. }
  195. return [failCount, successCount];
  196. }
  197. function testManyToOne(){
  198. console.log("TESTING MANY TO ONE");
  199. var failCount = 0;
  200. var successCount = 0;
  201. var stdCode = "_sum = 0\nlist = [1,2,3,4]\nfor item in list:\n _sum = _sum + item\nprint(_sum)";
  202. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu2_ + _item_\nprint(_accu_)";
  203. var insTree = new StretchyTreeMatcher(insCode);
  204. var insAST = insTree.rootNode;
  205. var stdAST = parseCode(stdCode);
  206. var mappings = insTree.findMatches(stdAST.astNode)[0];
  207. var debugPrint = false;
  208. if(mappings){
  209. if(mappings.conflictKeys.length != 0){
  210. console.error("Conflicting keys when there shouldn't be");
  211. debugPrint = true;
  212. failCount++;
  213. }else
  214. successCount++;
  215. if(mappings.symbolTable.size() != 4 ||
  216. mappings.symbolTable.values[0].length != 3 ||
  217. mappings.symbolTable.values[1].length != 2 ||
  218. mappings.symbolTable.values[2].length != 2 ||
  219. mappings.symbolTable.values[3].length != 1){
  220. debugPrint = true;
  221. failCount++;
  222. console.error("inconsistent symbol matching");
  223. }else
  224. successCount++;
  225. }else{
  226. debugPrint = true;
  227. console.log("no mapping found");
  228. }
  229. if(debugPrint){
  230. console.log(insAST.astNode);
  231. console.log(stdAST.astNode);
  232. console.log(mappings);
  233. }
  234. return [failCount, successCount];
  235. }
  236. function testCommutativity(){
  237. console.log("TESTING COMMUTATIVITY ADDITION");
  238. var failCount = 0;
  239. var successCount = 0;
  240. var stdCode = "_sum = 0\nlist = [1,2,3,4]\nfor item in list:\n _sum = item + _sum\nprint(_sum)";
  241. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu_ + _item_\nprint(_accu_)";
  242. var insTree = new StretchyTreeMatcher(insCode);
  243. var insAST = insTree.rootNode;
  244. var stdAST = parseCode(stdCode);
  245. var mappings = insTree.findMatches(stdAST.astNode)[0];
  246. var debugPrint = false;
  247. if(mappings){
  248. if(mappings.conflictKeys.length != 0){
  249. debugPrint = true;
  250. failCount++;
  251. console.error("Conflicting keys in ADDITION when there shouldn't be");
  252. }else
  253. successCount++;
  254. }else{
  255. debugPrint = true;
  256. failCount++;
  257. console.error("No mapping found when mapping should have been found");
  258. }
  259. if(debugPrint){
  260. console.log(insAST.astNode);
  261. console.log(stdAST.astNode);
  262. console.log(mappings);
  263. }
  264. debugPrint = false;
  265. return [failCount, successCount];
  266. }
  267. function testOneToMany(){
  268. console.log("TESTING ONE TO MANY");
  269. var failCount = 0;
  270. var successCount = 0;
  271. var stdCode = "_sum = 0\nlist = [1,2,3,4]\nfor item in list:\n _sum = _sum + _sum\nprint(_sum)";
  272. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu_ + _item_\nprint(_accu_)";
  273. var insTree = new StretchyTreeMatcher(insCode);
  274. var insAST = insTree.rootNode;
  275. var stdAST = parseCode(stdCode);
  276. var mappings = insTree.findMatches(stdAST.astNode);
  277. var debugPrint = false;
  278. if(mappings){
  279. failCount++;
  280. console.error("found match when match shouldn't be found");
  281. }else
  282. successCount++;
  283. if(debugPrint){
  284. console.log(insAST.astNode);
  285. console.log(stdAST.astNode);
  286. console.log(mappings);
  287. }
  288. return [failCount, successCount];
  289. }
  290. function testMultiMatch(){
  291. console.log("TESTING MULTI-MATCH");
  292. var failCount = 0;
  293. var successCount = 0;
  294. var debugPrint = false;
  295. //var stdCode = "_sum = 0\ncount = 0\nlist = [1,2,3,4]\nfor item in list:\n _sum = _sum + item\n count = count + 1\nprint(_sum)";
  296. var stdCode = "_sum = 0\ncount = 0\n_list = [1,2,3,4]\nfor item in _list:\n _sum = _sum + count\n count = _sum + count\nprint(_sum)";
  297. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu_ + __exp__\nprint(_accu_)";
  298. var insTree = new StretchyTreeMatcher(insCode);
  299. var insAST = insTree.rootNode;
  300. var stdAST = parseCode(stdCode);
  301. var mappings = insTree.findMatches(stdAST.astNode);
  302. if(mappings.length > 1){
  303. console.error("too many matchings found");
  304. failCount++;
  305. debugPrint = true;
  306. }else
  307. successCount++;
  308. if(debugPrint){
  309. console.log(insAST);
  310. console.log(stdAST);
  311. console.log(mappings);
  312. }
  313. debugPrint = false;
  314. var insCode = "_accu_ = 0\n_iList_ = __listInit__\nfor _item_ in _iList_:\n _accu_ = _accu_ + __exp__";
  315. insTree = new StretchyTreeMatcher(insCode);
  316. insAST = insTree.rootNode;
  317. mappings = insTree.findMatches(stdAST.astNode);
  318. if(mappings.length < 2){
  319. console.error("Not enough mappings found");
  320. failCount++;
  321. debugPrint = true;
  322. }else
  323. successCount++;
  324. if(debugPrint){
  325. console.log(insAST);
  326. console.log(stdAST);
  327. console.log(mappings);
  328. }
  329. return [failCount, successCount];
  330. }
  331. function testPass(){
  332. console.log("TESTING PASS MATCH");
  333. var failCount = 0;
  334. var successCount = 0;
  335. var debugPrint = false;
  336. var stdCode = 'import matplotlib.pyplot as plt\nquakes = [1,2,3,4]\nquakes_in_miles = []\nfor quakes in quakes:\n quakes_in_miles.append(quake * 0.62)\nplt.hist(quakes_in_miles)\nplt.xlabel("Depth in Miles")\nplt.ylabel("Number of Earthquakes")\nplt.title("Distribution of Depth in Miles of Earthquakes")\nplt.show()';
  337. var insCode = "for _item_ in _item_:\n pass";
  338. var insTree = new StretchyTreeMatcher(insCode);
  339. var insAST = insTree.rootNode;
  340. var stdAST = parseCode(stdCode);
  341. var mappings = insTree.findMatches(stdAST.astNode);
  342. if(!mappings){
  343. console.error("mapping should have been found");
  344. failCount++;
  345. debugPrint = true;
  346. }else
  347. successCount++;
  348. if(debugPrint){
  349. console.log(insAST);
  350. console.log(stdAST);
  351. console.log(mappings);
  352. }
  353. return [failCount, successCount];
  354. }
  355. function testMetaStretch(){
  356. console.log("TESTING META STRETCH");
  357. var failCount = 0;
  358. var successCount = 0;
  359. var debugPrint = false;
  360. var stdCode = 'steps_hiked_list = [1,2,3,4]\n' +
  361. 'total = 0\n' +
  362. 'for steps_hiked in steps_hiked_list:\n' +
  363. ' total = steps_hiked + total\n steps = steps + 1';
  364. var insCode = "for ___ in ___:\n" +
  365. " ___ = _sum_ + ___";
  366. var insTree = new StretchyTreeMatcher(insCode);
  367. var insAST = insTree.rootNode;
  368. var stdAST = parseCode(stdCode);
  369. var mappings = insTree.findMatches(stdAST.astNode);
  370. if(!mappings){
  371. console.error("mapping should have been found");
  372. failCount++;
  373. debugPrint = true;
  374. }else{
  375. if (mappings.length != 3){
  376. console.log("Should find exactly 3 matches, instead found " + mappings.length)
  377. failCount++;
  378. debugPrint = true;
  379. }else
  380. successCount++;
  381. }
  382. if(debugPrint){
  383. console.log(insAST);
  384. console.log(stdAST);
  385. console.log(mappings);
  386. }
  387. return [failCount, successCount];
  388. }
  389. function tabulateResults(currentCounts, result){
  390. currentCounts[0] += result[0];
  391. currentCounts[1] += result[1];
  392. return currentCounts;
  393. }
  394. function runTreeCompTestSuiteHelper(){
  395. var currentCounts = [0, 0];
  396. tabulateResults(currentCounts, testShallowMatch());
  397. tabulateResults(currentCounts, testGenericMatch());
  398. tabulateResults(currentCounts, testManyToOne());
  399. tabulateResults(currentCounts, testCommutativity());
  400. tabulateResults(currentCounts, testOneToMany());
  401. tabulateResults(currentCounts, testMultiMatch());
  402. tabulateResults(currentCounts, testPass());
  403. tabulateResults(currentCounts, testMetaStretch());
  404. return currentCounts;
  405. }
  406. function runTreeCompTestSuite(){
  407. var result = runTreeCompTestSuiteHelper();
  408. console.log(result[0] + " out of " + (result[0] + result[1]) + " tests failed");
  409. }
  410. runTreeCompTestSuite();