1
+ /**
2
+ * @fileoverview Tests for the bytecode cache generation script.
3
+ */
4
+
5
+ const fs = require ( 'node:fs' ) ;
6
+ const path = require ( 'node:path' ) ;
7
+ const Module = require ( 'node:module' ) ;
8
+
9
+ // Mock the functions used from node:module
10
+ const mockEnableCompileCache = jasmine . createSpy ( 'enableCompileCache' ) ;
11
+ const mockFlushCompileCache = jasmine . createSpy ( 'flushCompileCache' ) ;
12
+ Module . enableCompileCache = mockEnableCompileCache ;
13
+ Module . flushCompileCache = mockFlushCompileCache ;
14
+
15
+ /**
16
+ * Helper to run the script.
17
+ */
18
+ const runScript = ( ) => {
19
+ require ( './main.js' ) ;
20
+ } ;
21
+
22
+ describe ( 'Bytecode Cache Generation Script' , ( ) => {
23
+ let originalArgv ;
24
+ let originalCwd ;
25
+ let processExitSpy ;
26
+ let consoleErrorSpy ;
27
+ let fsExistsSyncSpy ;
28
+ let fsRmSyncSpy ;
29
+ let fsMkdirSyncSpy ;
30
+ let requireSpy ;
31
+ const originalModuleLoad = Module . _load ;
32
+
33
+ const entrypoint = 'test_entrypoint.js' ;
34
+ const cacheDirName = '.test_cache' ;
35
+ const cachePath = path . join ( '/tmp' , cacheDirName ) ;
36
+
37
+ beforeEach ( ( ) => {
38
+ // Backup original values
39
+ originalArgv = process . argv ;
40
+ originalCwd = process . cwd ;
41
+
42
+ // Mock process.argv
43
+ process . argv = [ 'node' , 'main.js' , entrypoint , cacheDirName ] ;
44
+
45
+ // Mock process.cwd
46
+ process . cwd = ( ) => '/tmp' ;
47
+
48
+ // Spy on process.exit
49
+ processExitSpy = spyOn ( process , 'exit' ) . and . stub ( ) ; // Prevent test runner exit
50
+
51
+ // Spy on console.error
52
+ consoleErrorSpy = spyOn ( console , 'error' ) ;
53
+
54
+ // Spy on fs methods
55
+ fsExistsSyncSpy = spyOn ( fs , 'existsSync' ) ;
56
+ fsRmSyncSpy = spyOn ( fs , 'rmSync' ) ;
57
+ fsMkdirSyncSpy = spyOn ( fs , 'mkdirSync' ) ;
58
+
59
+ // Spy on Module._load
60
+ requireSpy = spyOn ( Module , '_load' ) . and . callFake ( ( request , parent , isMain ) => {
61
+ if ( request === entrypoint ) {
62
+ // Simulate successful require of the entrypoint
63
+ return { exports : { } } ;
64
+ }
65
+ // For other requires (like node:fs, etc.), use the original loader
66
+ return originalModuleLoad ( request , parent , isMain ) ;
67
+ } ) ;
68
+
69
+ // Reset mock module spies
70
+ mockEnableCompileCache . calls . reset ( ) ;
71
+ mockFlushCompileCache . calls . reset ( ) ;
72
+ } ) ;
73
+
74
+ afterEach ( ( ) => {
75
+ // Restore original values
76
+ process . argv = originalArgv ;
77
+ process . cwd = originalCwd ;
78
+
79
+ // Clear require cache for the main script
80
+ delete require . cache [ require . resolve ( './main.js' ) ] ;
81
+ } ) ;
82
+
83
+ it ( 'should generate cache successfully when cache dir does not exist' , ( ) => {
84
+ fsExistsSyncSpy . withArgs ( cachePath ) . and . returnValue ( false ) ;
85
+
86
+ runScript ( ) ;
87
+
88
+ expect ( fsExistsSyncSpy ) . toHaveBeenCalledWith ( cachePath ) ;
89
+ expect ( fsRmSyncSpy ) . not . toHaveBeenCalled ( ) ;
90
+ expect ( fsMkdirSyncSpy ) . toHaveBeenCalledWith ( cachePath ) ;
91
+ expect ( mockEnableCompileCache ) . toHaveBeenCalledWith ( cachePath ) ;
92
+ // Check that the entrypoint was required by the script
93
+ expect ( requireSpy ) . toHaveBeenCalledWith ( entrypoint , jasmine . anything ( ) , false ) ;
94
+ expect ( mockFlushCompileCache ) . toHaveBeenCalled ( ) ;
95
+ expect ( processExitSpy ) . not . toHaveBeenCalled ( ) ;
96
+ expect ( consoleErrorSpy ) . not . toHaveBeenCalled ( ) ;
97
+ } ) ;
98
+
99
+ it ( 'should populate cache dir if it exists' , ( ) => {
100
+ fsExistsSyncSpy . withArgs ( cachePath ) . and . returnValue ( true ) ;
101
+
102
+ runScript ( ) ;
103
+
104
+ expect ( fsExistsSyncSpy ) . toHaveBeenCalledWith ( cachePath ) ;
105
+ expect ( mockEnableCompileCache ) . toHaveBeenCalledWith ( cachePath ) ;
106
+ // Check that the entrypoint was required by the script
107
+ expect ( requireSpy ) . toHaveBeenCalledWith ( entrypoint , jasmine . anything ( ) , false ) ;
108
+ expect ( mockFlushCompileCache ) . toHaveBeenCalled ( ) ;
109
+ expect ( processExitSpy ) . not . toHaveBeenCalled ( ) ;
110
+ expect ( consoleErrorSpy ) . not . toHaveBeenCalled ( ) ;
111
+ } ) ;
112
+
113
+ it ( 'should exit with error if entrypoint is not provided' , ( ) => {
114
+ process . argv = [ 'node' , 'main.js' ] ;
115
+ runScript ( ) ;
116
+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( jasmine . stringMatching ( / A p p l i c a t i o n e n t r y p o i n t n o t p r o v i d e d / ) ) ;
117
+ expect ( processExitSpy ) . toHaveBeenCalledWith ( 1 ) ;
118
+ } ) ;
119
+
120
+ it ( 'should exit with error if cache directory name is not provided' , ( ) => {
121
+ process . argv = [ 'node' , 'main.js' , entrypoint ] ;
122
+ runScript ( ) ;
123
+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( jasmine . stringMatching ( / C a c h e d i r e c t o r y n a m e n o t p r o v i d e d / ) ) ;
124
+ expect ( processExitSpy ) . toHaveBeenCalledWith ( 1 ) ;
125
+ } ) ;
126
+
127
+ it ( 'should exit with error if require fails inside the script' , ( ) => {
128
+ fsExistsSyncSpy . and . returnValue ( false ) ;
129
+ const requireError = new Error ( 'Module not found' ) ;
130
+
131
+ // Override the default fake for this test to make entrypoint require fail
132
+ requireSpy . and . callFake ( ( request , parent , isMain ) => {
133
+ if ( request === entrypoint ) {
134
+ throw requireError ;
135
+ }
136
+ return originalModuleLoad ( request , parent , isMain ) ;
137
+ } ) ;
138
+
139
+ runScript ( ) ;
140
+
141
+ expect ( mockEnableCompileCache ) . toHaveBeenCalledWith ( cachePath ) ;
142
+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( ' Warning: Error during cache generation, build will continue without it.' , requireError ) ;
143
+ expect ( processExitSpy ) . toHaveBeenCalledWith ( 1 ) ;
144
+ expect ( mockFlushCompileCache ) . not . toHaveBeenCalled ( ) ;
145
+ } ) ;
146
+
147
+ it ( 'should exit with error if fs.mkdirSync fails' , ( ) => {
148
+ fsExistsSyncSpy . and . returnValue ( false ) ;
149
+ const mkdirError = new Error ( 'Permission denied' ) ;
150
+ fsMkdirSyncSpy . and . throwError ( mkdirError ) ;
151
+
152
+ runScript ( ) ;
153
+
154
+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith ( ' Warning: Error during cache generation, build will continue without it.' , mkdirError ) ;
155
+ expect ( processExitSpy ) . toHaveBeenCalledWith ( 1 ) ;
156
+ expect ( mockEnableCompileCache ) . not . toHaveBeenCalled ( ) ;
157
+ } ) ;
158
+ } ) ;
0 commit comments