11import { EventEmitter } from "events"
2+ import * as path from "path"
23import { PassThrough } from "stream"
34
45import { spawn } from "child_process"
56
67import {
7- escapePowerShellLiteral ,
88 extractSingleFileTarXzArchive ,
99 extractSingleFileZipArchive ,
1010 extractTarGzArchive ,
11+ extractTarXzArchive ,
12+ extractZipArchive ,
1113 runProcess ,
1214} from "../archive"
1315
@@ -40,8 +42,17 @@ describe("managed binary archive utilities", () => {
4042 } )
4143 } )
4244
43- it ( "escapes PowerShell single-quoted literals" , ( ) => {
44- expect ( escapePowerShellLiteral ( "C:\\it's\\archive.zip" ) ) . toBe ( "C:\\it''s\\archive.zip" )
45+ it ( "kills a process that exceeds its timeout" , async ( ) => {
46+ vi . useFakeTimers ( )
47+ const child = createChild ( )
48+ mockSpawn . mockReturnValue ( child as unknown as ReturnType < typeof spawn > )
49+ const processResult = runProcess ( "tool" , [ ] , 100 )
50+ const assertion = expect ( processResult ) . rejects . toThrow ( "tool timed out" )
51+
52+ await vi . advanceTimersByTimeAsync ( 100 )
53+ await assertion
54+ expect ( child . kill ) . toHaveBeenCalledWith ( "SIGKILL" )
55+ vi . useRealTimers ( )
4556 } )
4657
4758 it ( "extracts tar.gz archives with hardened flags" , async ( ) => {
@@ -58,6 +69,43 @@ describe("managed binary archive utilities", () => {
5869 )
5970 } )
6071
72+ it ( "extracts tar.xz archives with hardened flags" , async ( ) => {
73+ const child = createChild ( )
74+ mockSpawn . mockReturnValue ( child as unknown as ReturnType < typeof spawn > )
75+ const extraction = extractTarXzArchive ( "/tmp/archive.tar.xz" , "/tmp/output" )
76+ child . emit ( "close" , 0 )
77+ await extraction
78+
79+ const expectedArgs = [ "-xJf" , "/tmp/archive.tar.xz" , "-C" , "/tmp/output" , "--no-same-owner" ]
80+ if ( process . platform === "linux" ) expectedArgs . push ( "--no-overwrite-dir" )
81+ expect ( mockSpawn ) . toHaveBeenCalledWith ( "tar" , expectedArgs , {
82+ shell : false ,
83+ stdio : [ "ignore" , "pipe" , "pipe" ] ,
84+ } )
85+ } )
86+
87+ it ( "extracts ZIP archives with platform-safe process arguments" , async ( ) => {
88+ const child = createChild ( )
89+ mockSpawn . mockReturnValue ( child as unknown as ReturnType < typeof spawn > )
90+ const extraction = extractZipArchive ( "/tmp/archive.zip" , "/tmp/output" )
91+ child . emit ( "close" , 0 )
92+ await extraction
93+
94+ if ( process . platform === "win32" ) {
95+ expect ( mockSpawn ) . toHaveBeenCalledWith (
96+ "powershell" ,
97+ [ "-NoProfile" , "-NonInteractive" , "-Command" , expect . any ( String ) , "/tmp/archive.zip" , "/tmp/output" ] ,
98+ expect . objectContaining ( { shell : false } ) ,
99+ )
100+ } else {
101+ expect ( mockSpawn ) . toHaveBeenCalledWith (
102+ "unzip" ,
103+ [ "-o" , "/tmp/archive.zip" , "-d" , "/tmp/output" ] ,
104+ expect . objectContaining ( { shell : false } ) ,
105+ )
106+ }
107+ } )
108+
61109 it ( "validates a single-file tar.xz layout before extraction" , async ( ) => {
62110 const listing = createChild ( )
63111 const extraction = createChild ( )
@@ -73,7 +121,7 @@ describe("managed binary archive utilities", () => {
73121 expect ( mockSpawn ) . toHaveBeenNthCalledWith (
74122 2 ,
75123 "tar" ,
76- [ "-xJf" , "/tmp/archive.tar.xz" , "-C" , "/tmp/output" , "binary" ] ,
124+ [ "-xJf" , "/tmp/archive.tar.xz" , "-C" , "/tmp/output" , "./ binary" ] ,
77125 expect . any ( Object ) ,
78126 )
79127 } )
@@ -85,9 +133,10 @@ describe("managed binary archive utilities", () => {
85133 child . emit ( "close" , 0 )
86134 await extraction
87135
88- const script = mockSpawn . mock . calls [ 0 ] [ 1 ] [ 3 ]
136+ const args = mockSpawn . mock . calls [ 0 ] [ 1 ]
137+ const script = args [ 3 ]
89138 expect ( script ) . toContain ( "$entries.Count -ne 1" )
90- expect ( script ) . toContain ( "binary.exe " )
91- expect ( script ) . toContain ( "Tool archive has an unexpected layout" )
139+ expect ( script ) . not . toContain ( "C:\\archive.zip " )
140+ expect ( args . slice ( 4 ) ) . toEqual ( [ "C:\\ archive.zip" , path . join ( "C:\\output" , "binary.exe" ) , "binary.exe" , "Tool" ] )
92141 } )
93142} )
0 commit comments