UNPKG

8.82 kBJavaScriptView Raw
1'use strict';
2
3var test = require('tap').test
4 , EventEmitter = require('events').EventEmitter
5 , cls = require('../context.js')
6 ;
7
8function fresh(name, context) {
9 context.tearDown(function () {
10 cls.destroyNamespace(name);
11 });
12 return cls.createNamespace(name);
13}
14
15test("event emitters bound to CLS context", function (t) {
16 t.plan(12);
17
18 t.test("handler registered in context", function (t) {
19 t.plan(1);
20
21 var n = fresh('in', this)
22 , ee = new EventEmitter()
23 ;
24
25 n.run(function () {
26 n.set('value', 'hello');
27 n.bindEmitter(ee);
28 ee.on('event', function () {
29 t.equal(n.get('value'), 'hello', "value still set in EE.");
30 });
31 });
32
33 ee.emit('event');
34 });
35
36 t.test("once handler registered in context", function (t) {
37 t.plan(1);
38
39 var n = fresh('inOnce', this)
40 , ee = new EventEmitter()
41 ;
42
43 n.run(function () {
44 n.set('value', 'hello');
45 n.bindEmitter(ee);
46 ee.once('event', function () {
47 t.equal(n.get('value'), 'hello', "value still set in EE.");
48 });
49 });
50
51 ee.emit('event');
52 });
53
54 t.test("handler registered out of context", function (t) {
55 t.plan(1);
56
57 var n = fresh('out', this)
58 , ee = new EventEmitter()
59 ;
60
61 ee.on('event', function () {
62 t.equal(n.get('value'), 'hello', "value still set in EE.");
63 });
64
65 n.run(function () {
66 n.set('value', 'hello');
67 n.bindEmitter(ee);
68
69 ee.emit('event');
70 });
71 });
72
73 t.test("once handler registered out of context", function (t) {
74 t.plan(1);
75
76 var n = fresh('outOnce', this)
77 , ee = new EventEmitter()
78 ;
79
80 ee.once('event', function () {
81 t.equal(n.get('value'), 'hello', "value still set in EE.");
82 });
83
84 n.run(function () {
85 n.set('value', 'hello');
86 n.bindEmitter(ee);
87
88 ee.emit('event');
89 });
90 });
91
92 t.test("once handler registered out of context on Readable", function (t) {
93 var Readable = require('stream').Readable;
94
95 if (Readable) {
96 t.plan(12);
97
98 var n = fresh('outOnceReadable', this)
99 , re = new Readable()
100 ;
101
102 re._read = function () {};
103
104 t.ok(n.name, "namespace has a name");
105 t.equal(n.name, 'outOnceReadable', "namespace has a name");
106
107 re.once('data', function (data) {
108 t.equal(n.get('value'), 'hello', "value still set in EE");
109 t.equal(data, 'blah', "emit still works");
110 });
111
112 n.run(function () {
113 n.set('value', 'hello');
114
115 t.notOk(re.emit.__wrapped, "emit is not wrapped");
116 t.notOk(re.on.__wrapped, "on is not wrapped");
117 t.notOk(re.addListener.__wrapped, "addListener is not wrapped");
118
119 n.bindEmitter(re);
120
121 t.ok(re.emit.__wrapped, "emit is wrapped");
122 t.ok(re.on.__wrapped, "on is wrapped");
123 t.ok(re.addListener.__wrapped, "addListener is wrapped");
124
125 t.equal(typeof re._events.data, 'function', 'only the one data listener');
126 t.notOk(re._events.data['context@outOnceReadable'], "context isn't on listener");
127
128 re.emit('data', 'blah');
129 });
130 }
131 else {
132 t.comment("this test requires node 0.10+");
133 t.end();
134 }
135 });
136
137 t.test("emitter with newListener that removes handler", function (t) {
138 t.plan(3);
139
140 var n = fresh('newListener', this)
141 , ee = new EventEmitter()
142 ;
143
144 // add monkeypatching to ee
145 n.bindEmitter(ee);
146
147 function listen() {
148 ee.on('data', function (chunk) {
149 t.equal(chunk, 'chunk', 'listener still works');
150 });
151 }
152
153 ee.on('newListener', function handler(event) {
154 if (event !== 'data') return;
155
156 this.removeListener('newListener', handler);
157 t.notOk(this.listeners('newListener').length, 'newListener was removed');
158 process.nextTick(listen);
159 });
160
161 ee.on('drain', function (chunk) {
162 process.nextTick(function () {
163 ee.emit('data', chunk);
164 });
165 });
166
167 ee.on('data', function (chunk) {
168 t.equal(chunk, 'chunk', 'got data event');
169 });
170
171 ee.emit('drain', 'chunk');
172 });
173
174 t.test("handler registered in context on Readable", function (t) {
175 var Readable = require('stream').Readable;
176
177 if (Readable) {
178 t.plan(12);
179
180 var n = fresh('outOnReadable', this)
181 , re = new Readable()
182 ;
183
184 re._read = function () {};
185
186 t.ok(n.name, "namespace has a name");
187 t.equal(n.name, 'outOnReadable', "namespace has a name");
188
189 n.run(function () {
190 n.set('value', 'hello');
191
192 n.bindEmitter(re);
193
194 t.ok(re.emit.__wrapped, "emit is wrapped");
195 t.ok(re.on.__wrapped, "on is wrapped");
196 t.ok(re.addListener.__wrapped, "addListener is wrapped");
197
198 re.on('data', function (data) {
199 t.equal(n.get('value'), 'hello', "value still set in EE");
200 t.equal(data, 'blah', "emit still works");
201 });
202 });
203
204 t.ok(re.emit.__wrapped, "emit is still wrapped");
205 t.ok(re.on.__wrapped, "on is still wrapped");
206 t.ok(re.addListener.__wrapped, "addListener is still wrapped");
207
208 t.equal(typeof re._events.data, 'function', 'only the one data listener');
209 t.ok(re._events.data['cls@contexts']['context@outOnReadable'],
210 "context is bound to listener");
211
212 re.emit('data', 'blah');
213 }
214 else {
215 t.comment("this test requires node 0.10+");
216 t.end();
217 }
218 });
219
220 t.test("handler added but used entirely out of context", function (t) {
221 t.plan(2);
222
223 var n = fresh('none', this)
224 , ee = new EventEmitter()
225 ;
226
227 n.run(function () {
228 n.set('value', 'hello');
229 n.bindEmitter(ee);
230 });
231
232 ee.on('event', function () {
233 t.ok(n, "n is set");
234 t.notOk(n.get('value'), "value shouldn't be visible");
235 });
236
237 ee.emit('event');
238 });
239
240 t.test("handler added but no listeners registered", function (t) {
241 t.plan(3);
242
243 var http = require('http')
244 , n = fresh('no_listener', this)
245 ;
246
247 // only fails on Node < 0.10
248 var server = http.createServer(function (req, res) {
249 n.bindEmitter(req);
250
251 t.doesNotThrow(function () {
252 req.emit('event');
253 });
254
255 res.writeHead(200, {"Content-Length" : 4});
256 res.end('WORD');
257 });
258 server.listen(8080);
259
260 http.get('http://localhost:8080/', function (res) {
261 t.equal(res.statusCode, 200, "request came back OK");
262
263 res.setEncoding('ascii');
264 res.on('data', function (body) {
265 t.equal(body, 'WORD');
266
267 server.close();
268 });
269 });
270 });
271
272 t.test("listener with parameters added but not bound to context", function (t) {
273 t.plan(2);
274
275 var ee = new EventEmitter()
276 , n = fresh('param_list', this)
277 ;
278
279 function sent(value) {
280 t.equal(value, 3, "sent value is correct");
281 }
282
283 ee.on('send', sent);
284 n.bindEmitter(ee);
285 t.doesNotThrow(function () {
286 ee.emit('send', 3);
287 });
288 });
289
290 t.test("listener that throws doesn't leave removeListener wrapped", function (t) {
291 t.plan(4);
292
293 var ee = new EventEmitter()
294 , n = fresh('kaboom', this)
295 ;
296
297 n.bindEmitter(ee);
298
299 function kaboom() {
300 throw new Error('whoops');
301 }
302
303 n.run(function () {
304 ee.on('bad', kaboom);
305
306 t.throws(function () { ee.emit('bad'); });
307 t.equal(typeof ee.removeListener, 'function', 'removeListener is still there');
308 t.notOk(ee.removeListener.__wrapped, "removeListener got unwrapped");
309 t.equal(ee._events.bad, kaboom, "listener isn't still bound");
310 });
311 });
312
313 t.test("emitter bound to multiple namespaces handles them correctly", function (t) {
314 t.plan(8);
315
316 var ee = new EventEmitter()
317 , ns1 = cls.createNamespace('1')
318 , ns2 = cls.createNamespace('2')
319 ;
320
321 // emulate an incoming data emitter
322 setTimeout(function () {
323 ee.emit('data', 'hi');
324 }, 10);
325
326 t.doesNotThrow(function () { ns1.bindEmitter(ee); });
327 t.doesNotThrow(function () { ns2.bindEmitter(ee); });
328
329 ns1.run(function () {
330 ns2.run(function () {
331 ns1.set('name', 'tom1');
332 ns2.set('name', 'tom2');
333
334 t.doesNotThrow(function () { ns1.bindEmitter(ee); });
335 t.doesNotThrow(function () { ns2.bindEmitter(ee); });
336
337 ns1.run(function () {
338 process.nextTick(function () {
339 t.equal(ns1.get('name'), 'tom1', "ns1 value correct");
340 t.equal(ns2.get('name'), 'tom2', "ns2 value correct");
341
342 ns1.set('name', 'bob');
343 ns2.set('name', 'alice');
344
345 ee.on('data', function () {
346 t.equal(ns1.get('name'), 'bob', "ns1 value bound onto emitter");
347 t.equal(ns2.get('name'), 'alice', "ns2 value bound onto emitter");
348 });
349 });
350 });
351 });
352 });
353 });
354});