UNPKG

9.96 kBJavaScriptView Raw
1/*
2 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * Cloudkick licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Many of the modifications to 'assert' that take place here are borrowed
18 * from the 'Expresso' test framework:
19 * <http://visionmedia.github.com/expresso/>
20 *
21 * Expresso
22 * Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
23 * (MIT Licensed)
24 */
25
26var util = require('util');
27var url = require('url');
28var http = require('http');
29var https = require('https');
30
31var port = parseInt((Math.random() * (65500 - 2000) + 2000), 10);
32
33// Code bellow is taken from Node core
34// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
35//
36// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
37//
38// Originally from narwhal.js (http://narwhaljs.org)
39// Copyright (c) 2009 Thomas Robinson <280north.com>
40//
41// Permission is hereby granted, free of charge, to any person obtaining a copy
42// of this software and associated documentation files (the 'Software'), to
43// deal in the Software without restriction, including without limitation the
44// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
45// sell copies of the Software, and to permit persons to whom the Software is
46// furnished to do so, subject to the following conditions:
47//
48// The above copyright notice and this permission notice shall be included in
49// all copies or substantial portions of the Software.
50//
51// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
55// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
56// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
57
58var origAssert = require('assert');
59
60var assert = {};
61
62 /*
63 * Alias deepEqual as eql for complex equality
64 */
65 assert.eql = origAssert.deepEqual;
66
67 /**
68 * Assert that `val` is null.
69 *
70 * @param {Mixed} val
71 * @param {String} msg
72 */
73 assert.isNull = function(val, msg) {
74 assert.strictEqual(null, val, msg);
75 };
76
77 assert.ifError = function(err) {
78 if (err) {
79 if (err instanceof Error) {
80 Error.captureStackTrace(err, arguments.callee);
81 }
82
83 throw err;
84 }
85 };
86
87 /**
88 * Assert that `val` is not null.
89 *
90 * @param {Mixed} val
91 * @param {String} msg
92 */
93 assert.isNotNull = function(val, msg) {
94 assert.notStrictEqual(null, val, msg);
95 };
96
97 /**
98 * Assert that `val` is undefined.
99 *
100 * @param {Mixed} val
101 * @param {String} msg
102 */
103 assert.isUndefined = function(val, msg) {
104 assert.strictEqual(undefined, val, msg);
105 };
106
107 /**
108 * Assert that `val` is not undefined.
109 *
110 * @param {Mixed} val
111 * @param {String} msg
112 */
113 assert.isDefined = function(val, msg) {
114 assert.notStrictEqual(undefined, val, msg);
115 };
116
117 /**
118 * Assert that `obj` is `type`.
119 *
120 * @param {Mixed} obj
121 * @param {String} type
122 * @api public
123 */
124 assert.type = function(obj, type, msg){
125 var real = typeof obj;
126 msg = msg || 'typeof ' + util.inspect(obj) + ' is ' + real + ', expected ' + type;
127 assert.ok(type === real, msg);
128 };
129
130 /**
131 * Assert that `str` matches `regexp`.
132 *
133 * @param {String} str
134 * @param {RegExp} regexp
135 * @param {String} msg
136 */
137 assert.match = function(str, regexp, msg) {
138 msg = msg || util.inspect(str) + ' does not match ' + util.inspect(regexp);
139 assert.ok(regexp.test(str), msg);
140 };
141
142 /**
143 * Assert that `val` is within `obj`.
144 *
145 * Examples:
146 *
147 * assert.includes('foobar', 'bar');
148 * assert.includes(['foo', 'bar'], 'foo');
149 *
150 * @param {String|Array} obj
151 * @param {Mixed} val
152 * @param {String} msg
153 */
154 assert.includes = function(obj, val, msg) {
155 msg = msg || util.inspect(obj) + ' does not include ' + util.inspect(val);
156 assert.ok(obj.indexOf(val) >= 0, msg);
157 };
158
159 /**
160 * Assert length of `val` is `n`.
161 *
162 * @param {Mixed} val
163 * @param {Number} n
164 * @param {String} msg
165 */
166 assert.length = function(val, n, msg) {
167 msg = msg || util.inspect(val) + ' has length of ' + val.length + ', expected ' + n;
168 assert.equal(n, val.length, msg);
169 };
170
171 /**
172 * Assert response from `server` with
173 * the given `req` object and `res` assertions object.
174 *
175 * @param {Server} server
176 * @param {Object} req
177 * @param {Object|Function} res
178 * @param {String} msg
179 */
180 assert.response = function(server, req, res, msg){
181 // Callback as third or fourth arg
182 var callback = typeof res === 'function'
183 ? res
184 : typeof msg === 'function'
185 ? msg
186 : function(){};
187
188 // Default messate to test title
189 if (typeof msg === 'function') msg = null;
190 msg = msg || assert.testTitle;
191 msg += '. ';
192
193 // Pending responses
194 server.__pending = server.__pending || 0;
195 server.__pending++;
196
197 server.listen(server.__port = port++, '127.0.0.1');
198
199 process.nextTick(function() {
200 // Issue request
201 var timer;
202 var trailer;
203 var method = req.method || 'GET';
204 var status = res.status || res.statusCode;
205 var data = req.data || req.body;
206 var streamer = req.streamer;
207 var timeout = req.timeout || 0;
208 var headers = req.headers || {};
209
210 for (trailer in req.trailers) {
211 if (req.trailers.hasOwnProperty(trailer)) {
212 if (headers['Trailer']) {
213 headers['Trailer'] += ', ' + trailer;
214 }
215 else {
216 headers['Trailer'] = trailer;
217 }
218 }
219 }
220
221 var urlParsed = url.parse(req.url);
222 var reqOptions = {
223 'host': '127.0.0.1',
224 'port': server.__port,
225 'path': urlParsed.pathname,
226 'method': method,
227 'headers': headers
228 };
229
230 var reqMethod = (urlParsed.protocol === 'http:' || !urlParsed.hasOwnProperty('protocol')) ? http.request : https.request;
231 var request = http.request(reqOptions);
232
233 if (req.trailers) {
234 request.addTrailers(req.trailers);
235 }
236
237 // Timeout
238 if (timeout) {
239 timer = setTimeout(function(){
240 --server.__pending || server.close();
241 delete req.timeout;
242 assert.fail(msg + 'Request timed out after ' + timeout + 'ms.');
243 }, timeout);
244 }
245
246 if (data) request.write(data);
247
248 request.addListener('response', function(response) {
249 response.body = '';
250 response.setEncoding('utf8');
251 response.addListener('data', function(chunk){ response.body += chunk; });
252 response.addListener('end', function(){
253 --server.__pending || server.close();
254 if (timer) clearTimeout(timer);
255
256 // Assert response body
257 if (res.body !== undefined) {
258 assert.equal(
259 response.body,
260 res.body,
261 msg + 'Invalid response body.\n'
262 + ' Expected: ' + util.inspect(res.body) + '\n'
263 + ' Got: ' + util.inspect(response.body)
264 );
265 }
266
267 // Assert response status
268 if (typeof status === 'number') {
269 assert.equal(
270 response.statusCode,
271 status,
272 msg + 'Invalid response status code.\n'
273 + ' Expected: [{' + status + '}\n'
274 + ' Got: {' + response.sttusCode + '}'
275 );
276 }
277
278 // Assert response headers
279 if (res.headers) {
280 var keys = Object.keys(res.headers);
281 for (var i = 0, len = keys.length; i < len; ++i) {
282 var name = keys[i];
283 var actual = response.headers[name.toLowerCase()];
284 var expected = res.headers[name];
285 assert.equal(
286 actual,
287 expected,
288 msg + 'Invalid response header [bold]{' + name + '}.\n'
289 + ' Expected: {' + expected + '}\n'
290 + ' Got: {' + actual + '}'
291 );
292 }
293 }
294
295 callback(response);
296 });
297 });
298
299 if (streamer) {
300 streamer(request);
301 }
302 else {
303 request.end();
304 }
305 });
306};
307
308function merge(obj1, obj2, ignore) {
309 obj1 = obj1 || assert;
310 ignore = ignore || [];
311
312 for (var key in obj2) {
313 if (obj2.hasOwnProperty(key) && ignore.indexOf(key) === -1) {
314 obj1[key] = obj2[key];
315 }
316 }
317}
318
319function getAssertModule(test) {
320 assert.AssertionError = function AssertionError(options) {
321 origAssert.AssertionError.call(this, options);
322 this.test = test;
323 };
324
325 util.inherits(assert.AssertionError, origAssert.AssertionError);
326
327 var ignore = ['AssertionError'];
328 for (var key in origAssert) {
329 if (origAssert.hasOwnProperty(key) && ignore.indexOf(key) === -1) {
330 assert[key] = (function(key) {
331 return function() {
332 try {
333 origAssert[key].apply(null, arguments);
334 }
335 catch (err) {
336 err.test = test;
337 throw err;
338 }
339 }
340 })(key);
341 }
342 }
343
344 return assert;
345}
346
347exports.getAssertModule = getAssertModule;
348exports.merge = merge;