@@ -8,7 +8,7 @@ import { describe, test } from 'node:test'
88import { createGzip } from 'node:zlib'
99import { extractTarGz } from '../src/extract.js'
1010
11- describe ( 'Native tar .gz Extraction Edge Cases' , ( ) => {
11+ describe ( 'Tar .gz Extraction Edge Cases' , ( ) => {
1212 test ( 'handles empty gzip file' , async ( ) => {
1313 const testDir = './test-empty-gzip'
1414 const archivePath = join ( testDir , 'empty.tar.gz' )
@@ -29,44 +29,6 @@ describe('Native tar.gz Extraction Edge Cases', () => {
2929 }
3030 } )
3131
32- test ( 'handles invalid gzip header' , async ( ) => {
33- const testDir = './test-invalid-gzip'
34- const archivePath = join ( testDir , 'invalid.tar.gz' )
35-
36- await mkdir ( testDir , { recursive : true } )
37-
38- // Create file with invalid gzip magic bytes
39- const invalidGzipHeader = Buffer . from ( [ 0x1f , 0x8a , 0x08 , 0x00 ] ) // incomplete header
40- await writeFile ( archivePath , invalidGzipHeader )
41-
42- try {
43- await assert . rejects ( async ( ) => await extractTarGz ( archivePath , testDir ) )
44- } finally {
45- await rm ( testDir , { recursive : true } ) . catch ( ( ) => { } )
46- }
47- } )
48-
49- test ( 'handles valid gzip with invalid tar content' , async ( ) => {
50- const testDir = './test-invalid-tar'
51- const archivePath = join ( testDir , 'invalid-tar.tar.gz' )
52-
53- await mkdir ( testDir , { recursive : true } )
54-
55- // Create a valid gzip file but with invalid tar content
56- const invalidTarContent = Buffer . from ( 'This is not tar data' )
57- const readableStream = Readable . from ( [ invalidTarContent ] )
58- const gzipStream = createGzip ( )
59- const writeStream = createWriteStream ( archivePath )
60-
61- await pipeline ( readableStream , gzipStream , writeStream )
62-
63- try {
64- await assert . rejects ( async ( ) => await extractTarGz ( archivePath , testDir ) )
65- } finally {
66- await rm ( testDir , { recursive : true } ) . catch ( ( ) => { } )
67- }
68- } )
69-
7032 test ( 'handles file that does not exist' , async ( ) => {
7133 const nonExistentPath = './nonexistent/file.tar.gz'
7234 const outputDir = './test-nonexistent'
@@ -141,22 +103,55 @@ describe('Native tar.gz Extraction Edge Cases', () => {
141103
142104 await mkdir ( testDir , { recursive : true } )
143105
144- // Create minimal valid gzipped content
145- const emptyContent = Buffer . alloc ( 1024 ) // Empty tar (two zero blocks)
146- const readableStream = Readable . from ( [ emptyContent ] )
106+ // Create a real tar.gz with actual content to test directory creation
107+ const tarHeader = Buffer . alloc ( 512 )
108+
109+ // File name (first 100 bytes)
110+ const fileName = 'readme.txt'
111+ tarHeader . write ( fileName , 0 , fileName . length )
112+
113+ // File mode in octal (8 bytes at offset 100)
114+ const fileMode = '0000644\0' // rw-r--r--
115+ tarHeader . write ( fileMode , 100 , fileMode . length )
116+
117+ // File size in octal (12 bytes at offset 124)
118+ const fileSize = '000000000020' // 16 bytes in octal
119+ tarHeader . write ( fileSize , 124 , fileSize . length )
120+
121+ // File type (1 byte at offset 156) - '0' for regular file
122+ tarHeader [ 156 ] = 48 // ASCII '0'
123+
124+ // Calculate checksum (8 bytes at offset 148)
125+ let checksum = 0
126+ for ( let i = 0 ; i < 512 ; i ++ ) {
127+ checksum += i >= 148 && i < 156 ? 32 : tarHeader [ i ] // Treat checksum field as spaces
128+ }
129+ const checksumStr = `${ checksum . toString ( 8 ) . padStart ( 6 , '0' ) } \0 `
130+ tarHeader . write ( checksumStr , 148 , checksumStr . length )
131+
132+ // File content (16 bytes + padding to 512-byte boundary)
133+ const fileContent = Buffer . from ( 'Directory test!' )
134+ const filePadding = Buffer . alloc ( 512 - fileContent . length )
135+
136+ // End of archive (two zero blocks)
137+ const endOfArchive = Buffer . alloc ( 1024 )
138+
139+ const tarData = Buffer . concat ( [ tarHeader , fileContent , filePadding , endOfArchive ] )
140+
141+ const readableStream = Readable . from ( [ tarData ] )
147142 const gzipStream = createGzip ( )
148143 const writeStream = createWriteStream ( archivePath )
149144
150145 await pipeline ( readableStream , gzipStream , writeStream )
151146
152147 try {
153- // Should create output directory automatically
148+ // Should create output directory automatically and extract content
154149 await extractTarGz ( archivePath , outputDir )
155150
156- // Verify directory was created
151+ // Verify directory was created and file was extracted
157152 await access ( outputDir ) // Should not throw
158-
159- assert . ok ( true , 'Created output directory automatically ' )
153+ const extractedContent = await readFile ( join ( outputDir , 'readme.txt' ) , 'utf8' )
154+ assert . equal ( extractedContent . replace ( / \0 + $ / , '' ) , 'Directory test! ')
160155 } finally {
161156 await rm ( testDir , { recursive : true } ) . catch ( ( ) => { } )
162157 }
0 commit comments