Skip to content

Commit 1973680

Browse files
committed
WIP: basic running test, fails because of a bundle server bug
Signed-off-by: Victoria Dye <[email protected]>
1 parent d8277ad commit 1973680

File tree

5 files changed

+141
-23
lines changed

5 files changed

+141
-23
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
/bin/
44
/_dist/
55
/_docs/
6+
/_test/
67
node_modules/

test/e2e/cucumber.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
"requireModule": ["ts-node/register"],
44
"require": ["features/**/*.ts"],
55
"publishQuiet": true,
6-
"format": ["summary"],
6+
"format": ["progress"],
77
"formatOptions": {
88
"snippetInterface": "async-await"
9+
},
10+
"worldParameters": {
11+
"bundleServerCommand": "../../bin/git-bundle-server",
12+
"bundleWebServerCommand": "../../bin/git-bundle-web-server",
13+
"trashDirectoryBase": "../../_test/e2e"
914
}
1015
}
1116
}

test/e2e/features/basic.feature

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ Feature: Basic bundle server usage
44
Given the bundle web server is running at port 8080
55

66
Scenario: First-time bundle server setup
7-
Given the bundle server has been initialized with 'https://github.com/git/git.git'
8-
When I clone from 'https://github.com/git/git.git' with a bundle URI
9-
Then bundles are downloaded and used
10-
11-
Scenario: Second-time bundle server setup
12-
Given the bundle server has been initialized with 'https://github.com/git/git.git'
13-
When I clone from 'https://github.com/git/git.git' with a bundle URI
7+
Given the bundle server has been initialized with 'https://github.com/vdye/asset-hash.git'
8+
When I clone from 'https://github.com/vdye/asset-hash.git' with a bundle URI
149
Then bundles are downloaded and used
Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,47 @@
11
import * as assert from 'assert'
2-
import * as child_process from 'child_process'
3-
import { Given, When, Then } from '@cucumber/cucumber'
2+
import { BundleServerWorld } from '../support/world'
3+
import { Given, When, Then, After } from '@cucumber/cucumber'
44

5-
Given('the bundle web server is running at port {int}', async function(port: number) {
6-
console.log(`Hosting bundle web server at ${port}`)
5+
Given('the bundle web server is running at port {int}', async function(this: BundleServerWorld, port: number) {
6+
this.startWebServer(port)
77
})
88

9-
Then('bundles are downloaded and used', async function() {
10-
// const exec = util.promisify(child_process.exec)
11-
// const stdout, stderr = exec('git status')
12-
// child_process
13-
const child = child_process.spawnSync("git status", { shell: true })
14-
console.log(child.stderr.toString())
15-
assert.strict(true)
9+
Given('the bundle server has been initialized with {string}', async function(this: BundleServerWorld, url: string) {
10+
const result = this.bundleServerInit(url)
11+
assert.strictEqual(result.status, 0, "git-bundle-server init failed")
1612
})
1713

18-
When('I clone from {string} with a bundle URI', async function(url: string) {
19-
console.log(`Cloning from ${url}`)
14+
When('I clone from {string} with a bundle URI', async function(this: BundleServerWorld, url: string) {
15+
this.cloneWithBundleUri(url)
2016
})
2117

22-
Given('the bundle server has been initialized with {string}', async function(url: string) {
23-
console.log(`Initializing bundle server with ${url}`)
18+
Then('bundles are downloaded and used', async function(this: BundleServerWorld) {
19+
// Verify the command executed as-expected
20+
if (this.cloneResult === undefined) {
21+
throw new Error("Tried to access clone result before clone")
22+
}
23+
24+
// Exit code
25+
assert.strictEqual(this.cloneResult.status, 0, "git clone failed")
26+
27+
// Ensure warning wasn't thrown
28+
this.cloneResult.stderr.toString().split("\n").forEach(function(line) {
29+
if (line.startsWith("warning: failed to download bundle from URI")) {
30+
assert.fail(line)
31+
}
32+
})
33+
34+
// TODO: verify results of 'for-each-ref'
35+
const result = this.runGitInLocalRepo("for-each-ref", "--format=%(refname)")
36+
assert.strictEqual(result.status, 0, "git for-each-ref failed")
37+
38+
const bundleRefRegex = new RegExp('^refs/bundles/.*$')
39+
const bundleRefs = this.cloneResult.stdout.toString().split("\n").filter(function(line) {
40+
return bundleRefRegex.test(line)
41+
})
42+
assert.strict(bundleRefs.length > 0, "No bundle refs found in the repo")
2443
})
44+
45+
After(function (this: BundleServerWorld) {
46+
this.cleanup()
47+
});

test/e2e/features/support/world.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { setWorldConstructor, World, IWorldOptions } from '@cucumber/cucumber'
2+
import { randomUUID, randomBytes } from 'crypto'
3+
import * as child_process from 'child_process'
4+
import * as fs from 'fs'
5+
import * as path from 'path'
6+
7+
interface BundleServerParameters {
8+
bundleServerCommand: string
9+
bundleWebServerCommand: string
10+
trashDirectoryBase: string
11+
}
12+
13+
export class BundleServerWorld extends World<BundleServerParameters> {
14+
// Internal variables
15+
private trashDirectory: string
16+
private webServer: child_process.ChildProcess | undefined
17+
private bundleUriBase: string | undefined
18+
private route: string | undefined
19+
20+
cloneResult: child_process.SpawnSyncReturns<Buffer> | undefined
21+
22+
23+
constructor(options: IWorldOptions<BundleServerParameters>) {
24+
super(options)
25+
26+
// Set up the trash directory
27+
this.trashDirectory = this.pathParamToAbsolute(
28+
path.join(this.parameters.trashDirectoryBase, randomUUID())
29+
)
30+
fs.mkdirSync(this.trashDirectory, { recursive: true });
31+
}
32+
33+
pathParamToAbsolute(relPath: string): string {
34+
let absPath = this.parameters.bundleWebServerCommand
35+
if (!path.isAbsolute(absPath)) {
36+
// Assume relative path is relative to 'test/e2e'
37+
absPath = path.resolve(__dirname, "../..", relPath)
38+
}
39+
return absPath
40+
}
41+
42+
startWebServer(port: number): void {
43+
if (this.webServer !== undefined) {
44+
throw new Error("Tried to start web server, but web server is already running")
45+
}
46+
47+
const webServerCmd = this.pathParamToAbsolute(this.parameters.bundleWebServerCommand)
48+
this.webServer = child_process.spawn(webServerCmd, ["--port", String(port)])
49+
this.bundleUriBase = `http://localhost:${port}/`
50+
}
51+
52+
bundleServerInit(url: string): child_process.SpawnSyncReturns<Buffer> {
53+
const serverCliCmd = this.pathParamToAbsolute(this.parameters.bundleServerCommand)
54+
this.route = `e2e/${randomBytes(8).toString('hex')}`
55+
return child_process.spawnSync(serverCliCmd, ["init", url, this.route])
56+
}
57+
58+
cloneWithBundleUri(url: string): void {
59+
if (this.route === undefined || this.bundleUriBase === undefined) {
60+
throw new Error("Bundle URI is not initialized")
61+
}
62+
63+
this.cloneResult = child_process.spawnSync("git",
64+
["clone", `--bundle-uri=${this.bundleUriBase}/${this.route}/`, url, this.trashDirectory]
65+
)
66+
}
67+
68+
runGitInLocalRepo(...args: string[]): child_process.SpawnSyncReturns<Buffer> {
69+
return child_process.spawnSync("git",
70+
["-C", this.trashDirectory].concat(args)
71+
)
72+
}
73+
74+
cleanup(): void {
75+
// Stop the web server
76+
if (this.webServer !== undefined) {
77+
const killed = this.webServer.kill('SIGINT')
78+
if (!killed) {
79+
console.warn("Web server process was not successfully stopped")
80+
}
81+
}
82+
83+
// Delete the added route
84+
if (this.route !== undefined) {
85+
const serverCliCmd = this.pathParamToAbsolute(this.parameters.bundleServerCommand)
86+
child_process.spawnSync(serverCliCmd, ["delete", this.route])
87+
}
88+
89+
// Delete the trash directory
90+
fs.rmSync(this.trashDirectory, { recursive: true })
91+
}
92+
}
93+
94+
setWorldConstructor(BundleServerWorld)

0 commit comments

Comments
 (0)