EngineTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. using System;
  2. using System.IO;
  3. using System.Reflection;
  4. using Xunit;
  5. using Xunit.Extensions;
  6. namespace Jint.Tests.Runtime
  7. {
  8. public class EngineTests
  9. {
  10. private Engine RunTest(string source)
  11. {
  12. var engine = new Engine(cfg => cfg
  13. .WithDelegate("log", new Action<object>(Console.WriteLine))
  14. .WithDelegate("assert", new Action<bool>(Assert.True))
  15. );
  16. engine.Execute(source);
  17. return engine;
  18. }
  19. [Theory]
  20. [InlineData("Scratch.js")]
  21. public void ShouldInterpretScriptFile(string file)
  22. {
  23. const string prefix = "Jint.Tests.Runtime.Scripts.";
  24. var assembly = Assembly.GetExecutingAssembly();
  25. var scriptPath = prefix + file;
  26. using (var stream = assembly.GetManifestResourceStream(scriptPath))
  27. if (stream != null)
  28. using (var sr = new StreamReader(stream))
  29. {
  30. var source = sr.ReadToEnd();
  31. RunTest(source);
  32. }
  33. }
  34. [Theory]
  35. [InlineData(42d, "42")]
  36. [InlineData("Hello", "'Hello'")]
  37. public void ShouldInterpretLiterals(object expected, string source)
  38. {
  39. var engine = new Engine();
  40. var result = engine.GetValue(engine.Execute(source));
  41. Assert.Equal(expected, result);
  42. }
  43. [Fact]
  44. public void ShouldInterpretVariableDeclaration()
  45. {
  46. var engine = new Engine();
  47. var result = engine.GetValue(engine.Execute("var foo = 'bar'; foo;"));
  48. Assert.Equal("bar", result);
  49. }
  50. [Theory]
  51. [InlineData(4d, "1 + 3")]
  52. [InlineData(-2d, "1 - 3")]
  53. [InlineData(3d, "1 * 3")]
  54. [InlineData(2d, "6 / 3")]
  55. [InlineData(9, "15 & 9")]
  56. [InlineData(15, "15 | 9")]
  57. [InlineData(6, "15 ^ 9")]
  58. [InlineData(36, "9 << 2")]
  59. [InlineData(2, "9 >> 2")]
  60. [InlineData((uint)4, "19 >>> 2")]
  61. public void ShouldInterpretBinaryExpression(object expected, string source)
  62. {
  63. var engine = new Engine();
  64. var result = engine.GetValue(engine.Execute(source));
  65. Assert.Equal(expected, result);
  66. }
  67. [Fact]
  68. public void ShouldEvaluateHasOwnProperty()
  69. {
  70. RunTest(@"
  71. var x = {};
  72. x.Bar = 42;
  73. assert(x.hasOwnProperty('Bar'));
  74. ");
  75. }
  76. [Fact]
  77. public void FunctionConstructorsShouldCreateNewObjects()
  78. {
  79. RunTest(@"
  80. var Vehicle = function () {};
  81. var vehicle = new Vehicle();
  82. assert(vehicle != undefined);
  83. ");
  84. }
  85. [Fact]
  86. public void NewObjectsInheritFunctionConstructorProperties()
  87. {
  88. RunTest(@"
  89. var Vehicle = function () {};
  90. var vehicle = new Vehicle();
  91. Vehicle.prototype.wheelCount = 4;
  92. assert(vehicle.wheelCount == 4);
  93. assert((new Vehicle()).wheelCount == 4);
  94. ");
  95. }
  96. [Fact]
  97. public void NewObjectsShouldUsePrivateProperties()
  98. {
  99. RunTest(@"
  100. var Vehicle = function (color) {
  101. this.color = color;
  102. };
  103. var vehicle = new Vehicle('tan');
  104. assert(vehicle.color == 'tan');
  105. ");
  106. }
  107. [Fact]
  108. public void FunctionConstructorsShouldDefinePrototypeChain()
  109. {
  110. RunTest(@"
  111. function Vehicle() {};
  112. var vehicle = new Vehicle();
  113. assert(vehicle.hasOwnProperty('constructor') == false);
  114. ");
  115. }
  116. [Fact]
  117. public void NewObjectsConstructorIsObject()
  118. {
  119. RunTest(@"
  120. var o = new Object();
  121. assert(o instanceof Object);
  122. assert(o.constructor == Object);
  123. ");
  124. }
  125. [Fact]
  126. public void NewObjectsConstructorShouldBeConstructorObject()
  127. {
  128. RunTest(@"
  129. var Vehicle = function () {};
  130. var vehicle = new Vehicle();
  131. assert(vehicle.constructor == Vehicle);
  132. ");
  133. }
  134. [Fact]
  135. public void NewObjectsIntanceOfConstructorObject()
  136. {
  137. RunTest(@"
  138. var Vehicle = function () {};
  139. var vehicle = new Vehicle();
  140. assert(vehicle instanceof Vehicle);
  141. ");
  142. }
  143. [Fact]
  144. public void ShouldEvaluateForLoops()
  145. {
  146. RunTest(@"
  147. var foo = 0;
  148. for (var i = 0; i < 5; i++) {
  149. foo += i;
  150. }
  151. assert(foo == 10);
  152. ");
  153. }
  154. [Fact]
  155. public void ShouldEvaluateRecursiveFunctions()
  156. {
  157. RunTest(@"
  158. function fib(n) {
  159. if (n < 2) {
  160. return n;
  161. }
  162. return fib(n - 1) + fib(n - 2);
  163. }
  164. var result = fib(6);
  165. assert(result == 8);
  166. ");
  167. }
  168. [Fact]
  169. public void ShouldAccessObjectProperties()
  170. {
  171. RunTest(@"
  172. var o = {};
  173. o.Foo = 'bar';
  174. o.Baz = 42;
  175. o.Blah = o.Foo + o.Baz;
  176. assert(o.Blah == 'bar42');
  177. ");
  178. }
  179. [Fact]
  180. public void ShouldConstructArray()
  181. {
  182. RunTest(@"
  183. var o = [];
  184. assert(o.length == 0);
  185. ");
  186. }
  187. [Fact]
  188. public void ArrayPushShouldIncrementLength()
  189. {
  190. RunTest(@"
  191. var o = [];
  192. o.push(1);
  193. assert(o.length == 1);
  194. ");
  195. }
  196. [Fact]
  197. public void ArrayPopShouldDecrementLength()
  198. {
  199. RunTest(@"
  200. var o = [42, 'foo'];
  201. var pop = o.pop();
  202. assert(o.length == 1);
  203. assert(pop == 'foo');
  204. ");
  205. }
  206. [Fact]
  207. public void ArrayConstructor()
  208. {
  209. RunTest(@"
  210. var o = [];
  211. assert(o.constructor == Array);
  212. assert(o.hasOwnProperty('constructor') == false);
  213. ");
  214. }
  215. [Fact]
  216. public void DateConstructor()
  217. {
  218. RunTest(@"
  219. var o = new Date();
  220. assert(o.constructor == Date);
  221. assert(o.hasOwnProperty('constructor') == false);
  222. ");
  223. }
  224. [Fact]
  225. public void MathObjectIsDefined()
  226. {
  227. RunTest(@"
  228. var o = Math.abs(-1)
  229. assert(o == 1);
  230. ");
  231. }
  232. [Fact]
  233. public void VoidShouldReturnUndefined()
  234. {
  235. RunTest(@"
  236. assert(void 0 === undefined);
  237. var x = '1';
  238. assert(void x === undefined);
  239. x = 'x';
  240. assert (isNaN(void x) === true);
  241. x = new String('-1');
  242. assert (void x === undefined);
  243. ");
  244. }
  245. [Fact]
  246. public void TypeofObjectShouldReturnString()
  247. {
  248. RunTest(@"
  249. assert(typeof x === 'undefined');
  250. assert(typeof 0 === 'number');
  251. var x = 0;
  252. assert (typeof x === 'number');
  253. var x = new Object();
  254. assert (typeof x === 'object');
  255. ");
  256. }
  257. [Fact]
  258. public void MathAbsReturnsAbsolute()
  259. {
  260. RunTest(@"
  261. assert(1 == Math.abs(-1));
  262. ");
  263. }
  264. [Fact]
  265. public void NaNIsNan()
  266. {
  267. RunTest(@"
  268. var x = NaN;
  269. assert(isNaN(NaN));
  270. assert(isNaN(Math.abs(x)));
  271. ");
  272. }
  273. [Fact]
  274. public void ToNumberHandlesStringObject()
  275. {
  276. RunTest(@"
  277. x = new String('1');
  278. x *= undefined;
  279. assert(isNaN(x));
  280. ");
  281. }
  282. [Fact]
  283. public void FunctionScopesAreChained()
  284. {
  285. RunTest(@"
  286. var x = 0;
  287. function f1(){
  288. function f2(){
  289. return x;
  290. };
  291. return f2();
  292. var x = 1;
  293. }
  294. assert(f1() === undefined);
  295. ");
  296. }
  297. [Fact]
  298. public void EvalFunctionParseAndExecuteCode()
  299. {
  300. RunTest(@"
  301. var x = 0;
  302. eval('assert(x == 0)');
  303. ");
  304. }
  305. [Fact]
  306. public void ForInStatement()
  307. {
  308. RunTest(@"
  309. var x, y, z, str = '';
  310. for(z in this) {
  311. str += z;
  312. }
  313. assert(str == 'xyzstr');
  314. ");
  315. }
  316. [Fact]
  317. public void WithStatement()
  318. {
  319. RunTest(@"
  320. with (Math) {
  321. assert(cos(0) == 1);
  322. }
  323. ");
  324. }
  325. [Fact]
  326. public void ObjectExpression()
  327. {
  328. RunTest(@"
  329. var o = { x: 1 };
  330. assert(o.x == 1);
  331. ");
  332. }
  333. [Fact]
  334. public void StringFunctionCreatesString()
  335. {
  336. RunTest(@"
  337. assert(Strint(NaN) === 'NaN');
  338. ");
  339. }
  340. [Fact]
  341. public void ScopeChainInWithStatement()
  342. {
  343. RunTest(@"
  344. var x = 0;
  345. var myObj = {x : 'obj'};
  346. function f1(){
  347. var x = 1;
  348. function f2(){
  349. with(myObj){
  350. return x;
  351. }
  352. };
  353. return f2();
  354. }
  355. assert(f1() === 'obj');
  356. ");
  357. }
  358. [Fact]
  359. public void TryCatchBlockStatement()
  360. {
  361. RunTest(@"
  362. var x, y, z;
  363. try {
  364. x = 1;
  365. throw new TypeError();
  366. x = 2;
  367. }
  368. catch(e) {
  369. assert(x == 1);
  370. assert(e instanceof TypeError);
  371. y = 1;
  372. }
  373. finally {
  374. assert(x == 1);
  375. z = 1;
  376. }
  377. assert(x == 1);
  378. assert(y == 1);
  379. assert(z == 1);
  380. ");
  381. }
  382. [Theory]
  383. [InlineData(double.NaN, "parseInt(NaN)")]
  384. [InlineData(double.NaN, "parseInt(null)")]
  385. [InlineData(double.NaN, "parseInt(undefined)")]
  386. [InlineData(double.NaN, "parseInt(new Boolean(true))")]
  387. [InlineData(double.NaN, "parseInt(Infinity)")]
  388. [InlineData(-1, "parseInt(-1)")]
  389. [InlineData(-1, "parseInt('-1')")]
  390. public void ShouldEvaluateParseInt(object expected, string source)
  391. {
  392. var engine = new Engine();
  393. var result = engine.GetValue(engine.Execute(source));
  394. Assert.Equal(expected, result);
  395. }
  396. /*
  397. [Fact]
  398. public void ()
  399. {
  400. RunTest(@"
  401. ");
  402. }
  403. */
  404. }
  405. }