Skip to content

Commit 82b60ce

Browse files
authored
fix: verified-fetch supports HEAD requests (#222)
* test: remove HEAD handling in gwc server * fix: verified-fetch handles HEAD requests * fix: set correct contentType for dag-json * fix: set correct content-length for dag-json * test: ensure we can skip and run specific tests * test: update test expectations NOTE: a lot of removed successful tests, but they are passing when explicitly ran (except the multi-range ones) * test: dag-json content-type
1 parent d49d6f6 commit 82b60ce

File tree

12 files changed

+114
-757
lines changed

12 files changed

+114
-757
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ node_modules
77
package-lock.json
88
yarn.lock
99
.vscode
10+
removed-passing-tests.json

packages/gateway-conformance/src/conformance.spec.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import { GWC_IMAGE } from './constants.js'
1010
import expectedFailingTests from './expected-failing-tests.json' with { type: 'json' }
1111
import expectedPassingTests from './expected-passing-tests.json' with { type: 'json' }
1212
import { getReportDetails } from './get-report-details.js'
13+
import { getTestsToRun } from './get-tests-to-run.js'
14+
import { getTestsToSkip } from './get-tests-to-skip.js'
15+
1316
const logger = prefixLogger('gateway-conformance')
1417

1518
function getGatewayConformanceBinaryPath (): string {
@@ -114,7 +117,15 @@ describe('@helia/verified-fetch - gateway conformance', function () {
114117
const log = logger.forComponent('output:all')
115118

116119
before(async function () {
117-
const { stderr, stdout } = await execa(binaryPath, getConformanceTestArgs('all', [], []), { reject: false, cancelSignal: AbortSignal.timeout(200000) })
120+
const testsToSkip: string[] = getTestsToSkip()
121+
const testsToRun: string[] = getTestsToRun()
122+
const cancelSignal = AbortSignal.timeout(200000)
123+
const { stderr, stdout } = await execa(binaryPath, getConformanceTestArgs('all', [], [
124+
...(testsToRun.length > 0 ? ['-run', `${testsToRun.join('|')}`] : []),
125+
...(testsToSkip.length > 0 ? ['-skip', `${testsToSkip.join('|')}`] : [])
126+
]), { reject: false, cancelSignal })
127+
128+
expect(cancelSignal.aborted).to.be.false()
118129

119130
log(stdout)
120131
log.error(stderr)
@@ -143,7 +154,7 @@ describe('@helia/verified-fetch - gateway conformance', function () {
143154
})
144155
}
145156

146-
const knownSuccessRate = 46.01
157+
const knownSuccessRate = 44.14
147158
it(`has expected success rate of ${knownSuccessRate}%`, () => {
148159
// check latest success rate with `SUCCESS_RATE=100 npm run test -- -g 'total'`
149160
const expectedSuccessRate = process.env.SUCCESS_RATE != null ? Number.parseFloat(process.env.SUCCESS_RATE) : knownSuccessRate

packages/gateway-conformance/src/expected-failing-tests.json

Lines changed: 1 addition & 353 deletions
Large diffs are not rendered by default.

packages/gateway-conformance/src/expected-passing-tests.json

Lines changed: 6 additions & 390 deletions
Large diffs are not rendered by default.

packages/gateway-conformance/src/fixtures/basic-server.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,6 @@ interface CallVerifiedFetchOptions {
7777

7878
async function callVerifiedFetch (req: IncomingMessage, res: Response, { serverPort, useSessions, verifiedFetch }: CallVerifiedFetchOptions): Promise<void> {
7979
const log = logger('basic-server:request')
80-
if (req.method === 'HEAD') {
81-
res.writeHead(200)
82-
res.end()
83-
return
84-
}
8580

8681
if (req.url == null) {
8782
// this should never happen
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { getWontFixTests } from './get-wontfix-tests.js'
2+
3+
/**
4+
*
5+
* You can see output for specific tests with something like
6+
*
7+
* @example
8+
*
9+
* ```
10+
* DEBUG="gateway-conformance*,gateway-conformance*:trace" RUN_TESTS='TestNativeDag/HEAD_plain_JSON_codec_with_no_explicit_format_returns_HTTP_200.*' npm run test
11+
* ```
12+
*
13+
* If you run `npm run update` and see that some passing tests are removed, you should probably verify that those tests
14+
* pass. You can chose to not update `expected-failing-tests.json` and `expected-passing-tests.json` and then choose to
15+
* save the removed passing tests to a file to ensure that they do still pass with a command like:
16+
*
17+
* @example
18+
* ```
19+
* DEBUG="gateway-conformance*,gateway-conformance*:trace" RUN_TESTS="$(jq -r '.[]' removed-passing-tests.json | paste -sd ',' -)" npm run test
20+
* ```
21+
*/
22+
export function getTestsToRun (): string[] {
23+
const envTestsToRun = process.env.RUN_TESTS != null ? process.env.RUN_TESTS.split(',') : []
24+
// by default, we filter out tests that we know we are not going to fix...
25+
// set FORCE_RUN=true to run all tests you set in RUN_TESTS (even if they are in the wontfix list)
26+
const shouldFilterOutWontFixTests = process.env.FORCE_RUN == null
27+
const wontFixTests = getWontFixTests()
28+
// TODO: tests to run can be gotest based regex, we need to be smarter about filtering.
29+
const testsToRun = shouldFilterOutWontFixTests ? envTestsToRun.filter((test) => !wontFixTests.includes(test)) : envTestsToRun
30+
return testsToRun
31+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { getWontFixTests } from './get-wontfix-tests.js'
2+
3+
/**
4+
*
5+
* you can skip certain tests by setting SKIP_TESTS to a comma-separated list of test names
6+
*
7+
* @example
8+
*
9+
* ```
10+
* SKIP_TESTS='TestNativeDag/HEAD_plain_JSON_codec_with_no_explicit_format_returns_HTTP_200.*' npm run test
11+
* ```
12+
*/
13+
export function getTestsToSkip (): string[] {
14+
const envTestsToSkip = process.env.SKIP_TESTS != null ? process.env.SKIP_TESTS.split(',') : []
15+
const testsToSkip = [...getWontFixTests(), ...envTestsToSkip]
16+
return testsToSkip
17+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function getWontFixTests (): string[] {
2+
return [
3+
// these tests are dependent upon supporting multi-range requests: https://github.com/ipfs/helia-verified-fetch/pull/207
4+
'TestNativeDag/Convert_application%2Fvnd.ipld.dag-cbor_to_application%2Fvnd.ipld.dag-json_with_range_request_includes_correct_bytes_-_multi_range/Check_1',
5+
'TestNativeDag/Convert_application%2Fvnd.ipld.dag-cbor_to_application%2Fvnd.ipld.dag-json_with_range_request_includes_correct_bytes_-_multi_range'
6+
]
7+
}

packages/gateway-conformance/src/update-expected-tests.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ if (failingTestAdditions.length > 0 || passingTestAdditions.length > 0) {
7777

7878
if (!answer) {
7979
console.log('Aborting.')
80+
81+
if (passingTestRemovals.length > 0) {
82+
// to help with debugging, we can save the removed passing tests to a file to ensure that they do still pass with a command like:
83+
// DEBUG="gateway-conformance*,gateway-conformance*:trace" RUN_TESTS="$(jq -r '.[]' removed-passing-tests.json | paste -sd ',' -)" npm run test
84+
const shouldSaveRemovedPassingTests = await confirm('Should we save the removed passing tests to removed-passing-tests.json file?')
85+
if (shouldSaveRemovedPassingTests) {
86+
await writeFile('removed-passing-tests.json', JSON.stringify(passingTestRemovals, null, 2) + '\n')
87+
}
88+
}
89+
8090
process.exit(0)
8191
}
8292
await writeFile(expectedPassingTestsPath, JSON.stringify(passingTests, null, 2) + '\n')

packages/verified-fetch/src/plugins/plugin-handle-json.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,25 @@ export class JsonPlugin extends BasePlugin {
5353
body = block
5454
}
5555

56+
let contentType: string
57+
if (accept == null) {
58+
if (ipldDagJson.code === cid.code) {
59+
contentType = 'application/vnd.ipld.dag-json'
60+
} else {
61+
contentType = 'application/json'
62+
}
63+
} else {
64+
contentType = accept.split(';')[0]
65+
}
66+
5667
context.byteRangeContext.setBody(body)
5768

5869
const response = okRangeResponse(resource, context.byteRangeContext.getBody(), { byteRangeContext: context.byteRangeContext, log: this.log })
59-
response.headers.set('content-type', accept ?? 'application/json')
70+
this.log.trace('setting content-type to %s', contentType)
71+
response.headers.set('content-type', contentType)
72+
if (!context.byteRangeContext.isValidRangeRequest) {
73+
response.headers.set('content-length', body.length.toString())
74+
}
6075
return response
6176
}
6277
}

0 commit comments

Comments
 (0)