Add API documentation (#447)
parent
3612a815e6
commit
f2cdb63498
@ -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) |
||||||
|
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 |
||||||
|
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…
Reference in new issue