1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var assert = require('assert'),
|
10 | fs = require('fs'),
|
11 | path = require('path'),
|
12 | spawn = require('child_process').spawn,
|
13 | util = require('util'),
|
14 | vows = require('vows'),
|
15 | winston = require('../lib/winston');
|
16 |
|
17 | var helpers = exports;
|
18 |
|
19 | helpers.size = function (obj) {
|
20 | var size = 0, key;
|
21 | for (key in obj) {
|
22 | if (obj.hasOwnProperty(key)) {
|
23 | size++;
|
24 | }
|
25 | }
|
26 |
|
27 | return size;
|
28 | };
|
29 |
|
30 | helpers.tryUnlink = function (file) {
|
31 | try { fs.unlinkSync(file) }
|
32 | catch (ex) { }
|
33 | };
|
34 |
|
35 | helpers.assertDateInfo = function (info) {
|
36 | assert.isNumber(Date.parse(info));
|
37 | };
|
38 |
|
39 | helpers.assertProcessInfo = function (info) {
|
40 | assert.isNumber(info.pid);
|
41 | assert.isNumber(info.uid);
|
42 | assert.isNumber(info.gid);
|
43 | assert.isString(info.cwd);
|
44 | assert.isString(info.execPath);
|
45 | assert.isString(info.version);
|
46 | assert.isArray(info.argv);
|
47 | assert.isObject(info.memoryUsage);
|
48 | };
|
49 |
|
50 | helpers.assertOsInfo = function (info) {
|
51 | assert.isArray(info.loadavg);
|
52 | assert.isNumber(info.uptime);
|
53 | };
|
54 |
|
55 | helpers.assertTrace = function (trace) {
|
56 | trace.forEach(function (site) {
|
57 | assert.isTrue(!site.column || typeof site.column === 'number');
|
58 | assert.isTrue(!site.line || typeof site.line === 'number');
|
59 | assert.isTrue(!site.file || typeof site.file === 'string');
|
60 | assert.isTrue(!site.method || typeof site.method === 'string');
|
61 | assert.isTrue(!site.function || typeof site.function === 'string');
|
62 | assert.isTrue(typeof site.native === 'boolean');
|
63 | });
|
64 | };
|
65 |
|
66 | helpers.assertLogger = function (logger, level) {
|
67 | assert.instanceOf(logger, winston.Logger);
|
68 | assert.isFunction(logger.log);
|
69 | assert.isFunction(logger.add);
|
70 | assert.isFunction(logger.remove);
|
71 | assert.equal(logger.level, level || "info");
|
72 | Object.keys(logger.levels).forEach(function (method) {
|
73 | assert.isFunction(logger[method]);
|
74 | });
|
75 | };
|
76 |
|
77 | helpers.assertConsole = function (transport) {
|
78 | assert.instanceOf(transport, winston.transports.Console);
|
79 | assert.isFunction(transport.log);
|
80 | };
|
81 |
|
82 | helpers.assertMemory = function (transport) {
|
83 | assert.instanceOf(transport, winston.transports.Memory);
|
84 | assert.isFunction(transport.log);
|
85 | };
|
86 |
|
87 | helpers.assertFile = function (transport) {
|
88 | assert.instanceOf(transport, winston.transports.File);
|
89 | assert.isFunction(transport.log);
|
90 | };
|
91 |
|
92 | helpers.assertCouchdb = function (transport) {
|
93 | assert.instanceOf(transport, winston.transports.Couchdb);
|
94 | assert.isFunction(transport.log);
|
95 | };
|
96 |
|
97 | helpers.assertHandleExceptions = function (options) {
|
98 | return {
|
99 | topic: function () {
|
100 | var that = this,
|
101 | child = spawn('node', [options.script]);
|
102 |
|
103 | helpers.tryUnlink(options.logfile);
|
104 | child.on('exit', function () {
|
105 | fs.readFile(options.logfile, that.callback);
|
106 | });
|
107 | },
|
108 | "should save the error information to the specified file": function (err, data) {
|
109 | assert.isTrue(!err);
|
110 | data = JSON.parse(data);
|
111 |
|
112 | assert.isObject(data);
|
113 | helpers.assertProcessInfo(data.process);
|
114 | helpers.assertOsInfo(data.os);
|
115 | helpers.assertTrace(data.trace);
|
116 | if (options.message) {
|
117 | assert.equal('uncaughtException: ' + options.message, data.message);
|
118 | }
|
119 | }
|
120 | };
|
121 | };
|
122 |
|
123 | helpers.assertFailedTransport = function (transport) {
|
124 | return {
|
125 | topic: function () {
|
126 | var self = this;
|
127 | transport.on('error', function(emitErr){
|
128 | transport.log('error', 'test message 2', {}, function(logErr, logged){
|
129 | self.callback(emitErr, logErr);
|
130 | });
|
131 | });
|
132 | transport.log('error', 'test message');
|
133 | },
|
134 | "should emit an error": function (emitErr, logErr) {
|
135 | assert.instanceOf(emitErr, Error);
|
136 | assert.equal(emitErr.code, 'ENOENT');
|
137 | },
|
138 | "should enter noop failed state": function (emitErr, logErr) {
|
139 | assert.instanceOf(logErr, Error);
|
140 | assert.equal(transport._failures, transport.maxRetries);
|
141 | }
|
142 | };
|
143 | };
|
144 |
|
145 | helpers.testNpmLevels = function (transport, assertMsg, assertFn) {
|
146 | return helpers.testLevels(winston.config.npm.levels, transport, assertMsg, assertFn);
|
147 | };
|
148 |
|
149 | helpers.testSyslogLevels = function (transport, assertMsg, assertFn) {
|
150 | return helpers.testLevels(winston.config.syslog.levels, transport, assertMsg, assertFn);
|
151 | };
|
152 |
|
153 | helpers.testLevels = function (levels, transport, assertMsg, assertFn) {
|
154 | var tests = {};
|
155 |
|
156 | Object.keys(levels).forEach(function (level) {
|
157 | var test = {
|
158 | topic: function () {
|
159 | transport.log(level, 'test message', {}, this.callback.bind(this, null));
|
160 | }
|
161 | };
|
162 |
|
163 | test[assertMsg] = assertFn;
|
164 | tests['with the ' + level + ' level'] = test;
|
165 | });
|
166 |
|
167 | var metadatatest = {
|
168 | topic: function () {
|
169 | transport.log('info', 'test message', { metadata: true }, this.callback.bind(this, null));
|
170 | }
|
171 | };
|
172 |
|
173 | metadatatest[assertMsg] = assertFn;
|
174 | tests['when passed metadata'] = metadatatest;
|
175 |
|
176 | var primmetadatatest = {
|
177 | topic: function () {
|
178 | transport.log('info', 'test message', 'metadata', this.callback.bind(this, null));
|
179 | }
|
180 | };
|
181 |
|
182 | primmetadatatest[assertMsg] = assertFn;
|
183 | tests['when passed primitive metadata'] = primmetadatatest;
|
184 |
|
185 | var circmetadata = { };
|
186 | circmetadata['metadata'] = circmetadata;
|
187 |
|
188 | var circmetadatatest = {
|
189 | topic: function () {
|
190 | transport.log('info', 'test message', circmetadata, this.callback.bind(this, null));
|
191 | }
|
192 | };
|
193 |
|
194 | circmetadatatest[assertMsg] = assertFn;
|
195 | tests['when passed circular metadata'] = circmetadatatest;
|
196 |
|
197 | return tests;
|
198 | };
|
199 |
|
200 | helpers.assertOptionsThrow = function (options, errMsg) {
|
201 | return function () {
|
202 | assert.throws(
|
203 | function () {
|
204 | try {
|
205 | new (winston.transports.Console)(options);
|
206 | } catch (err) {
|
207 | throw(err);
|
208 | }
|
209 | },
|
210 | new RegExp('^' + errMsg.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$')
|
211 | );
|
212 | }
|
213 | };
|
214 |
|
215 | helpers.assertStderrLevels = function (transport, stderrLevels) {
|
216 | return function () {
|
217 | assert.equal(
|
218 | JSON.stringify(Object.keys(transport.stderrLevels).sort()),
|
219 | JSON.stringify(stderrLevels.sort())
|
220 | );
|
221 | }
|
222 | };
|
223 |
|
224 | helpers.testLoggingToStreams = function (levels, transport, stderrLevels, stdMocks) {
|
225 | return {
|
226 | topic: function () {
|
227 | stdMocks.use();
|
228 | transport.showLevel = true;
|
229 | Object.keys(levels).forEach(function (level) {
|
230 | transport.log(
|
231 | level,
|
232 | level + ' should go to ' + (stderrLevels.indexOf(level) > -1 ? 'stderr' : 'stdout'),
|
233 | {},
|
234 | function () {}
|
235 | );
|
236 | });
|
237 | var output = stdMocks.flush();
|
238 | stdMocks.restore();
|
239 | this.callback(null, output, levels);
|
240 | },
|
241 | "output should go to the appropriate streams": function (ign, output, levels) {
|
242 | var outCount = 0,
|
243 | errCount = 0;
|
244 | Object.keys(levels).forEach(function (level) {
|
245 | var line;
|
246 | if (stderrLevels.indexOf(level) > -1) {
|
247 | line = output.stderr[errCount++];
|
248 | assert.equal(line, level + ': ' + level + ' should go to stderr\n');
|
249 | } else {
|
250 | line = output.stdout[outCount++];
|
251 | assert.equal(line, level + ': ' + level + ' should go to stdout\n');
|
252 | }
|
253 | });
|
254 | }
|
255 | }
|
256 | };
|