-
Notifications
You must be signed in to change notification settings - Fork 84
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
Update conformance testee for @connectrpc/connect-web #1183
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
/.tmp | ||
/packages/*/dist | ||
/packages/connect-web-test/local.log | ||
/packages/connect-node-test/.connect-node-h1-server.* | ||
/packages/connect-web/conformance/logs/* | ||
node_modules | ||
.wrangler | ||
.wrangler |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,6 @@ NODE18_VERSION ?= v18.16.0 | |
NODE16_VERSION ?= v16.20.0 | ||
NODE_OS = $(subst Linux,linux,$(subst Darwin,darwin,$(shell uname -s))) | ||
NODE_ARCH = $(subst x86_64,x64,$(subst aarch64,arm64,$(shell uname -m))) | ||
CONFORMANCE_BROWSER ?= chrome | ||
|
||
node_modules: package-lock.json | ||
npm ci | ||
|
@@ -205,23 +204,27 @@ testconnectfastifyconformance: $(BUILD)/connect-fastify | |
npm run -w packages/connect-fastify conformance | ||
|
||
.PHONY: testwebconformance | ||
testwebconformance: testwebchromeconformance testwebfirefoxconformance testwebsafariconformance | ||
testwebconformance: testwebchromeconformance testwebfirefoxconformance testwebsafariconformance testwebnodeconformance | ||
|
||
.PHONY: testwebchromeconformance | ||
testwebchromeconformance: $(BUILD)/connect-web | ||
npm run -w packages/connect-web conformance:client:chrome | ||
npm run -w packages/connect-web conformance:client:chrome:promise | ||
npm run -w packages/connect-web conformance:client:chrome:callback | ||
|
||
.PHONY: testwebfirefoxconformance | ||
testwebfirefoxconformance: $(BUILD)/connect-web | ||
npm run -w packages/connect-web conformance:client:firefox | ||
npm run -w packages/connect-web conformance:client:firefox:promise | ||
npm run -w packages/connect-web conformance:client:firefox:callback | ||
|
||
.PHONY: testwebsafariconformance | ||
testwebsafariconformance: $(BUILD)/connect-web | ||
npm run -w packages/connect-web conformance:client:safari | ||
npm run -w packages/connect-web conformance:client:safari:promise | ||
npm run -w packages/connect-web conformance:client:safari:callback | ||
|
||
.PHONY: testwebconformancelocal | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This didn't work as documented. Since the npm script runs two commands with |
||
testwebconformancelocal: $(BUILD)/connect-conformance | ||
npm run -w packages/connect-web conformance:client:browser -- --browser $(CONFORMANCE_BROWSER) | ||
.PHONY: testwebnodeconformance | ||
testwebnodeconformance: $(BUILD)/connect-web | ||
npm run -w packages/connect-web conformance:client:node:promise | ||
npm run -w packages/connect-web conformance:client:node:callback | ||
|
||
.PHONY: testcloudflareconformance | ||
testcloudflareconformance: $(BUILD)/connect-conformance $(BUILD)/connect-node | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,7 @@ import { | |
chmodSync, | ||
mkdirSync, | ||
} from "node:fs"; | ||
import { join as joinPath } from "node:path"; | ||
import { join as joinPath, basename } from "node:path"; | ||
import { unzipSync, gunzipSync } from "fflate"; | ||
import * as tar from "tar-stream"; | ||
import { pipeline } from "node:stream/promises"; | ||
|
@@ -34,15 +34,18 @@ const [, version] = /conformance:(v\d+\.\d+\.\d+)/.exec(scripts.generate) ?? [ | |
"?", | ||
]; | ||
|
||
const name = "connectconformance"; | ||
const downloadUrl = `https://github.com/connectrpc/conformance/releases/download/${version}`; | ||
|
||
export async function run() { | ||
const { archive, bin } = getArtifactNameForEnv(); | ||
const tempDir = getTempDir(); | ||
const artifactName = getArtifactNameForEnv(); | ||
const assetPath = joinPath(tempDir, artifactName); | ||
await download(`${downloadUrl}/${artifactName}`, assetPath); | ||
execFileSync(await extractBin(assetPath), process.argv.slice(2), { | ||
const binPath = joinPath(tempDir, bin); | ||
if (!existsSync(binPath)) { | ||
const archivePath = joinPath(tempDir, archive); | ||
await download(`${downloadUrl}/${archive}`, archivePath); | ||
await extractBin(archivePath, binPath); | ||
} | ||
execFileSync(binPath, process.argv.slice(2), { | ||
stdio: "inherit", | ||
}); | ||
} | ||
|
@@ -58,31 +61,28 @@ async function download(url: string, path: string) { | |
writeFileSync(path, new Uint8Array(await res.arrayBuffer())); | ||
} | ||
|
||
async function extractBin(path: string) { | ||
if (path.endsWith(".zip")) { | ||
const unzipped = unzipSync(readFileSync(path), { | ||
async function extractBin(archivePath: string, binPath: string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Running the |
||
const binName = basename(binPath); | ||
if (archivePath.endsWith(".zip")) { | ||
const unzipped = unzipSync(readFileSync(archivePath), { | ||
filter(file) { | ||
return file.name === "connectconformance.exe"; | ||
return file.name === binName; | ||
}, | ||
}); | ||
const binBytes = unzipped["connectconformance.exe"] as | ||
| Uint8Array | ||
| undefined; | ||
const binBytes = unzipped[binName] as Uint8Array | undefined; | ||
if (binBytes === undefined) { | ||
throw new Error("Failed to extract connectconformance.exe"); | ||
throw new Error(`Failed to extract ${binName}`); | ||
} | ||
const bin = joinPath(getTempDir(), "connectconformance.exe"); | ||
writeFileSync(bin, binBytes); | ||
return bin; | ||
writeFileSync(binPath, binBytes); | ||
} | ||
const bin = joinPath(getTempDir(), "connectconformance"); | ||
const extract = tar.extract(); | ||
extract.on("entry", (header, stream, next) => { | ||
if (header.name === "connectconformance") { | ||
if (header.name === binName) { | ||
const chunks: Buffer[] = []; | ||
stream.on("data", (chunk: Buffer) => chunks.push(chunk)); | ||
stream.on("end", () => { | ||
writeFileSync(bin, Buffer.concat(chunks)); | ||
writeFileSync(binPath, Buffer.concat(chunks)); | ||
chmodSync(binPath, 0o755); | ||
next(); | ||
}); | ||
} else { | ||
|
@@ -93,14 +93,12 @@ async function extractBin(path: string) { | |
await pipeline( | ||
new Readable({ | ||
read() { | ||
this.push(gunzipSync(readFileSync(path))); | ||
this.push(gunzipSync(readFileSync(archivePath))); | ||
this.push(null); | ||
}, | ||
}), | ||
extract, | ||
); | ||
chmodSync(bin, 755); | ||
return bin; | ||
} | ||
|
||
function getTempDir() { | ||
|
@@ -111,9 +109,10 @@ function getTempDir() { | |
return tempDir; | ||
} | ||
|
||
function getArtifactNameForEnv() { | ||
function getArtifactNameForEnv(): { archive: string; bin: string } { | ||
let build = ""; | ||
let ext = ".tar.gz"; | ||
let bin = "connectconformance"; | ||
switch (os.platform()) { | ||
case "darwin": | ||
switch (os.arch()) { | ||
|
@@ -141,6 +140,7 @@ function getArtifactNameForEnv() { | |
break; | ||
case "win32": | ||
ext = ".zip"; | ||
bin = "connectconformance.exe"; | ||
switch (os.arch()) { | ||
case "arm64": | ||
build = "Windows-arm64"; | ||
|
@@ -155,5 +155,8 @@ function getArtifactNameForEnv() { | |
default: | ||
throw new Error(`Unsupported platform: ${os.platform()}`); | ||
} | ||
return `${name}-${version}-${build}${ext}`; | ||
return { | ||
archive: `connectconformance-${version}-${build}${ext}`, | ||
bin, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,6 @@ | |
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import { ConnectError } from "@connectrpc/connect"; | ||
import { | ||
invokeWithCallbackClient, | ||
invokeWithPromiseClient, | ||
|
@@ -31,8 +30,7 @@ declare global { | |
} | ||
} | ||
|
||
// The main entry point into the browser code running in Puppeteer/headless Chrome. | ||
// This function is invoked by the page.evaluate call in grpcwebclient. | ||
// This function is invoked by the browser.executeAsync call in client.ts | ||
async function runTestCase( | ||
data: number[], | ||
useCallbackClient: boolean, | ||
|
@@ -42,18 +40,17 @@ async function runTestCase( | |
testName: req.testName, | ||
}); | ||
try { | ||
let invoke; | ||
if (useCallbackClient) { | ||
invoke = invokeWithCallbackClient; | ||
} else { | ||
invoke = invokeWithPromiseClient; | ||
} | ||
const result = await invoke(createTransport(req), req); | ||
const transport = createTransport(req); | ||
const result = useCallbackClient | ||
? await invokeWithCallbackClient(transport, req) | ||
: await invokeWithPromiseClient(transport, req); | ||
res.result = { case: "response", value: result }; | ||
} catch (err) { | ||
res.result = { | ||
case: "error", | ||
value: new ClientErrorResult({ message: ConnectError.from(err).message }), | ||
value: new ClientErrorResult({ | ||
message: `Failed to run test case: ${String(err)}`, | ||
}), | ||
Comment on lines
+51
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrapping the error isn't helpful here, this keeps more info. |
||
}; | ||
} | ||
return Array.from(res.toBinary()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're running conformance tests for
@connectrpc/connect-web
on Node.js now. They run quick enough, seems worth it.