@@ -3,6 +3,7 @@ import * as admin from 'firebase-admin';
33import * as functions from 'firebase-functions' ;
44import * as fs from 'fs' ;
55import * as https from 'https' ;
6+ import { PubSub } from '@google-cloud/pubsub' ;
67
78export * from './pubsub-tests' ;
89export * from './database-tests' ;
@@ -18,6 +19,7 @@ import * as utils from './test-utils';
1819import * as testLab from './testLab-utils' ;
1920
2021import 'firebase-functions' ; // temporary shim until process.env.FIREBASE_CONFIG available natively in GCF(BUG 63586213)
22+ import { config } from 'firebase-functions' ;
2123const firebaseConfig = JSON . parse ( process . env . FIREBASE_CONFIG ) ;
2224admin . initializeApp ( ) ;
2325const REGION = functions . config ( ) . functions . test_region ;
@@ -37,26 +39,42 @@ function callHttpsTrigger(name: string, data: any, baseUrl) {
3739 ) ;
3840}
3941
40- function callScheduleTrigger ( functionName : string , region : string ) {
41- return new Promise ( ( resolve , reject ) => {
42+ async function callScheduleTrigger ( functionName : string , region : string ) {
43+ const accessToken = await admin . credential
44+ . applicationDefault ( )
45+ . getAccessToken ( ) ;
46+ return new Promise < string > ( ( resolve , reject ) => {
4247 const request = https . request (
4348 {
4449 method : 'POST' ,
4550 host : 'cloudscheduler.googleapis.com' ,
46- path : `projects/${ firebaseConfig . projectId } /locations/us-central1/jobs/firebase-schedule-${ functionName } -${ region } :run` ,
51+ path : `/v1/ projects/${ firebaseConfig . projectId } /locations/us-central1/jobs/firebase-schedule-${ functionName } -${ region } :run` ,
4752 headers : {
4853 'Content-Type' : 'application/json' ,
54+ Authorization : `Bearer ${ accessToken . access_token } ` ,
4955 } ,
5056 } ,
5157 ( response ) => {
58+ if ( response . statusCode ! / 100 != 2 ) {
59+ reject (
60+ new Error ( 'Failed request with status ' + response . statusCode ! )
61+ ) ;
62+ return ;
63+ }
5264 let body = '' ;
5365 response . on ( 'data' , ( chunk ) => {
5466 body += chunk ;
5567 } ) ;
56- response . on ( 'end' , ( ) => resolve ( body ) ) ;
68+ response . on ( 'end' , ( ) => {
69+ console . log ( `Successfully scheduled function ${ functionName } ` ) ;
70+ resolve ( body ) ;
71+ } ) ;
5772 }
5873 ) ;
59- request . on ( 'error' , reject ) ;
74+ request . on ( 'error' , ( err ) => {
75+ console . error ( 'Failed to schedule cloud scheduler job with error' , err ) ;
76+ reject ( err ) ;
77+ } ) ;
6078 request . write ( '{}' ) ;
6179 request . end ( ) ;
6280 } ) ;
@@ -67,14 +85,13 @@ export const integrationTests: any = functions
6785 . runWith ( {
6886 timeoutSeconds : 540 ,
6987 } )
70- . https . onRequest ( ( req : Request , resp : Response ) => {
88+ . https . onRequest ( async ( req : Request , resp : Response ) => {
7189 // We take the base url for our https call (cloudfunctions.net, txckloud.net, etc) from the request
7290 // so that it changes with the environment that the tests are run in
7391 const baseUrl = req . hostname
7492 . split ( '.' )
7593 . slice ( 1 )
7694 . join ( '.' ) ;
77- const pubsub : any = require ( '@google-cloud/pubsub' ) ( ) ;
7895 const testId = admin
7996 . database ( )
8097 . ref ( )
@@ -83,114 +100,107 @@ export const integrationTests: any = functions
83100 . database ( )
84101 . ref ( `testRuns/${ testId } /timestamp` )
85102 . set ( Date . now ( ) ) ;
103+ const testIdRef = admin . database ( ) . ref ( `testRuns/${ testId } ` ) ;
86104 console . log ( 'testId is: ' , testId ) ;
87105 fs . writeFile ( '/tmp/' + testId + '.txt' , 'test' , ( ) => { } ) ;
88- return Promise . all ( [
89- // A database write to trigger the Firebase Realtime Database tests.
90- admin
91- . database ( )
92- . ref ( `dbTests/${ testId } /start` )
93- . set ( { '.sv' : 'timestamp' } ) ,
94- // A Pub/Sub publish to trigger the Cloud Pub/Sub tests.
95- pubsub
96- . topic ( 'pubsubTests' )
97- . publisher ( )
98- . publish ( Buffer . from ( JSON . stringify ( { testId } ) ) ) ,
99- // A user creation to trigger the Firebase Auth user creation tests.
100- admin
101- . auth ( )
102- . createUser ( {
103- email : `${ testId } @fake.com` ,
104- password : 'secret' ,
105- displayName : `${ testId } ` ,
106- } )
107- . then ( ( userRecord ) => {
108- // A user deletion to trigger the Firebase Auth user deletion tests.
109- admin . auth ( ) . deleteUser ( userRecord . uid ) ;
110- } ) ,
111- // A firestore write to trigger the Cloud Firestore tests.
112- admin
113- . firestore ( )
114- . collection ( 'tests' )
115- . doc ( testId )
116- . set ( { test : testId } ) ,
117- // Invoke a callable HTTPS trigger.
118- callHttpsTrigger ( 'callableTests' , { foo : 'bar' , testId } , baseUrl ) ,
119- // A Remote Config update to trigger the Remote Config tests.
120- admin . credential
121- . applicationDefault ( )
122- . getAccessToken ( )
123- . then ( ( accessToken ) => {
124- const options = {
125- hostname : 'firebaseremoteconfig.googleapis.com' ,
126- path : `/v1/projects/${ firebaseConfig . projectId } /remoteConfig` ,
127- method : 'PUT' ,
128- headers : {
129- Authorization : 'Bearer ' + accessToken . access_token ,
130- 'Content-Type' : 'application/json; UTF-8' ,
131- 'Accept-Encoding' : 'gzip' ,
132- 'If-Match' : '*' ,
133- } ,
134- } ;
135- const request = https . request ( options , ( resp ) => { } ) ;
136- request . write ( JSON . stringify ( { version : { description : testId } } ) ) ;
137- request . end ( ) ;
138- } ) ,
139- // A storage upload to trigger the Storage tests
140- admin
141- . storage ( )
142- . bucket ( )
143- . upload ( '/tmp/' + testId + '.txt' ) ,
144- testLab . startTestRun ( firebaseConfig . projectId , testId ) ,
145- // Invoke the schedule for our scheduled function to fire
146- callScheduleTrigger ( 'schedule' , 'us-central1' ) ,
147- ] )
148- . then ( ( ) => {
149- // On test completion, check that all tests pass and reply "PASS", or provide further details.
150- console . log ( 'Waiting for all tests to report they pass...' ) ;
151- const ref = admin . database ( ) . ref ( `testRuns/${ testId } ` ) ;
152- return new Promise ( ( resolve , reject ) => {
153- let testsExecuted = 0 ;
154- ref . on ( 'child_added' , ( snapshot ) => {
155- testsExecuted += 1 ;
156- if ( snapshot . key != 'timestamp' && ! snapshot . val ( ) . passed ) {
157- reject (
158- new Error (
159- `test ${ snapshot . key } failed; see database for details.`
160- )
161- ) ;
162- return ;
163- }
164- console . log (
165- `${ snapshot . key } passed (${ testsExecuted } of ${ numTests } )`
166- ) ;
167- if ( testsExecuted < numTests ) {
168- // Not all tests have completed. Wait longer.
169- return ;
170- }
171- // All tests have passed!
172- resolve ( ) ;
173- } ) ;
174- } )
175- . then ( ( ) => {
176- ref . off ( ) ; // No more need to listen.
177- return Promise . resolve ( ) ;
106+ try {
107+ await Promise . all ( [
108+ // A database write to trigger the Firebase Realtime Database tests.
109+ admin
110+ . database ( )
111+ . ref ( `dbTests/${ testId } /start` )
112+ . set ( { '.sv' : 'timestamp' } ) ,
113+ // A Pub/Sub publish to trigger the Cloud Pub/Sub tests.
114+ new PubSub ( )
115+ . topic ( 'pubsubTests' )
116+ . publish ( Buffer . from ( JSON . stringify ( { testId } ) ) ) ,
117+ // A user creation to trigger the Firebase Auth user creation tests.
118+ admin
119+ . auth ( )
120+ . createUser ( {
121+ email : `${ testId } @fake.com` ,
122+ password : 'secret' ,
123+ displayName : `${ testId } ` ,
178124 } )
179- . catch ( ( err ) => {
180- ref . off ( ) ; // No more need to listen.
181- return Promise . reject ( err ) ;
182- } ) ;
183- } )
184- . then ( ( ) => {
185- console . log ( 'All tests pass!' ) ;
186- resp . status ( 200 ) . send ( 'PASS \n' ) ;
187- } )
188- . catch ( ( err ) => {
189- console . log ( `Some tests failed: ${ err } ` ) ;
190- resp
191- . status ( 500 )
192- . send (
193- `FAIL - details at https://${ process . env . GCLOUD_PROJECT } .firebaseio.com/testRuns/${ testId } `
125+ . then ( ( userRecord ) => {
126+ // A user deletion to trigger the Firebase Auth user deletion tests.
127+ admin . auth ( ) . deleteUser ( userRecord . uid ) ;
128+ } ) ,
129+ // A firestore write to trigger the Cloud Firestore tests.
130+ admin
131+ . firestore ( )
132+ . collection ( 'tests' )
133+ . doc ( testId )
134+ . set ( { test : testId } ) ,
135+ // Invoke a callable HTTPS trigger.
136+ callHttpsTrigger ( 'callableTests' , { foo : 'bar' , testId } , baseUrl ) ,
137+ // A Remote Config update to trigger the Remote Config tests.
138+ admin . credential
139+ . applicationDefault ( )
140+ . getAccessToken ( )
141+ . then ( ( accessToken ) => {
142+ const options = {
143+ hostname : 'firebaseremoteconfig.googleapis.com' ,
144+ path : `/v1/projects/${ firebaseConfig . projectId } /remoteConfig` ,
145+ method : 'PUT' ,
146+ headers : {
147+ Authorization : 'Bearer ' + accessToken . access_token ,
148+ 'Content-Type' : 'application/json; UTF-8' ,
149+ 'Accept-Encoding' : 'gzip' ,
150+ 'If-Match' : '*' ,
151+ } ,
152+ } ;
153+ const request = https . request ( options , ( resp ) => { } ) ;
154+ request . write ( JSON . stringify ( { version : { description : testId } } ) ) ;
155+ request . end ( ) ;
156+ } ) ,
157+ // A storage upload to trigger the Storage tests
158+ admin
159+ . storage ( )
160+ . bucket ( )
161+ . upload ( '/tmp/' + testId + '.txt' ) ,
162+ testLab . startTestRun ( firebaseConfig . projectId , testId ) ,
163+ // Invoke the schedule for our scheduled function to fire
164+ callScheduleTrigger ( 'schedule' , 'us-central1' ) ,
165+ ] ) ;
166+
167+ // On test completion, check that all tests pass and reply "PASS", or provide further details.
168+ console . log ( 'Waiting for all tests to report they pass...' ) ;
169+ await new Promise < void > ( ( resolve , reject ) => {
170+ setTimeout ( ( ) => reject ( new Error ( 'Timeout' ) ) , 5 * 60 * 1000 ) ;
171+ let testsExecuted = 0 ;
172+ testIdRef . on ( 'child_added' , ( snapshot ) => {
173+ testsExecuted += 1 ;
174+ if ( snapshot . key != 'timestamp' && ! snapshot . val ( ) . passed ) {
175+ reject (
176+ new Error (
177+ `test ${ snapshot . key } failed; see database for details.`
178+ )
179+ ) ;
180+ return ;
181+ }
182+ console . log (
183+ `${ snapshot . key } passed (${ testsExecuted } of ${ numTests } )`
194184 ) ;
185+ if ( testsExecuted < numTests ) {
186+ // Not all tests have completed. Wait longer.
187+ return ;
188+ }
189+ // All tests have passed!
190+ resolve ( ) ;
191+ } ) ;
195192 } ) ;
193+ console . log ( 'All tests pass!' ) ;
194+ resp . status ( 200 ) . send ( 'PASS \n' ) ;
195+ } catch ( err ) {
196+ console . log ( `Some tests failed: ${ err } ` ) ;
197+ resp
198+ . status ( 500 )
199+ . send (
200+ `FAIL - details at ${ functions . firebaseConfig ( )
201+ . databaseURL ! } /testRuns/${ testId } `
202+ ) ;
203+ } finally {
204+ testIdRef . off ( 'child_added' ) ;
205+ }
196206 } ) ;
0 commit comments