1- /*
2- TruffleConfig Paths
3- ===========================
4- build_directory /users/myPath/to/someProject/build
5- contracts_directory. /users/myPath/to/someProject/contracts
6- working_directory /users/myPath/to/someProject
7- contracts_build_directory /users/myPath/to/someProject/build/contracts
8-
9- Compilation options override
10- ----------------------------
11- build_directory /users/myPath/to/someProject/.coverageArtifacts
12- contracts_directory /users/myPath/to/someProject/.coverageContracts
13-
14- Test options override
15- ---------------------
16- contracts_directory, /users/myPath/to/someProject/.coverageContracts
17- contracts_build_directory, /users/myPath/to/someProject/.coverageArtifacts/contracts
18- provider ganache.provider (async b/c vm must be resolved)
19- logger add filter for unused variables...
20-
21- Truffle Lib API
22- ===============
23- load: const truffle = require("truffle") (or require("sc-truffle"))
24- compilation: await truffle.contracts.compile(config)
25- test: await truffle.test.run(config)
26- */
27-
281const App = require ( './../lib/app' ) ;
2+ const PluginUI = require ( './plugin-assets/truffle.ui' ) ;
3+
294const pkg = require ( './../package.json' ) ;
305const req = require ( 'req-cwd' ) ;
316const death = require ( 'death' ) ;
@@ -34,79 +9,78 @@ const dir = require('node-dir');
349const Web3 = require ( 'web3' ) ;
3510const util = require ( 'util' ) ;
3611const globby = require ( 'globby' ) ;
12+ const shell = require ( 'shelljs' ) ;
3713const globalModules = require ( 'global-modules' ) ;
3814
15+ /**
16+ * Truffle Plugin: `truffle run coverage [options]`
17+ * @param {Object } truffleConfig @truffle /config config
18+ * @return {Promise }
19+ */
3920async function plugin ( truffleConfig ) {
21+ let ui ;
4022 let app ;
4123 let error ;
4224 let truffle ;
4325 let testsErrored = false ;
44- let coverageConfig ;
45- let solcoverjs ;
4626
47- // Load truffle lib, .solcover.js & launch app
27+ // This needs it's own try block because this logic
28+ // runs before app.cleanUp is defined.
4829 try {
49- ( truffleConfig . solcoverjs )
50- ? solcoverjs = path . join ( truffleConfig . working_directory , truffleConfig . solcoverjs )
51- : solcoverjs = path . join ( truffleConfig . working_directory , '.solcover.js' ) ;
52-
53- coverageConfig = req . silent ( solcoverjs ) || { } ;
54- coverageConfig . cwd = truffleConfig . working_directory ;
55- coverageConfig . originalContractsDir = truffleConfig . contracts_directory ;
56- coverageConfig . log = coverageConfig . log || truffleConfig . logger . log ;
30+ ui = new PluginUI ( truffleConfig . logger . log ) ;
5731
58- app = new App ( coverageConfig ) ;
32+ if ( truffleConfig . help ) return ui . report ( 'help' ) ; // Bail if --help
5933
60- if ( truffleConfig . help ) {
61- return app . ui . report ( 'truffle-help' )
62- }
34+ truffle = loadTruffleLibrary ( ui , truffleConfig ) ;
35+ app = new App ( loadSolcoverJS ( ui , truffleConfig ) ) ;
6336
64- truffle = loadTruffleLibrary ( app ) ;
37+ } catch ( err ) { throw err }
6538
66- } catch ( err ) {
67- throw err ;
68- }
69-
70- // Instrument and test..
7139 try {
72- death ( app . cleanUp ) ; // This doesn't work...
40+ // Catch interrupt signals
41+ death ( app . cleanUp ) ;
7342
74- // Launch in-process provider
43+ // Provider / Server launch
7544 const provider = await app . provider ( truffle . ganache ) ;
7645 const web3 = new Web3 ( provider ) ;
7746 const accounts = await web3 . eth . getAccounts ( ) ;
7847 const nodeInfo = await web3 . eth . getNodeInfo ( ) ;
7948 const ganacheVersion = nodeInfo . split ( '/' ) [ 1 ] ;
8049
81- app . ui . report ( 'truffle-version' , [ truffle . version ] ) ;
82- app . ui . report ( 'ganache-version' , [ ganacheVersion ] ) ;
83- app . ui . report ( 'coverage-version' , [ pkg . version ] ) ;
50+ // Version Info
51+ ui . report ( 'truffle-version' , [ truffle . version ] ) ;
52+ ui . report ( 'ganache-version' , [ ganacheVersion ] ) ;
53+ ui . report ( 'coverage-version' , [ pkg . version ] ) ;
8454
85- // Bail early if user ran: --version
86- if ( truffleConfig . version ) return ;
55+ if ( truffleConfig . version ) return app . cleanUp ( ) ; // Bail if --version
8756
88- // Write instrumented sources to temp folder
57+ // Instrument
58+ app . sanityCheckContext ( ) ;
59+ app . generateStandardEnvironment ( ) ;
8960 app . instrument ( ) ;
9061
91- // Ask truffle to use temp folders
62+ // Filesystem & Compiler Re-configuration
9263 truffleConfig . contracts_directory = app . contractsDir ;
9364 truffleConfig . build_directory = app . artifactsDir ;
94- truffleConfig . contracts_build_directory = paths . artifacts ( truffleConfig , app ) ;
9565
96- // Additional config
66+ truffleConfig . contracts_build_directory = path . join (
67+ app . artifactsDir ,
68+ path . basename ( truffleConfig . contracts_build_directory )
69+ ) ;
70+
9771 truffleConfig . all = true ;
98- truffleConfig . test_files = tests ( app , truffleConfig ) ;
72+ truffleConfig . test_files = getTestFilePaths ( ui , truffleConfig ) ;
9973 truffleConfig . compilers . solc . settings . optimizer . enabled = false ;
10074
101- // Compile
75+ // Compile Instrumented Contracts
10276 await truffle . contracts . compile ( truffleConfig ) ;
10377
104- // Launch in-process provider
78+ // Network Re-configuration
10579 const networkName = 'soliditycoverage' ;
10680 truffleConfig . network = networkName ;
10781
108- // Truffle alternately complains that fields are and
109- // are not manually set
82+ // Truffle complains that these keys * are not* set when running plugin fn directly.
83+ // But throws saying they *cannot* be manually set when running as truffle command.
11084 try {
11185 truffleConfig . network_id = "*" ;
11286 truffleConfig . provider = provider ;
@@ -133,6 +107,7 @@ async function plugin(truffleConfig){
133107 error = e ;
134108 }
135109
110+
136111 // Finish
137112 await app . cleanUp ( ) ;
138113
@@ -142,68 +117,112 @@ async function plugin(truffleConfig){
142117
143118// -------------------------------------- Helpers --------------------------------------------------
144119
145- function tests ( app , truffle ) {
120+ /**
121+ * Returns a list of test files to pass to mocha.
122+ * @param {Object } ui reporter utility
123+ * @param {Object } truffle truffleConfig
124+ * @return {String[] } list of files to pass to mocha
125+ */
126+ function getTestFilePaths ( ui , truffle ) {
146127 let target ;
147128
129+ // Handle --file <path|glob> cli option (subset of tests)
148130 ( typeof truffle . file === 'string' )
149131 ? target = globby . sync ( [ truffle . file ] )
150132 : target = dir . files ( truffle . test_directory , { sync : true } ) || [ ] ;
151133
134+ // Filter native solidity tests and warn that they're skipped
152135 const solregex = / .* \. ( s o l ) $ / ;
153136 const hasSols = target . filter ( f => f . match ( solregex ) != null ) ;
154137
155- if ( hasSols . length > 0 ) app . ui . report ( 'sol-tests' , [ hasSols . length ] ) ;
138+ if ( hasSols . length > 0 ) ui . report ( 'sol-tests' , [ hasSols . length ] ) ;
156139
140+ // Return list of test files
157141 const testregex = / .* \. ( j s | t s | e s | e s 6 | j s x ) $ / ;
158142 return target . filter ( f => f . match ( testregex ) != null ) ;
159143}
160144
161145
162- function loadTruffleLibrary ( app ) {
163146
164- // Case: from local node_modules
147+ /**
148+ * Tries to load truffle module library and reports source. User can force use of
149+ * a non-local version using cli flags (see option). Load order is:
150+ *
151+ * 1. local node_modules
152+ * 2. global node_modules
153+ * 3. fail-safe (truffle lib v 5.0.31 at ./plugin-assets/truffle.library)
154+ *
155+ * @param {Object } ui reporter utility
156+ * @param {Object } truffleConfig config
157+ * @return {Module }
158+ */
159+ function loadTruffleLibrary ( ui , truffleConfig ) {
160+
161+ // Local
165162 try {
163+ if ( truffleConfig . useGlobalTruffle || truffleConfig . usePluginTruffle ) throw null ;
164+
166165 const lib = require ( "truffle" ) ;
167- app . ui . report ( 'truffle -local' ) ;
166+ ui . report ( 'lib -local' ) ;
168167 return lib ;
169168
170169 } catch ( err ) { } ;
171170
172- // Case: global
171+ // Global
173172 try {
173+ if ( truffleConfig . usePluginTruffle ) throw null ;
174+
174175 const globalTruffle = path . join ( globalModules , 'truffle' ) ;
175176 const lib = require ( globalTruffle ) ;
176- app . ui . report ( 'truffle -global' ) ;
177+ ui . report ( 'lib -global' ) ;
177178 return lib ;
178179
179180 } catch ( err ) { } ;
180181
181- // Default: fallback
182+ // Plugin Copy @ v 5.0.31
182183 try {
184+ if ( truffleConfig . forceLibFailure ) throw null ; // For err unit testing
183185
184- app . ui . report ( 'truffle -warn' ) ;
185- return require ( "./truffle.library" ) }
186+ ui . report ( 'lib -warn' ) ;
187+ return require ( "./plugin-assets/ truffle.library" )
186188
187- catch ( err ) {
188- const msg = app . ui . generate ( 'truffle -fail' , [ err ] ) ;
189+ } catch ( err ) {
190+ const msg = ui . generate ( 'lib -fail' , [ err ] ) ;
189191 throw new Error ( msg ) ;
190192 } ;
191193
192194}
193195
194- /**
195- * Functions to generate substitute paths for instrumented contracts and artifacts.
196- * @type {Object }
197- */
198- const paths = {
196+ function loadSolcoverJS ( ui , truffleConfig ) {
197+ let coverageConfig ;
198+ let solcoverjs ;
199199
200- // "contracts_build_directory":
201- artifacts : ( truffle , app ) => {
202- return path . join (
203- app . artifactsDir ,
204- path . basename ( truffle . contracts_build_directory )
205- )
200+ // Handle --solcoverjs flag
201+ ( truffleConfig . solcoverjs )
202+ ? solcoverjs = path . join ( truffleConfig . working_directory , truffleConfig . solcoverjs )
203+ : solcoverjs = path . join ( truffleConfig . working_directory , '.solcover.js' ) ;
204+
205+ // Catch solcoverjs syntax errors
206+ if ( shell . test ( '-e' , solcoverjs ) ) {
207+
208+ try {
209+ coverageConfig = require ( solcoverjs ) ;
210+ } catch ( error ) {
211+ error . message = ui . generate ( 'solcoverjs-fail' ) + error . message ;
212+ throw new Error ( error )
213+ }
214+
215+ // Config is optional
216+ } else {
217+ coverageConfig = { } ;
206218 }
219+
220+ coverageConfig . log = truffleConfig . logger . log ;
221+ coverageConfig . cwd = truffleConfig . working_directory ;
222+ coverageConfig . originalContractsDir = truffleConfig . contracts_directory ;
223+
224+ return coverageConfig ;
207225}
208226
227+
209228module . exports = plugin ;
0 commit comments