Skip to content

Instantly share code, notes, and snippets.

@Raynos
Created January 12, 2017 22:18
Show Gist options
  • Save Raynos/df7e115943abe75aa5a4e01744dd5ec8 to your computer and use it in GitHub Desktop.
Save Raynos/df7e115943abe75aa5a4e01744dd5ec8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var assert = require('assert');
function GocovParser(gocovObj) {
this.input = gocovObj;
this.fileLocCache = Object.create(null);
this.output = Object.create(null);
}
GocovParser.prototype.parse = function parse() {
for (var i = 0; i < this.input.Packages.length; i++) {
var p = this.input.Packages[i];
var name = p.Name;
var functions = p.Functions;
for (var j = 0; j < functions.length; j++) {
this.parseFunction(name, functions[j]);
}
}
};
GocovParser.prototype.parseFunction =
function parseFunction(folderName, functionInfo) {
// console.error('functionInfo', functionInfo);
var filePath = path.join(process.cwd(), functionInfo.File);
var fileObj = this.output[filePath];
if (!fileObj) {
fileObj = this.output[filePath] = new FileCoverageInfo(filePath);
}
var fileLoc = this.fileLocCache[filePath];
if (!fileLoc) {
fileLoc = this.fileLocCache[filePath] = new FileLoc(filePath);
}
var fnName = functionInfo.Name;
var startOffset = functionInfo.Start;
var endOffset = functionInfo.End;
var startLoc = fileLoc.computeFunctionStartLocation(startOffset);
var endLoc = fileLoc.computeFunctionEndLocation(endOffset);
// console.error('functionLoc', {
// start: startLoc,
// end: endLoc
// });
var fnId = fileObj.fnCounter;
fileObj.f[fnId] = 1
fileObj.fnMap[fnId] = {
name: fnName,
line: startLoc.line,
loc: {
start: startLoc,
end: endLoc
},
skip: false
};
fileObj.fnCounter++;
for (var i = 0; i < functionInfo.Statements.length; i++) {
var statement = functionInfo.Statements[i];
var startLoc = fileLoc.computeStatementLocation(statement.Start);
var endLoc = fileLoc.computeStatementLocation(statement.End);
var sId = fileObj.sCounter;
fileObj.s[sId] = statement.Reached;
fileObj.statementMap[sId] = {
start: startLoc,
end: endLoc
};
// console.error('handleStatement', {
// fnName: fnName,
// offsets: [statement.Start,statement.End],
// fileName: filePath,
// start: startLoc,
// end: endLoc
// });
fileObj.sCounter++;
}
};
function FileCoverageInfo(filePath) {
this.path = filePath;
// statement counts, st id -> count
this.s = Object.create(null);
this.sCounter = 1;
// branch counts, br id -> count
this.b = Object.create(null);
// function counts, fn id -> count
this.f = Object.create(null);
this.fnCounter = 1;
// fnMap, fn id -> FnInfo{name, line, loc, skip}
this.fnMap = Object.create(null);
// statementMap, st id -> Loc{start, end}
this.statementMap = Object.create(null);
// branchMap, st id -> BrInfo{line, type, locations}
this.branchMap = Object.create(null);
}
function FileLoc(fileName) {
this.fileName = fileName;
this.fileContent = fs.readFileSync(fileName, 'utf8');
this.lines = this.fileContent.split('\n');
this.lineStarts = [];
var soFar = 0;
for (var i = 0; i < this.lines.length; i++) {
this.lineStarts[i] = soFar;
soFar += this.lines[i].length + 1;
}
}
FileLoc.prototype.computeStatementLocation =
function computeStatementLocation(offset) {
var text = this.fileContent.slice(0, offset);
var lineNo = text.split('\n').length;
var lineStart = this.lineStarts[lineNo - 1];
// console.error('info', lineNo, lineStart, offset - lineStart);
return {
line: lineNo,
column: offset - lineStart
};
}
FileLoc.prototype.computeFunctionStartLocation =
function computeFunctionStartLocation(offset) {
var text = this.fileContent.slice(0, offset);
var lineNo = text.split('\n').length;
assert(lineNo > 0, "lineNo must not be zero...");
return {
line: lineNo,
column: 0
};
};
FileLoc.prototype.computeFunctionEndLocation =
function computeFunctionEndLocation(offset) {
var text = this.fileContent.slice(0, offset);
var lineNo = text.split('\n').length;
assert(lineNo > 0, "lineNo must not be zero...");
return {
line: lineNo,
column: this.lines[lineNo - 1].length
};
};
function main() {
var fileName = process.argv[2] || '';
var isExists = fs.existsSync(fileName);
if (!isExists) {
console.error('./gocov-to-istanbul-coverage.js [gocov.json]')
console.error('Cannot find file $1')
console.error('')
process.exit(1)
return;
}
var text = fs.readFileSync(fileName, 'utf8');
var gocov = JSON.parse(text);
var parser = new GocovParser(gocov);
parser.parse();
console.log(JSON.stringify(parser.output));
}
if (require.main === module) {
main();
}
# Use go test to generate coverage into ./coverage/cover.out
# go test ./... -cover -coverprofile ./coverage/cover.out
.PHONY: view-istanbul
view-istanbul:
@go get github.com/axw/gocov/gocov
@gocov convert ./coverage/cover.out > coverage/gocov.json
@node ./scripts/gocov-to-istanbul-coverage.js ./coverage/gocov.json \
> coverage/istanbul.json
istanbul report --root ./coverage --include "**/istanbul.json" html
@if [ $$(which xdg-open) ]; then \
xdg-open coverage/index.html; \
else \
open coverage/index.html; \
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment