@@ -3,7 +3,12 @@ import fs from "node:fs/promises"
33import path from "node:path"
44import test , { type TestContext } from "node:test"
55
6- import { createScenarioWorkspace , preserveScenarioWorkspace , removeScenarioWorkspace } from "./scenarioWorkspace"
6+ import {
7+ createScenarioWorkspace ,
8+ preserveScenarioWorkspace ,
9+ preserveScenarioWorkspaceForRunner ,
10+ removeScenarioWorkspace ,
11+ } from "./scenarioWorkspace"
712
813async function scenario ( t : TestContext ) {
914 const workspace = await createScenarioWorkspace ( )
@@ -127,45 +132,55 @@ void test("records collection failures without copying raw files and still clean
127132 await assert . rejects ( fs . access ( workspace . root ) , { code : "ENOENT" } )
128133} )
129134
130- for ( const failure of [ "partial write" , "rename" ] as const ) {
131- for ( const existing of [ false , true ] ) {
132- void test ( `keeps the source after a failed ${ failure } , previous artifact: ${ existing } ` , async ( t ) => {
133- const { workspace, destination } = await scenario ( t )
134- await fs . mkdir ( destination , { recursive : true } )
135- const artifact = path . join ( destination , "diagnostics.json" )
136- const previous = JSON . stringify ( { previous : true } )
137- if ( existing ) await fs . writeFile ( artifact , previous )
138- const write = fs . writeFile
139- if ( failure === "partial write" ) {
140- t . mock . method ( fs , "writeFile" , async ( file : Parameters < typeof fs . writeFile > [ 0 ] ) => {
141- await write ( file , '{"partial":' )
142- throw Object . assign ( new Error ( "disk failed" ) , { code : "EIO" } )
143- } )
144- } else {
145- t . mock . method ( fs , "rename" , async ( ) => {
146- throw Object . assign ( new Error ( "rename failed" ) , { code : "EIO" } )
147- } )
148- }
149- await assert . rejects ( preserveScenarioWorkspace ( workspace ) , { code : "EIO" } )
150- await fs . access ( workspace . root )
151- if ( existing ) assert . equal ( await fs . readFile ( artifact , "utf8" ) , previous )
152- else await assert . rejects ( fs . access ( artifact ) , { code : "ENOENT" } )
153- assert . deepEqual ( await fs . readdir ( destination ) , existing ? [ "diagnostics.json" ] : [ ] )
154- } )
135+ const preservationEntries = [
136+ { name : "retryable preservation" , preserve : preserveScenarioWorkspace , keepsSource : true } ,
137+ { name : "runner cleanup" , preserve : preserveScenarioWorkspaceForRunner , keepsSource : false } ,
138+ ]
139+
140+ for ( const entry of preservationEntries ) {
141+ for ( const failure of [ "partial write" , "rename" ] as const ) {
142+ for ( const existing of [ false , true ] ) {
143+ void test ( `${ entry . name } : failed ${ failure } , previous artifact: ${ existing } ` , async ( t ) => {
144+ const { workspace, destination } = await scenario ( t )
145+ await fs . mkdir ( destination , { recursive : true } )
146+ const artifact = path . join ( destination , "diagnostics.json" )
147+ const previous = JSON . stringify ( { previous : true } )
148+ if ( existing ) await fs . writeFile ( artifact , previous )
149+ const write = fs . writeFile
150+ if ( failure === "partial write" ) {
151+ t . mock . method ( fs , "writeFile" , async ( file : Parameters < typeof fs . writeFile > [ 0 ] ) => {
152+ await write ( file , '{"partial":' )
153+ throw Object . assign ( new Error ( "disk failed" ) , { code : "EIO" } )
154+ } )
155+ } else {
156+ t . mock . method ( fs , "rename" , async ( ) => {
157+ throw Object . assign ( new Error ( "rename failed" ) , { code : "EIO" } )
158+ } )
159+ }
160+ await assert . rejects ( entry . preserve ( workspace ) , { code : "EIO" } )
161+ if ( entry . keepsSource ) await fs . access ( workspace . root )
162+ else await assert . rejects ( fs . access ( workspace . root ) , { code : "ENOENT" } )
163+ if ( existing ) assert . equal ( await fs . readFile ( artifact , "utf8" ) , previous )
164+ else await assert . rejects ( fs . access ( artifact ) , { code : "ENOENT" } )
165+ assert . deepEqual ( await fs . readdir ( destination ) , existing ? [ "diagnostics.json" ] : [ ] )
166+ } )
167+ }
155168 }
156169}
157170
158- void test ( "publishes complete diagnostics before removing the source workspace" , async ( t ) => {
159- const { workspace, destination } = await scenario ( t )
160- const rename = fs . rename
161- t . mock . method ( fs , "rename" , async ( source : string , target : string ) => {
162- assert . equal ( target , path . join ( destination , "diagnostics.json" ) )
163- await fs . access ( workspace . root )
164- await assert . rejects ( fs . access ( target ) , { code : "ENOENT" } )
165- assert ( JSON . parse ( await fs . readFile ( source , "utf8" ) ) . sources )
166- await rename ( source , target )
171+ for ( const entry of preservationEntries ) {
172+ void test ( `${ entry . name } : publishes complete diagnostics before removing the source workspace` , async ( t ) => {
173+ const { workspace, destination } = await scenario ( t )
174+ const rename = fs . rename
175+ t . mock . method ( fs , "rename" , async ( source : string , target : string ) => {
176+ assert . equal ( target , path . join ( destination , "diagnostics.json" ) )
177+ await fs . access ( workspace . root )
178+ await assert . rejects ( fs . access ( target ) , { code : "ENOENT" } )
179+ assert ( JSON . parse ( await fs . readFile ( source , "utf8" ) ) . sources )
180+ await rename ( source , target )
181+ } )
182+ await entry . preserve ( workspace )
183+ assert . deepEqual ( await fs . readdir ( destination ) , [ "diagnostics.json" ] )
184+ await assert . rejects ( fs . access ( workspace . root ) , { code : "ENOENT" } )
167185 } )
168- await preserveScenarioWorkspace ( workspace )
169- assert . deepEqual ( await fs . readdir ( destination ) , [ "diagnostics.json" ] )
170- await assert . rejects ( fs . access ( workspace . root ) , { code : "ENOENT" } )
171- } )
186+ }
0 commit comments