testcjdroute.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. var Fs = require("fs");
  16. var nThen = require("nthen");
  17. var Fs_stat = function (file, callback) {
  18. Fs.stat(file, function (err, ret) {
  19. if (err === 'ENOENT') {
  20. console.log("Magical ENOENT on a file which definitely does exist, good job Linus");
  21. setTimeout(function () {
  22. Fs_stat(file, callback);
  23. }, 1000);
  24. } else {
  25. callback(err, ret);
  26. }
  27. });
  28. };
  29. var getTests = function (file, tests, isSubnode, callback) {
  30. if (/\/(.git|build_.*|node_build|contrib)\//.test(file)) { callback(); return; }
  31. if (isSubnode && /\/dht\//.test(file)) { callback(); return; }
  32. Fs_stat(file, function (err, stat) {
  33. if (err) { throw err; }
  34. if (stat.isDirectory()) {
  35. nThen(function (waitFor) {
  36. Fs.readdir(file, waitFor(function (err, list) {
  37. if (err) { throw err; }
  38. list.forEach(function (subFile) {
  39. getTests(file + '/' + subFile, tests, isSubnode, waitFor());
  40. });
  41. }));
  42. }).nThen(function (waitFor) {
  43. callback();
  44. });
  45. return;
  46. } else if (/_test\.c$/.test(file) && tests.indexOf(file) === -1) {
  47. tests.push(file);
  48. }
  49. callback();
  50. });
  51. };
  52. var rmFuzz = function (builder, cb) {
  53. var inputs = builder.config.buildDir + '/fuzz_inputs';
  54. Fs_stat(inputs, function (err, stat) {
  55. if (err && err.code === 'ENOENT') {
  56. Fs.mkdir(inputs, function (err, ret) {
  57. if (err) { throw err; }
  58. return void cb();
  59. });
  60. return;
  61. } else if (err) {
  62. throw err;
  63. }
  64. if (!stat.isDirectory()) {
  65. throw new Error(inputs + ' found, and it is a file, not a directory');
  66. }
  67. Fs.readdir(inputs, function (err, list) {
  68. if (err) { throw err; }
  69. var nt = nThen;
  70. list.forEach(function (f) {
  71. nt = nt(function (w) {
  72. Fs.unlink(inputs + '/' + f, w(function (err) {
  73. if (err) { throw err; }
  74. }));
  75. }).nThen;
  76. });
  77. nt(function (w) { cb(); });
  78. });
  79. });
  80. };
  81. var mkFuzzCase = function (inFile, outPath, testId, cb) {
  82. Fs.readFile(inFile, 'utf8', function (err, ret) {
  83. if (err) { throw err; }
  84. ret = ret.replace(/#[^\n]*\n/g, '');
  85. ret = ret.replace(/[\s]*/g, '');
  86. var out = new Buffer(ret, 'hex');
  87. var id = new Buffer(4);
  88. id.writeInt32BE(testId, 0);
  89. Fs.writeFile(outPath, Buffer.concat([id, out]), function (err) {
  90. if (err) { throw err; }
  91. cb();
  92. });
  93. });
  94. };
  95. var mkFuzz = function (builder, testPath, testId, fuzzCases, cb) {
  96. var inputs = builder.config.buildDir + '/fuzz_inputs';
  97. nThen(function (w) {
  98. var casesPath = testPath.replace(/\.c$/, '_cases');
  99. Fs.readdir(casesPath, w(function (err, list) {
  100. if (err && err.code === 'ENOENT') {
  101. return void console.log("Fuzz test [" + testPath + "] has no test cases");
  102. }
  103. if (err) { throw err; }
  104. var nt = nThen;
  105. list.forEach(function (f) {
  106. nt = nt(function (w) {
  107. var fNoExt = f.replace(/\..*$/, '');
  108. var outPath = inputs + '/' + (testPath + fNoExt).replace(/[^a-zA-Z0-9_-]/g, '_');
  109. fuzzCases.push('"' + outPath + '",');
  110. var inFile = casesPath + '/' + f;
  111. mkFuzzCase(inFile, outPath, testId, w());
  112. }).nThen;
  113. });
  114. nt(w());
  115. }));
  116. }).nThen(function (w) {
  117. cb();
  118. });
  119. };
  120. var generate = module.exports.generate = function (file, builder, isSubnode, callback)
  121. {
  122. var tests = [];
  123. var fuzzCases = [];
  124. var prototypes = [];
  125. var listContent = [];
  126. var fuzzTests = [];
  127. nThen(function (w) {
  128. getTests('.', tests, isSubnode, w());
  129. rmFuzz(builder, w());
  130. }).nThen(function (w) {
  131. tests.forEach(function (test) {
  132. //console.log(test);
  133. var testProto = /^.*\/([^\/]+)\.c$/.exec(test)[1];
  134. file.links.push(test);
  135. var cflags = (builder.config['cflags'+test] = builder.config['cflags'+test] || []);
  136. if (test.indexOf('_fuzz_test') > -1) {
  137. cflags.push(
  138. '-D', 'CJDNS_FUZZ_INIT='+testProto+'_FUZZ_INIT',
  139. '-D', 'CJDNS_FUZZ_MAIN='+testProto+'_FUZZ_MAIN'
  140. );
  141. prototypes.push(
  142. 'void* '+testProto+
  143. '_FUZZ_INIT(struct Allocator*, struct Random*, struct EventBase*);',
  144. 'void '+testProto+'_FUZZ_MAIN(void* ctx, struct Message* fuzz);'
  145. );
  146. mkFuzz(builder, test, fuzzTests.length, fuzzCases, w());
  147. fuzzTests.push('{' +
  148. '.init = '+testProto+'_FUZZ_INIT, ' +
  149. '.name = "'+test.replace(/^.*\/|.c$/g, '')+'", ' +
  150. '.fuzz = '+testProto+'_FUZZ_MAIN, ' +
  151. '},');
  152. } else {
  153. var main = testProto + '_main';
  154. cflags.push(
  155. '-D', 'main='+main,
  156. '-D', main+'(...)='+main+'(int argc, char** argv);int '+main+'(int argc, char** argv)'
  157. );
  158. prototypes.push('int '+main+'(int argc, char** argv);');
  159. listContent.push('{ .func = '+main+', .name = "'+test.replace(/^.*\/|.c$/g, '')+'" },');
  160. }
  161. });
  162. }).nThen(function (w) {
  163. file.testcjdroute_fuzzCases = fuzzCases.join(' ');
  164. file.testcjdroute_tests = listContent.join(' ');
  165. file.testcjdroute_fuzzTests = fuzzTests.join(' ');
  166. file.testcjdroute_prototypes = prototypes.join(' ');
  167. callback();
  168. });
  169. };