github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/webdriver/datastore.js (about) 1 /** 2 * Copyright 2019 The WPT Dashboard Project. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 const http = require('http'); 8 const process = require('process'); 9 const { spawn } = require('child_process'); 10 11 const { debug } = require('debug'); 12 const log = debug('wpt.fyi'); 13 14 const ready = Symbol('ready'); 15 16 class DatastoreEmulator { 17 /** 18 * @typedef {object} DatastoreEmulatorConfig 19 * @property {string} project 20 * @property {number} port 21 */ 22 /** 23 * @param {DatastoreEmulatorConfig} config 24 */ 25 constructor(config) { 26 this.config = Object.freeze( 27 Object.assign({ 28 project: 'test-app', 29 port: 9091, 30 }, config) 31 ); 32 this.process = startDatastoreEmulator(this.config); 33 this[ready] = this._awaitReady(this.process); 34 } 35 36 /** 37 * @type {Promise} ready 38 */ 39 get ready() { 40 return this[ready]; 41 } 42 43 _awaitReady(process) { 44 return new Promise(resolve => { 45 function retryRequest(url) { 46 http.get(url, (res) => { 47 if (res.statusCode == 200) { 48 resolve(); 49 } else { 50 retryRequest(url); 51 } 52 }).on('error', () => { 53 retryRequest(url); 54 }); 55 } 56 retryRequest(`http://127.0.0.1:${this.config.port}`); 57 58 const logDatastoreEmulator = debug('wpt.fyi:datastore'); 59 process.stderr.on('data', buffer => { 60 logDatastoreEmulator(buffer.toString()); 61 }); 62 }); 63 } 64 65 close() { 66 return new Promise(resolve => { 67 this.process.on('close', () => { 68 resolve(); 69 }); 70 http.request( 71 `http://127.0.0.1:${this.config.port}/shutdown`, 72 {method: 'POST'} 73 ).end(); 74 }); 75 } 76 } 77 78 /** 79 * Launch a dev_appserver.py subprocess. 80 * 81 * @param {object} config 82 * @returns DatastoreEmulator 83 */ 84 function launch(config) { 85 return new DatastoreEmulator(config); 86 } 87 88 function startDatastoreEmulator(config) { 89 const child = spawn('gcloud', 90 [ 91 'beta', 92 'emulators', 93 'datastore', 94 'start', 95 '--no-store-on-disk', 96 '--consistency=1.0', 97 `--project=${config.project}`, 98 `--host-port=127.0.0.1:${config.port}`, 99 ]); 100 process.on('exit', () => { 101 log('killing Datastore emulator subprocess...'); 102 child.kill(); 103 }); 104 return child; 105 } 106 107 module.exports = { DatastoreEmulator, launch };