Source File
pods.go
Belonging Package
internal/coverage/pods
// Copyright 2022 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package podsimport ()// Pod encapsulates a set of files emitted during the executions of a// coverage-instrumented binary. Each pod contains a single meta-data// file, and then 0 or more counter data files that refer to that// meta-data file. Pods are intended to simplify processing of// coverage output files in the case where we have several coverage// output directories containing output files derived from more// than one instrumented executable. In the case where the files that// make up a pod are spread out across multiple directories, each// element of the "Origins" field below will be populated with the// index of the originating directory for the corresponding counter// data file (within the slice of input dirs handed to CollectPods).// The ProcessIDs field will be populated with the process ID of each// data file in the CounterDataFiles slice.type Pod struct {MetaFile stringCounterDataFiles []stringOrigins []intProcessIDs []int}// CollectPods visits the files contained within the directories in// the list 'dirs', collects any coverage-related files, partitions// them into pods, and returns a list of the pods to the caller, along// with an error if something went wrong during directory/file// reading.//// CollectPods skips over any file that is not related to coverage// (e.g. avoids looking at things that are not meta-data files or// counter-data files). CollectPods also skips over 'orphaned' counter// data files (e.g. counter data files for which we can't find the// corresponding meta-data file). If "warn" is true, CollectPods will// issue warnings to stderr when it encounters non-fatal problems (for// orphans or a directory with no meta-data files).func ( []string, bool) ([]Pod, error) {:= []string{}:= []int{}for , := range {, := os.ReadDir()if != nil {return nil,}for , := range {if .IsDir() {continue}= append(, filepath.Join(, .Name()))= append(, )}}return collectPodsImpl(, , ), nil}// CollectPodsFromFiles functions the same as "CollectPods" but// operates on an explicit list of files instead of a directory.func ( []string, bool) []Pod {return collectPodsImpl(, nil, )}type fileWithAnnotations struct {file stringorigin intpid int}type protoPod struct {mf stringelements []fileWithAnnotations}// collectPodsImpl examines the specified list of files and picks out// subsets that correspond to coverage pods. The first stage in this// process is collecting a set { M1, M2, ... MN } where each M_k is a// distinct coverage meta-data file. We then create a single pod for// each meta-data file M_k, then find all of the counter data files// that refer to that meta-data file (recall that the counter data// file name incorporates the meta-data hash), and add the counter// data file to the appropriate pod.//// This process is complicated by the fact that we need to keep track// of directory indices for counter data files. Here is an example to// motivate://// directory 1://// M1 covmeta.9bbf1777f47b3fcacb05c38b035512d6// C1 covcounters.9bbf1777f47b3fcacb05c38b035512d6.1677673.1662138360208416486// C2 covcounters.9bbf1777f47b3fcacb05c38b035512d6.1677637.1662138359974441782//// directory 2://// M2 covmeta.9bbf1777f47b3fcacb05c38b035512d6// C3 covcounters.9bbf1777f47b3fcacb05c38b035512d6.1677445.1662138360208416480// C4 covcounters.9bbf1777f47b3fcacb05c38b035512d6.1677677.1662138359974441781// M3 covmeta.a723844208cea2ae80c63482c78b2245// C5 covcounters.a723844208cea2ae80c63482c78b2245.3677445.1662138360208416480// C6 covcounters.a723844208cea2ae80c63482c78b2245.1877677.1662138359974441781//// In these two directories we have three meta-data files, but only// two are distinct, meaning that we'll wind up with two pods. The// first pod (with meta-file M1) will have four counter data files// (C1, C2, C3, C4) and the second pod will have two counter data files// (C5, C6).func collectPodsImpl( []string, []int, bool) []Pod {:= regexp.MustCompile(fmt.Sprintf(`^%s\.(\S+)$`, coverage.MetaFilePref)):= make(map[string]protoPod)for , := range {:= filepath.Base()if := .FindStringSubmatch(); != nil {:= [1]// We need to allow for the possibility of duplicate// meta-data files. If we hit this case, use the// first encountered as the canonical version.if , := []; ! {[] = protoPod{mf: }}// FIXME: should probably check file length and hash here for// the duplicate.}}:= regexp.MustCompile(fmt.Sprintf(coverage.CounterFileRegexp, coverage.CounterFilePref))for , := range {:= filepath.Base()if := .FindStringSubmatch(); != nil {:= [1] // meta hash, := strconv.Atoi([2])if != nil {continue}if , := []; {:= -1if != nil {= []}:= fileWithAnnotations{file: , origin: , pid: }.elements = append(.elements, )[] =} else {if {warning("skipping orphaned counter file: %s", )}}}}if len() == 0 {if {warning("no coverage data files found")}return nil}:= make([]Pod, 0, len())for , := range {slices.SortFunc(.elements, func(, fileWithAnnotations) int {if := cmp.Compare(.origin, .origin); != 0 {return}return strings.Compare(.file, .file)}):= Pod{MetaFile: .mf,CounterDataFiles: make([]string, 0, len(.elements)),Origins: make([]int, 0, len(.elements)),ProcessIDs: make([]int, 0, len(.elements)),}for , := range .elements {.CounterDataFiles = append(.CounterDataFiles, .file).Origins = append(.Origins, .origin).ProcessIDs = append(.ProcessIDs, .pid)}= append(, )}slices.SortFunc(, func(, Pod) int {return strings.Compare(.MetaFile, .MetaFile)})return}func warning( string, ...interface{}) {fmt.Fprintf(os.Stderr, "warning: ")fmt.Fprintf(os.Stderr, , ...)fmt.Fprintf(os.Stderr, "\n")}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |