general.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. var assert = require("assert");
  2. var parser = require("../src/openscad-parser").parser;
  3. function parse(s) {
  4. return parser.parse(s);
  5. }
  6. function check(test, expected) {
  7. assert.equal(parse(test), expected);
  8. }
  9. function run(test){
  10. var f = new Function(parse(test));
  11. return f();
  12. }
  13. exports["test variable assigments"] = function() {
  14. check("x = 123;", "var x;\nx = 123;");
  15. check("x = 123.456;", "var x;\nx = 123.456;");
  16. check("x = 2e-1;", "var x;\nx = 0.2;");
  17. check("x = \"string\";", "var x;\nx = \"string\";");
  18. check("x = true;", "var x;\nx = true;");
  19. check("x = false;", "var x;\nx = false;");
  20. }
  21. exports["test echo"] = function() {
  22. check("echo(\"string\");", "console.log(\"ECHO: \" + \"string\");");
  23. check("echo(123);", "console.log(\"ECHO: \" + 123);");
  24. check("echo(123.456);", "console.log(\"ECHO: \" + 123.456);");
  25. check("echo(2e-1);", "console.log(\"ECHO: \" + 0.2);");
  26. check("echo(true);", "console.log(\"ECHO: \" + true);");
  27. check("echo(false);", "console.log(\"ECHO: \" + false);");
  28. }
  29. exports["test comments"] = function() {
  30. parse("// single line comment");
  31. parse("myvar = 10; // The rest of the line is a comment");
  32. parse("/* Multi-line comments \n can span multiple lines.*/");
  33. }
  34. exports["test operations"] = function() {
  35. check("x = 5 + 4;", "var x;\nx = 9;");
  36. check("x = 5 - 4;", "var x;\nx = 1;");
  37. check("x = 2 * 2;", "var x;\nx = 4;");
  38. check("x = 6 / 2;", "var x;\nx = 3;");
  39. check("x = 5 % 2;", "var x;\nx = 1;");
  40. check("x = 5 < 6;", "var x;\nx = true;");
  41. check("x = 5 <= 6;", "var x;\nx = true;");
  42. check("x = 5 > 6;", "var x;\nx = false;");
  43. check("x = 5 >= 6;", "var x;\nx = false;");
  44. check("x = true && true;", "var x;\nx = true;");
  45. check("x = true || false;", "var x;\nx = true;");
  46. check("x = +5;","var x;\nx = 5;");
  47. check("x = -5;","var x;\nx = -5;");
  48. check("x = +5 + -5;","var x;\nx = 0;");
  49. }
  50. exports["test Variables are set at compile-time, not run-time"] = function() {
  51. var openscad = "// The value of 'a' reflects only the last set value\na = 0;\necho(a);\na = 5;\necho(a);";
  52. var stdout = process.stdout;
  53. var stdoutLog = [];
  54. install_hook_to(stdout);
  55. stdout.hook('write', function(string, encoding, fd, write) {
  56. stdoutLog.push(string);
  57. });
  58. try {
  59. run(openscad);
  60. assert.equal(stdoutLog.join(), "ECHO: 5\n,ECHO: 5\n");
  61. } finally {
  62. stdout.unhook('write');
  63. }
  64. }
  65. /* Useful function to temporarily override a method - used to record stdout
  66. via: http://stackoverflow.com/a/9624028/188624
  67. */
  68. var install_hook_to = function(obj) {
  69. if (obj.hook || obj.unhook) {
  70. throw new Error('Object already has properties hook and/or unhook');
  71. }
  72. obj.hook = function(_meth_name, _fn, _is_async) {
  73. var self = this,
  74. meth_ref;
  75. // Make sure method exists
  76. if (! (Object.prototype.toString.call(self[_meth_name]) === '[object Function]')) {
  77. throw new Error('Invalid method: ' + _meth_name);
  78. }
  79. // We should not hook a hook
  80. if (self.unhook.methods[_meth_name]) {
  81. throw new Error('Method already hooked: ' + _meth_name);
  82. }
  83. // Reference default method
  84. meth_ref = (self.unhook.methods[_meth_name] = self[_meth_name]);
  85. self[_meth_name] = function() {
  86. var args = Array.prototype.slice.call(arguments);
  87. // Our hook should take the same number of arguments
  88. // as the original method so we must fill with undefined
  89. // optional args not provided in the call
  90. while (args.length < meth_ref.length) {
  91. args.push(undefined);
  92. }
  93. // Last argument is always original method call
  94. args.push(function() {
  95. var args = arguments;
  96. if (_is_async) {
  97. process.nextTick(function() {
  98. meth_ref.apply(self, args);
  99. });
  100. } else {
  101. meth_ref.apply(self, args);
  102. }
  103. });
  104. _fn.apply(self, args);
  105. };
  106. };
  107. obj.unhook = function(_meth_name) {
  108. var self = this,
  109. ref = self.unhook.methods[_meth_name];
  110. if (ref) {
  111. self[_meth_name] = self.unhook.methods[_meth_name];
  112. delete self.unhook.methods[_meth_name];
  113. } else {
  114. throw new Error('Method not hooked: ' + _meth_name);
  115. }
  116. };
  117. obj.unhook.methods = {};
  118. };
  119. if(module === require.main) require("test").run(exports);