@@ -3,6 +3,8 @@ import * as cache from '@actions/cache';
33import * as core from '@actions/core' ;
44import * as cacheUtils from '../src/cache-utils' ;
55import { PackageManagerInfo } from '../src/package-managers' ;
6+ import fs , { ObjectEncodingOptions , PathLike } from 'fs' ;
7+ import { getToolchainDirectoriesFromCachedDirectories } from '../src/cache-utils' ;
68
79describe ( 'getCommandOutput' , ( ) => {
810 //Arrange
@@ -209,3 +211,178 @@ describe('isCacheFeatureAvailable', () => {
209211 expect ( warningSpy ) . toHaveBeenCalledWith ( warningMessage ) ;
210212 } ) ;
211213} ) ;
214+
215+ describe ( 'parseGoModForToolchainVersion' , ( ) => {
216+ const readFileSyncSpy = jest . spyOn ( fs , 'readFileSync' ) ;
217+
218+ afterEach ( ( ) => {
219+ jest . clearAllMocks ( ) ;
220+ } ) ;
221+
222+ it ( 'should return null when go.mod file not exist' , async ( ) => {
223+ //Arrange
224+ //Act
225+ const toolchainVersion = cacheUtils . parseGoModForToolchainVersion (
226+ '/tmp/non/exist/foo.bar'
227+ ) ;
228+ //Assert
229+ expect ( toolchainVersion ) . toBeNull ( ) ;
230+ } ) ;
231+
232+ it ( 'should return null when go.mod file is empty' , async ( ) => {
233+ //Arrange
234+ readFileSyncSpy . mockImplementation ( ( ) => '' ) ;
235+ //Act
236+ const toolchainVersion = cacheUtils . parseGoModForToolchainVersion ( 'go.mod' ) ;
237+ //Assert
238+ expect ( toolchainVersion ) . toBeNull ( ) ;
239+ } ) ;
240+
241+ it ( 'should return null when go.mod file does not contain toolchain version' , async ( ) => {
242+ //Arrange
243+ readFileSyncSpy . mockImplementation ( ( ) =>
244+ `
245+ module example-mod
246+
247+ go 1.21.0
248+
249+ require golang.org/x/tools v0.13.0
250+
251+ require (
252+ golang.org/x/mod v0.12.0 // indirect
253+ golang.org/x/sys v0.12.0 // indirect
254+ )
255+ ` . replace ( / ^ \s + / gm, '' )
256+ ) ;
257+ //Act
258+ const toolchainVersion = cacheUtils . parseGoModForToolchainVersion ( 'go.mod' ) ;
259+ //Assert
260+ expect ( toolchainVersion ) . toBeNull ( ) ;
261+ } ) ;
262+
263+ it ( 'should return go version when go.mod file contains go version' , ( ) => {
264+ //Arrange
265+ readFileSyncSpy . mockImplementation ( ( ) =>
266+ `
267+ module example-mod
268+
269+ go 1.21.0
270+
271+ toolchain go1.21.1
272+
273+ require golang.org/x/tools v0.13.0
274+
275+ require (
276+ golang.org/x/mod v0.12.0 // indirect
277+ golang.org/x/sys v0.12.0 // indirect
278+ )
279+ ` . replace ( / ^ \s + / gm, '' )
280+ ) ;
281+
282+ //Act
283+ const toolchainVersion = cacheUtils . parseGoModForToolchainVersion ( 'go.mod' ) ;
284+ //Assert
285+ expect ( toolchainVersion ) . toBe ( '1.21.1' ) ;
286+ } ) ;
287+
288+ it ( 'should return go version when go.mod file contains more than one go version' , ( ) => {
289+ //Arrange
290+ readFileSyncSpy . mockImplementation ( ( ) =>
291+ `
292+ module example-mod
293+
294+ go 1.21.0
295+
296+ toolchain go1.21.0
297+ toolchain go1.21.1
298+
299+ require golang.org/x/tools v0.13.0
300+
301+ require (
302+ golang.org/x/mod v0.12.0 // indirect
303+ golang.org/x/sys v0.12.0 // indirect
304+ )
305+ ` . replace ( / ^ \s + / gm, '' )
306+ ) ;
307+
308+ //Act
309+ const toolchainVersion = cacheUtils . parseGoModForToolchainVersion ( 'go.mod' ) ;
310+ //Assert
311+ expect ( toolchainVersion ) . toBe ( '1.21.1' ) ;
312+ } ) ;
313+ } ) ;
314+
315+ describe ( 'getToolchainDirectoriesFromCachedDirectories' , ( ) => {
316+ const readdirSyncSpy = jest . spyOn ( fs , 'readdirSync' ) ;
317+ const existsSyncSpy = jest . spyOn ( fs , 'existsSync' ) ;
318+ const lstatSync = jest . spyOn ( fs , 'lstatSync' ) ;
319+
320+ afterEach ( ( ) => {
321+ jest . clearAllMocks ( ) ;
322+ } ) ;
323+
324+ it ( 'should return empty array when cacheDirectories is empty' , async ( ) => {
325+ const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories (
326+ 'foo' ,
327+ [ ]
328+ ) ;
329+ expect ( toolcacheDirectories ) . toEqual ( [ ] ) ;
330+ } ) ;
331+
332+ it ( 'should return empty array when cacheDirectories does not contain /go/pkg' , async ( ) => {
333+ readdirSyncSpy . mockImplementation ( dir =>
334+ [ `${ dir } 1` , `${ dir } 2` , `${ dir } 3` ] . map ( s => {
335+ const de = new fs . Dirent ( ) ;
336+ de . name = s ;
337+ de . isDirectory = ( ) => true ;
338+ return de ;
339+ } )
340+ ) ;
341+
342+ const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories (
343+ '1.1.1' ,
344+ [ 'foo' , 'bar' ]
345+ ) ;
346+ expect ( toolcacheDirectories ) . toEqual ( [ ] ) ;
347+ } ) ;
348+
349+ it ( 'should return empty array when cacheDirectories does not contain toolchain@v[0-9.]+-go{goVersion}' , async ( ) => {
350+ readdirSyncSpy . mockImplementation ( dir =>
351+ [ `${ dir } 1` , `${ dir } 2` , `${ dir } 3` ] . map ( s => {
352+ const de = new fs . Dirent ( ) ;
353+ de . name = s ;
354+ de . isDirectory = ( ) => true ;
355+ return de ;
356+ } )
357+ ) ;
358+
359+ const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories (
360+ 'foo' ,
361+ [ 'foo/go/pkg/mod' , 'bar' ]
362+ ) ;
363+ expect ( toolcacheDirectories ) . toEqual ( [ ] ) ;
364+ } ) ;
365+
366+ it ( 'should return one entry when cacheDirectories contains toolchain@v[0-9.]+-go{goVersion} in /pkg/mod' , async ( ) => {
367+ let seqNo = 1 ;
368+ readdirSyncSpy . mockImplementation ( dir =>
369+ [ `[email protected] ${ seqNo ++ } ` ] . map ( s => { 370+ const de = new fs . Dirent ( ) ;
371+ de . name = s ;
372+ de . isDirectory = ( ) => true ;
373+ return de ;
374+ } )
375+ ) ;
376+ existsSyncSpy . mockReturnValue ( true ) ;
377+ // @ts -ignore - jest does not have relaxed mocks, so we ignore not-implemented methods
378+ lstatSync . mockImplementation ( ( ) => ( { isDirectory : ( ) => true } ) ) ;
379+
380+ const toolcacheDirectories = getToolchainDirectoriesFromCachedDirectories (
381+ '1.1.1' ,
382+ [ '/foo/go/pkg/mod' , 'bar' ]
383+ ) ;
384+ expect ( toolcacheDirectories ) . toEqual ( [
385+ '/foo/go/pkg/mod/golang.org/[email protected] ' 386+ ] ) ;
387+ } ) ;
388+ } ) ;
0 commit comments