Skip to content

Commit 6d156d1

Browse files
committed
Allow selection of region, timeout and memory allocation (#202)
1 parent 65047d0 commit 6d156d1

23 files changed

+799
-99
lines changed

integration_test/functions/src/firestore-tests.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import DocumentSnapshot = admin.firestore.DocumentSnapshot;
55

66
const testIdFieldName = 'documentId';
77

8-
export const firestoreTests: any = functions.firestore
9-
.document('tests/{documentId}')
8+
export const firestoreTests: any = functions
9+
.runWith({
10+
timeoutSeconds: 540,
11+
})
12+
.firestore.document('tests/{documentId}')
1013
.onCreate((s, c) => {
1114
return new TestSuite<DocumentSnapshot>('firestore document onWrite')
1215

integration_test/functions/src/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,13 @@ function callHttpsTrigger(name: string, data: any) {
4545
});
4646
}
4747

48-
export const integrationTests: any = functions.https.onRequest(
49-
(req: Request, resp: Response) => {
48+
export const integrationTests: any = functions
49+
.runWith({
50+
timeoutSeconds: 540,
51+
})
52+
.https.onRequest((req: Request, resp: Response) => {
53+
let pubsub: any = require('@google-cloud/pubsub')();
54+
5055
const testId = firebase
5156
.database()
5257
.ref()
@@ -134,5 +139,4 @@ export const integrationTests: any = functions.https.onRequest(
134139
}.firebaseio.com/testRuns/${testId}`
135140
);
136141
});
137-
}
138-
);
142+
});

spec/function-builder.spec.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2017 Firebase
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
import { expect } from 'chai';
24+
25+
import * as functions from '../src/index';
26+
27+
describe('FunctionBuilder', () => {
28+
before(() => {
29+
process.env.GCLOUD_PROJECT = 'not-a-project';
30+
});
31+
32+
after(() => {
33+
delete process.env.GCLOUD_PROJECT;
34+
});
35+
36+
it('should allow region to be set', () => {
37+
let fn = functions
38+
.region('my-region')
39+
.auth.user()
40+
.onCreate(user => user);
41+
42+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
43+
});
44+
45+
it('should allow multiple regions to be set', () => {
46+
let fn = functions
47+
.region('my-region', 'my-other-region')
48+
.auth.user()
49+
.onCreate(user => user);
50+
51+
expect(fn.__trigger.regions).to.deep.equal([
52+
'my-region',
53+
'my-other-region',
54+
]);
55+
});
56+
57+
it('should allow runtime options to be set', () => {
58+
let fn = functions
59+
.runWith({
60+
timeoutSeconds: 90,
61+
memory: '256MB',
62+
})
63+
.auth.user()
64+
.onCreate(user => user);
65+
66+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
67+
expect(fn.__trigger.timeout).to.deep.equal('90s');
68+
});
69+
70+
it('should allow both region and runtime options to be set', () => {
71+
let fn = functions
72+
.region('my-region')
73+
.runWith({
74+
timeoutSeconds: 90,
75+
memory: '256MB',
76+
})
77+
.auth.user()
78+
.onCreate(user => user);
79+
80+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
81+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
82+
expect(fn.__trigger.timeout).to.deep.equal('90s');
83+
});
84+
85+
it('should allow both region and runtime options to be set (reverse order)', () => {
86+
let fn = functions
87+
.runWith({
88+
timeoutSeconds: 90,
89+
memory: '256MB',
90+
})
91+
.region('my-region')
92+
.auth.user()
93+
.onCreate(user => user);
94+
95+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
96+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
97+
expect(fn.__trigger.timeout).to.deep.equal('90s');
98+
});
99+
100+
it('should throw an error if user chooses an unsupported memory allocation', () => {
101+
expect(() => {
102+
return functions.runWith({
103+
memory: 'unsupported',
104+
} as any);
105+
}).to.throw(Error);
106+
107+
expect(() => {
108+
return functions.region('some-region').runWith({
109+
memory: 'unsupported',
110+
} as any);
111+
}).to.throw(Error);
112+
});
113+
});

spec/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import './apps.spec';
3333
import './cloud-functions.spec';
3434
import './config.spec';
3535
import './testing.spec';
36+
import './function-builder.spec';
3637
import './providers/analytics.spec';
3738
import './providers/auth.spec';
3839
import './providers/database.spec';

spec/providers/analytics.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import * as analytics from '../../src/providers/analytics';
2424
import { expect } from 'chai';
2525
import { LegacyEvent } from '../../src/cloud-functions';
2626
import * as analytics_spec_input from './analytics.spec.input';
27+
import * as functions from '../../src/index';
2728

2829
describe('Analytics Functions', () => {
2930
describe('EventBuilder', () => {
@@ -35,6 +36,21 @@ describe('Analytics Functions', () => {
3536
delete process.env.GCLOUD_PROJECT;
3637
});
3738

39+
it('should allow both region and runtime options to be set', () => {
40+
let fn = functions
41+
.region('my-region')
42+
.runWith({
43+
timeoutSeconds: 90,
44+
memory: '256MB',
45+
})
46+
.analytics.event('event')
47+
.onLog(event => event);
48+
49+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
50+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
51+
expect(fn.__trigger.timeout).to.deep.equal('90s');
52+
});
53+
3854
describe('#onLog', () => {
3955
it('should return a TriggerDefinition with appropriate values', () => {
4056
const cloudFunction = analytics.event('first_open').onLog(() => null);

spec/providers/auth.spec.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23-
import * as auth from '../../src/providers/auth';
2423
import { expect } from 'chai';
2524
import * as firebase from 'firebase-admin';
26-
import { CloudFunction } from '../../src';
25+
import * as auth from '../../src/providers/auth';
26+
import { CloudFunction } from '../../src/cloud-functions';
27+
import * as functions from '../../src/index';
2728

2829
describe('Auth Functions', () => {
2930
describe('AuthBuilder', () => {
@@ -37,6 +38,21 @@ describe('Auth Functions', () => {
3738
delete process.env.GCLOUD_PROJECT;
3839
});
3940

41+
it('should allow both region and runtime options to be set', () => {
42+
let fn = functions
43+
.region('my-region')
44+
.runWith({
45+
timeoutSeconds: 90,
46+
memory: '256MB',
47+
})
48+
.auth.user()
49+
.onCreate(() => null);
50+
51+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
52+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
53+
expect(fn.__trigger.timeout).to.deep.equal('90s');
54+
});
55+
4056
describe('#onCreate', () => {
4157
it('should return a TriggerDefinition with appropriate values', () => {
4258
const cloudFunction = auth.user().onCreate(() => null);

spec/providers/crashlytics.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23+
import { expect } from 'chai';
24+
2325
import * as crashlytics from '../../src/providers/crashlytics';
2426
import { apps as appsNamespace } from '../../src/apps';
25-
import { expect } from 'chai';
27+
import * as functions from '../../src/index';
2628

2729
describe('Crashlytics Functions', () => {
2830
describe('Issue Builder', () => {
@@ -36,6 +38,21 @@ describe('Crashlytics Functions', () => {
3638
delete process.env.GCLOUD_PROJECT;
3739
});
3840

41+
it('should allow both region and runtime options to be set', () => {
42+
let fn = functions
43+
.region('my-region')
44+
.runWith({
45+
timeoutSeconds: 90,
46+
memory: '256MB',
47+
})
48+
.crashlytics.issue()
49+
.onNew(issue => issue);
50+
51+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
52+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
53+
expect(fn.__trigger.timeout).to.deep.equal('90s');
54+
});
55+
3956
describe('#onNew', () => {
4057
it('should return a TriggerDefinition with appropriate values', () => {
4158
const cloudFunction = crashlytics.issue().onNew(data => null);

spec/providers/database.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import * as database from '../../src/providers/database';
2424
import { expect } from 'chai';
2525
import { apps as appsNamespace } from '../../src/apps';
2626
import { applyChange } from '../../src/utils';
27+
import * as functions from '../../src/index';
2728

2829
describe('Database Functions', () => {
2930
describe('DatabaseBuilder', () => {
@@ -41,6 +42,21 @@ describe('Database Functions', () => {
4142
delete appsNamespace.singleton;
4243
});
4344

45+
it('should allow both region and runtime options to be set', () => {
46+
let fn = functions
47+
.region('my-region')
48+
.runWith({
49+
timeoutSeconds: 90,
50+
memory: '256MB',
51+
})
52+
.database.ref('/')
53+
.onCreate(snap => snap);
54+
55+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
56+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
57+
expect(fn.__trigger.timeout).to.deep.equal('90s');
58+
});
59+
4460
describe('#onWrite()', () => {
4561
it('should return "ref.write" as the event type', () => {
4662
let eventType = database.ref('foo').onWrite(() => null).__trigger

spec/providers/firestore.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import * as firestore from '../../src/providers/firestore';
2424
import * as _ from 'lodash';
2525
import { expect } from 'chai';
26+
import * as functions from '../../src/index';
2627

2728
describe('Firestore Functions', () => {
2829
function constructValue(fields: any) {
@@ -117,6 +118,21 @@ describe('Firestore Functions', () => {
117118
);
118119
});
119120

121+
it('should allow both region and runtime options to be set', () => {
122+
let fn = functions
123+
.region('my-region')
124+
.runWith({
125+
timeoutSeconds: 90,
126+
memory: '256MB',
127+
})
128+
.firestore.document('doc')
129+
.onCreate(snap => snap);
130+
131+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
132+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
133+
expect(fn.__trigger.timeout).to.deep.equal('90s');
134+
});
135+
120136
it('onCreate should have the "document.create" eventType', () => {
121137
let resource =
122138
'projects/project1/databases/(default)/documents/users/{uid}';

spec/providers/https.spec.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23+
import { expect } from 'chai';
2324
import * as express from 'express';
2425
import * as firebase from 'firebase-admin';
2526
import * as https from '../../src/providers/https';
@@ -28,7 +29,7 @@ import * as mocks from '../fixtures/credential/key.json';
2829
import * as nock from 'nock';
2930
import * as _ from 'lodash';
3031
import { apps as appsNamespace } from '../../src/apps';
31-
import { expect } from 'chai';
32+
import * as functions from '../../src/index';
3233

3334
describe('CloudHttpsBuilder', () => {
3435
describe('#onRequest', () => {
@@ -38,6 +39,20 @@ describe('CloudHttpsBuilder', () => {
3839
});
3940
expect(result.__trigger).to.deep.equal({ httpsTrigger: {} });
4041
});
42+
43+
it('should allow both region and runtime options to be set', () => {
44+
let fn = functions
45+
.region('my-region')
46+
.runWith({
47+
timeoutSeconds: 90,
48+
memory: '256MB',
49+
})
50+
.https.onRequest(() => null);
51+
52+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
53+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
54+
expect(fn.__trigger.timeout).to.deep.equal('90s');
55+
});
4156
});
4257
});
4358

@@ -490,6 +505,20 @@ describe('callable.FunctionBuilder', () => {
490505
},
491506
});
492507
});
508+
509+
it('should allow both region and runtime options to be set', () => {
510+
let fn = functions
511+
.region('my-region')
512+
.runWith({
513+
timeoutSeconds: 90,
514+
memory: '256MB',
515+
})
516+
.https.onCall(() => null);
517+
518+
expect(fn.__trigger.regions).to.deep.equal(['my-region']);
519+
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
520+
expect(fn.__trigger.timeout).to.deep.equal('90s');
521+
});
493522
});
494523
});
495524

0 commit comments

Comments
 (0)