Skip to content

Commit bd982bb

Browse files
jeysalcaptain-yossarian
authored andcommitted
HasteFS file size (jestjs#7580)
1 parent 55283bb commit bd982bb

File tree

13 files changed

+189
-63
lines changed

13 files changed

+189
-63
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
- `[jest-haste-map]` [**BREAKING**] Remove name from hash in `HasteMap.getCacheFilePath` ([#7218](https://github.com/facebook/jest/pull/7218))
1414
- `[babel-preset-jest]` [**BREAKING**] Export a function instead of an object for Babel 7 compatibility ([#7203](https://github.com/facebook/jest/pull/7203))
1515
- `[jest-haste-map]` [**BREAKING**] Expose relative paths when getting the file iterator ([#7321](https://github.com/facebook/jest/pull/7321))
16-
- `[jest-cli]` Print version ending in `-dev` when running a local Jest clone
16+
- `[jest-haste-map]` Add `hasteFS.getSize(path)` ([#7580](https://github.com/facebook/jest/pull/7580))
17+
- `[jest-cli]` Print version ending in `-dev` when running a local Jest clone ([#7582](https://github.com/facebook/jest/pull/7582))
1718
- `[jest-cli]` Add Support for `globalSetup` and `globalTeardown` in projects ([#6865](https://github.com/facebook/jest/pull/6865))
1819
- `[jest-runtime]` Add `extraGlobals` to config to load extra global variables into the execution vm ([#7454](https://github.com/facebook/jest/pull/7454))
1920
- `[jest-util]` Export `specialChars` containing Unicode characters and ANSI escapes for console output ([#7532](https://github.com/facebook/jest/pull/7532))

e2e/__tests__/haste_map_size.test.js

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
'use strict';
11+
12+
import os from 'os';
13+
import path from 'path';
14+
import HasteMap from 'jest-haste-map';
15+
import {cleanup, writeFiles} from '../Utils';
16+
17+
const DIR = path.resolve(os.tmpdir(), 'haste_map_size');
18+
19+
beforeEach(() => {
20+
cleanup(DIR);
21+
writeFiles(DIR, {
22+
'file.js': '"abc"',
23+
});
24+
});
25+
afterEach(() => cleanup(DIR));
26+
27+
const options = {
28+
extensions: ['js'],
29+
forceNodeFilesystemAPI: true,
30+
ignorePattern: / ^/,
31+
maxWorkers: 2,
32+
mocksPattern: '',
33+
name: 'tmp',
34+
platforms: [],
35+
retainAllFiles: true,
36+
rootDir: DIR,
37+
roots: [DIR],
38+
useWatchman: false,
39+
watch: false,
40+
};
41+
42+
test('reports the correct file size', async () => {
43+
const hasteMap = new HasteMap(options);
44+
const hasteFS = (await hasteMap.build()).hasteFS;
45+
expect(hasteFS.getSize(path.join(DIR, 'file.js'))).toBe(5);
46+
});
47+
48+
test('updates the file size when a file changes', async () => {
49+
const hasteMap = new HasteMap({...options, watch: true});
50+
await hasteMap.build();
51+
52+
writeFiles(DIR, {
53+
'file.js': '"asdf"',
54+
});
55+
const {hasteFS} = await new Promise(resolve =>
56+
hasteMap.once('change', resolve),
57+
);
58+
hasteMap.end();
59+
expect(hasteFS.getSize(path.join(DIR, 'file.js'))).toBe(6);
60+
});

packages/jest-cli/src/TestSequencer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ export default class TestSequencer {
6969
// fastest results.
7070
sort(tests: Array<Test>): Array<Test> {
7171
const stats = {};
72-
const fileSize = test =>
73-
stats[test.path] || (stats[test.path] = fs.statSync(test.path).size);
72+
const fileSize = ({path, context: {hasteFS}}) =>
73+
stats[path] || (stats[path] = hasteFS.getSize(path) || 0);
7474
const hasFailed = (cache, test) =>
7575
cache[test.path] && cache[test.path][0] === FAIL;
7676
const time = (cache, test) => cache[test.path] && cache[test.path][1];

packages/jest-cli/src/__tests__/test_sequencer.test.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ const context = {
2323
cacheDirectory: '/cache',
2424
name: 'test',
2525
},
26+
hasteFS: {
27+
getSize: path => path.length,
28+
},
2629
};
2730

2831
const secondContext = {
@@ -31,6 +34,9 @@ const secondContext = {
3134
cacheDirectory: '/cache2',
3235
name: 'test2',
3336
},
37+
hasteFS: {
38+
getSize: path => path.length,
39+
},
3440
};
3541

3642
const toTests = paths =>
@@ -45,7 +51,6 @@ beforeEach(() => {
4551

4652
fs.readFileSync = jest.fn(() => '{}');
4753
fs.existsSync = () => true;
48-
fs.statSync = jest.fn(filePath => ({size: filePath.length}));
4954
fs.writeFileSync = jest.fn();
5055
});
5156

packages/jest-haste-map/src/HasteFS.js

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ export default class HasteFS {
2828
return (fileMetadata && fileMetadata[H.ID]) || null;
2929
}
3030

31+
getSize(file: Path): ?number {
32+
const fileMetadata = this._getFileData(file);
33+
return (fileMetadata && fileMetadata[H.SIZE]) || null;
34+
}
35+
3136
getDependencies(file: Path): ?Array<string> {
3237
const fileMetadata = this._getFileData(file);
3338
return (fileMetadata && fileMetadata[H.DEPENDENCIES]) || null;

packages/jest-haste-map/src/__tests__/index.test.js

+44-18
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jest.mock('../crawlers/watchman', () =>
5151
if (list[file]) {
5252
const hash = computeSha1 ? mockHashContents(list[file]) : null;
5353

54-
data.files.set(relativeFilePath, ['', 32, 0, [], hash]);
54+
data.files.set(relativeFilePath, ['', 32, 42, 0, [], hash]);
5555
} else {
5656
data.files.delete(relativeFilePath);
5757
}
@@ -337,26 +337,28 @@ describe('HasteMap', () => {
337337

338338
expect(data.files).toEqual(
339339
createMap({
340-
'fruits/Banana.js': ['Banana', 32, 1, ['Strawberry'], null],
341-
'fruits/Pear.js': ['Pear', 32, 1, ['Banana', 'Strawberry'], null],
342-
'fruits/Strawberry.js': ['Strawberry', 32, 1, [], null],
343-
'fruits/__mocks__/Pear.js': ['', 32, 1, ['Melon'], null],
340+
'fruits/Banana.js': ['Banana', 32, 42, 1, ['Strawberry'], null],
341+
'fruits/Pear.js': ['Pear', 32, 42, 1, ['Banana', 'Strawberry'], null],
342+
'fruits/Strawberry.js': ['Strawberry', 32, 42, 1, [], null],
343+
'fruits/__mocks__/Pear.js': ['', 32, 42, 1, ['Melon'], null],
344344
// node modules
345345
'fruits/node_modules/fbjs/lib/flatMap.js': [
346346
'flatMap',
347347
32,
348+
42,
348349
1,
349350
[],
350351
null,
351352
],
352353
'fruits/node_modules/react/React.js': [
353354
'React',
354355
32,
356+
42,
355357
1,
356358
['Component'],
357359
null,
358360
],
359-
'vegetables/Melon.js': ['Melon', 32, 1, [], null],
361+
'vegetables/Melon.js': ['Melon', 32, 42, 1, [], null],
360362
}),
361363
);
362364

@@ -405,11 +407,18 @@ describe('HasteMap', () => {
405407

406408
// The node crawler returns "null" for the SHA-1.
407409
data.files = createMap({
408-
'fruits/Banana.js': ['Banana', 32, 0, ['Strawberry'], null],
409-
'fruits/Pear.js': ['Pear', 32, 0, ['Banana', 'Strawberry'], null],
410-
'fruits/Strawberry.js': ['Strawberry', 32, 0, [], null],
411-
'fruits/__mocks__/Pear.js': ['', 32, 0, ['Melon'], null],
412-
'vegetables/Melon.js': ['Melon', 32, 0, [], null],
410+
'fruits/Banana.js': ['Banana', 32, 42, 0, ['Strawberry'], null],
411+
'fruits/Pear.js': [
412+
'Pear',
413+
32,
414+
42,
415+
0,
416+
['Banana', 'Strawberry'],
417+
null,
418+
],
419+
'fruits/Strawberry.js': ['Strawberry', 32, 42, 0, [], null],
420+
'fruits/__mocks__/Pear.js': ['', 32, 42, 0, ['Melon'], null],
421+
'vegetables/Melon.js': ['Melon', 32, 42, 0, [], null],
413422
});
414423

415424
return Promise.resolve(data);
@@ -430,34 +439,39 @@ describe('HasteMap', () => {
430439
'fruits/Banana.js': [
431440
'Banana',
432441
32,
442+
42,
433443
1,
434444
['Strawberry'],
435445
'7772b628e422e8cf59c526be4bb9f44c0898e3d1',
436446
],
437447
'fruits/Pear.js': [
438448
'Pear',
439449
32,
450+
42,
440451
1,
441452
['Banana', 'Strawberry'],
442453
'89d0c2cc11dcc5e1df50b8af04ab1b597acfba2f',
443454
],
444455
'fruits/Strawberry.js': [
445456
'Strawberry',
446457
32,
458+
42,
447459
1,
448460
[],
449461
'e8aa38e232b3795f062f1d777731d9240c0f8c25',
450462
],
451463
'fruits/__mocks__/Pear.js': [
452464
'',
453465
32,
466+
42,
454467
1,
455468
['Melon'],
456469
'8d40afbb6e2dc78e1ba383b6d02cafad35cceef2',
457470
],
458471
'vegetables/Melon.js': [
459472
'Melon',
460473
32,
474+
42,
461475
1,
462476
[],
463477
'f16ccf6f2334ceff2ddb47628a2c5f2d748198ca',
@@ -507,6 +521,7 @@ describe('HasteMap', () => {
507521
expect(data.files.get('fruits/node_modules/fbjs/fbjs.js')).toEqual([
508522
'',
509523
32,
524+
42,
510525
0,
511526
[],
512527
null,
@@ -604,18 +619,20 @@ describe('HasteMap', () => {
604619
'fruits/Strawberry.android.js': [
605620
'Strawberry',
606621
32,
622+
42,
607623
1,
608624
['Blackberry'],
609625
null,
610626
],
611627
'fruits/Strawberry.ios.js': [
612628
'Strawberry',
613629
32,
630+
42,
614631
1,
615632
['Raspberry'],
616633
null,
617634
],
618-
'fruits/Strawberry.js': ['Strawberry', 32, 1, ['Banana'], null],
635+
'fruits/Strawberry.js': ['Strawberry', 32, 42, 1, ['Banana'], null],
619636
}),
620637
);
621638

@@ -702,7 +719,14 @@ describe('HasteMap', () => {
702719
expect(useBuitinsInContext(data.clocks)).toEqual(mockClocks);
703720

704721
const files = new Map(initialData.files);
705-
files.set('fruits/Banana.js', ['Banana', 32, 1, ['Kiwi'], null]);
722+
files.set('fruits/Banana.js', [
723+
'Banana',
724+
32,
725+
42,
726+
1,
727+
['Kiwi'],
728+
null,
729+
]);
706730

707731
expect(useBuitinsInContext(data.files)).toEqual(files);
708732

@@ -962,7 +986,7 @@ describe('HasteMap', () => {
962986
watchman.mockImplementation(options =>
963987
mockImpl(options).then(() => {
964988
const {data} = options;
965-
data.files.set('fruits/invalid/file.js', ['', 34, 0, []]);
989+
data.files.set('fruits/invalid/file.js', ['', 34, 44, 0, []]);
966990
return data;
967991
}),
968992
);
@@ -1060,7 +1084,7 @@ describe('HasteMap', () => {
10601084
node.mockImplementation(options => {
10611085
const {data} = options;
10621086
data.files = createMap({
1063-
'fruits/Banana.js': ['', 32, 0, [], null],
1087+
'fruits/Banana.js': ['', 32, 42, 0, [], null],
10641088
});
10651089
return Promise.resolve(data);
10661090
});
@@ -1073,7 +1097,7 @@ describe('HasteMap', () => {
10731097

10741098
expect(data.files).toEqual(
10751099
createMap({
1076-
'fruits/Banana.js': ['Banana', 32, 1, ['Strawberry'], null],
1100+
'fruits/Banana.js': ['Banana', 32, 42, 1, ['Strawberry'], null],
10771101
}),
10781102
);
10791103

@@ -1091,7 +1115,7 @@ describe('HasteMap', () => {
10911115
node.mockImplementation(options => {
10921116
const {data} = options;
10931117
data.files = createMap({
1094-
'fruits/Banana.js': ['', 32, 0, [], null],
1118+
'fruits/Banana.js': ['', 32, 42, 0, [], null],
10951119
});
10961120
return Promise.resolve(data);
10971121
});
@@ -1104,7 +1128,7 @@ describe('HasteMap', () => {
11041128

11051129
expect(data.files).toEqual(
11061130
createMap({
1107-
'fruits/Banana.js': ['Banana', 32, 1, ['Strawberry'], null],
1131+
'fruits/Banana.js': ['Banana', 32, 42, 1, ['Strawberry'], null],
11081132
}),
11091133
);
11101134
});
@@ -1184,11 +1208,13 @@ describe('HasteMap', () => {
11841208
const MOCK_STAT_FILE = {
11851209
isDirectory: () => false,
11861210
mtime: {getTime: () => 45},
1211+
size: 55,
11871212
};
11881213

11891214
const MOCK_STAT_FOLDER = {
11901215
isDirectory: () => true,
11911216
mtime: {getTime: () => 45},
1217+
size: 55,
11921218
};
11931219

11941220
hm_it('handles several change events at once', async hm => {

packages/jest-haste-map/src/constants.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ export default {
2020
/* file map attributes */
2121
ID: 0,
2222
MTIME: 1,
23-
VISITED: 2,
24-
DEPENDENCIES: 3,
25-
SHA1: 4,
23+
SIZE: 2,
24+
VISITED: 3,
25+
DEPENDENCIES: 4,
26+
SHA1: 5,
2627

2728
/* module map attributes */
2829
PATH: 0,

0 commit comments

Comments
 (0)