@zenfs/core 1.1.4 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/backends/fetch.js +5 -5
  2. package/dist/config.js +1 -0
  3. package/license.md +1 -1
  4. package/package.json +5 -3
  5. package/readme.md +3 -8
  6. package/scripts/make-index.js +3 -3
  7. package/scripts/test.js +31 -0
  8. package/tests/assignment.ts +20 -0
  9. package/tests/common.ts +21 -0
  10. package/tests/data/49chars.txt +1 -0
  11. package/tests/data/a.js +46 -0
  12. package/tests/data/a1.js +46 -0
  13. package/tests/data/elipses.txt +1 -0
  14. package/tests/data/empty.txt +0 -0
  15. package/tests/data/exit.js +22 -0
  16. package/tests/data/x.txt +1 -0
  17. package/tests/devices.test.ts +29 -0
  18. package/tests/fs/appendFile.test.ts +33 -0
  19. package/tests/fs/chmod.test.ts +48 -0
  20. package/tests/fs/dir.test.ts +156 -0
  21. package/tests/fs/directory.test.ts +129 -0
  22. package/tests/fs/errors.test.ts +53 -0
  23. package/tests/fs/exists.test.ts +22 -0
  24. package/tests/fs/links.test.ts +46 -0
  25. package/tests/fs/open.test.ts +39 -0
  26. package/tests/fs/permissions.test.ts +52 -0
  27. package/tests/fs/read.test.ts +67 -0
  28. package/tests/fs/readFile.test.ts +73 -0
  29. package/tests/fs/readdir.test.ts +87 -0
  30. package/tests/fs/rename.test.ts +107 -0
  31. package/tests/fs/stat.test.ts +48 -0
  32. package/tests/fs/streams.test.ts +177 -0
  33. package/tests/fs/times.test.ts +84 -0
  34. package/tests/fs/truncate.test.ts +94 -0
  35. package/tests/fs/watch.test.ts +124 -0
  36. package/tests/fs/write.test.ts +58 -0
  37. package/tests/fs/writeFile.test.ts +69 -0
  38. package/tests/handle.test.ts +60 -0
  39. package/tests/mutex.test.ts +62 -0
  40. package/tests/path.test.ts +34 -0
  41. package/tests/port/channel.test.ts +39 -0
  42. package/tests/port/config.test.ts +31 -0
  43. package/tests/port/config.worker.ts +5 -0
  44. package/tests/port/remote.test.ts +33 -0
  45. package/tests/port/remote.worker.ts +5 -0
  46. package/tests/port/timeout.test.ts +48 -0
  47. package/tests/readme.md +5 -0
  48. package/tests/setup/common.ts +28 -0
  49. package/tests/setup/cow+fetch.ts +43 -0
  50. package/tests/setup/memory.ts +3 -0
  51. package/tests/tsconfig.json +14 -0
  52. package/src/backends/backend.ts +0 -160
  53. package/src/backends/fetch.ts +0 -179
  54. package/src/backends/file_index.ts +0 -210
  55. package/src/backends/memory.ts +0 -50
  56. package/src/backends/overlay.ts +0 -568
  57. package/src/backends/port/fs.ts +0 -335
  58. package/src/backends/port/readme.md +0 -54
  59. package/src/backends/port/rpc.ts +0 -167
  60. package/src/backends/readme.md +0 -3
  61. package/src/backends/store/fs.ts +0 -715
  62. package/src/backends/store/readme.md +0 -9
  63. package/src/backends/store/simple.ts +0 -146
  64. package/src/backends/store/store.ts +0 -173
  65. package/src/config.ts +0 -152
  66. package/src/credentials.ts +0 -31
  67. package/src/devices.ts +0 -471
  68. package/src/emulation/async.ts +0 -834
  69. package/src/emulation/constants.ts +0 -182
  70. package/src/emulation/dir.ts +0 -138
  71. package/src/emulation/index.ts +0 -8
  72. package/src/emulation/path.ts +0 -440
  73. package/src/emulation/promises.ts +0 -1098
  74. package/src/emulation/shared.ts +0 -135
  75. package/src/emulation/streams.ts +0 -34
  76. package/src/emulation/sync.ts +0 -845
  77. package/src/emulation/watchers.ts +0 -193
  78. package/src/error.ts +0 -307
  79. package/src/file.ts +0 -661
  80. package/src/filesystem.ts +0 -174
  81. package/src/index.ts +0 -25
  82. package/src/inode.ts +0 -132
  83. package/src/mixins/async.ts +0 -208
  84. package/src/mixins/index.ts +0 -5
  85. package/src/mixins/mutexed.ts +0 -257
  86. package/src/mixins/readonly.ts +0 -96
  87. package/src/mixins/shared.ts +0 -25
  88. package/src/mixins/sync.ts +0 -58
  89. package/src/polyfills.ts +0 -21
  90. package/src/stats.ts +0 -363
  91. package/src/utils.ts +0 -288
@@ -0,0 +1,87 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import { fs } from '../common.js';
4
+
5
+ const testDir = 'test-dir';
6
+ const testFiles = ['file1.txt', 'file2.txt', 'file3.txt'];
7
+ const testDirectories = ['subdir1', 'subdir2'];
8
+
9
+ await fs.promises.mkdir(testDir);
10
+ for (const file of testFiles) {
11
+ await fs.promises.writeFile(`${testDir}/${file}`, 'Sample content');
12
+ }
13
+ for (const dir of testDirectories) {
14
+ await fs.promises.mkdir(`${testDir}/${dir}`);
15
+ for (const file of ['file4.txt', 'file5.txt']) {
16
+ await fs.promises.writeFile(`${testDir}/${dir}/${file}`, 'Sample content');
17
+ }
18
+ }
19
+
20
+ suite('readdir and readdirSync', () => {
21
+ test('readdir returns files and directories', async () => {
22
+ const dirents = await fs.promises.readdir(testDir, { withFileTypes: true });
23
+ const files = dirents.filter(dirent => dirent.isFile()).map(dirent => dirent.name);
24
+ const dirs = dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name);
25
+
26
+ assert(testFiles.every(file => files.includes(file)));
27
+ assert(testDirectories.every(dir => dirs.includes(dir)));
28
+ });
29
+
30
+ test('readdirSync returns files and directories', () => {
31
+ const dirents = fs.readdirSync(testDir, { withFileTypes: true });
32
+ const files = dirents.filter(dirent => dirent.isFile()).map(dirent => dirent.name);
33
+ const dirs = dirents.filter(dirent => dirent.isDirectory()).map(dirent => dirent.name);
34
+
35
+ assert(testFiles.every(file => files.includes(file)));
36
+ assert(testDirectories.every(dir => dirs.includes(dir)));
37
+ });
38
+
39
+ test('readdir returns Dirent objects', async () => {
40
+ const dirents = await fs.promises.readdir(testDir, { withFileTypes: true });
41
+ assert(dirents[0] instanceof fs.Dirent);
42
+ });
43
+
44
+ test('readdirSync returns Dirent objects', () => {
45
+ const dirents = fs.readdirSync(testDir, { withFileTypes: true });
46
+ assert(dirents[0] instanceof fs.Dirent);
47
+ });
48
+
49
+ test('readdir works without withFileTypes option', async () => {
50
+ const files = await fs.promises.readdir(testDir);
51
+ assert(testFiles.every(entry => files.includes(entry)));
52
+ assert(testDirectories.every(entry => files.includes(entry)));
53
+ });
54
+
55
+ test('readdirSync works without withFileTypes option', () => {
56
+ const files = fs.readdirSync(testDir);
57
+ assert(testFiles.every(entry => files.includes(entry)));
58
+ assert(testDirectories.every(entry => files.includes(entry)));
59
+ });
60
+
61
+ test('readdir returns files recursively', async () => {
62
+ const entries = await fs.promises.readdir(testDir, { recursive: true });
63
+ assert(entries.includes('file1.txt'));
64
+ assert(entries.includes('subdir1/file4.txt'));
65
+ assert(entries.includes('subdir2/file5.txt'));
66
+ });
67
+
68
+ test('readdir returns Dirent recursively', async () => {
69
+ const entries = await fs.promises.readdir(testDir, { recursive: true, withFileTypes: true });
70
+ assert.equal(entries[0].path, 'file1.txt');
71
+ assert.equal(entries[4].path, 'subdir1/file4.txt');
72
+ assert.equal(entries[entries.length - 1].path, 'subdir2/file5.txt');
73
+ });
74
+
75
+ // New test for readdirSync with recursive: true
76
+ test('readdirSync returns files recursively', () => {
77
+ const entries = fs.readdirSync(testDir, { recursive: true });
78
+ assert(entries.includes('file1.txt'));
79
+ assert(entries.includes('subdir1/file4.txt'));
80
+ assert(entries.includes('subdir2/file5.txt'));
81
+ });
82
+
83
+ test('Cyrillic file names', () => {
84
+ fs.writeFileSync('/мой-файл.txt', 'HELLO!', 'utf-8');
85
+ assert(fs.readdirSync('/').includes('мой-файл.txt'));
86
+ });
87
+ });
@@ -0,0 +1,107 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import { ErrnoError } from '../../src/error.js';
4
+ import { fs } from '../common.js';
5
+
6
+ suite('Rename', () => {
7
+ /**
8
+ * Creates the following directory structure within `dir`:
9
+ * - _rename_me
10
+ * - lol.txt
11
+ * - file.dat
12
+ */
13
+ async function populate(dir: string) {
14
+ await fs.promises.mkdir(dir + '/_rename_me');
15
+ await fs.promises.writeFile(dir + '/file.dat', 'filedata');
16
+ await fs.promises.writeFile(dir + '/_rename_me/lol.txt', 'lololol');
17
+ }
18
+
19
+ /**
20
+ * Check that the directory structure created in populate_directory remains.
21
+ */
22
+ async function check_directory(dir: string) {
23
+ const contents = await fs.promises.readdir(dir);
24
+ assert(contents.length === 2);
25
+
26
+ const subContents = await fs.promises.readdir(dir + '/_rename_me');
27
+ assert(subContents.length === 1);
28
+
29
+ assert(await fs.promises.exists(dir + '/file.dat'));
30
+ assert(await fs.promises.exists(dir + '/_rename_me/lol.txt'));
31
+ }
32
+
33
+ test('rename directory', async () => {
34
+ const oldDir = '/rename_test';
35
+ const newDir = '/rename_test2';
36
+
37
+ await fs.promises.mkdir(oldDir);
38
+
39
+ await populate(oldDir);
40
+
41
+ await fs.promises.rename(oldDir, oldDir);
42
+
43
+ await check_directory(oldDir);
44
+
45
+ await fs.promises.rename(oldDir, newDir);
46
+
47
+ await check_directory(newDir);
48
+
49
+ assert(!(await fs.promises.exists(oldDir)));
50
+
51
+ await fs.promises.mkdir(oldDir);
52
+ await populate(oldDir);
53
+ await fs.promises.rename(oldDir, newDir + '/newDir');
54
+ });
55
+
56
+ test('rename file', async () => {
57
+ const dir = '/rename_file_test';
58
+ const one = dir + '/fun.js';
59
+ const two = dir + '/fun2.js';
60
+
61
+ await fs.promises.mkdir(dir);
62
+ await fs.promises.writeFile(one, 'while(1) alert("Hey! Listen!");');
63
+ await fs.promises.rename(one, one);
64
+ await fs.promises.rename(one, two);
65
+
66
+ await fs.promises.writeFile(one, 'hey');
67
+ await fs.promises.rename(one, two);
68
+
69
+ assert((await fs.promises.readFile(two, 'utf8')) === 'hey');
70
+ assert(!(await fs.promises.exists(one)));
71
+ });
72
+
73
+ test('File to Directory and Directory to File Rename', async () => {
74
+ const dir = '/rename_filedir_test';
75
+ const file = '/rename_filedir_test.txt';
76
+
77
+ await fs.promises.mkdir(dir);
78
+ await fs.promises.writeFile(file, 'file contents go here');
79
+
80
+ await fs.promises.rename(file, dir).catch((error: ErrnoError) => {
81
+ assert(error instanceof ErrnoError);
82
+ assert(error.code === 'EISDIR' || error.code === 'EPERM');
83
+ });
84
+
85
+ // JV: Removing test for now. I noticed that you can do that in Node v0.12 on Mac,
86
+ // but it might be FS independent.
87
+ /*fs.rename(dir, file, function (e) {
88
+ if (e == null) {
89
+ throw new Error("Failed invariant: Cannot rename a directory over a file.");
90
+ } else {
91
+ assert(e.code === 'ENOTDIR');
92
+ }
93
+ });*/
94
+ });
95
+
96
+ test('rename directory inside itself', async () => {
97
+ const renDir1 = '/renamedir_1';
98
+ const renDir2 = '/renamedir_1/lol';
99
+
100
+ await fs.promises.mkdir(renDir1);
101
+
102
+ await fs.promises.rename(renDir1, renDir2).catch((error: ErrnoError) => {
103
+ assert(error instanceof ErrnoError);
104
+ assert(error.code === 'EBUSY');
105
+ });
106
+ });
107
+ });
@@ -0,0 +1,48 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import { Stats } from '../../src/stats.js';
4
+ import { fs } from '../common.js';
5
+
6
+ suite('Stats', () => {
7
+ const existing_file = 'x.txt';
8
+
9
+ test('stat empty path', () => {
10
+ assert.rejects(fs.promises.stat(''));
11
+ });
12
+
13
+ test('stat directory', async () => {
14
+ const stats = await fs.promises.stat('/');
15
+ assert(stats instanceof Stats);
16
+ });
17
+
18
+ test('lstat directory', async () => {
19
+ const stats = await fs.promises.lstat('/');
20
+ assert(stats instanceof Stats);
21
+ });
22
+
23
+ test('FileHandle.stat', async () => {
24
+ const handle = await fs.promises.open(existing_file, 'r');
25
+ const stats = await handle.stat();
26
+ assert(stats instanceof Stats);
27
+ await handle.close();
28
+ });
29
+
30
+ test('fstatSync file', () => {
31
+ const fd = fs.openSync(existing_file, 'r');
32
+ const stats = fs.fstatSync(fd);
33
+ assert(stats instanceof Stats);
34
+ fs.close(fd);
35
+ });
36
+
37
+ test('stat file', async () => {
38
+ const stats = await fs.promises.stat(existing_file);
39
+ assert(!stats.isDirectory());
40
+ assert(stats.isFile());
41
+ assert(!stats.isSocket());
42
+ assert(!stats.isBlockDevice());
43
+ assert(!stats.isCharacterDevice());
44
+ assert(!stats.isFIFO());
45
+ assert(!stats.isSymbolicLink());
46
+ assert(stats instanceof Stats);
47
+ });
48
+ });
@@ -0,0 +1,177 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import { fs } from '../common.js';
4
+
5
+ // Top-level initialization
6
+ const testFilePath = 'test-file.txt';
7
+ const testData = 'Hello, World!';
8
+ await fs.promises.writeFile(testFilePath, testData);
9
+
10
+ const testFilePathWrite = 'test-file-write.txt';
11
+ await fs.promises.writeFile(testFilePathWrite, ''); // Ensure the file exists
12
+
13
+ suite('ReadStream', () => {
14
+ test('ReadStream reads data correctly', (_, done) => {
15
+ const readStream = fs.createReadStream(testFilePath);
16
+ let data = '';
17
+ readStream.on('data', chunk => {
18
+ data += chunk;
19
+ });
20
+ readStream.on('end', () => {
21
+ assert(data == testData);
22
+ done();
23
+ });
24
+ readStream.on('error', err => {
25
+ done(err);
26
+ });
27
+ });
28
+
29
+ test('ReadStream close method works', (_, done) => {
30
+ const readStream = fs.createReadStream(testFilePath);
31
+ let closed = false;
32
+ readStream.on('close', () => {
33
+ closed = true;
34
+ });
35
+ readStream.close(err => {
36
+ assert(err === undefined);
37
+ assert(closed);
38
+ done();
39
+ });
40
+ });
41
+
42
+ test('ReadStream declared properties', () => {
43
+ const readStream = new fs.ReadStream();
44
+ assert(readStream.bytesRead === undefined);
45
+ assert(readStream.path === undefined);
46
+ assert(readStream.pending === undefined);
47
+
48
+ // Assign values
49
+ readStream.bytesRead = 10;
50
+ readStream.path = testFilePath;
51
+ readStream.pending = false;
52
+
53
+ assert(readStream.bytesRead === 10);
54
+ assert(readStream.path === testFilePath);
55
+ assert(!readStream.pending);
56
+ });
57
+
58
+ test('ReadStream close method can be called multiple times', (_, done) => {
59
+ const readStream = new fs.ReadStream();
60
+ readStream.close(err => {
61
+ assert(err === undefined);
62
+ // Call close again
63
+ readStream.close(err2 => {
64
+ assert(err2 === undefined);
65
+ done();
66
+ });
67
+ });
68
+ });
69
+ });
70
+
71
+ suite('WriteStream', () => {
72
+ test.skip('WriteStream writes data correctly', (_, done) => {
73
+ const writeStream = fs.createWriteStream(testFilePathWrite);
74
+ writeStream.write(testData, 'utf8', err => {
75
+ if (err) {
76
+ done(err);
77
+ return;
78
+ }
79
+ writeStream.end();
80
+ });
81
+ writeStream.on('finish', () => {
82
+ assert(fs.readFileSync(testFilePathWrite, 'utf8') == testData);
83
+ done();
84
+ });
85
+ writeStream.on('error', err => {
86
+ done(err);
87
+ });
88
+ });
89
+
90
+ test('WriteStream close method works', (_, done) => {
91
+ const writeStream = fs.createWriteStream(testFilePathWrite);
92
+ let closed = false;
93
+ writeStream.on('close', () => {
94
+ closed = true;
95
+ });
96
+ writeStream.close(err => {
97
+ assert(err === undefined);
98
+ assert(closed);
99
+ done();
100
+ });
101
+ });
102
+
103
+ test('WriteStream declared properties', () => {
104
+ const writeStream = new fs.WriteStream();
105
+ assert(writeStream.bytesWritten === undefined);
106
+ assert(writeStream.path === undefined);
107
+ assert(writeStream.pending === undefined);
108
+
109
+ // Assign values
110
+ writeStream.bytesWritten = 20;
111
+ writeStream.path = testFilePathWrite;
112
+ writeStream.pending = true;
113
+
114
+ assert(writeStream.bytesWritten === 20);
115
+ assert(writeStream.path === testFilePathWrite);
116
+ assert(writeStream.pending);
117
+ });
118
+
119
+ test('WriteStream close method can be called multiple times', (_, done) => {
120
+ const writeStream = new fs.WriteStream();
121
+ writeStream.close(err => {
122
+ assert(err === undefined);
123
+ // Call close again
124
+ writeStream.close(err2 => {
125
+ assert(err2 === undefined);
126
+ done();
127
+ });
128
+ });
129
+ });
130
+ });
131
+
132
+ suite('FileHandle', () => {
133
+ test.skip('FileHandle.createReadStream reads data correctly', async () => {
134
+ const fileHandle = await fs.promises.open(testFilePath, 'r');
135
+ const readStream = fileHandle.createReadStream();
136
+ let data = '';
137
+ await new Promise<void>((resolve, reject) => {
138
+ readStream.on('data', chunk => {
139
+ data += chunk;
140
+ });
141
+ readStream.on('end', () => {
142
+ assert(data == testData);
143
+ resolve();
144
+ });
145
+ readStream.on('error', reject);
146
+ });
147
+ await fileHandle.close();
148
+ });
149
+
150
+ test.skip('FileHandle.createWriteStream writes data correctly', async () => {
151
+ const fileHandle = await fs.promises.open(testFilePathWrite, 'w');
152
+ const writeStream = fileHandle.createWriteStream();
153
+ await new Promise<void>((resolve, reject) => {
154
+ writeStream.write(testData, 'utf8', err => {
155
+ if (err) return reject(err);
156
+ writeStream.end();
157
+ });
158
+ writeStream.on('finish', resolve);
159
+ writeStream.on('error', reject);
160
+ });
161
+ const data = await fs.promises.readFile(testFilePathWrite, 'utf8');
162
+ assert(data == testData);
163
+ await fileHandle.close();
164
+ });
165
+
166
+ test('FileHandle.createReadStream after close should throw', async () => {
167
+ const fileHandle = await fs.promises.open(testFilePath, 'r');
168
+ await fileHandle.close();
169
+ assert.throws(() => fileHandle.createReadStream());
170
+ });
171
+
172
+ test.skip('FileHandle.createWriteStream after close should throw', async () => {
173
+ const fileHandle = await fs.promises.open(testFilePathWrite, 'w');
174
+ await fileHandle.close();
175
+ assert.throws(() => fileHandle.createWriteStream());
176
+ });
177
+ });
@@ -0,0 +1,84 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import { wait } from 'utilium';
4
+ import { ErrnoError } from '../../src/error.js';
5
+ import { _toUnixTimestamp } from '../../src/utils.js';
6
+ import { fs } from '../common.js';
7
+
8
+ suite('times', () => {
9
+ const path = 'x.txt';
10
+
11
+ function expect_assert(resource: string | number, atime: Date | number, mtime: Date | number) {
12
+ const stats = typeof resource == 'string' ? fs.statSync(resource) : fs.fstatSync(resource);
13
+ // check up to single-second precision since sub-second precision is OS and fs dependent
14
+ assert(_toUnixTimestamp(atime) == _toUnixTimestamp(stats.atime));
15
+ assert(_toUnixTimestamp(mtime) == _toUnixTimestamp(stats.mtime));
16
+ }
17
+
18
+ async function runTest(atime: Date | number, mtime: Date | number): Promise<void> {
19
+ await fs.promises.utimes(path, atime, mtime);
20
+ expect_assert(path, atime, mtime);
21
+
22
+ await fs.promises.utimes('foobarbaz', atime, mtime).catch((error: ErrnoError) => {
23
+ assert(error instanceof ErrnoError);
24
+ assert(error.code === 'ENOENT');
25
+ });
26
+
27
+ // don't close this fd
28
+ const handle = await fs.promises.open(path, 'r');
29
+
30
+ await handle.utimes(atime, mtime);
31
+ expect_assert(handle.fd, atime, mtime);
32
+
33
+ fs.utimesSync(path, atime, mtime);
34
+ expect_assert(path, atime, mtime);
35
+
36
+ // some systems don't have futimes
37
+ // if there's an error, it be ENOSYS
38
+ try {
39
+ fs.futimesSync(handle.fd, atime, mtime);
40
+ expect_assert(handle.fd, atime, mtime);
41
+ } catch (error: any) {
42
+ assert(error instanceof ErrnoError);
43
+ assert(error.code === 'ENOSYS');
44
+ }
45
+
46
+ try {
47
+ fs.utimesSync('foobarbaz', atime, mtime);
48
+ } catch (error: any) {
49
+ assert(error instanceof ErrnoError);
50
+ assert(error.code === 'ENOENT');
51
+ }
52
+
53
+ try {
54
+ fs.futimesSync(-1, atime, mtime);
55
+ } catch (error: any) {
56
+ assert(error instanceof ErrnoError);
57
+ assert(error.code == 'EBADF');
58
+ }
59
+ }
60
+
61
+ test('utimes works', async () => {
62
+ await runTest(new Date('1982/09/10 13:37:00'), new Date('1982/09/10 13:37:00'));
63
+ await runTest(new Date(), new Date());
64
+ await runTest(123456.789, 123456.789);
65
+ const stats = fs.statSync(path);
66
+ await runTest(stats.atime, stats.mtime);
67
+ });
68
+
69
+ test('read changes atime', async () => {
70
+ const before = fs.statSync(path).atimeMs;
71
+ fs.readFileSync(path);
72
+ await wait(100);
73
+ const after = fs.statSync(path).atimeMs;
74
+ assert(before < after);
75
+ });
76
+
77
+ test('write changes mtime', async () => {
78
+ const before = fs.statSync(path).mtimeMs;
79
+ fs.writeFileSync(path, 'cool');
80
+ await wait(100);
81
+ const after = fs.statSync(path).mtimeMs;
82
+ assert(before < after);
83
+ });
84
+ });
@@ -0,0 +1,94 @@
1
+ import assert from 'node:assert';
2
+ import { suite, test } from 'node:test';
3
+ import type { FileHandle } from '../../src/emulation/promises.js';
4
+ import { fs } from '../common.js';
5
+
6
+ const path: string = 'truncate-file.txt',
7
+ size = 1024 * 16,
8
+ data = new Uint8Array(size).fill('x'.charCodeAt(0));
9
+
10
+ suite('Truncate, sync', () => {
11
+ test('initial write', () => {
12
+ fs.writeFileSync(path, data);
13
+ assert(fs.statSync(path).size === size);
14
+ });
15
+
16
+ test('truncate to 1024', () => {
17
+ fs.truncateSync(path, 1024);
18
+ assert(fs.statSync(path).size === 1024);
19
+ });
20
+
21
+ test('truncate to 0', () => {
22
+ fs.truncateSync(path);
23
+ assert(fs.statSync(path).size === 0);
24
+ });
25
+
26
+ test('write', () => {
27
+ fs.writeFileSync(path, data);
28
+ assert(fs.statSync(path).size === size);
29
+ });
30
+
31
+ let fd: number;
32
+ test('open r+', () => {
33
+ fd = fs.openSync(path, 'r+');
34
+ });
35
+
36
+ test('ftruncate to 1024', () => {
37
+ fs.ftruncateSync(fd, 1024);
38
+ assert(fs.fstatSync(fd).size === 1024);
39
+ });
40
+
41
+ test('ftruncate to 0', () => {
42
+ fs.ftruncateSync(fd);
43
+ assert(fs.fstatSync(fd).size === 0);
44
+ });
45
+
46
+ test('close fd', () => {
47
+ fs.closeSync(fd);
48
+ });
49
+ });
50
+ suite('Truncate, async', () => {
51
+ const statSize = async (path: string) => (await fs.promises.stat(path)).size;
52
+
53
+ test('initial write', async () => {
54
+ await fs.promises.writeFile(path, data);
55
+
56
+ assert((await statSize(path)) === 1024 * 16);
57
+ });
58
+
59
+ test('truncate to 1024', async () => {
60
+ await fs.promises.truncate(path, 1024);
61
+ assert((await statSize(path)) === 1024);
62
+ });
63
+
64
+ test('truncate to 0', async () => {
65
+ await fs.promises.truncate(path);
66
+ assert((await statSize(path)) === 0);
67
+ });
68
+
69
+ test('write', async () => {
70
+ await fs.promises.writeFile(path, data);
71
+ assert((await statSize(path)) === size);
72
+ });
73
+
74
+ let handle: FileHandle;
75
+ test('open w', async () => {
76
+ handle = await fs.promises.open(path, 'w');
77
+ });
78
+
79
+ test('handle.truncate to 1024', async () => {
80
+ await handle.truncate(1024);
81
+ await handle.sync();
82
+ assert((await statSize(path)) === 1024);
83
+ });
84
+
85
+ test('handle.truncate to 0', async () => {
86
+ await handle.truncate();
87
+ await handle.sync();
88
+ assert((await statSize(path)) === 0);
89
+ });
90
+
91
+ test('close handle', async () => {
92
+ await handle.close();
93
+ });
94
+ });