Home | History | Annotate | Download | only in test
      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package test
      6 
      7 import (
      8 	"cmd/go/internal/base"
      9 	"fmt"
     10 	"io"
     11 	"os"
     12 	"path/filepath"
     13 	"sync"
     14 )
     15 
     16 var coverMerge struct {
     17 	f          *os.File
     18 	sync.Mutex // for f.Write
     19 }
     20 
     21 // initCoverProfile initializes the test coverage profile.
     22 // It must be run before any calls to mergeCoverProfile or closeCoverProfile.
     23 // Using this function clears the profile in case it existed from a previous run,
     24 // or in case it doesn't exist and the test is going to fail to create it (or not run).
     25 func initCoverProfile() {
     26 	if testCoverProfile == "" {
     27 		return
     28 	}
     29 	if !filepath.IsAbs(testCoverProfile) && testOutputDir != "" {
     30 		testCoverProfile = filepath.Join(testOutputDir, testCoverProfile)
     31 	}
     32 
     33 	// No mutex - caller's responsibility to call with no racing goroutines.
     34 	f, err := os.Create(testCoverProfile)
     35 	if err != nil {
     36 		base.Fatalf("%v", err)
     37 	}
     38 	_, err = fmt.Fprintf(f, "mode: %s\n", testCoverMode)
     39 	if err != nil {
     40 		base.Fatalf("%v", err)
     41 	}
     42 	coverMerge.f = f
     43 }
     44 
     45 // mergeCoverProfile merges file into the profile stored in testCoverProfile.
     46 // It prints any errors it encounters to ew.
     47 func mergeCoverProfile(ew io.Writer, file string) {
     48 	if coverMerge.f == nil {
     49 		return
     50 	}
     51 	coverMerge.Lock()
     52 	defer coverMerge.Unlock()
     53 
     54 	expect := fmt.Sprintf("mode: %s\n", testCoverMode)
     55 	buf := make([]byte, len(expect))
     56 	r, err := os.Open(file)
     57 	if err != nil {
     58 		// Test did not create profile, which is OK.
     59 		return
     60 	}
     61 	defer r.Close()
     62 
     63 	n, err := io.ReadFull(r, buf)
     64 	if n == 0 {
     65 		return
     66 	}
     67 	if err != nil || string(buf) != expect {
     68 		fmt.Fprintf(ew, "error: test wrote malformed coverage profile.\n")
     69 		return
     70 	}
     71 	_, err = io.Copy(coverMerge.f, r)
     72 	if err != nil {
     73 		fmt.Fprintf(ew, "error: saving coverage profile: %v\n", err)
     74 	}
     75 }
     76 
     77 func closeCoverProfile() {
     78 	if coverMerge.f == nil {
     79 		return
     80 	}
     81 	if err := coverMerge.f.Close(); err != nil {
     82 		base.Errorf("closing coverage profile: %v", err)
     83 	}
     84 }
     85