Skip to content

Commit 7fba3da

Browse files
control log levels and filter tests by file and description
1 parent 817c39a commit 7fba3da

File tree

1 file changed

+104
-5
lines changed

1 file changed

+104
-5
lines changed

Cakefile

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
oldConsole = require 'console'
12
fs = require 'fs'
23
os = require 'os'
34
path = require 'path'
@@ -30,6 +31,60 @@ header = """
3031
majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10
3132

3233

34+
class CakeConsole extends oldConsole.Console
35+
@LEVELS: ['debug', 'info', 'log', 'warn', 'error', 'trace']
36+
@levelNumsMap: do =>
37+
ret = {}
38+
ret[k] = i for k, i in @LEVELS
39+
ret
40+
@validLevels: => "[#{(@LEVELS.map (l) -> "'#{l}'").join ', '}]"
41+
42+
constructor: ({@level = 'log', ...opts} = {}) ->
43+
super opts
44+
unless @level in @constructor.LEVELS
45+
throw new TypeError "argument '#{@level}' was not a valid log level
46+
(should be: #{@constructor.validLevels()})"
47+
48+
@getLevelNum: (l) => @levelNumsMap[l] ? throw new TypeError "invalid level #{l}"
49+
curLevelNum: -> @constructor.getLevelNum @level
50+
doesThisLevelApply: (l) -> @curLevelNum() <= @constructor.getLevelNum l
51+
52+
# TODO: for some reason this is done lazily in buildParser, so let's do the same here.
53+
helpers.extend global, require 'util'
54+
for l in @LEVELS
55+
do (l) => @::[l] = (...args) ->
56+
if @doesThisLevelApply l
57+
# NB: it's literally impossible to extend Console and propagate to the parent class because
58+
# of some horrific unexplained initialization code used for the singleton console
59+
# object, which employs a very complex prototype chain that makes it impossible to do
60+
# the simple thing: https://github.com/nodejs/node/blob/17fae65c72321659390c4cbcd9ddaf248accb953/lib/internal/console/global.js#L29-L33.
61+
# Undo the prototype chain nonsense and bind the method back to our subclass.
62+
(oldConsole[l].bind @) ...args
63+
else global.format ...args
64+
65+
@stdio: ({
66+
stdout = process.stdout,
67+
stderr = process.stderr,
68+
...opts,
69+
} = {}) => new @ {
70+
stdout,
71+
stderr,
72+
...opts
73+
}
74+
75+
76+
option '-l', '--level [LEVEL]', 'log level [debug < info < log(default) < warn < error]'
77+
78+
setupConsole = ({level} = {}) ->
79+
global.cakeConsole = CakeConsole.stdio {level}
80+
global.console = global.cakeConsole
81+
console.log "log level = #{level}"
82+
83+
consoleTask = (name, description, action) ->
84+
global.task name, description, ({level = 'log', ...opts} = {}) ->
85+
setupConsole {level}
86+
action {...opts}
87+
3388
# Log a message with a color.
3489
log = (message, color, explanation) ->
3590
console.log color + message + reset + ' ' + (explanation or '')
@@ -60,6 +115,7 @@ buildParser = ->
60115
buildExceptParser = (callback) ->
61116
files = fs.readdirSync 'src'
62117
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
118+
console.info {files}
63119
run ['-c', '-o', 'lib/coffeescript'].concat(files), callback
64120

65121
build = (callback) ->
@@ -121,7 +177,7 @@ watchAndBuildAndTest = (harmony = no) ->
121177
buildAndTest no, harmony
122178

123179

124-
task 'build', 'build the CoffeeScript compiler from source', build
180+
consoleTask 'build', 'build the CoffeeScript compiler from source', build
125181

126182
task 'build:parser', 'build the Jison parser only', buildParser
127183

@@ -190,7 +246,7 @@ task 'build:browser:full', 'merge the built scripts into a single file for use i
190246
console.log "built ... running browser tests:"
191247
invoke 'test:browser'
192248

193-
task 'build:watch', 'watch and continually rebuild the CoffeeScript compiler, running tests on each build', ->
249+
consoleTask 'build:watch', 'watch and continually rebuild the CoffeeScript compiler, running tests on each build', ->
194250
watchAndBuildAndTest()
195251

196252
task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript compiler, running harmony tests on each build', ->
@@ -400,16 +456,37 @@ task 'bench', 'quick benchmark of compilation time', ->
400456
console.log "total #{ fmt total }"
401457

402458

459+
class PatternSet
460+
constructor: (patternStrings = []) ->
461+
@matchers = (new RegExp p for p in patternStrings when p isnt '')
462+
463+
isEmpty: -> @matchers.length is 0
464+
465+
iterMatchers: -> @matchers[Symbol.iterator]()
466+
467+
matches: (arg) -> if @isEmpty() then yes else @iterMatchers().some (m) -> (m.exec arg)?
468+
469+
@fromCommaDelimitedList: (commaListStr) => new @ (commaListStr ? '').split /,/
470+
@empty: => new @ []
471+
472+
403473
# Run the CoffeeScript test suite.
404-
runTests = (CoffeeScript) ->
474+
runTests = (CoffeeScript, {filePatterns, descPatterns} = {}) ->
405475
CoffeeScript.register() unless global.testingBrowser
406476

477+
filePatterns ?= PatternSet.empty()
478+
descPatterns ?= PatternSet.empty()
479+
console.log {filePatterns, descPatterns}
480+
407481
# These are attached to `global` so that they’re accessible from within
408482
# `test/async.coffee`, which has an async-capable version of
409483
# `global.test`.
410484
global.currentFile = null
411485
global.passedTests = 0
412486
global.failures = []
487+
global.filteredOut =
488+
files: []
489+
tests: []
413490

414491
global[name] = func for name, func of require 'assert'
415492

@@ -429,9 +506,22 @@ runTests = (CoffeeScript) ->
429506
error: err
430507
description: description
431508
source: fn.toString() if fn.toString?
509+
onFilteredOut = (description, fn) ->
510+
console.info "test '#{description}' was filtered out by patterns"
511+
filteredOut.tests.push
512+
filename: global.currentFile
513+
description: description
514+
fn: fn
515+
onFilteredFile = (file) ->
516+
console.info "file '#{file}' was filtered out by patterns"
517+
filteredOut.files.push
518+
filename: file
432519

433520
# Our test helper function for delimiting different test cases.
434521
global.test = (description, fn) ->
522+
unless descPatterns.matches description
523+
onFilteredOut description, fn
524+
return
435525
try
436526
fn.test = {description, currentFile}
437527
result = fn.call(fn)
@@ -445,6 +535,7 @@ runTests = (CoffeeScript) ->
445535
passedTests++
446536
catch err
447537
onFail description, fn, err
538+
console.info "passed: #{description} in #{currentFile}"
448539

449540
helpers.extend global, require './test/support/helpers'
450541

@@ -483,6 +574,9 @@ runTests = (CoffeeScript) ->
483574

484575
startTime = Date.now()
485576
for file in files when helpers.isCoffee file
577+
unless filePatterns.matches file
578+
onFilteredFile file
579+
continue
486580
literate = helpers.isLiterate file
487581
currentFile = filename = path.join 'test', file
488582
code = fs.readFileSync filename
@@ -495,9 +589,14 @@ runTests = (CoffeeScript) ->
495589
Promise.reject() if failures.length isnt 0
496590

497591

498-
task 'test', 'run the CoffeeScript language test suite', ->
499-
runTests(CoffeeScript).catch -> process.exit 1
592+
option '-f', '--file [REGEXP*]', 'test file patterns to match'
593+
option '-d', '--desc [REGEXP*]', 'test description patterns to match'
500594

595+
consoleTask 'test', 'run the CoffeeScript language test suite', ({file, desc} = {}) ->
596+
testOptions =
597+
filePatterns: new PatternSet file
598+
descPatterns: new PatternSet desc
599+
runTests(CoffeeScript, testOptions).catch -> process.exit 1
501600

502601
task 'test:browser', 'run the test suite against the modern browser compiler in a headless browser', ->
503602
# Create very simple web server to serve the two files we need.

0 commit comments

Comments
 (0)