Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ module.exports = {

[<sup>*</sup> Advanced use][14]

## API

Solidity-coverage's core methods and many utilities are available as an API.

```javascript
const CoverageAPI = require('solidity-coverage/api');
```

[Documentation available here][28].

## FAQ

Common problems & questions:
Expand Down Expand Up @@ -171,3 +181,4 @@ $ yarn
[25]: https://github.com/sc-forks/solidity-coverage/issues/417
[26]: https://buidler.dev/
[27]: https://www.trufflesuite.com/docs
[28]: https://github.com/sc-forks/solidity-coverage/blob/beta/docs/api.md
368 changes: 368 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,368 @@
# Solidity-Coverage API Documentation

`solidity-coverage`'s API provides test coverage measurement for the Solidity language.
The repository contains two complete coverage tool/plugin implementations (for Buidler and Truffle)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a link to plugins....

which can be used as sources if you're building something similar.

`solidity-coverage`'s core algorithm resembles the one used by [Istanbul][3] for javascript programs.
It tracks line and branch locations by 'instrumenting' solidity contracts with special solidity
statements and detecting their execution in a coverage-enabled EVM. As such, its API spans the
full set of tasks typically required to run a solidity test suite.

+ compile
+ ethereum client launch
+ test
+ report outcome and exit

[3]: https://github.com/gotwarlost/istanbul

The API's corresponding methods are:

+ `instrument`: Rewrites contracts for instrumented compilation. Generates an instrumentation data map.
+ `ganache`: Launches a ganache client with coverage collection enabled in its VM. As the client
runs it will mark line/branch hits on the instrumentation data map.
+ `report`: Generates a coverage report from the data collected by the VM after tests complete. Converts
the instrumentation data map into an object IstanbulJS can process.
+ `finish`: Shuts client down

The library also includes some file system [utilities](#Utils) which are helpful for managing the
disposable set of contracts/artifacts which coverage must use in lieu of the 'real' contracts/artifacts.

# Table of Contents

- [API Methods](#api)
* [constructor](#constructor)
* [instrument](#instrument)
* [ganache](#ganache)
* [report](#report)
* [finish](#finish)
* [getInstrumentationData](#getinstrumentationdata)
* [setInstrumentationData](#setinstrumentationdata)
- [Utils Methods](#utils)
* [loadSolcoverJS](#loadsolcoverjs)
* [assembleFiles](#assemblefiles)
* [getTempLocations](#gettemplocations)
* [setupTempFolders](#setuptempfolders)
* [save](#save)
* [finish](#finish-1)

# API

**Example**
```javascript
const CoverageAPI = require("solidity-coverage/api");
const api = new CoverageAPI(options);
```

## constructor

Creates a coverage API instance. Configurable.

**Parameters**

- `options` **Object** : API options

| Option <img width=200/>| Type <img width=200/> | Default <img width=1300/> | Description <img width=800/> |
| ------ | ---- | ------- | ----------- |
| port | *Number* | 8555 | Port to launch client on |
| silent | *Boolean* | false | Suppress logging output |
| client | *Object* | `require("ganache-core")` | JS Ethereum client |
| providerOptions | *Object* | `{ }` | [ganache-core options][1] |
| skipFiles | *Array* | `[]` | Array of contracts or folders (with paths expressed relative to the `contracts` directory) that should be skipped when doing instrumentation. |
| istanbulFolder | *String* | `./coverage` | Folder location for Istanbul coverage reports. |
| istanbulReporter | *Array* | `['html', 'lcov', 'text', 'json']` | [Istanbul coverage reporters][2] |

[1]: https://github.com/trufflesuite/ganache-core#options
[2]: https://istanbul.js.org/docs/advanced/alternative-reporters/

--------------

## instrument

Instruments a set of sources to prepare them for compilation.

:warning: **Important:** Instrumented sources must be compiled with **solc optimization OFF** :warning:

**Parameters**

- `contracts` **Object[]**: Array of solidity sources and their paths

Returns **Object[]** in the same format as the `contracts` param, but with sources instrumented.

**Example**
```javascript
const contracts = [{
source: "contract Simple { uint x = 5; }",
canonicalPath: "/Users/user/project/contracts/Simple.sol",
relativePath: "Simple.sol" // Optional, used for pretty printing.
},...]

const instrumented = api.instrument(contracts)
```

--------------

## ganache

Enables coverage data collection on an in-process ganache server. By default, will return
a url after server has begun listening on the port specified in the [config](#constructor)
(or 8555 by default). When `autoLaunchServer` is false, method returns`ganache.server`
so the consumer can control the 'server.listen' invocation themselves.

**Parameters**

- `client` **Object**: (*Optional*) ganache module
- `autoLaunchServer` **Boolean**: (*Optional*)

Returns **Promise** Address of server to connect to, or initialized, unlaunched server

**Example**
```javascript
const client = require('ganache-cli');

const api = new CoverageAPI( { client: client } );
const address = await api.ganache();

> http://127.0.0.1:8555

// Alternatively...

const server = await api.ganache(client, false);
await pify(server.listen()(8545));
```

--------------

## report

Generates coverage report using IstanbulJS

**Parameters**

- `istanbulFolder` **String**: (*Optional*) path to folder IstanbulJS will deposit coverage reports in.

Returns **Promise**

**Example**
```javascript
await api.report('./coverage_4A3cd2b'); // Default folder name is 'coverage'
```

-------------

## finish

Shuts down coverage-enabled ganache server instance

Returns **Promise**

**Example**
```javascript
const client = require('ganache-cli');

await api.ganache(client); // Server listening...
await api.finish(); // Server shut down.
```

-------------

## getInstrumentationData

Returns a copy of the hit map created during instrumentation. Useful if you'd like to delegate
coverage collection to multiple processes.

Returns **Object** instrumentation data;


**Example**
```javascript
const contracts = api.instrument(contracts);
const data = api.getInstrumentationData();
save(data);
```

-------------

## setInstrumentationData

Sets the hit map object generated during instrumentation. Useful if you'd like
to collect or convert data to coverage for an instrumentation which was generated
in a different process.

**Example**
```javascript
const data = load(data);
api.setIntrumentationData(data);

// Client will collect data for the loaded map
const address = await api.ganache(client);

// Or to `report` instrumentation data which was collected in a different process.
const data = load(data);
api.setInstrumentationData(data);

api.report();
```

----------------------------------------------------------------------------------------------------

# Utils

```javascript
const utils = require('solidity-coverage/utils');
```

Many of the utils methods take a `config` object param which
defines the absolute paths to your project root and contracts directory.

**Example**
```javascript
const config = {
workingDir: process.cwd(),
contractsDir: path.join(process.cwd(), 'contracts'),
}
```
-------------

## loadSolcoverJS

Loads `.solcoverjs`. Users may specify options described in the README in `.solcover.js` config
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a link to README options

file which your application needs to consume.

**Parameters**

- `config` **Object**: [See *config* above](#Utils)

Returns **Object** Normalized coverage config


**Example**
```javascript
const solcoverJS = utils.loadSolcoverJS(config);
const api = new CoverageAPI(solcoverJS);
```

-------------

## assembleFiles

Loads contracts from the filesystem in a format that can be passed directly to the
[api.instrument](#instrument) method. Filters by an optional `skipFiles` parameter.

**Parameters**

- `config` **Object**: [See *config* above](#Utils)
- `skipFiles` **String[]**: (*Optional*) Array of files or folders to skip
[See API *constructor*](#constructor)

Returns **Object** with `targets` and `skipped` keys. These are Object arrays of contract sources
and paths.

**Example**
```javascript
const {
targets,
skipped
} = utils.assembleFiles(config, ['Migrations.sol'])

const instrumented = api.instrument(targets);
```

--------------

## getTempLocations

Returns a pair of canonically named temporary directory paths for contracts
and artifacts. Instrumented assets can be compiled from and written to these so the unit tests can
use them as sources.

**Parameters**

- `config` **Object**: [See *config* above](#Utils)

Returns **Object** with two absolute paths to disposable folders, `tempContractsDir`, `tempArtifactsDir`.
These directories are named `.coverage_contracts` and `.coverage_artifacts`.

**Example**
```javascript
const {
tempContractsDir,
tempArtifactsDir
} = utils.getTempLocations(config)

utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir)

// Later, you can call `utils.finish` to delete these...
utils.finish(config, api)
```

----------

## setupTempFolders

Creates temporary directories to store instrumented contracts and their compilation artifacts in.

**Parameters**

- `config` **Object**: [See *config* above](#Utils)
- `tempContractsDir` **String**: absolute path to temporary contracts directory
- `tempArtifactsDir` **String**: absolute path to temporary artifacts directory

**Example**
```javascript
const {
tempContractsDir,
tempArtifactsDir
} = utils.getTempLocations(config)

utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir);
```
-------------

## save

Writes an array of instrumented sources in the object format returned by
[api.instrument](#instrument) to a temporary directory.

**Parameters**

- `contracts` **Object[]**: array of contracts & paths generated by [api.instrument](#instrument)
- `originalDir` **String**: absolute path to original contracts directory
- `tempDir` **String**: absolute path to temp contracts directory (the destination of the save)

**Example**
```javascript
const {
tempContractsDir,
tempArtifactsDir
} = utils.getTempLocations(config)

utils.setupTempFolders(config, tempContractsDir, tempArtifactsDir);

const instrumented = api.instrument(targets);

utils.save(instrumented, config.contractsDir, tempContractsDir);
```

-------------

## finish

Deletes temporary folders and shuts the ganache server down. Is tolerant - if folders or ganache
server don't exist it will return silently.

**Parameters**

- `config` **Object**: [See *config* above](#Utils)
- `api` **Object**: (*Optional*) coverage api instance whose own `finish` method will be called

Returns **Promise**

**Example**
```javascript
await utils.finish();
```




Loading