Skip to content

Commit

Permalink
test: verify that bundle server started
Browse files Browse the repository at this point in the history
Update the 'bundleServer.startWebServer()' method to wait for indication
that the web server has successfully started (the "Server is running at
address..." message) before returning successfully. If the process stops
before that, or a timeout of 2s is reached, an error is thrown.

However, because the "Server is running..." printout happens in parallel
with the setup done in 'ListenAndServe[TLS]()', it is possible that the
message is printed and immediately followed with an exit due to a server
startup error. To mitigate that, add a 0.1s pause before printing the
message and, in the tests, only set the status to 'ok' if the 'close' event
has not been triggered by the time the startup message is processed.

Signed-off-by: Victoria Dye <[email protected]>
  • Loading branch information
vdye committed May 11, 2023
1 parent 7a17362 commit b6304c7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
10 changes: 10 additions & 0 deletions cmd/git-bundle-web-server/bundle-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,16 @@ func (b *bundleWebServer) StartServerAsync(ctx context.Context) {
}
}(ctx)

// Wait 0.1s before reporting that the server is started in case
// 'listenAndServeFunc' exits immediately.
//
// It's a hack, but a necessary one because 'ListenAndServe[TLS]()' doesn't
// have any mechanism of notifying if it starts successfully, only that it
// fails. We could get around that by copying/reimplementing those functions
// with a print statement inserted at the right place, but that's way more
// cumbersome than just adding a delay here (see:
// https://stackoverflow.com/questions/53332667/how-to-notify-when-http-server-starts-successfully).
time.Sleep(time.Millisecond * 100)
fmt.Println("Server is running at address " + b.server.Addr)
}

Expand Down
30 changes: 28 additions & 2 deletions test/shared/classes/bundleServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,38 @@ export class BundleServer {
this.bundleWebServerCmd = bundleWebServerCmd
}

startWebServer(port: number): void {
async startWebServer(port: number): Promise<void> {
if (this.webServerProcess) {
throw new Error("Tried to start web server, but web server is already running")
}
this.webServerProcess = child_process.spawn(this.bundleWebServerCmd, ["--port", String(port)])
const webServerProcess = child_process.spawn(this.bundleWebServerCmd, ["--port", String(port)])
this.webServerProcess = webServerProcess
this.bundleUriBase = `http://localhost:${port}/`

// Now, ensure the server is running
var timer: NodeJS.Timeout | undefined
var ok: boolean | undefined

await Promise.race([
new Promise<void>(resolve => webServerProcess.stdout.on('data', (data: string) => {
if (data.includes("Server is running at address") && ok === undefined) {
ok = true
resolve() // server is running
}
})),
new Promise<void>(resolve => webServerProcess.on('close', () => {
ok = false
resolve() // program failed to start/exited early
})),
new Promise(resolve => timer = setTimeout(resolve, 2000)) // fallback timeout
])

// If it's still running, clear the timeout so it doesn't delay shutdown
clearTimeout(timer)

if (!ok) {
throw new Error('Failed to start web server')
}
}

init(remote: RemoteRepo, routePrefix: string, route: string = ""): child_process.SpawnSyncReturns<Buffer> {
Expand Down
2 changes: 1 addition & 1 deletion test/shared/features/step_definitions/bundleServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { Given } from '@cucumber/cucumber'
import { BundleServerWorldBase } from '../../support/world'

Given('the bundle web server was started at port {int}', async function (this: BundleServerWorldBase, port: number) {
this.bundleServer.startWebServer(port)
await this.bundleServer.startWebServer(port)
})

0 comments on commit b6304c7

Please sign in to comment.