New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@tact-lang/coverage

Package Overview
Dependencies
Maintainers
3
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tact-lang/coverage - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

dist/integration/integrate.spec.d.ts

3

dist/collector/coverage.d.ts
/// <reference types="node" />
import { Maybe } from "../utils/maybe";
import { LogEntry } from "./parseVMLogs";

@@ -18,4 +19,4 @@ type CollectedCell = {

logs: LogEntry[];
gasLimit: bigint;
gasLimit?: Maybe<bigint>;
}): void;
export {};

@@ -52,5 +52,25 @@ "use strict";

function collectCoverage(args) {
// Determine gas limit
let gasLimit = 1000000000n;
if (typeof args.gasLimit === 'bigint') {
gasLimit = args.gasLimit;
}
else {
// Try to determine gas limit from logs, ignoring the first opcode that usually
// is the SETCP 0 and means nothing
if (args.logs.length > 4) {
if (args.logs[0].kind === 'stack'
&& args.logs[1].kind === 'cell'
&& args.logs[2].kind === 'execute'
&& args.logs[3].kind === 'gas') {
if (args.logs[2].command === 'SETCP 0') {
gasLimit = args.logs[3].remaining;
}
}
}
}
// Collect coverage
let collector = args.collector;
let logs = args.logs;
let gasRemaining = args.gasLimit;
let gasRemaining = gasLimit;
let offset = 0;

@@ -67,6 +87,4 @@ while (offset < logs.length) {

if (cell.kind === 'execute' && cell.command.startsWith('implicit ')) {
while (offset < logs.length) {
if (logs[offset].kind === 'gas') {
break;
}
// Skip non-gas
while (logs[offset].kind !== 'gas') {
offset++;

@@ -90,7 +108,16 @@ }

}
// Load gas
// Collect all intermediate messages
let messages = [];
while (logs[offset].kind !== 'gas') {
messages.push(logs[offset++]);
}
// Check for gas limit change
let gasLimitChange = messages.find((v) => v.kind === 'gas-limit-change');
if (gasLimitChange) {
let delta = gasLimitChange.limit - gasLimit;
gasLimit = gasLimitChange.limit;
gasRemaining += delta;
}
// Look for end of execution
let gas = logs[offset++];
if (gas.kind === 'output_action') { // Skip output action
gas = logs[offset++];
}
if (gas.kind !== 'gas') {

@@ -97,0 +124,0 @@ throw new Error('Expected gas entry, got: ' + cell.kind + " at " + offset);

@@ -37,5 +37,25 @@ "use strict";

});
it('should collect coverage', () => {
it('should parse logs with empty lines', () => {
let logs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log2.txt'), 'utf8');
(0, parseVMLogs_1.parseVMLogs)(logs);
});
// it('should collect coverage', () => {
// // Collect coverage
// let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.txt'), 'utf8');
// let logs = parseVMLogs(rawLogs);
// let collector = new CoverageCollector();
// collectCoverage({
// collector,
// logs,
// gasLimit: 1000000000n
// });
// expect(collector.export()).toMatchSnapshot();
// // Print coverage
// let rawCode = Cell.fromBoc(fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.boc')))[0];
// let res = printCoverage(rawCode, collector);
// fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log1.html'), res);
// });
it('should collect coverage 2', () => {
// Collect coverage
let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.txt'), 'utf8');
let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log2.txt'), 'utf8');
let logs = (0, parseVMLogs_1.parseVMLogs)(rawLogs);

@@ -45,11 +65,10 @@ let collector = new coverage_1.CoverageCollector();

collector,
logs,
gasLimit: 1000000000n
logs
});
expect(collector.export()).toMatchSnapshot();
// Print coverage
let rawCode = ton_core_1.Cell.fromBoc(fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.boc')))[0];
let rawCode = ton_core_1.Cell.fromBase64('te6ccgEBCAEAlwABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC48oMI1xgg0x/TH9MfAvgju/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhYhgBD0eG+lIJgC0wfUMAH7AJEy4gGz5lsBpMjLH8sfy//J7VQABNAwAgFIBgcAF7s5ztRNDTPzHXC/+AARuMl+1E0NcLH4');
let res = (0, printCoverage_1.printCoverage)(rawCode, collector);
fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log1.html'), res);
fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log2.html'), res);
});
});

@@ -15,4 +15,8 @@ export type LogEntry = {

} | {
kind: 'output_action';
kind: 'gas-limit-change';
limit: bigint;
} | {
kind: 'info';
message: string;
};
export declare function parseVMLogs(logs: string): LogEntry[];

@@ -5,3 +5,3 @@ "use strict";

function parseVMLogs(logs) {
let lines = logs.split('\n');
let lines = logs.split('\n').map((v) => v.trim()).filter((v) => v.length > 0);
let res = [];

@@ -28,7 +28,8 @@ for (let l of lines) {

}
else if (l.startsWith('installing an output action')) {
res.push({ kind: 'output_action' });
else if (l.startsWith('changing gas limit to ')) {
let limit = BigInt(l.substring('changing gas limit to '.length));
res.push({ kind: 'gas-limit-change', limit });
}
else {
throw new Error('Unknown log line: ' + l);
res.push({ kind: 'info', message: l });
}

@@ -35,0 +36,0 @@ }

@@ -57,3 +57,5 @@ "use strict";

let line = span('.'.repeat(indent * 2), 'padding') + span(src.op, 'opcode');
let cov = collector.coverageForCell(src.hash);
// console.log(src.hash.toLowerCase());
// console.log(src);
let cov = collector.coverageForCell(src.hash.toLowerCase());
let lineClass;

@@ -60,0 +62,0 @@ if (cov && cov.offsets.has(src.offset)) {

@@ -52,4 +52,3 @@ "use strict";

logs: parsed,
collector,
gasLimit: 1000000000n
collector
});

@@ -56,0 +55,0 @@ }

{
"name": "@tact-lang/coverage",
"version": "0.0.1",
"version": "0.0.2",
"main": "dist/index.js",

@@ -18,3 +18,3 @@ "repository": "https://github.com/tact-lang/ton-coverage.git",

"dependencies": {
"@tact-lang/opcode": "^0.0.5",
"@tact-lang/opcode": "^0.0.9",
"prando": "^6.0.1",

@@ -26,2 +26,3 @@ "teslabot": "^1.5.0",

"@release-it/keep-a-changelog": "^3.1.0",
"@tact-lang/emulator": "^3.4.1",
"@types/jest": "^29.2.5",

@@ -28,0 +29,0 @@ "@types/node": "^18.11.18",

@@ -13,6 +13,29 @@ import * as fs from 'fs';

});
it('should collect coverage', () => {
it('should parse logs with empty lines', () => {
let logs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log2.txt'), 'utf8');
parseVMLogs(logs);
});
// it('should collect coverage', () => {
// // Collect coverage
// let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.txt'), 'utf8');
// let logs = parseVMLogs(rawLogs);
// let collector = new CoverageCollector();
// collectCoverage({
// collector,
// logs,
// gasLimit: 1000000000n
// });
// expect(collector.export()).toMatchSnapshot();
// // Print coverage
// let rawCode = Cell.fromBoc(fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.boc')))[0];
// let res = printCoverage(rawCode, collector);
// fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log1.html'), res);
// });
it('should collect coverage 2', () => {
// Collect coverage
let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.txt'), 'utf8');
let rawLogs = fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log2.txt'), 'utf8');
let logs = parseVMLogs(rawLogs);

@@ -22,4 +45,3 @@ let collector = new CoverageCollector();

collector,
logs,
gasLimit: 1000000000n
logs
});

@@ -29,6 +51,6 @@ expect(collector.export()).toMatchSnapshot();

// Print coverage
let rawCode = Cell.fromBoc(fs.readFileSync(path.resolve(__dirname, '__testdata__', 'log1.boc')))[0];
let rawCode = Cell.fromBase64('te6ccgEBCAEAlwABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC48oMI1xgg0x/TH9MfAvgju/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhYhgBD0eG+lIJgC0wfUMAH7AJEy4gGz5lsBpMjLH8sfy//J7VQABNAwAgFIBgcAF7s5ztRNDTPzHXC/+AARuMl+1E0NcLH4');
let res = printCoverage(rawCode, collector);
fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log1.html'), res);
fs.writeFileSync(path.resolve(__dirname, '__testdata__', 'log2.html'), res);
});
});

@@ -0,1 +1,2 @@

import { Maybe } from "../utils/maybe";
import { LogEntry } from "./parseVMLogs";

@@ -51,7 +52,28 @@

logs: LogEntry[],
gasLimit: bigint
gasLimit?: Maybe<bigint>
}) {
// Determine gas limit
let gasLimit = 1000000000n;
if (typeof args.gasLimit === 'bigint') {
gasLimit = args.gasLimit;
} else {
// Try to determine gas limit from logs, ignoring the first opcode that usually
// is the SETCP 0 and means nothing
if (args.logs.length > 4) {
if (args.logs[0].kind === 'stack'
&& args.logs[1].kind === 'cell'
&& args.logs[2].kind === 'execute'
&& args.logs[3].kind === 'gas') {
if (args.logs[2].command === 'SETCP 0') {
gasLimit = args.logs[3].remaining;
}
}
}
}
// Collect coverage
let collector = args.collector;
let logs = args.logs;
let gasRemaining = args.gasLimit;
let gasRemaining = gasLimit;
let offset = 0;

@@ -71,6 +93,4 @@ while (offset < logs.length) {

if (cell.kind === 'execute' && cell.command.startsWith('implicit ')) {
while (offset < logs.length) {
if (logs[offset].kind === 'gas') {
break;
}
// Skip non-gas
while (logs[offset].kind !== 'gas') {
offset++;

@@ -97,7 +117,18 @@ }

// Load gas
// Collect all intermediate messages
let messages: LogEntry[] = [];
while (logs[offset].kind !== 'gas') {
messages.push(logs[offset++]);
}
// Check for gas limit change
let gasLimitChange = messages.find((v) => v.kind === 'gas-limit-change');
if (gasLimitChange) {
let delta = (gasLimitChange as { limit: bigint }).limit - gasLimit;
gasLimit = (gasLimitChange as { limit: bigint }).limit;
gasRemaining += delta;
}
// Look for end of execution
let gas = logs[offset++];
if (gas.kind === 'output_action') { // Skip output action
gas = logs[offset++]
}
if (gas.kind !== 'gas') {

@@ -104,0 +135,0 @@ throw new Error('Expected gas entry, got: ' + cell.kind + " at " + offset);

@@ -15,7 +15,11 @@ export type LogEntry = {

} | {
kind: 'output_action'
kind: 'gas-limit-change',
limit: bigint
} | {
kind: 'info',
message: string
}
export function parseVMLogs(logs: string) {
let lines = logs.split('\n');
let lines = logs.split('\n').map((v) => v.trim()).filter((v) => v.length > 0);
let res: LogEntry[] = [];

@@ -38,6 +42,7 @@ for (let l of lines) {

res.push({ kind: 'stack', stack });
} else if (l.startsWith('installing an output action')) {
res.push({ kind: 'output_action' });
} else if (l.startsWith('changing gas limit to ')) {
let limit = BigInt(l.substring('changing gas limit to '.length));
res.push({ kind: 'gas-limit-change', limit });
} else {
throw new Error('Unknown log line: ' + l);
res.push({ kind: 'info', message: l });
}

@@ -44,0 +49,0 @@ }

@@ -60,3 +60,5 @@ import { decompileAll, Printer } from "@tact-lang/opcode";

let line = span('.'.repeat(indent * 2), 'padding') + span(src.op, 'opcode');
let cov = collector.coverageForCell(src.hash);
// console.log(src.hash.toLowerCase());
// console.log(src);
let cov = collector.coverageForCell(src.hash.toLowerCase());
let lineClass: string;

@@ -63,0 +65,0 @@ if (cov && cov.offsets.has(src.offset)) {

@@ -30,4 +30,3 @@ import { collectCoverage, CoverageCollector } from "../collector/coverage";

logs: parsed,
collector,
gasLimit: 1000000000n
collector
});

@@ -34,0 +33,0 @@ } catch (e) {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc