[Pkg-javascript-commits] [node-coveralls] 10/332: changed to use lcov input format only.
Bastien Roucariès
rouca at moszumanska.debian.org
Thu Nov 9 13:53:33 UTC 2017
This is an automated email from the git hooks/post-receive script.
rouca pushed a commit to branch master
in repository node-coveralls.
commit 112119e43cb048cfa0dbd98d6e03833b8ca4b619
Author: cainus <gregg at caines.ca>
Date: Wed Mar 27 23:48:04 2013 -0700
changed to use lcov input format only.
---
.travis.yml | 3 +
bin/coveralls.js | 141 +++-----------------------
fixtures/lib/index.js | 224 +++++++++++++++++++++++++++++++++++++++++
fixtures/onefile.lcov | 116 +++++++++++++++++++++
lib/convertLcovToCoveralls.js | 90 +++++++++++++++++
lib/parser.js | 131 ++++++++++++++++++++++++
lib/sendToCoveralls.js | 11 ++
package.json | 6 +-
test/convertLcovToCoveralls.js | 27 +++++
9 files changed, 616 insertions(+), 133 deletions(-)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..debfa19
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - 0.8
diff --git a/bin/coveralls.js b/bin/coveralls.js
index 37ea880..7769a0f 100644
--- a/bin/coveralls.js
+++ b/bin/coveralls.js
@@ -1,149 +1,32 @@
#!/usr/bin/env node
-
-var http = require('http');
-var request = require('request');
-var FormData = require('form-data');
-var TRAVIS_JOB_ID = process.env.TRAVIS_JOB_ID || 'unknown';
+var sendToCoveralls = require('../lib/sendToCoveralls');
+var convertLcovToCoveralls = require('../lib/convertLcovToCoveralls');
process.stdin.resume();
process.stdin.setEncoding('utf8');
-var inJson = '';
+var input = '';
process.stdin.on('data', function(chunk) {
- inJson += chunk;
+ input += chunk;
});
process.stdin.on('end', function() {
- reportToCoveralls(inJson);
+ inputToCoveralls(input);
});
-// cleans off any leading / trailing non-json garbage
-var trimToJson = function(inJson){
- inJson = inJson.replace(/^[^\{]*/, '');
- inJson = inJson.replace(/\}[^\}]*$/, '}');
- return inJson;
-};
-
-var convertCoverageValue = function(val){
- if (val === ""){
- return null;
- }
- if (val > 0){
- return 1;
- }
- return 0;
-};
-
-var convertFileObject = function(file){
- var source = '';
- var coverage = [];
- for (var lineNumber in file.source){
- source += file.source[lineNumber].source + "\n";
- coverage.push(convertCoverageValue(
- file.source[lineNumber].coverage));
- }
- return { name : file.filename,
- source : source,
- coverage : coverage };
-};
-
-var convertJsonCovToCoveralls = function(data){
- var files = data.files;
- var postJson = {
- service_job_id : TRAVIS_JOB_ID,
- service_name : "travis-ci",
- source_files : []
- };
- files.forEach(function(file){
- postJson.source_files.push(convertFileObject(file));
- });
- return postJson;
-};
-
-var sendToCoveralls = function(postJson){
- var str = JSON.stringify(postJson);
- var url = 'https://coveralls.io/api/v1/jobs';
- request({url : url, method : 'POST', form : { json : str}}, function(err, response, body){
+var inputToCoveralls = function(input){
+ console.log(input);
+ var postData = convertLcovToCoveralls(input);
+ sendToCoveralls(postData, function(err, response, body){
if (err){
throw err;
}
+ if (response.statusCode >= 400){
+ throw "Bad response: " + response.statusCode + " " + body;
+ }
console.log(response.statusCode);
console.log(body);
});
-};
-
-var reportToCoveralls = function(inJson){
- inJson = trimToJson(inJson);
- var data = JSON.parse(inJson);
- console.log("successfully read json from json-cov.");
- postJson = convertJsonCovToCoveralls(data);
- console.log(JSON.stringify(postJson));
- console.log("successfully converted input json to coveralls format.");
- sendToCoveralls(postJson);
};
-
-
-/* example coveralls json file
-
-
-{
- "service_job_id": "1234567890",
- "service_name": "travis-ci",
- "source_files": [
- {
- "name": "example.rb",
- "source": "def four\n 4\nend",
- "coverage": [null, 1, null]
- },
- {
- "name": "two.rb",
- "source": "def seven\n eight\n nine\nend",
- "coverage": [null, 1, 0, null]
- }
- ]
-}
-
-
-*/
-
-/* example json-cov file
-
-{
- "filename": "CRUDCollection.js",
- "coverage": 94.20289855072464,
- "hits": 65,
- "misses": 4,
- "sloc": 69,
- "source": {
- "1": {
- "source": "var JSV = require('JSV').JSV;",
- "coverage": 1
- },
- "2": {
- "source": "var _ = require('underscore');",
- "coverage": 1
- },
- "3": {
- "source": "",
- "coverage": ""
- },
- "4": {
- "source": "var CRUDCollection = function(options){",
- "coverage": 1
- },
- "5": {
- "source": "",
- "coverage": ""
- },
- "6": {
- "source": " if (!options || (!options.list && !options.collectionGET)){",
- "coverage": 24
- },
-
-
-
-
-
-*/
diff --git a/fixtures/lib/index.js b/fixtures/lib/index.js
new file mode 100644
index 0000000..4a22c7a
--- /dev/null
+++ b/fixtures/lib/index.js
@@ -0,0 +1,224 @@
+var nodeUrl = require('url');
+var querystring = require('querystring');
+var _ = require('underscore');
+
+var UrlGrey = function(url){
+ this.url = url;
+ this._parsed = null;
+};
+
+UrlGrey.prototype.parsed = function(){
+ if (!this._parsed){
+ this._parsed = nodeUrl.parse(this.url);
+ var p = this._parsed;
+ if (p.protocol){
+ p.protocol = p.protocol.slice(0,-1);
+ } else {
+ p.protocol = 'http';
+ }
+ if (p.hash){
+ p.hash = p.hash.substring(1);
+ }
+ p.username = '';
+ p.password = '';
+ if (!p.hostname){
+ p.hostname = 'localhost';
+ }
+ if (!p.port){
+ p.port = 80;
+ } else {
+ p.port = parseInt(p.port, 10);
+ }
+ if (p.auth){
+ var auth = p.auth.split(':');
+ p.username = auth[0];
+ p.password = auth[1];
+ }
+ }
+ return this._parsed;
+};
+
+UrlGrey.prototype.query = function(mergeObject){
+ var path;
+ if (mergeObject === false){
+ // clear the query entirely if the input === false
+ return this.queryString('');
+ }
+
+ var url = this.url;
+ if (!mergeObject){
+ var parsed = nodeUrl.parse(url);
+ if (!!parsed.search){
+ var qstr = parsed.search.substring(1);
+ return querystring.parse(qstr);
+ }
+ return {};
+ } else {
+ // read the object out
+ var oldQuery = querystring.parse(this.queryString());
+ _.each(mergeObject, function(v, k){
+ if (v === null){
+ delete oldQuery[k];
+ } else {
+ oldQuery[k] = v;
+ }
+ });
+ var newString = querystring.stringify(oldQuery, '&', '=');
+ return this.queryString(newString);
+ }
+};
+
+
+addPropertyGetterSetter('protocol');
+addPropertyGetterSetter('port');
+addPropertyGetterSetter('username');
+addPropertyGetterSetter('password');
+addPropertyGetterSetter('hostname');
+addPropertyGetterSetter('hash');
+// add a method called queryString that manipulates 'query'
+addPropertyGetterSetter('query', 'queryString');
+addPropertyGetterSetter('pathname', 'path');
+
+UrlGrey.prototype.path = function(){
+ var args = _.toArray(arguments);
+ if (args.length !== 0){
+ var obj = new UrlGrey(this.toString());
+ var str = _.flatten(args).join('/');
+ str = str.replace(/\/+/g, '/'); // remove double slashes
+ str = str.replace(/\/$/, ''); // remove all trailing slashes
+ if (str[0] !== '/'){ str = '/' + str; }
+ obj.parsed().pathname = str;
+ return obj;
+ }
+ return this.parsed().pathname;
+};
+
+
+UrlGrey.prototype.encode = function(str){
+ return querystring.escape(str);
+};
+
+UrlGrey.prototype.decode = function(str){
+ return querystring.unescape(str);
+};
+
+UrlGrey.prototype.parent = function(){
+ // read-only. (can't SET parent)
+ var pieces = this.path().split("/");
+ var popped = pieces.pop();
+ if (popped === ''){ // ignore trailing slash
+ pieces.pop();
+ }
+ return this.path(pieces.join("/"));
+};
+
+UrlGrey.prototype.child = function(suffix){
+ if (suffix){
+ suffix = encodeURIComponent(suffix);
+ return this.path(this.path(), suffix);
+ } else {
+ // if no suffix, return the child
+ var pieces = this.path().split("/");
+ var last = _.last(pieces);
+ if ((pieces.length > 1) && (last === '')){
+ // ignore trailing slashes
+ pieces.pop();
+ last = _.last(pieces);
+ }
+ return last;
+ }
+};
+
+UrlGrey.prototype.toJSON = function(){
+ return this.toString();
+};
+
+UrlGrey.prototype.toString = function(){
+ var p = this.parsed();
+ var userinfo = p.username + ':' + p.password;
+ var retval = this.protocol() + '://';
+ if (userinfo != ':'){
+ retval += userinfo + '@';
+ }
+ retval += p.hostname;
+ if (this.port() !== 80){
+ retval += ':' + this.port();
+ }
+ retval += this.path() === '/' ? '' : this.path();
+ var qs = this.queryString();
+ if (qs){
+ retval += '?' + qs;
+ }
+ if (p.hash){
+ retval += '#' + p.hash;
+ }
+ return retval;
+};
+
+/*
+UrlGrey.prototype.absolute = function(path){
+ if (path[0] == '/'){
+ path = path.substring(1);
+ }
+ var parsed = nodeUrl.parse(path);
+ if (!!parsed.protocol){ // if it's already absolute, just return it
+ return path;
+ }
+ return this._protocol + "://" + this._host + '/' + path;
+};
+
+// TODO make this interpolate vars into the url. both sinatra style and url-tempates
+// TODO name this:
+UrlGrey.prototype.get = function(nameOrPath, varDict){
+ if (!!nameOrPath){
+ if (!!varDict){
+ return this.absolute(this._router.getUrl(nameOrPath, varDict));
+ }
+ return this.absolute(this._router.getUrl(nameOrPath));
+ }
+ return this.url;
+};*/
+
+/*
+// TODO needs to take a template as an input
+UrlGrey.prototype.param = function(key, defaultValue){
+ var value = this.params()[key];
+ if (!!value) {
+ return value;
+ }
+ return defaultValue;
+};
+
+// TODO extract params, given a template?
+// TODO needs to take a template as an input
+UrlGrey.prototype.params = function(inUrl){
+ if (!!inUrl){
+ return this._router.pathVariables(inUrl);
+ }
+ if (!!this._params){
+ return this._params;
+ }
+ return this._router.pathVariables(this.url);
+};
+*/
+
+// TODO relative() // takes an absolutepath and returns a relative one
+// TODO absolute() // takes a relative path and returns an absolute one.
+
+
+
+module.exports = function(url){ return new UrlGrey(url); };
+
+function addPropertyGetterSetter(propertyName, methodName){
+ if (!methodName){
+ methodName = propertyName;
+ }
+ UrlGrey.prototype[methodName] = function(str){
+ if (!!str || str === ''){
+ var obj = new UrlGrey(this.toString());
+ obj.parsed()[propertyName] = str;
+ return obj;
+ }
+ return this.parsed()[propertyName];
+ };
+}
diff --git a/fixtures/onefile.lcov b/fixtures/onefile.lcov
new file mode 100644
index 0000000..bc24682
--- /dev/null
+++ b/fixtures/onefile.lcov
@@ -0,0 +1,116 @@
+make[1]: Entering directory `/home/cainus/urlgrey'
+SF:index.js
+DA:1,1
+DA:2,1
+DA:3,1
+DA:5,1
+DA:6,66
+DA:7,66
+DA:10,1
+DA:11,323
+DA:12,63
+DA:13,63
+DA:14,63
+DA:15,60
+DA:17,3
+DA:19,63
+DA:20,32
+DA:22,63
+DA:23,63
+DA:24,63
+DA:25,3
+DA:27,63
+DA:28,60
+DA:30,3
+DA:32,63
+DA:33,27
+DA:34,27
+DA:35,27
+DA:38,323
+DA:41,1
+DA:42,5
+DA:43,5
+DA:45,2
+DA:48,3
+DA:49,3
+DA:50,1
+DA:51,1
+DA:52,1
+DA:53,1
+DA:55,0
+DA:58,2
+DA:59,2
+DA:60,2
+DA:61,0
+DA:63,2
+DA:66,2
+DA:67,2
+DA:72,1
+DA:73,1
+DA:74,1
+DA:75,1
+DA:76,1
+DA:77,1
+DA:79,1
+DA:80,1
+DA:82,1
+DA:83,87
+DA:84,87
+DA:85,6
+DA:86,6
+DA:87,6
+DA:88,6
+DA:89,9
+DA:90,6
+DA:91,6
+DA:93,81
+DA:97,1
+DA:98,1
+DA:101,1
+DA:102,1
+DA:105,1
+DA:107,2
+DA:108,2
+DA:109,2
+DA:110,1
+DA:112,2
+DA:115,1
+DA:116,3
+DA:117,1
+DA:118,1
+DA:121,2
+DA:122,2
+DA:123,2
+DA:125,1
+DA:126,1
+DA:128,2
+DA:132,1
+DA:133,1
+DA:136,1
+DA:137,50
+DA:138,50
+DA:139,50
+DA:140,50
+DA:141,20
+DA:143,50
+DA:144,50
+DA:145,2
+DA:147,50
+DA:148,50
+DA:149,50
+DA:150,31
+DA:152,50
+DA:153,24
+DA:155,50
+DA:210,40
+DA:212,1
+DA:213,8
+DA:214,6
+DA:216,8
+DA:217,186
+DA:218,21
+DA:219,21
+DA:220,21
+DA:222,165
+end_of_record
+make[1]: Leaving directory `/home/cainus/urlgrey'
diff --git a/lib/convertLcovToCoveralls.js b/lib/convertLcovToCoveralls.js
new file mode 100644
index 0000000..cd3ee6d
--- /dev/null
+++ b/lib/convertLcovToCoveralls.js
@@ -0,0 +1,90 @@
+var TRAVIS_JOB_ID = process.env.TRAVIS_JOB_ID || 'unknown';
+var fs = require('fs');
+var lcovParse = require('./parser');
+
+var detailsToCoverage = function(length, details){
+ var coverage = new Array(length);
+ details.forEach(function(obj){
+ coverage[obj.line] = obj.hit;
+ });
+ return coverage;
+};
+
+var convertLcovFileObject = function(file, filepath){
+ var path = filepath + "/" + file.file;
+ var source = fs.readFileSync(path, 'utf8');
+ var lines = source.split("\n");
+ var coverage = detailsToCoverage(lines.length, file.lines.details);
+ return { name : file.file,
+ source : source,
+ coverage : coverage };
+};
+
+var convertLcovToCoveralls = function(input, filepath){
+ filepath = filepath || 'lib';
+ if (filepath[0] !== '/'){
+ filepath = process.cwd() + '/' + filepath;
+ }
+ var parsed = lcovParse(input);
+ var postJson = {
+ service_job_id : TRAVIS_JOB_ID,
+ service_name : "travis-ci",
+ source_files : []
+ };
+ parsed.forEach(function(file){
+ postJson.source_files.push(convertLcovFileObject(file, filepath));
+ });
+ return postJson;
+};
+
+module.exports = convertLcovToCoveralls;
+
+/* example coveralls json file
+
+
+{
+ "service_job_id": "1234567890",
+ "service_name": "travis-ci",
+ "source_files": [
+ {
+ "name": "example.rb",
+ "source": "def four\n 4\nend",
+ "coverage": [null, 1, null]
+ },
+ {
+ "name": "two.rb",
+ "source": "def seven\n eight\n nine\nend",
+ "coverage": [null, 1, 0, null]
+ }
+ ]
+}
+
+
+example output from lcov parser:
+
+ [
+ {
+ "file": "index.js",
+ "lines": {
+ "found": 0,
+ "hit": 0,
+ "details": [
+ {
+ "line": 1,
+ "hit": 1
+ },
+ {
+ "line": 2,
+ "hit": 1
+ },
+ {
+ "line": 3,
+ "hit": 1
+ },
+ {
+ "line": 5,
+ "hit": 1
+ },
+
+*/
+
diff --git a/lib/parser.js b/lib/parser.js
new file mode 100644
index 0000000..83b2c3d
--- /dev/null
+++ b/lib/parser.js
@@ -0,0 +1,131 @@
+/*
+Software License Agreement (BSD License)
+
+Copyright (c) 2012, Dav Glass <davglass at gmail.com>.
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* The name of Dav Glass may not be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Dav Glass.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+var lcovParse = function(str) {
+ var data = [], item = {};
+
+ str = str.split('\n');
+ str.forEach(function(line) {
+ line = line.trim();
+
+ var parts = line.split(':'), lines, fn;
+
+ switch (parts[0].toUpperCase()) {
+ case 'TN':
+ item.title = parts[1].trim();
+ break;
+ case 'SF':
+ item.file = parts[1].trim();
+ break;
+ case 'FNF':
+ item.functions.found = Number(parts[1].trim());
+ break;
+ case 'FNH':
+ item.functions.hit = Number(parts[1].trim());
+ break;
+ case 'LF':
+ item.lines.found = Number(parts[1].trim());
+ break;
+ case 'LH':
+ item.lines.hit = Number(parts[1].trim());
+ break;
+ case 'DA':
+ if (!item.lines) {
+ item.lines = {
+ found: 0,
+ hit: 0,
+ details: []
+ };
+ }
+ lines = parts[1].split(',');
+ item.lines.details.push({
+ line: Number(lines[0]),
+ hit: Number(lines[1])
+ });
+ break;
+ case 'FN':
+ if (!item.functions) {
+ item.functions = {
+ hit: 0,
+ found: 0,
+ details: []
+ };
+ }
+ fn = parts[1].split(',');
+ item.functions.details.push({
+ name: fn[1],
+ line: Number(fn[0])
+ });
+ break;
+ case 'FNDA':
+ fn = parts[1].split(',');
+ item.functions.details.some(function(i, k) {
+ if (i.name === fn[1] && i.hit === undefined) {
+ item.functions.details[k].hit = Number(fn[0]);
+ return true;
+ }
+ });
+ break;
+ case 'BRDA':
+ if (!item.branches) {
+ item.branches = {
+ hit: 0,
+ found: 0,
+ details: []
+ };
+ }
+ fn = parts[1].split(',');
+ item.branches.details.push({
+ line: Number(fn[0]),
+ block: Number(fn[1]),
+ branch: Number(fn[2]),
+ taken: ((fn[3] === '-') ? 0 : Number(fn[3]))
+ });
+ break;
+ case 'BRF':
+ item.branches.found = Number(parts[1]);
+ break;
+ case 'BRH':
+ item.branches.hit = Number(parts[1]);
+ break;
+ }
+
+ if (line.indexOf('end_of_record') > -1) {
+ data.push(item);
+ item = {};
+ }
+ });
+ return data;
+};
+
+module.exports = lcovParse;
diff --git a/lib/sendToCoveralls.js b/lib/sendToCoveralls.js
new file mode 100644
index 0000000..b3514c6
--- /dev/null
+++ b/lib/sendToCoveralls.js
@@ -0,0 +1,11 @@
+var request = require('request');
+
+var sendToCoveralls = function(obj, cb){
+ var str = JSON.stringify(obj);
+ var url = 'https://coveralls.io/api/v1/jobs';
+ request({url : url, method : 'POST', form : { json : str}}, function(err, response, body){
+ cb(err, response, body);
+ });
+};
+
+module.exports = sendToCoveralls;
diff --git a/package.json b/package.json
index 0fc55d9..cb37c26 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "coveralls",
"description" : "takes json-cov output into stdin and POSTs to coveralls.io",
"keywords" : ["coverage", "coveralls"],
- "version": "1.1.3",
+ "version": "2.0.0",
"bugs": {
"url": "https://github.com/cainus/node-coveralls/issues"
},
@@ -20,9 +20,7 @@
}
],
"dependencies": {
- "underscore" : "1.3.3",
- "request" : "2.16.2",
- "form-data" : "0.0.7"
+ "request" : "2.16.2"
},
"devDependencies" : {
"mocha" : "1.8.1",
diff --git a/test/convertLcovToCoveralls.js b/test/convertLcovToCoveralls.js
new file mode 100644
index 0000000..df8c5cf
--- /dev/null
+++ b/test/convertLcovToCoveralls.js
@@ -0,0 +1,27 @@
+var convertLcovToCoveralls = require('../lib/convertLcovToCoveralls');
+var should = require('should');
+var fs = require('fs');
+
+describe("convertLcovToCoveralls", function(){
+ it ("should convert a simple lcov file", function(){
+ process.env.TRAVIS_JOB_ID = -1;
+ var path = __dirname + "/../fixtures/onefile.lcov";
+ var input = fs.readFileSync(path, "utf8");
+ var libpath = __dirname + "/../fixtures/lib";
+ var output = convertLcovToCoveralls(input, libpath);
+ output.source_files[0].name.should.equal("index.js");
+ output.source_files[0].source.split("\n").length.should.equal(225);
+ output.source_files[0].coverage[55].should.equal(0);
+ output.source_files[0].coverage[61].should.equal(0);
+ });
+
+ it ("should work with a relative path as well", function(){
+ process.env.TRAVIS_JOB_ID = -1;
+ var path = __dirname + "/../fixtures/onefile.lcov";
+ var input = fs.readFileSync(path, "utf8");
+ var libpath = "fixtures/lib";
+ var output = convertLcovToCoveralls(input, libpath);
+ output.source_files[0].name.should.equal("index.js");
+ output.source_files[0].source.split("\n").length.should.equal(225);
+ });
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-coveralls.git
More information about the Pkg-javascript-commits
mailing list