@@ -126,9 +126,9 @@ elapsed time in the summary line.
126126
127127The rule for a match in the cache is that the run involves the same
128128test binary and the flags on the command line come entirely from a
129- restricted set of 'cacheable' test flags, defined as -benchtime, -cover,
130- -covermode , -coverprofile , -cpu, -list, -parallel, -run, -short, -timeout ,
131- -failfast, -fullpath and -v.
129+ restricted set of 'cacheable' test flags, defined as -benchtime,
130+ -coverprofile , -outputdir , -cpu, -list, -parallel, -run, -short,
131+ -timeout, - failfast, -fullpath and -v.
132132If a run of go test has any test or non-test flags outside this set,
133133the result is not cached. To disable test caching, use any test flag
134134or argument other than the cacheable flags. The idiomatic way to disable
@@ -1672,7 +1672,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
16721672 a .TestOutput = & buf
16731673 t := fmt .Sprintf ("%.3fs" , time .Since (t0 ).Seconds ())
16741674
1675- mergeCoverProfile (a . Objdir + "_cover_.out" )
1675+ mergeCoverProfile (coverProfTempFile ( a ) )
16761676
16771677 if err == nil {
16781678 norun := ""
@@ -1694,7 +1694,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
16941694 cmd .Stdout .Write ([]byte ("\n " ))
16951695 }
16961696 fmt .Fprintf (cmd .Stdout , "ok \t %s\t %s%s%s\n " , a .Package .ImportPath , t , coveragePercentage (out ), norun )
1697- r .c .saveOutput (a , coverProfTempFile ( a ) )
1697+ r .c .saveOutput (a )
16981698 } else {
16991699 if testFailFast {
17001700 testShouldFailFast .Store (true )
@@ -1794,14 +1794,7 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
17941794 cacheArgs = append (cacheArgs , arg )
17951795 case "-test.coverprofile" ,
17961796 "-test.outputdir" :
1797- // The `-coverprofile` and `-outputdir` arguments, which
1798- // only affect the location of profile output, are cacheable. This
1799- // is based on the process where, upon a cache hit, stored profile
1800- // data is copied to the specified output location. This mechanism
1801- // ensures that output location preferences are honored without
1802- // modifying the profile's content, thereby justifying their
1803- // cacheability without impacting cache integrity. This allows
1804- // cached coverage profiles to be written to different files.
1797+ // These are cacheable and do not invalidate the cache when they change.
18051798 // Note that this list is documented above,
18061799 // so if you add to this list, update the docs too.
18071800 default :
@@ -1875,6 +1868,20 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
18751868 // Parse cached result in preparation for changing run time to "(cached)".
18761869 // If we can't parse the cached result, don't use it.
18771870 data , entry , err = cache .GetBytes (cache .Default (), testAndInputKey (testID , testInputsID ))
1871+
1872+ // Merge cached cover profile data to cover profile.
1873+ if testCoverProfile != "" {
1874+ // Specifically ignore entry as it will be the same as above.
1875+ cpData , _ , err := cache .GetFile (cache .Default (), coverProfileAndInputKey (testID , testInputsID ))
1876+ if err != nil {
1877+ if cache .DebugTest {
1878+ fmt .Fprintf (os .Stderr , "testcache: %s: cached cover profile missing: %v\n " , a .Package .ImportPath , err )
1879+ }
1880+ return false
1881+ }
1882+ mergeCoverProfile (cpData )
1883+ }
1884+
18781885 if len (data ) == 0 || data [len (data )- 1 ] != '\n' {
18791886 if cache .DebugTest {
18801887 if err != nil {
@@ -1915,21 +1922,6 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
19151922 j ++
19161923 }
19171924 c .buf .Write (data [j :])
1918-
1919- // Write coverage data to profile.
1920- if cfg .BuildCover {
1921- // The cached coverprofile has the same expiration time as the
1922- // test result it corresponds to. That time is already checked
1923- // above, so we can ignore the entry returned by GetFile here.
1924- f , _ , err := cache .GetFile (cache .Default (), coverProfileAndInputKey (testID , testInputsID ))
1925- if err != nil {
1926- if cache .DebugTest {
1927- fmt .Fprintf (os .Stderr , "testcache: %s: cached test result valid but cached coverage profile missing: %v\n " , a .Package .ImportPath , err )
1928- }
1929- return false
1930- }
1931- mergeCoverProfile (f )
1932- }
19331925 return true
19341926}
19351927
@@ -2083,7 +2075,7 @@ func coverProfileAndInputKey(testID, testInputsID cache.ActionID) cache.ActionID
20832075 return cache .Subkey (testAndInputKey (testID , testInputsID ), "coverprofile" )
20842076}
20852077
2086- func (c * runCache ) saveOutput (a * work.Action , coverProfileFile string ) {
2078+ func (c * runCache ) saveOutput (a * work.Action ) {
20872079 if c .id1 == (cache.ActionID {}) && c .id2 == (cache.ActionID {}) {
20882080 return
20892081 }
@@ -2104,21 +2096,14 @@ func (c *runCache) saveOutput(a *work.Action, coverProfileFile string) {
21042096 if err != nil {
21052097 return
21062098 }
2107- var saveCoverProfile = func ( testID cache. ActionID ) {}
2108- if coverProfileFile != "" {
2109- coverProfile , err : = os .Open ( coverProfileFile )
2110- if err = = nil {
2111- saveCoverProfile = func ( testID cache.ActionID ) {
2112- cache . Default (). Put ( coverProfileAndInputKey ( testID , testInputsID ), coverProfile )
2099+ var coverProfile [] byte
2100+ if testCoverProfile != "" {
2101+ coverProfile , err = os .ReadFile ( coverProfTempFile ( a ) )
2102+ if err ! = nil {
2103+ if cache .DebugTest {
2104+ fmt . Fprintf ( os . Stderr , "testcache: %s: reading cover profile: %v \n " , a . Package . ImportPath , err )
21132105 }
2114- defer func () {
2115- if err := coverProfile .Close (); err != nil && cache .DebugTest {
2116- base .Errorf ("closing temporary coverprofile: %v" , err )
2117- }
2118- }()
2119- } else if cache .DebugTest {
2120- // Not indicative of a problem, as the test may not have generated a cover profile yet.
2121- fmt .Fprintf (os .Stderr , "testcache: %s: opening temporary coverprofile: %s\n " , a .Package .ImportPath , err )
2106+ return
21222107 }
21232108 }
21242109 if c .id1 != (cache.ActionID {}) {
@@ -2127,15 +2112,19 @@ func (c *runCache) saveOutput(a *work.Action, coverProfileFile string) {
21272112 }
21282113 cache .PutNoVerify (cache .Default (), c .id1 , bytes .NewReader (testlog ))
21292114 cache .PutNoVerify (cache .Default (), testAndInputKey (c .id1 , testInputsID ), bytes .NewReader (a .TestOutput .Bytes ()))
2130- saveCoverProfile (c .id1 )
2115+ if coverProfile != nil {
2116+ cache .PutNoVerify (cache .Default (), coverProfileAndInputKey (c .id1 , testInputsID ), bytes .NewReader (coverProfile ))
2117+ }
21312118 }
21322119 if c .id2 != (cache.ActionID {}) {
21332120 if cache .DebugTest {
21342121 fmt .Fprintf (os .Stderr , "testcache: %s: save test ID %x => input ID %x => %x\n " , a .Package .ImportPath , c .id2 , testInputsID , testAndInputKey (c .id2 , testInputsID ))
21352122 }
21362123 cache .PutNoVerify (cache .Default (), c .id2 , bytes .NewReader (testlog ))
21372124 cache .PutNoVerify (cache .Default (), testAndInputKey (c .id2 , testInputsID ), bytes .NewReader (a .TestOutput .Bytes ()))
2138- saveCoverProfile (c .id2 )
2125+ if coverProfile != nil {
2126+ cache .PutNoVerify (cache .Default (), coverProfileAndInputKey (c .id2 , testInputsID ), bytes .NewReader (coverProfile ))
2127+ }
21392128 }
21402129}
21412130
0 commit comments