UNPKG

11.6 kBtext/coffeescriptView Raw
1#mocha
2e = require 'expect.js'
3fs = require 'fs'
4path = require 'path'
5stream = require 'stream'
6
7class mockStream
8 constructor : () -> @chunks = []
9 write : (chunk) ->
10 @chunks.push chunk
11 clean : -> chunks = []
12 toString : (nocolor = true) ->
13 data = ''
14 for chunk in @chunks
15 data += chunk.toString()
16 data
17 toStringNoColor : (nocolor = true) ->
18 data = ''
19 for chunk in @chunks
20 data += chunk.toString()
21 data.replace /\x1b\[\d+m/g, '' # trim ansi color
22
23
24
25
26mock =
27 send : ''
28 headers : {}
29 req :
30 url : '/'
31 headers :
32 'user-agent' : 'mock server'
33 'referer' : 'mock refer'
34 socket :
35 remoteAddress : '127.0.0.1'
36 httpVersionMajor : 1
37 httpVersionMinor : 1
38 method : 'GET'
39 resp :
40 write : (data)-> mock.send += data.toString() if data?
41 end : (data)-> mock.send += data.toString() if data?
42 statusCode : 0
43 setHeader : (name, value) -> mock.headers[name.toLowerCase()] = value
44 getHeader : (name) -> mock.headers[name.toLowerCase()]
45 clean : ->
46 mock.send = ''
47 mock.headers = {}
48 mock.resp.statusCode = 0
49 mock.url = '/'
50mock.resp.headers = mock.headers
51
52describe 'JustLog', ->
53 jl = require '../lib/justlog'
54 {pre: predefined} = require '../lib/pattern'
55 options = stdout = stderr = l = null
56 dir = "#{__dirname}/log_file"
57
58 beforeEach ->
59 mock.clean()
60 stdout = new mockStream
61 stderr = new mockStream
62 options =
63 file:
64 path : "[#{dir}/test.txt]"
65 stdio :
66 stdout : stdout
67 stderr : stderr
68
69
70 afterEach (done)->
71 return done() if not l?
72 l.close ()->
73 setTimeout ->
74 try
75 for file in fs.readdirSync dir
76 # console.log file
77 fs.unlinkSync "#{dir}/#{file}"
78 fs.rmdirSync dir
79 done()
80 , 100
81 l = null
82
83 describe 'options init', ->
84 it 'check default options', (done)->
85 l = new jl
86 e(jl.INFO).to.be l.INFO
87 e(jl.DEBUG).to.be l.DEBUG
88 e(jl.WARN).to.be l.WARN
89 e(jl.ERROR).to.be l.ERROR
90
91 e(l.options.file.level).to.be jl.EXCEPTION
92 e(l.options.file.path).to.be "[#{process.cwd()}/logs/_mocha-]YYYY-MM-DD[.log]"
93 e(l.options.stdio.level).to.be jl.ALL
94 e(l.options.stdio.stdout).to.be process.stdout
95 e(l.options.stdio.stderr).to.be process.stderr
96 e(l.options.file.render.pattern).to.be 'file'
97 e(l.options.stdio.render.pattern).to.be 'color'
98 setTimeout done, 100
99 describe 'stdio', ->
100 it 'stdout with default output pattern', (done)->
101 options.file = false
102 l = new jl options
103 l.info 'simple info'
104 l.debug 'simple debug'
105 l.warn 'simple warn'
106 l.error 'simple error'
107 e(stdout.toStringNoColor()).to.match ///
108 ^
109 \d{2}:\d{2}:\d{2}\s
110 INFO\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\sinfo\n
111 \d{2}:\d{2}:\d{2}\s
112 DEBUG\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\sdebug\n
113 $
114 ///
115 e(stderr.toStringNoColor()).to.match ///
116 ^
117 \d{2}:\d{2}:\d{2}\s
118 WARN\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\swarn\n
119 \d{2}:\d{2}:\d{2}\s
120 ERROR\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\serror\n
121 $
122 ///
123 done()
124 it 'stdout with default output pattern', (done)->
125 options.file.level = 0
126 options.stdio.level = jl.INFO | jl.DEBUG
127 l = new jl options
128 l.info 'simple info', 'data2', 123
129 l.debug 'simple debug %s %d %s %j', 'data3', 456, [1, 2, 3], a:1
130 l.warn 'simple warn %s'
131 l.error 'simple error'
132 e(stdout.toStringNoColor()).to.match ///
133 ^
134 \d{2}:\d{2}:\d{2}\s
135 INFO\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\sinfo\sdata2\s123\n
136 \d{2}:\d{2}:\d{2}\s
137 DEBUG\s+(out/test/)?tests/test-justlog\.(js|coffee):\d+\ssimple\sdebug\sdata3\s456\s1,2,3\s\{"a":1\}\n
138 $
139 ///
140 e(stderr.toStringNoColor()).to.be ''
141 done()
142 describe 'file', ->
143 it 'write warn & error log with default pattern', (done)->
144 options.stdio = false
145 l = new jl options
146 l.info 'simple info'
147 l.debug 'simple debug'
148 l.warn 'simple warn'
149 l.error 'simple error'
150 l.close ->
151 e(fs.readFileSync(l.file.path).toString()).to.match ///
152 ^
153 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
154 \[WARN\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\swarn\n
155 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
156 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror\n
157 $
158 ///
159 done()
160
161 it 'rename file when current stream is not closed', (done)->
162 options.stdio.level = 0
163 options.file._watcher_timeout = 10
164
165 l = new jl options
166 flag = 0
167 l.on 'rename', (file) ->
168 flag++
169 e(file).to.be l.file.path
170 l.warn 'simple warn' # first log
171 setTimeout -> # remove 30 ms later
172 fs.renameSync l.file.path, l.file.path+'.move'
173 , 300
174 setTimeout -> # second log 60 ms later
175 l.error 'simple error'
176 , 600
177 setTimeout -> # remove 30 ms later
178 fs.renameSync l.file.path, l.file.path+'.move1'
179 , 900
180 setTimeout -> # second log 60 ms later
181 l.error 'simple error2'
182 , 1200
183 setTimeout -> # check two logfile 90 ms later
184 e(flag).to.be 2
185 l.close ()->
186 e(fs.readFileSync(l.file.path+'.move').toString()).to.match ///
187 ^
188 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
189 \[WARN\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\swarn\n
190 $
191 ///
192 e(fs.readFileSync(l.file.path+'.move1').toString()).to.match ///
193 ^
194 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
195 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror\n
196 $
197 ///
198 e(fs.readFileSync(l.file.path).toString()).to.match ///
199 ^
200 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
201 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror2\n
202 $
203 ///
204 done()
205 , 1500
206 it 'file inode changed when current stream is not closed', (done)->
207 # return done()
208 options.stdio = false
209 options.file._watcher_timeout = 10
210 l = new jl options
211 flag = 0
212 l.on 'rename', (file) ->
213 flag++
214 e(file).to.be l.file.path
215 l.warn 'simple warn' # first log
216 setTimeout -> # remove 30 ms later
217 fs.renameSync l.file.path, l.file.path+'.move'
218 fs.writeFileSync l.file.path, 'somedata1\n'
219 , 300
220 setTimeout -> # second log 60 ms later
221 l.error 'simple error'
222 , 600
223 setTimeout -> # remove 30 ms later
224 fs.renameSync l.file.path, l.file.path+'.move1'
225 fs.writeFileSync l.file.path, 'somedata2\n'
226 , 900
227 setTimeout -> # second log 60 ms later
228 l.error 'simple error2'
229 , 1200
230 setTimeout -> # check two logfile 90 ms later
231 e(flag).to.be 2
232 l.close ()->
233 e(fs.readFileSync(l.file.path+'.move').toString()).to.match ///
234 ^
235 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
236 \[WARN\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\swarn\n
237 $
238 ///
239 e(fs.readFileSync(l.file.path+'.move1').toString()).to.match ///
240 ^
241 somedata1\n
242 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
243 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror\n
244 $
245 ///
246 e(fs.readFileSync(l.file.path).toString()).to.match ///
247 ^
248 somedata2\n
249 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
250 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror2\n
251 $
252 ///
253 done()
254 , 1500
255
256 it 'logfile rotate by time', (done)->
257 nowMs = new Date().getMilliseconds()
258 this.timeout 10000
259 setTimeout ->
260 options.stdio = false
261 options.file.watcher_timeout = 10
262 options.file.path = "[#{dir}]/ss.txt"
263 l = new jl options
264 files = [l.file.path]
265 l.on 'rotate', (prev, curr) ->
266 files.push curr
267 tflag = 0
268 l.on 'timer', (ms)->
269 e(ms).to.below 1001
270 e(ms).to.above 99
271 tflag++
272 # console.log prev, curr
273 l.warn 'simple warn' # first log
274 setTimeout ->
275 l.error 'simple error1'
276 , 1000
277 setTimeout ->
278 l.error 'simple error2'
279 , 2000
280 setTimeout ->
281 l.error 'simple error3'
282 l.close ->
283 # console.log files
284 e(tflag).to.above 3
285 e(tflag).to.below 6
286 flag = 0
287 for k in files
288 switch ++flag
289 when 1
290 e(fs.readFileSync(k).toString()).to.match ///
291 ^
292 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
293 \[WARN\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\swarn\n
294 $
295 ///
296 when 2
297 e(fs.readFileSync(k).toString()).to.match ///
298 ^
299 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
300 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror1\n
301 $
302 ///
303 when 3
304 e(fs.readFileSync(k).toString()).to.match ///
305 ^
306 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
307 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror2\n
308 $
309 ///
310 when 4
311 e(fs.readFileSync(k).toString()).to.match ///
312 ^
313 \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s
314 \[ERROR\]\s+\((out/test/)?tests/test-justlog\.(js|coffee):\d+\)\ssimple\serror3\n
315 $
316 ///
317 fs.unlinkSync k
318 e(flag).to.be 4
319 done()
320 , 3000
321 , nowMs + 10
322 describe 'middleware', ->
323 it 'simple 200 response', (done)->
324 l = null
325 m = jl.middleware(options, (ll)->
326 l = ll
327 )
328 mock.resp.statusCode = 200
329 mock.req.url = '/simple_200'
330 m mock.req, mock.resp, -> setTimeout (->mock.resp.end 'some data1'), 20
331 setTimeout ->
332 mock.resp.end 'some data'
333 std = stdout.toString()
334 e(stdout.toString()).to.match ///
335 ^
336 \x1b\[33m127\.0\.0\.1\x1b\[0m\s
337 -\s
338 -\s
339 \[\d{1,2}/\w{3}/\d{4}:\d\d:\d\d:\d\d\s[\+\-]?\d{4}\]\s
340 "\x1b\[32mGET\x1b\[0m\s\x1b\[4m\x1b\[1m\x1b\[34m/simple_200\x1b\[0m\sHTTP/1.1"\s
341 \x1b\[32m200\x1b\[0m\s-\s
342 "\x1b\[34mmock\srefer\x1b\[0m"\s
343 "\x1b\[36mmock\sserver\x1b\[0m"\s
344 [12]\d\n
345 ///
346
347 fbody = fs.readFileSync(l.file.path).toString()
348 e(fbody).to.match
349 ///
350 ^
351 127\.0\.0\.1\s
352 -\s
353 -\s
354 \[\d{1,2}/\w{3}/\d{4}:\d\d:\d\d:\d\d\s[\+\-]?\d{4}\]\s
355 "GET\s /simple_200\sHTTP/1.1"\s
356 200\s-\s
357 "mock\srefer"\s
358 "mock\sserver"\s
359 [12]\d\n
360 ///
361 done()
362 , 100
363
364
365 # m()