Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

functions: add region tags to tests #1499

Merged
merged 1 commit into from
Oct 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions functions/background/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,25 @@ it('should make a promise request', async () => {
assert.ok(response.body.includes(`Example Domain`));
});

it('should return synchronously', () => {
assert.strictEqual(
program.helloSynchronous({
something: true,
}),
'Something is true!'
);
});

it('should throw an error', () => {
assert.throws(
() => {
describe('functions_background_synchronous', () => {
it('should return synchronously', () => {
assert.strictEqual(
program.helloSynchronous({
something: false,
});
},
Error,
'Something was not true!'
);
something: true,
}),
'Something is true!'
);
});

it('should throw an error', () => {
assert.throws(
() => {
program.helloSynchronous({
something: false,
});
},
Error,
'Something was not true!'
);
});
});
135 changes: 72 additions & 63 deletions functions/billing/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,28 @@ describe('functions/billing tests', () => {
await handleLinuxFailures(ffProc);
});

it('should notify Slack when budget is exceeded', async () => {
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const response = await requestRetry({
url: `${BASE_URL}/notifySlack`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
describe('functions_billing_slack', () => {
it('should notify Slack when budget is exceeded', async () => {
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const response = await requestRetry({
url: `${BASE_URL}/notifySlack`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
});

assert.strictEqual(response.statusCode, 200);
assert.strictEqual(
response.body,
'Slack notification sent successfully'
);
});

assert.strictEqual(response.statusCode, 200);
assert.strictEqual(response.body, 'Slack notification sent successfully');
});
});

Expand All @@ -105,60 +110,64 @@ describe('functions/billing tests', () => {
await handleLinuxFailures(ffProc);
});

it('should disable billing when budget is exceeded', async () => {
// Use functions framework to ensure sample follows GCF specification
// (Invoking it directly works too, but DOES NOT ensure GCF compatibility)
describe('functions_billing_stop', () => {
it('should disable billing when budget is exceeded', async () => {
// Use functions framework to ensure sample follows GCF specification
// (Invoking it directly works too, but DOES NOT ensure GCF compatibility)
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const response = await requestRetry({
url: `${BASE_URL}/stopBilling`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
});

assert.strictEqual(response.statusCode, 200);
assert.ok(response.body.includes('Billing disabled'));
});
});
});
});

describe('shuts down GCE instances', () => {
describe('functions_billing_limit', () => {
it('should attempt to shut down GCE instances when budget is exceeded', async () => {
// Mock GCE (because real GCE instances take too long to start/stop)
const listInstancesResponseMock = {
data: {
items: [{name: 'test-instance-1', status: 'RUNNING'}],
},
};

const computeMock = {
instances: {
list: sinon.stub().returns(listInstancesResponseMock),
stop: sinon.stub().resolves({data: {}}),
},
};

const googleapisMock = Object.assign({}, googleapis);
googleapisMock.google.compute = sinon.stub().returns(computeMock);

// Run test
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const response = await requestRetry({
url: `${BASE_URL}/stopBilling`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
});
const sample = proxyquire('../', {googleapis: googleapisMock}); // kokoro-allow-mock

assert.strictEqual(response.statusCode, 200);
assert.ok(response.body.includes('Billing disabled'));
});
});
});
await sample.limitUse(pubsubMessage);

describe('shuts down GCE instances', () => {
it('should attempt to shut down GCE instances when budget is exceeded', async () => {
// Mock GCE (because real GCE instances take too long to start/stop)
const listInstancesResponseMock = {
data: {
items: [{name: 'test-instance-1', status: 'RUNNING'}],
},
};

const computeMock = {
instances: {
list: sinon.stub().returns(listInstancesResponseMock),
stop: sinon.stub().resolves({data: {}}),
},
};

const googleapisMock = Object.assign({}, googleapis);
googleapisMock.google.compute = sinon.stub().returns(computeMock);

// Run test
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const sample = proxyquire('../', {googleapis: googleapisMock}); // kokoro-allow-mock

await sample.limitUse(pubsubMessage);

assert.strictEqual(computeMock.instances.list.calledOnce, true);
assert.ok(computeMock.instances.stop.calledOnce);
assert.strictEqual(computeMock.instances.list.calledOnce, true);
assert.ok(computeMock.instances.stop.calledOnce);
});
});
});
46 changes: 25 additions & 21 deletions functions/billing/test/periodic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,34 @@ before(async () => {
}
});

it('should shut down GCE instances when budget is exceeded', async () => {
const ffProc = execPromise(
`functions-framework --target=limitUse --signature-type=event`,
{timeout: 1000, shell: true, cwd}
);
describe('functions_billing_limit', () => {
it('should shut down GCE instances when budget is exceeded', async () => {
const ffProc = execPromise(
`functions-framework --target=limitUse --signature-type=event`,
{timeout: 1000, shell: true, cwd}
);

const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString('base64');
const pubsubMessage = {data: encodedData, attributes: {}};
const jsonData = {costAmount: 500, budgetAmount: 400};
const encodedData = Buffer.from(JSON.stringify(jsonData)).toString(
'base64'
);
const pubsubMessage = {data: encodedData, attributes: {}};

const response = await requestRetry({
url: `${BASE_URL}/`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
});
const response = await requestRetry({
url: `${BASE_URL}/`,
method: 'POST',
body: {data: pubsubMessage},
retryDelay: 200,
json: true,
});

// Wait for the functions framework to stop
// Must be BEFORE assertions, in case they fail
await ffProc;
// Wait for the functions framework to stop
// Must be BEFORE assertions, in case they fail
await ffProc;

console.log(response.body);
console.log(response.body);

assert.strictEqual(response.statusCode, 200);
assert.ok(response.body.includes('instance(s) stopped successfully'));
assert.strictEqual(response.statusCode, 200);
assert.ok(response.body.includes('instance(s) stopped successfully'));
});
});
112 changes: 57 additions & 55 deletions functions/composer-storage-trigger/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,62 +30,64 @@ const getSample = FetchStub => {
};
};

it('Handles error in JSON body', async () => {
const event = {
data: {
file: 'some-file',
},
};
const expectedMsg = 'Something bad happened.';
const bodyJson = {error: expectedMsg};
const body = {
json: sinon.stub().returns(bodyJson),
};
const sample = getSample(sinon.stub().resolves(body));
describe('composer_trigger', () => {
it('Handles error in JSON body', async () => {
const event = {
data: {
file: 'some-file',
},
};
const expectedMsg = 'Something bad happened.';
const bodyJson = {error: expectedMsg};
const body = {
json: sinon.stub().returns(bodyJson),
};
const sample = getSample(sinon.stub().resolves(body));

try {
await sample.program.triggerDag(event);
assert.fail('No error thrown');
} catch (err) {
assert.deepStrictEqual(err, new Error('Something bad happened.'));
}
});
try {
await sample.program.triggerDag(event);
assert.fail('No error thrown');
} catch (err) {
assert.deepStrictEqual(err, new Error('Something bad happened.'));
}
});

it('Handles error in IAP response.', async () => {
const event = {
data: {
file: 'some-file',
},
};
const expectedMsg = 'Default IAP Error Message.';
it('Handles error in IAP response.', async () => {
const event = {
data: {
file: 'some-file',
},
};
const expectedMsg = 'Default IAP Error Message.';

const serviceAccountAccessTokenRes = {
json: sinon.stub().resolves({access_token: 'default-access-token'}),
};
const signJsonClaimRes = {
json: sinon.stub().resolves({signature: 'default-jwt-signature'}),
};
const getTokenRes = {
json: sinon.stub().resolves({id_token: 'default-id-token'}),
};
const makeIapPostRequestRes = {
ok: false,
text: sinon.stub().resolves(expectedMsg),
};
const FetchStub = sinon
.stub()
.onCall(0)
.resolves(serviceAccountAccessTokenRes)
.onCall(1)
.resolves(signJsonClaimRes)
.onCall(2)
.resolves(getTokenRes)
.onCall(3)
.resolves(makeIapPostRequestRes);
const sample = getSample(FetchStub);
try {
await sample.program.triggerDag(event);
} catch (err) {
assert.deepStrictEqual(err, new Error(expectedMsg));
}
const serviceAccountAccessTokenRes = {
json: sinon.stub().resolves({access_token: 'default-access-token'}),
};
const signJsonClaimRes = {
json: sinon.stub().resolves({signature: 'default-jwt-signature'}),
};
const getTokenRes = {
json: sinon.stub().resolves({id_token: 'default-id-token'}),
};
const makeIapPostRequestRes = {
ok: false,
text: sinon.stub().resolves(expectedMsg),
};
const FetchStub = sinon
.stub()
.onCall(0)
.resolves(serviceAccountAccessTokenRes)
.onCall(1)
.resolves(signJsonClaimRes)
.onCall(2)
.resolves(getTokenRes)
.onCall(3)
.resolves(makeIapPostRequestRes);
const sample = getSample(FetchStub);
try {
await sample.program.triggerDag(event);
} catch (err) {
assert.deepStrictEqual(err, new Error(expectedMsg));
}
});
});
14 changes: 8 additions & 6 deletions functions/concepts/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ const sample = require('../');
beforeEach(tools.stubConsole);
afterEach(tools.restoreConsole);

it('should demonstrate error type behavior', () => {
const objError = new Error('Error object!');
describe('functions_concepts_error_object', () => {
it('should demonstrate error type behavior', () => {
const objError = new Error('Error object!');

const req = {body: {throwAsString: true}};
const res = {end: sinon.stub()};
const req = {body: {throwAsString: true}};
const res = {end: sinon.stub()};

sample.errorTypes(req, res);
assert.deepStrictEqual(console.error.getCall(0).args, [objError]);
sample.errorTypes(req, res);
assert.deepStrictEqual(console.error.getCall(0).args, [objError]);
});
});
Loading