forked from remotestorage/armadietto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rate_limiter_spec.js
118 lines (105 loc) · 3.65 KB
/
rate_limiter_spec.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* eslint-env mocha, chai, node */
const chai = require('chai');
const chaiHttp = require('chai-http');
const spies = require('chai-spies');
const expect = chai.expect;
const chaiAsPromised = require('chai-as-promised');
const Armadietto = require('../../lib/armadietto');
chai.use(chaiHttp);
chai.use(chaiAsPromised);
chai.use(spies);
// const req = chai.request('http://localhost:4568');
const store = {
get (username, path) {
return { item: null, versionMatch: true };
},
permissions (user, token) {
if (user === 'zebcoe' && token === 'a_token') {
return {
'/data': ['r']
};
}
}
};
const RateLimiter = require('../../lib/extensions/rate_limiter/rate_limiter');
RateLimiter.connect = () => {};
RateLimiter.rateLimiterRedis = {};
/**
* Below is the `opts` options object passed to Armadietto to intialize and dependency inject. E.g. we
* dependency inject `store` below.
*
* Middleware is also dependency injected in the same fashion as the `middleware` array.
*
* You can see this done in each test below, where we dependency inject an array of some combination of the
* above sample classes.
*/
const opts = {
store,
http: { port: 4567 },
logging: { log_dir: './test-log', stdout: [], log_files: ['error'] },
middleware: [RateLimiter],
extensions: {
rate_limiter: {
enabled: true
}
}
};
const sandbox = chai.spy.sandbox();
describe('rate_limiter', () => {
beforeEach((done) => {
(async () => {
sandbox.on(store, ['get']);
done();
})();
});
afterEach((done) => {
(async () => {
sandbox.restore();
done();
})();
});
const req = chai.request('http://localhost:4567');
const get = async (path) => {
const ret = await req.get(path)
.set('Authorization', 'Bearer a_token').send();
return ret;
};
it('rate limit storage request', async () => {
const server = new Armadietto(opts); /* no middleware stack setup for this test */
await server.boot();
const err = 'throttle';
sandbox.on(RateLimiter.rateLimiterRedis, 'consume', () => { throw err; });
const ret = await get('/storage/zebcoe@local.dev/data');
expect(RateLimiter.rateLimiterRedis.consume).to.have.been.called.exactly(1);
expect(ret.statusCode).to.eql(429);
await server.stop();
});
it('pass rate limit during storage request', async () => {
const server = new Armadietto(opts); /* no middleware stack setup for this test */
await server.boot();
sandbox.on(RateLimiter.rateLimiterRedis, 'consume', () => {});
const ret = await get('/storage/zebcoe@local.dev/data');
expect(RateLimiter.rateLimiterRedis.consume).to.have.been.called.exactly(1);
expect(ret.statusCode).to.not.eql(429);
await server.stop();
});
it('pass rate limit for storage OPTIONS request', async () => {
const server = new Armadietto(opts); /* no middleware stack setup for this test */
await server.boot();
const err = 'throttle';
sandbox.on(RateLimiter.rateLimiterRedis, 'consume', () => { throw err; });
const ret = await req.options('/storage/zebcoe@local.dev/data');
expect(RateLimiter.rateLimiterRedis.consume).to.have.been.called.exactly(0);
expect(ret.statusCode).to.not.eql(429);
await server.stop();
});
it('pass rate limit for non-storage request', async () => {
const server = new Armadietto(opts); /* no middleware stack setup for this test */
await server.boot();
sandbox.on(RateLimiter.rateLimiterRedis, 'consume', () => {});
const ret = await req.options('/blah');
expect(RateLimiter.rateLimiterRedis.consume).to.have.been.called.exactly(0);
expect(ret.statusCode).to.not.eql(429);
await server.stop();
});
});