Skip to content

Commit 8ab9533

Browse files
author
dbale-altoros
committed
fix exit codes and max-warnings on quiet
1 parent 1ffde5e commit 8ab9533

File tree

7 files changed

+460
-303
lines changed

7 files changed

+460
-303
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [5.0.0] - 2024-05-11
2+
### BREAKING CHANGES
3+
4+
15
## [4.5.4] - 2024-04-10
26
### Fixed
37
- `gas-custom-errors` improved logic to ranged pragma versions [#573](https://github.com/protofire/solhint/pull/573)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Options:
6161
6262
-V, --version output the version number
6363
-f, --formatter [name] report formatter name (stylish, table, tap, unix, json, compact, sarif)
64-
-w, --max-warnings [maxWarningsNumber] number of allowed warnings
64+
-w, --max-warnings [maxWarningsNumber] number of allowed warnings, works in quiet mode as well
6565
-c, --config [file_name] file to use as your .solhint.json
6666
-q, --quiet report errors only - default: false
6767
--ignore-path [file_name] file to use as your .solhintignore

docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
FROM node:20-alpine
22
LABEL maintainer="[email protected]"
3-
ENV VERSION=4.5.4
3+
ENV VERSION=5.0.0
44

55
RUN npm install -g solhint@"$VERSION"

e2e/formatters-test.js

Lines changed: 273 additions & 211 deletions
Large diffs are not rendered by default.

e2e/test.js

Lines changed: 123 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,82 +6,114 @@ const os = require('os')
66
const path = require('path')
77
const shell = require('shelljs')
88

9-
function useFixture(dir) {
10-
beforeEach(`switch to ${dir}`, function () {
11-
const fixturePath = path.join(__dirname, dir)
12-
13-
const tmpDirContainer = os.tmpdir()
14-
this.testDirPath = path.join(tmpDirContainer, `solhint-tests-${dir}`)
15-
16-
fs.ensureDirSync(this.testDirPath)
17-
fs.emptyDirSync(this.testDirPath)
18-
19-
fs.copySync(fixturePath, this.testDirPath)
20-
21-
shell.cd(this.testDirPath)
22-
})
9+
const EXIT_CODES = { BAD_OPTIONS: 255, OK: 0, REPORTED_ERRORS: 1 }
10+
11+
// ==================================================================
12+
// use these lines to execute locally in TEST directory
13+
// ==================================================================
14+
// const E2E = false
15+
// const NODE = 'node '
16+
17+
// ==================================================================
18+
// use these lines to E2E
19+
// ==================================================================
20+
const E2E = true
21+
const NODE = ''
22+
23+
function prepareContext(path) {
24+
let PREFIX
25+
let SUFFIX
26+
27+
if (E2E) {
28+
useFixture(path)
29+
PREFIX = ''
30+
SUFFIX = ' --disc'
31+
} else {
32+
PREFIX = `./e2e/${path}/`
33+
SUFFIX = `-c ${PREFIX}.solhint.json --disc`
34+
}
35+
return { PREFIX, SUFFIX }
2336
}
2437

2538
describe('e2e', function () {
39+
if (!E2E) shell.exec(`rm ./.solhint.json`)
40+
2641
describe('no config', function () {
27-
useFixture('01-no-config')
42+
const PATH = '01-no-config'
43+
prepareContext(PATH)
2844

29-
it('should fail', function () {
30-
const { code } = shell.exec('solhint Foo.sol')
45+
it('should fail when config file does not exists', function () {
46+
const { code, stderr } = shell.exec(`${NODE}solhint Foo.sol -c ./noconfig/.solhint.json`)
3147

32-
expect(code).to.equal(1)
48+
expect(code).to.equal(EXIT_CODES.BAD_OPTIONS)
49+
expect(stderr).to.include('couldnt be found')
3350
})
3451

3552
it('should create an initial config with --init', function () {
36-
const { code } = shell.exec('solhint --init')
53+
let solhintConfigPath
54+
if (E2E) solhintConfigPath = path.join(this.testDirPath, '.solhint.json')
55+
else solhintConfigPath = './.solhint.json'
3756

38-
expect(code).to.equal(0)
57+
const { code } = shell.exec(`${NODE}solhint --init`)
3958

40-
const solhintConfigPath = path.join(this.testDirPath, '.solhint.json')
59+
if (E2E) solhintConfigPath = path.join(this.testDirPath, '.solhint.json')
60+
else solhintConfigPath = './.solhint.json'
4161

62+
expect(code).to.equal(EXIT_CODES.OK)
4263
expect(fs.existsSync(solhintConfigPath)).to.be.true
4364
})
4465

4566
it('should print usage if called without arguments', function () {
46-
const { code, stdout } = shell.exec('solhint')
67+
const { code, stdout } = shell.exec(`${NODE}solhint`)
4768

48-
expect(code).to.equal(0)
69+
expect(code).to.equal(EXIT_CODES.OK)
4970
expect(stdout).to.include('Usage: solhint [options]')
5071
expect(stdout).to.include('Linter for Solidity programming language')
5172
expect(stdout).to.include('linting of source code data provided to STDIN')
5273
})
5374
})
5475

5576
describe('empty-config', function () {
56-
useFixture('02-empty-solhint-json')
77+
const PATH = '02-empty-solhint-json'
78+
const { PREFIX, SUFFIX } = prepareContext(PATH)
5779

5880
it('should print nothing', function () {
59-
const { code, stdout } = shell.exec('solhint Foo.sol')
81+
const { code, stdout } = shell.exec(`${NODE}solhint ${PREFIX}Foo.sol ${SUFFIX}`)
6082

61-
expect(code).to.equal(0)
83+
expect(code).to.equal(EXIT_CODES.OK)
6284
expect(stdout.trim()).to.equal('')
6385
})
6486

6587
it('should show warning when using --init', function () {
66-
const { code, stdout } = shell.exec('solhint --init')
88+
const { code, stdout } = shell.exec(`${NODE}solhint --init`)
6789

68-
expect(code).to.equal(0)
90+
expect(code).to.equal(EXIT_CODES.BAD_OPTIONS)
6991
expect(stdout.trim()).to.equal('Configuration file already exists')
7092
})
7193
})
7294

7395
describe('no-empty-blocks', function () {
74-
useFixture('03-no-empty-blocks')
96+
const PATH = '03-no-empty-blocks'
97+
const { PREFIX, SUFFIX } = prepareContext(PATH)
98+
99+
describe('No contracts to lint', function () {
100+
it('should fail with appropiate message', function () {
101+
const { code, stderr } = shell.exec(`${NODE}solhint Foo.sol ${SUFFIX}`)
102+
103+
expect(code).to.equal(EXIT_CODES.BAD_OPTIONS)
104+
expect(stderr).to.include('No files to lint!')
105+
})
106+
})
75107

76-
it('should end correctly (exit w/0), found 1 error', function () {
77-
const { code, stdout } = shell.exec('solhint Foo.sol')
108+
it('should end with REPORTED_ERRORS = 1 because report contains errors', function () {
109+
const { code, stdout } = shell.exec(`${NODE}solhint ${PREFIX}Foo.sol ${SUFFIX}`)
78110

79-
expect(code).to.equal(0)
111+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
80112
expect(stdout.trim()).to.contain('Code contains empty blocks')
81113
})
82114

83115
it('should work with stdin, exit 0, found 1 error', async function () {
84-
const child = cp.exec('solhint stdin')
116+
const child = cp.exec(`${NODE}solhint stdin ${PREFIX}Foo.sol ${SUFFIX}`)
85117

86118
const stdoutPromise = getStream(child.stdout)
87119

@@ -95,78 +127,114 @@ describe('e2e', function () {
95127
child.stdin.end()
96128

97129
const code = await codePromise
98-
99-
expect(code).to.equal(0)
100-
101130
const stdout = await stdoutPromise
102131

132+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
103133
expect(stdout.trim()).to.contain('Code contains empty blocks')
104134
})
105135
})
106136

107137
describe('.sol on path', function () {
108-
useFixture('04-dotSol-on-path')
138+
const PATH = '04-dotSol-on-path'
139+
const { PREFIX, SUFFIX } = prepareContext(PATH)
109140

110141
it('should handle directory names that end with .sol', function () {
111-
const { code } = shell.exec('solhint contracts/**/*.sol')
112-
expect(code).to.equal(0)
142+
const { code } = shell.exec(`${NODE}solhint ${PREFIX}contracts/**/*.sol ${SUFFIX}`)
143+
expect(code).to.equal(EXIT_CODES.OK)
113144
})
114145
})
115146

116147
describe('--max-warnings parameter tests', function () {
148+
const PATH = '05-max-warnings'
149+
const { PREFIX, SUFFIX } = prepareContext(PATH)
150+
117151
// Foo contract has 6 warnings
118152
// Foo2 contract has 1 error and 14 warnings
119-
useFixture('05-max-warnings')
120153
const warningExceededMsg = 'Solhint found more warnings than the maximum specified'
121154
const errorFound =
122155
'Error/s found on rules! [max-warnings] param is ignored. Fixing errors enables max-warnings'
123156

124157
it('should not display [warnings exceeded] for max 7 warnings', function () {
125-
const { code, stdout } = shell.exec('solhint contracts/Foo.sol --max-warnings 7')
126-
expect(code).to.equal(0)
158+
const { code, stdout } = shell.exec(
159+
`${NODE}solhint ${PREFIX}contracts/Foo.sol --max-warnings 7 ${SUFFIX}`
160+
)
161+
expect(code).to.equal(EXIT_CODES.OK)
127162
expect(stdout.trim()).to.not.contain(warningExceededMsg)
128163
})
129164

130-
it('should display [warnings exceeded] for max 3 warnings and exit with 0', function () {
131-
const { code, stdout } = shell.exec('solhint contracts/Foo.sol --max-warnings 3')
165+
it('should display [warnings exceeded] for max 3 warnings and exit with 1', function () {
166+
const { code, stdout } = shell.exec(
167+
`${NODE}solhint ${PREFIX}contracts/Foo.sol --max-warnings 3 ${SUFFIX}`
168+
)
132169

133-
expect(code).to.equal(1)
170+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
134171
expect(stdout.trim()).to.contain(warningExceededMsg)
135172
})
136173

137174
it('should return error for Compiler version rule, ignoring 3 --max-warnings', function () {
138-
const { code, stdout } = shell.exec('solhint contracts/Foo2.sol --max-warnings 3')
175+
const { code, stdout } = shell.exec(
176+
`${NODE}solhint ${PREFIX}contracts/Foo2.sol --max-warnings 3 ${SUFFIX}`
177+
)
139178

140-
expect(code).to.equal(0)
179+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
141180
expect(stdout.trim()).to.contain(errorFound)
142181
})
143182

144183
it('should return error for Compiler version rule. No message for max-warnings', function () {
145-
const { code, stdout } = shell.exec('solhint contracts/Foo2.sol --max-warnings 27')
146-
expect(code).to.equal(0)
184+
const { code, stdout } = shell.exec(
185+
`${NODE}solhint ${PREFIX}contracts/Foo2.sol --max-warnings 27 ${SUFFIX}`
186+
)
187+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
147188
expect(stdout.trim()).to.not.contain(errorFound)
148189
})
190+
191+
it('should NOT display warningns nor error but exit with 1 because max is 3 warnings', function () {
192+
const { code } = shell.exec(
193+
`${NODE}solhint ${PREFIX}contracts/Foo.sol --max-warnings 3 ${SUFFIX} -q`
194+
)
195+
196+
expect(code).to.equal(EXIT_CODES.REPORTED_ERRORS)
197+
})
149198
})
150199

151200
describe('Linter - foundry-test-functions with shell', () => {
201+
const PATH = '07-foundry-test'
202+
const { PREFIX, SUFFIX } = prepareContext(PATH)
203+
152204
// Foo contract has 1 warning
153205
// FooTest contract has 1 error
154-
useFixture('07-foundry-test')
155206

156207
it(`should raise error for empty blocks only`, () => {
157-
const { code, stdout } = shell.exec('solhint contracts/Foo.sol')
208+
const { code, stdout } = shell.exec(`${NODE}solhint ${PREFIX}contracts/Foo.sol ${SUFFIX}`)
158209

159-
expect(code).to.equal(0)
210+
expect(code).to.equal(EXIT_CODES.OK)
160211
expect(stdout.trim()).to.contain('Code contains empty blocks')
161212
})
162213

163214
it(`should raise error for wrongFunctionDefinitionName() only`, () => {
164-
const { code, stdout } = shell.exec('solhint -c test/.solhint.json test/FooTest.sol')
215+
const SUFFIX2 = `-c ${PREFIX}test/.solhint.json --disc`
216+
const { code, stdout } = shell.exec(`${NODE}solhint ${PREFIX}test/FooTest.sol ${SUFFIX2}`)
165217

166-
expect(code).to.equal(0)
218+
expect(code).to.equal(EXIT_CODES.OK)
167219
expect(stdout.trim()).to.contain(
168-
'Function wrongFunctionDefinitionName() must match Foundry test naming convention'
220+
'Function wrongFunctionDefinitionName() must match Foundry test naming convention '
169221
)
170222
})
171223
})
172224
})
225+
226+
function useFixture(dir) {
227+
beforeEach(`switch to ${dir}`, function () {
228+
const fixturePath = path.join(__dirname, dir)
229+
230+
const tmpDirContainer = os.tmpdir()
231+
this.testDirPath = path.join(tmpDirContainer, `solhint-tests-${dir}`)
232+
233+
fs.ensureDirSync(this.testDirPath)
234+
fs.emptyDirSync(this.testDirPath)
235+
236+
fs.copySync(fixturePath, this.testDirPath)
237+
238+
shell.cd(this.testDirPath)
239+
})
240+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "solhint",
3-
"version": "4.5.4",
3+
"version": "5.0.0",
44
"description": "Solidity Code Linter",
55
"main": "lib/index.js",
66
"keywords": [

0 commit comments

Comments
 (0)