1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 | const Stream = require('stream');
|
6 |
|
7 | const Code = require('code');
|
8 | const Lab = require('lab');
|
9 |
|
10 | const Squeeze = require('..').Squeeze;
|
11 | const SafeJson = require('..').SafeJson;
|
12 |
|
13 | const lab = exports.lab = Lab.script();
|
14 | const expect = Code.expect;
|
15 | const describe = lab.describe;
|
16 | const it = lab.it;
|
17 |
|
18 | const internals = {
|
19 | readStream() {
|
20 |
|
21 | const stream = new Stream.Readable({ objectMode: true });
|
22 | stream._read = () => {};
|
23 | return stream;
|
24 | }
|
25 | };
|
26 |
|
27 | describe('Squeeze', () => {
|
28 |
|
29 | describe('subscription()', () => {
|
30 |
|
31 | it('converts *, null, undefined, 0, and false to an empty array, indicating all tags are acceptable', { plan: 5 }, (done) => {
|
32 |
|
33 | const tags = ['*', null, undefined, false, 0];
|
34 | for (let i = 0; i < tags.length; ++i) {
|
35 |
|
36 | const result = Squeeze.subscription({ error: tags[i] });
|
37 |
|
38 | expect(result.error).to.deep.equal([]);
|
39 | }
|
40 | done();
|
41 | });
|
42 |
|
43 | it('converts a single tag to an array', { plan: 1 }, (done) => {
|
44 |
|
45 | const result = Squeeze.subscription({ error: 'hapi' });
|
46 | expect(result.error).to.deep.equal(['hapi']);
|
47 | done();
|
48 | });
|
49 | });
|
50 |
|
51 | describe('filter()', () => {
|
52 |
|
53 | it('returns true if this reporter should report this event type', { plan: 1 }, (done) => {
|
54 |
|
55 | const subscription = Squeeze.subscription({ log: '*' });
|
56 | expect(Squeeze.filter(subscription, { event: 'log', tags: ['request', 'server', 'error', 'hapi'] })).to.be.true();
|
57 | done();
|
58 | });
|
59 |
|
60 | it('returns false if this report should not report this event type', { plan: 1 }, (done) => {
|
61 |
|
62 | const subscription = Squeeze.subscription({ log: '*' });
|
63 | expect(Squeeze.filter(subscription, { event: 'ops', tags: ['*'] })).to.be.false();
|
64 | done();
|
65 | });
|
66 |
|
67 | it('returns true if the event is matched, but there are not any tags with the data', { plan: 1 }, (done) => {
|
68 |
|
69 | const subscription = Squeeze.subscription({ log: '*' });
|
70 | expect(Squeeze.filter(subscription, { event: 'log' })).to.be.true();
|
71 | done();
|
72 | });
|
73 |
|
74 | it('returns false if the subscriber has tags, but the matched event does not have any', { plan: 1 }, (done) => {
|
75 |
|
76 | const subscription = Squeeze.subscription({ error: 'db' });
|
77 | expect(Squeeze.filter(subscription, { event: 'error', tags: [] })).to.be.false();
|
78 | done();
|
79 | });
|
80 |
|
81 | it('returns true if the event and tag match', { plan: 1 }, (done) => {
|
82 |
|
83 | const subscription = Squeeze.subscription({ error: ['high', 'medium', 'log'] });
|
84 | expect(Squeeze.filter(subscription, { event: 'error', tags: ['hapi', 'high', 'db', 'severe'] })).to.be.true();
|
85 | done();
|
86 | });
|
87 |
|
88 | it('returns false by default', { plan: 1 }, (done) => {
|
89 |
|
90 | const subscription = Squeeze.subscription({ request: 'hapi' });
|
91 | expect(Squeeze.filter(subscription, { event: 'request' })).to.be.false();
|
92 | done();
|
93 | });
|
94 |
|
95 | it('returns false if "tags" is not an array', { plan: 1 }, (done) => {
|
96 |
|
97 | const subscription = Squeeze.subscription({ request: 'hapi' });
|
98 | expect(Squeeze.filter(subscription, { event: 'request', tags: 'hapi' })).to.be.false();
|
99 | done();
|
100 | });
|
101 | });
|
102 |
|
103 | it('does not forward events if "filter()" is false', { plan: 1 }, (done) => {
|
104 |
|
105 | const stream = new Squeeze({ request: '*' });
|
106 | const result = [];
|
107 |
|
108 | stream.on('data', (data) => {
|
109 |
|
110 | result.push(data);
|
111 | });
|
112 |
|
113 | stream.on('end', () => {
|
114 |
|
115 | expect(result).to.deep.equal([{
|
116 | event: 'request',
|
117 | id: 1
|
118 | }]);
|
119 | done();
|
120 | });
|
121 |
|
122 | const read = internals.readStream();
|
123 |
|
124 | read.pipe(stream);
|
125 |
|
126 | read.push({ event: 'request', id: 1 });
|
127 | read.push({ event: 'ops', id: 2 });
|
128 | read.push(null);
|
129 | });
|
130 |
|
131 | it('remains open as long as the read stream does not end it', { plan: 1 }, (done) => {
|
132 |
|
133 | const stream = new Squeeze({ request: '*' });
|
134 | const result = [];
|
135 |
|
136 | stream.on('data', (data) => {
|
137 |
|
138 | result.push(data);
|
139 | });
|
140 |
|
141 | stream.on('end', () => {
|
142 |
|
143 | expect.fail('End should never be called');
|
144 | });
|
145 |
|
146 | const read = internals.readStream();
|
147 |
|
148 | read.pipe(stream);
|
149 |
|
150 | read.push({ event: 'request', id: 1 });
|
151 | read.push({ event: 'request', id: 2 });
|
152 |
|
153 | setTimeout(() => {
|
154 |
|
155 | read.push({ event: 'request', id: 3 });
|
156 | read.push({ event: 'request', id: 4 });
|
157 |
|
158 | expect(result).to.deep.equal([
|
159 | { event: 'request', id: 1 },
|
160 | { event: 'request', id: 2 },
|
161 | { event: 'request', id: 3 },
|
162 | { event: 'request', id: 4 }
|
163 | ]);
|
164 | done();
|
165 | }, 500);
|
166 | });
|
167 |
|
168 | it('throws an error if "events" not a truthy object', { plan: 2 }, (done) => {
|
169 |
|
170 | expect(() => {
|
171 |
|
172 | new Squeeze('request');
|
173 | }).to.throw('events must be an object');
|
174 | expect(() => {
|
175 |
|
176 | new Squeeze(1);
|
177 | }).to.throw('events must be an object');
|
178 |
|
179 | done();
|
180 | });
|
181 |
|
182 | it('allows empty event arguments', { plan: 1 }, (done) => {
|
183 |
|
184 | const stream = new Squeeze(null);
|
185 |
|
186 | expect(stream._subscription).to.deep.equal(Object.create(null));
|
187 | done();
|
188 | });
|
189 | });
|
190 |
|
191 | describe('SafeJson', () => {
|
192 |
|
193 | it('safely handles circular references in incoming data', { plan: 1 }, (done) => {
|
194 |
|
195 | let result = '';
|
196 | const stream = new SafeJson();
|
197 | const read = internals.readStream();
|
198 |
|
199 | const message = {
|
200 | x: 1
|
201 | };
|
202 | message.y = message;
|
203 |
|
204 | stream.on('data', (data) => {
|
205 |
|
206 | result += data;
|
207 | });
|
208 |
|
209 | stream.on('end', () => {
|
210 |
|
211 | expect(result).to.equal('{"x":1,"y":"[Circular ~]"}{"foo":"bar"}');
|
212 | done();
|
213 | });
|
214 |
|
215 | read.pipe(stream);
|
216 |
|
217 | read.push(message);
|
218 | read.push({ foo: 'bar' });
|
219 | read.push(null);
|
220 | });
|
221 |
|
222 | it('adds a seperator value when specified', { plan: 1 }, (done) => {
|
223 |
|
224 | let result = '';
|
225 | const stream = new SafeJson({}, { separator: '#' });
|
226 | const read = internals.readStream();
|
227 |
|
228 | stream.on('data', (data) => {
|
229 |
|
230 | result += data;
|
231 | });
|
232 |
|
233 | stream.on('end', () => {
|
234 |
|
235 | expect(result).to.equal('{"foo":"bar"}#{"bar":"baz"}#');
|
236 | done();
|
237 | });
|
238 |
|
239 | read.pipe(stream);
|
240 |
|
241 | read.push({ foo: 'bar' });
|
242 | read.push({ bar: 'baz' });
|
243 | read.push(null);
|
244 | });
|
245 | });
|