Commit cdb67852 authored by Maurelian's avatar Maurelian Committed by Matthew Slipper

ctb: Put test-name checks into an object

parent 3e5fea45
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
const testPath = './contracts/test' type Check = {
const testFiles = fs.readdirSync(testPath) check: (name: string, parts: string[]) => void,
makeError: (name: string) => Error,
}
// Given a test function name, ensures it matches the expected format /**
const handleFunctionName = (name: string) => { * Function name checks
if (!name.startsWith('test')) { */
return const FunctionNameChecks: { [name: string]: Check } = {
} invalidCase: {
const parts = name.split('_') check: (name: string, parts: string[]): void => {
parts.forEach((part) => { parts.forEach((part) => {
// Good enough approximation for camelCase if (part[0] !== part[0].toLowerCase())
if (part[0] !== part[0].toLowerCase()) { throw FunctionNameChecks.invalidCase.makeError(name)
throw new Error( })
`Invalid test name: ${name}.\n Test name parts should be in camelCase` },
) makeError: (name: string): Error => new Error(
} `Invalid test name: ${name}.\n Test name parts should be in camelCase.`
})
if (parts.length < 3 || parts.length > 4) {
throw new Error(
`Invalid test name: ${name}.\n Test names should have either 3 or 4 parts, each separated by underscores`
) )
} },
if (!['test', 'testFuzz', 'testDiff'].includes(parts[0])) { invalidNumParts: {
throw new Error( check: (name: string, parts: string[]): void => {
`Invalid test name: ${name}.\n Names should begin with either "test" or "testFuzz"` if (parts.length < 3 || parts.length > 4)
throw FunctionNameChecks.invalidNumParts.makeError(name)
},
makeError: (name: string): Error => new Error(
`Invalid test name: ${name}.\n Test names should have either 3 or 4 parts, each separated by underscores.`
) )
} },
if ( invalidPrefix: {
!['succeeds', 'reverts', 'fails', 'benchmark', 'works'].includes( check: (name: string, parts: string[]): void => {
parts[parts.length - 1] if (!['test', 'testFuzz', 'testDiff'].includes(parts[0]))
) && throw FunctionNameChecks.invalidPrefix.makeError(name)
parts[parts.length - 2] !== 'benchmark' },
) { makeError: (name: string): Error => new Error(
throw new Error( `Invalid test name: ${name}.\n Names should begin with "test", "testFuzz", or "testDiff".`
`Invalid test name: ${name}.\n Test names should end with either "succeeds", "reverts", "fails", "differential" or "benchmark[_num]"`
) )
} },
if ( invalidTestResult: {
['reverts', 'fails'].includes(parts[parts.length - 1]) && check: (name: string, parts: string[]): void => {
parts.length < 4 if (
) { !['succeeds', 'reverts', 'fails', 'benchmark', 'works'].includes(
throw new Error( parts[parts.length - 1]
) &&
parts[parts.length - 2] !== 'benchmark'
)
throw FunctionNameChecks.invalidTestResult.makeError(name)
},
makeError: (name: string): Error => new Error(
`Invalid test name: ${name}.\n Test names should end with either "succeeds", "reverts", "fails", "works" or "benchmark[_num]".`
)
},
noFailureReason: {
check: (name: string, parts: string[]): void => {
if (
['reverts', 'fails'].includes(parts[parts.length - 1]) &&
parts.length < 4
)
throw FunctionNameChecks.noFailureReason.makeError(name)
},
makeError: (name: string): Error => new Error(
`Invalid test name: ${name}.\n Failure tests should have 4 parts. The third part should indicate the reason for failure.` `Invalid test name: ${name}.\n Failure tests should have 4 parts. The third part should indicate the reason for failure.`
) )
} }
} }
// Given a test function name, ensures it matches the expected format
const handleFunctionName = (name: string) => {
if (!name.startsWith('test'))
return
const parts = name.split('_')
Object.values(FunctionNameChecks).forEach(({ check }) => check(name, parts))
}
// Todo: define this function for validating contract names // Todo: define this function for validating contract names
// Given a test contract name, ensures it matches the expected format // Given a test contract name, ensures it matches the expected format
const handleContractName = (name: string) => { const handleContractName = (name: string) => {
name name
} }
for (const testFile of testFiles) { const main = async () => {
const filePath = path.join(testPath, testFile) const testPath = './contracts/test'
const lines = fs const testFiles = fs.readdirSync(testPath)
.readFileSync(filePath, 'utf-8')
.split('\n') for (const testFile of testFiles) {
.map((l) => l.trim()) const filePath = path.join(testPath, testFile)
let currentContract: string const lines = fs
for (const line of lines) { .readFileSync(filePath, 'utf-8')
if (line.startsWith('contract')) { .split('\n')
currentContract = line.split(' ')[1] .map((l) => l.trim())
handleContractName(line) let currentContract: string
continue for (const line of lines) {
} else if (line.startsWith('function')) { if (line.startsWith('contract')) {
const funcName = line.split(' ')[1].split('(')[0] currentContract = line.split(' ')[1]
try { handleContractName(line)
handleFunctionName(funcName) continue
} catch (error) { } else if (line.startsWith('function')) {
throw new Error( const funcName = line.split(' ')[1].split('(')[0]
`In ${filePath}::${currentContract}:\n ${error.message}` try {
) handleFunctionName(funcName)
} catch (error) {
throw new Error(
`In ${filePath}::${currentContract}:\n ${error.message}`
)
}
continue
} }
continue
} }
} }
} }
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment