mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-10-19 12:43:39 +00:00
test(managed-agent): parse only complete rows in the wedge driver wire (#14496)
* test(managed-agent): parse only complete rows in the wedge driver wire * test(managed-agent): pin the wire reader to complete rows The blocked-wedge driver's wire reader had no executable coverage: the driver cannot be imported (it parses argv and boots a daemon at load), and the Java gates that spawn it are skipped on PR events. Extract the parse into a side-effect-free helper so a unit test can exercise it, and pin the mutants that matter with two complete rows plus an unterminated tail. --------- Co-authored-by: 易良 <1204183885@qq.com>
This commit is contained in:
parent
b3c5d3ed1e
commit
c6018c63b5
3 changed files with 74 additions and 17 deletions
|
|
@ -34,6 +34,7 @@ import { LISTENING_LINE_RE, stopDaemon } from './daemon-process.js';
|
|||
import { HOSTED_HOME_PREFIX } from '../scratch-dir.js';
|
||||
import { relayUpstream } from './hosted-relay-headers.js';
|
||||
import { waitUntil } from './hosted-harness-process.js';
|
||||
import { parseWireRows, type WireRow } from './wire-rows.js';
|
||||
|
||||
const config = JSON.parse(await readFile(process.argv[2], 'utf8')) as {
|
||||
tenantId: string;
|
||||
|
|
@ -544,25 +545,9 @@ const model = await startFakeOpenAIServer(({ body }) => {
|
|||
|
||||
const daemon = await new WedgeDaemon().start(model.baseUrl);
|
||||
|
||||
interface WireRow {
|
||||
kind?: string;
|
||||
requestId?: number;
|
||||
at?: number;
|
||||
method?: string;
|
||||
url?: string;
|
||||
operation?: string;
|
||||
status?: number;
|
||||
requestSnippet?: string;
|
||||
responseSnippet?: string;
|
||||
replied?: string;
|
||||
}
|
||||
|
||||
async function readWire(): Promise<WireRow[]> {
|
||||
try {
|
||||
return (await readFile(config.wireFile, 'utf8'))
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
.map((line) => JSON.parse(line) as WireRow);
|
||||
return parseWireRows(await readFile(config.wireFile, 'utf8'));
|
||||
} catch (cause) {
|
||||
if ((cause as NodeJS.ErrnoException)?.code === 'ENOENT') return [];
|
||||
throw cause;
|
||||
|
|
|
|||
41
integration-tests/helpers/wire-rows.test.ts
Normal file
41
integration-tests/helpers/wire-rows.test.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2026 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { parseWireRows } from './wire-rows.js';
|
||||
|
||||
describe('parseWireRows', () => {
|
||||
it('returns no rows for an empty buffer', () => {
|
||||
expect(parseWireRows('')).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns no rows when the only row has no trailing newline yet', () => {
|
||||
expect(parseWireRows('{"kind":"a"}')).toEqual([]);
|
||||
});
|
||||
|
||||
it('drops an unterminated tail and keeps the complete rows', () => {
|
||||
// Two complete rows keep lastIndexOf -> indexOf observable; with a single
|
||||
// complete row that mutant survives.
|
||||
expect(parseWireRows('{"kind":"a"}\n{"kind":"b"}\n{"kind":"c"')).toEqual([
|
||||
{ kind: 'a' },
|
||||
{ kind: 'b' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns one row for a single terminated row', () => {
|
||||
expect(parseWireRows('{"kind":"a"}\n')).toEqual([{ kind: 'a' }]);
|
||||
});
|
||||
|
||||
it('returns no rows for a buffer that is only a newline', () => {
|
||||
expect(parseWireRows('\n')).toEqual([]);
|
||||
});
|
||||
|
||||
it('still throws on a malformed complete row', () => {
|
||||
expect(() => parseWireRows('{"kind":"a"}\n{"kind":\n')).toThrow(
|
||||
SyntaxError,
|
||||
);
|
||||
});
|
||||
});
|
||||
31
integration-tests/helpers/wire-rows.ts
Normal file
31
integration-tests/helpers/wire-rows.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2026 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
export interface WireRow {
|
||||
kind?: string;
|
||||
requestId?: number;
|
||||
at?: number;
|
||||
method?: string;
|
||||
url?: string;
|
||||
operation?: string;
|
||||
status?: number;
|
||||
requestSnippet?: string;
|
||||
responseSnippet?: string;
|
||||
replied?: string;
|
||||
}
|
||||
|
||||
// The blocked-wedge driver appends each row with one appendFile of
|
||||
// JSON.stringify(row) + '\n', and polls the same file from the same process,
|
||||
// so a read can land mid-append. Parse only complete rows: an unterminated
|
||||
// tail is the row still being written, and the next poll reads it whole. A
|
||||
// complete-but-malformed row still reaches JSON.parse and throws.
|
||||
export function parseWireRows(text: string): WireRow[] {
|
||||
return text
|
||||
.slice(0, text.lastIndexOf('\n') + 1)
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
.map((line) => JSON.parse(line) as WireRow);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue