Переглянути джерело

test: add performance tests

Estevao Soares dos Santos 8 роки тому
батько
коміт
43ff0b643e

+ 8 - 0
Gruntfile.js

@@ -188,8 +188,16 @@ module.exports = function (grunt) {
     grunt.task.run(['lint', 'concat:test', 'simplemocha:single', 'clean']);
   });
 
+  grunt.registerTask('performancejs', function () {
+    'use strict';
+    var perf = require('./test/node/performance.js');
+    perf.runTests();
+    perf.generateLogs();
+  });
+
   grunt.registerTask('lint', ['jshint', 'jscs']);
   grunt.registerTask('test', ['clean', 'lint', 'concat:test', 'simplemocha:node', 'clean']);
+  grunt.registerTask('performance', ['concat:test', 'performancejs', 'clean']);
   grunt.registerTask('build', ['test', 'concat:dist', 'uglify', 'endline']);
   grunt.registerTask('prep-release', ['build', 'conventionalChangelog']);
 

+ 15 - 2
dist/showdown.js

@@ -1,4 +1,4 @@
-;/*! showdown 21-12-2016 */
+;/*! showdown 23-12-2016 */
 (function(){
 /**
  * Created by Tivie on 13-07-2015.
@@ -110,6 +110,18 @@ function getDefaultOpts(simple) {
   }
   return ret;
 }
+
+function allOptionsOn() {
+  'use strict';
+  var options = getDefaultOpts(true),
+      ret = {};
+  for (var opt in options) {
+    if (options.hasOwnProperty(opt)) {
+      ret[opt] = true;
+    }
+  }
+  return ret;
+}
 
 /**
  * Created by Tivie on 06-01-2015.
@@ -136,7 +148,8 @@ var showdown = {},
         simpleLineBreaks:                     true,
         requireSpaceBeforeHeadingText:        true
       },
-      vanilla: getDefaultOpts(true)
+      vanilla: getDefaultOpts(true),
+      allOn: allOptionsOn()
     };
 
 /**

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/showdown.js.map


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/showdown.min.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/showdown.min.js.map


+ 2 - 0
package.json

@@ -52,8 +52,10 @@
     "grunt-simple-mocha": "^0.4.0",
     "js-beautify": "^1.5.6",
     "load-grunt-tasks": "^3.2.0",
+    "performance-now": "^0.2.0",
     "quiet-grunt": "^0.2.3",
     "semver": "^5.0.0",
+    "semver-sort": "0.0.4",
     "sinon": "^1.14.1",
     "source-map-support": "^0.2.9"
   },

+ 1 - 0
performance.json

@@ -0,0 +1 @@
+{"1.5.4":[{"suiteName":"Basic","cycles":100,"tests":[{"name":"Simple \"Hello World\"","time":0.30990324000000025,"maxTime":5.549075,"minTime":0.14916800000000308},{"name":"readme.md","time":8.072704459999997,"maxTime":17.975579000000003,"minTime":7.220064999999977}]}]}

+ 10 - 0
performance.log.md

@@ -0,0 +1,10 @@
+# Performance Tests for showdown
+
+
+## [version 1.5.4](https://github.com/showdownjs/showdown/tree/)
+
+### Test Suite: Basic (100 cycles)
+ - **Simple "Hello World":** took 0.310ms (*max: 5.549ms; min: 0.149ms*)
+ - **readme.md:** took 8.073ms (*max: 17.976ms; min: 7.220ms*)
+
+

+ 12 - 0
src/options.js

@@ -108,3 +108,15 @@ function getDefaultOpts(simple) {
   }
   return ret;
 }
+
+function allOptionsOn() {
+  'use strict';
+  var options = getDefaultOpts(true),
+      ret = {};
+  for (var opt in options) {
+    if (options.hasOwnProperty(opt)) {
+      ret[opt] = true;
+    }
+  }
+  return ret;
+}

+ 2 - 1
src/showdown.js

@@ -23,7 +23,8 @@ var showdown = {},
         simpleLineBreaks:                     true,
         requireSpaceBeforeHeadingText:        true
       },
-      vanilla: getDefaultOpts(true)
+      vanilla: getDefaultOpts(true),
+      allOn: allOptionsOn()
     };
 
 /**

+ 38 - 0
test/node/performance.js

@@ -0,0 +1,38 @@
+/**
+ * Created by Tivie on 21/12/2016.
+ */
+'use strict';
+var fs = require('fs'),
+    showdown = require('../bootstrap').showdown,
+    converter = new showdown.Converter(),
+    pkg = require('../../package.json'),
+    performance = require('../performance/performance.js');
+
+performance.setLibraryName(pkg.name);
+performance.setVersion(pkg.version);
+performance.setGithubLink('https://github.com/showdownjs/showdown/tree/');
+
+var
+  runTests = function () {
+    new performance.Suite('Basic')
+      .setOption('cycles', 100)
+      .add('Simple "Hello World"', function () {
+        converter.makeHtml('*Hello* **World**!');
+      })
+      .add('readme.md', {
+        prepare: function () {
+          return fs.readFileSync('README.md', 'utf8');
+        },
+        test: function (mdText) {
+          converter.makeHtml(mdText);
+        }
+      });
+  },
+  generateLogs = function () {
+    performance.generateLog();
+  };
+
+module.exports = {
+  runTests: runTests,
+  generateLogs: generateLogs
+};

+ 227 - 0
test/performance/performance.js

@@ -0,0 +1,227 @@
+/**
+ * Created by Tivie on 21/12/2016.
+ */
+'use strict';
+var now = require('performance-now'),
+    fs = require('fs'),
+    semverSort = require('semver-sort'),
+    performance = {
+      version: '',
+      libraryName: '',
+      MDFile: 'performance.log.md',
+      logFile: 'performance.json',
+      testSuites: [],
+      silent: false,
+      githubLink: ''
+    };
+
+performance.setVersion = function (version) {
+  performance.version = version;
+};
+
+performance.setLibraryName = function (name) {
+  performance.libraryName = name;
+};
+
+performance.setGithubLink = function (url) {
+  performance.githubLink = url;
+};
+
+performance.generateLog = function (filename, MDFilename) {
+  filename = filename || performance.logFile;
+  MDFilename = MDFilename || performance.MDFile;
+
+  fs.closeSync(fs.openSync(filename, 'a'));
+
+  var json = fs.readFileSync(filename),
+      jsonParsed;
+
+  try {
+    jsonParsed = JSON.parse(json);
+  }
+  catch (err) {
+    jsonParsed = {};
+  }
+
+  var jData = [];
+
+  for (var i = 0; i < performance.testSuites.length; ++i) {
+    // Suite
+    var suiteName = performance.testSuites[i].getSuiteName(),
+        cycles = performance.testSuites[i].getOption('cycles'),
+        subJData = {
+          suiteName: suiteName,
+          cycles: cycles,
+          tests: []
+        },
+        testSuite = performance.testSuites[i].getTests();
+    //make sure tests have ran first
+    if (!performance.testSuites[i].hasRun()) {
+      performance.testSuites[i].run();
+    }
+
+    // loop through tests
+    for (var ii = 0; ii < testSuite.length; ++ii) {
+      // Test
+      var test = testSuite[ii];
+      subJData.tests.push({
+        name: test.name,
+        time: test.time,
+        maxTime: test.maxTime,
+        minTime: test.minTime
+      });
+    }
+    jData.push(subJData);
+  }
+  jsonParsed[performance.version] = jData;
+
+  //Sort jsonParsed
+  var versions = [];
+  for (var version in jsonParsed) {
+    if (jsonParsed.hasOwnProperty(version)) {
+      versions.push(version);
+    }
+  }
+
+  semverSort.desc(versions);
+
+  var finalJsonObj = {};
+
+  for (i = 0; i < versions.length; ++i) {
+    if (jsonParsed.hasOwnProperty(versions[i])) {
+      finalJsonObj[versions[i]] = jsonParsed[versions[i]];
+    }
+  }
+
+  fs.writeFileSync(filename, JSON.stringify(finalJsonObj));
+
+  generateMD(MDFilename, finalJsonObj);
+};
+
+function generateMD(filename, obj) {
+  fs.closeSync(fs.openSync(filename, 'w'));
+
+  // generate MD
+  var otp = '# Performance Tests for ' + performance.libraryName + '\n\n\n';
+
+  for (var version in obj) {
+    if (obj.hasOwnProperty(version)) {
+      otp += '## [version ' + version + '](' + performance.githubLink + ')\n\n';
+      var testSuite = obj[version];
+      for (var i = 0; i < testSuite.length; ++i) {
+        otp += '### Test Suite: ' + testSuite[i].suiteName + ' (' + testSuite[i].cycles + ' cycles)\n';
+        var tests = testSuite[i].tests;
+        for (var ii = 0; ii < tests.length; ++ii) {
+          var time = parseFloat(tests[ii].time).toFixed(3),
+              maxTime = parseFloat(tests[ii].maxTime).toFixed(3),
+              minTime = parseFloat(tests[ii].minTime).toFixed(3);
+          otp += ' - **' + tests[ii].name + ':** took ' + time + 'ms (*max: ' + maxTime + 'ms; min: ' + minTime + 'ms*)\n';
+        }
+        otp += '\n';
+      }
+      otp += '\n';
+    }
+  }
+  fs.writeFileSync(filename, otp);
+}
+
+performance.Suite = function (name) {
+  var suiteName = name || '',
+    tests = [],
+    hasRunFlag = false,
+    options = {
+      cycles: 20
+    };
+
+  this.setOption = function (key, val) {
+    options[key] = val;
+    return this;
+  };
+
+  this.getOption = function (key) {
+    return options[key];
+  };
+
+  this.add = function (name, obj) {
+    if (typeof obj === 'function') {
+      obj = {
+        prepare: function () {},
+        test: obj,
+        teardown: function () {}
+      };
+    }
+
+    if (!obj.hasOwnProperty('test')) {
+      throw 'obj must have a property called test';
+    }
+
+    if (typeof obj.test !== 'function') {
+      throw 'obj test property must be a function';
+    }
+
+    if (!obj.hasOwnProperty('prepare')) {
+      obj.prepare = function () {};
+    }
+
+    if (!obj.hasOwnProperty('teardown')) {
+      obj.teardown = function () {};
+    }
+
+    if (typeof obj.prepare !== 'function') {
+      throw 'obj prepare property must be a function';
+    }
+
+    if (typeof obj.teardown !== 'function') {
+      throw 'obj teardown property must be a function';
+    }
+
+    tests.push({
+      name: name,
+      obj: obj,
+      time: 0,
+      maxTime: 0,
+      minTime: 0
+    });
+    return this;
+  };
+
+  this.run = function run () {
+    var nn = options.cycles;
+    console.log('running tests: ' + nn + ' cycles each.');
+    for (var i = 0; i < tests.length; ++i) {
+      var times = [],
+        passVar = tests[i].obj.prepare();
+      for (var ii = 0; ii < nn; ++ii) {
+        var before = now();
+        tests[i].obj.test(passVar);
+        var after = now();
+        times.push(after - before);
+      }
+      var total = times.reduce(function (a, b) {return a + b;}, 0);
+      tests[i].time = total / options.cycles;
+      tests[i].minTime = Math.min.apply(null, times);
+      tests[i].maxTime = Math.max.apply(null, times);
+      if (!options.silent) {
+        console.log(tests[i].name + ' took an average of ' + tests[i].time + 'ms (min: ' + tests[i].minTime + 'ms; max: ' + tests[i].maxTime + 'ms');
+      }
+    }
+    hasRunFlag = true;
+    return this;
+  };
+
+  this.hasRun = function () {
+    return hasRunFlag;
+  };
+
+  this.getSuiteName = function () {
+    return suiteName;
+  };
+
+  this.getTests = function () {
+    return tests;
+  };
+
+  performance.testSuites.push(this);
+};
+
+module.exports = performance;

Деякі файли не було показано, через те що забагато файлів було змінено