1// Copyright 2019 Istio Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cover
16
17import (
18	"fmt"
19	"sync"
20)
21
22var registry = &Registry{
23	blocks: make(map[string]*blockState),
24}
25
26// Registry for code coverage blocks
27type Registry struct {
28	mu     sync.RWMutex
29	blocks map[string]*blockState
30}
31
32// GetRegistry returns the singleton code coverage block registry.
33func GetRegistry() *Registry {
34	return registry
35}
36
37// Register code coverage data structure
38func (r *Registry) Register(
39	length int, context string,
40	readPosFn ReadPosFn, readStmtFn ReadStmtFn, readCountFn ReadCountFn, clearCountFn ClearCountFn) {
41	e := initEntry(length, context, readPosFn, readStmtFn, readCountFn, clearCountFn)
42
43	r.mu.Lock()
44
45	_, found := r.blocks[context]
46	if !found {
47		r.blocks[context] = e
48	}
49
50	r.mu.Unlock()
51
52	if found {
53		panic(fmt.Sprintf("Registry.Register: Name already registered: %q", context))
54	}
55}
56
57// Snapshot the coverage data from registered coverage data structures
58func (r *Registry) Snapshot() {
59	r.mu.RLock()
60	defer r.mu.RUnlock()
61
62	for _, e := range r.blocks {
63		e.Capture()
64	}
65}
66
67// Clear the coverage data from registered coverage data structures
68func (r *Registry) Clear() {
69	r.mu.RLock()
70	defer r.mu.RUnlock()
71
72	for _, e := range r.blocks {
73		e.Clear()
74	}
75}
76
77// GetCoverage collects Read from all registered blocks.
78func (r *Registry) GetCoverage() *Coverage {
79	r.mu.RLock()
80	defer r.mu.RUnlock()
81
82	sn := make([]*Block, 0, len(r.blocks))
83
84	for _, e := range r.blocks {
85		sn = append(sn, e.Read())
86	}
87
88	return &Coverage{
89		Blocks: sn,
90	}
91}
92