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