Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
da4bbd42
Commit
da4bbd42
authored
Aug 24, 2018
by
Katharine Berry
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add runtime coverage support.
parent
aa2a7d00
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
177 additions
and
20 deletions
+177
-20
golang.sh
hack/lib/golang.sh
+11
-20
coverage.go
pkg/util/coverage/coverage.go
+83
-0
coverage_disabled.go
pkg/util/coverage/coverage_disabled.go
+29
-0
fake_test_deps.go
pkg/util/coverage/fake_test_deps.go
+54
-0
No files found.
hack/lib/golang.sh
View file @
da4bbd42
...
@@ -474,32 +474,22 @@ kube::golang::create_coverage_dummy_test() {
...
@@ -474,32 +474,22 @@ kube::golang::create_coverage_dummy_test() {
local
name
=
"
$(
basename
"
$package
"
)
"
local
name
=
"
$(
basename
"
$package
"
)
"
cat
<<
EOF
>
$(
kube::golang::path_for_coverage_dummy_test
"
$package
"
)
cat
<<
EOF
>
$(
kube::golang::path_for_coverage_dummy_test
"
$package
"
)
package main
package main
import (
import (
"flag"
"testing"
"os"
"k8s.io/kubernetes/pkg/util/coverage"
"strconv"
"testing"
"time"
)
)
func TestMain(m *testing.M) {
// We need to pass coverage instructions to the unittest framework, so we hijack os.Args
func TestMain(m *testing.M) {
original_args := os.Args
// Get coverage running
now := time.Now().UnixNano()
coverage.InitCoverage("
${
name
}
")
test_args := []string{os.Args[0], "-test.coverprofile=/tmp/k8s-
${
name
}
-" + strconv.FormatInt(now, 10) + ".cov"}
os.Args = test_args
// This is sufficient for the unit tests to be set up.
flag.Parse()
// Restore the original args for use by the program.
os.Args = original_args
// Go!
// Go!
main()
main()
// Make sure we actually write the profiling information to disk, if we make it here.
// Make sure we actually write the profiling information to disk, if we make it here.
// On long-running services, or anything that calls os.Exit(), this is insufficient,
// On long-running services, or anything that calls os.Exit(), this is insufficient,
// so be sure to call this from inside the binary too.
// so be sure to call this from inside the binary too.
// TODO: actually have some code here.
coverage.FlushCoverage()
}
}
EOF
EOF
}
}
...
@@ -530,6 +520,7 @@ kube::golang::build_some_binaries() {
...
@@ -530,6 +520,7 @@ kube::golang::build_some_binaries() {
-covermode
count
\
-covermode
count
\
-coverpkg
k8s.io/...
\
-coverpkg
k8s.io/...
\
"
${
build_args
[@]
}
"
\
"
${
build_args
[@]
}
"
\
-tags
coverage
\
"
$package
"
"
$package
"
kube::golang::delete_coverage_dummy_test
"
$package
"
kube::golang::delete_coverage_dummy_test
"
$package
"
else
else
...
...
pkg/util/coverage/coverage.go
0 → 100644
View file @
da4bbd42
// +build coverage
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package coverage provides tools for coverage-instrumented binaries to collect and
// flush coverage information.
package
coverage
import
(
"flag"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/wait"
"os"
"testing"
"time"
)
const
flushInterval
=
5
*
time
.
Second
var
coverageFile
string
// tempCoveragePath returns a temporary file to write coverage information to.
// The file is in the same directory as the destination, ensuring os.Rename will work.
func
tempCoveragePath
()
string
{
return
coverageFile
+
".tmp"
}
// InitCoverage is called from the dummy unit test to prepare Go's coverage framework.
// Clients should never need to call it.
func
InitCoverage
(
name
string
)
{
// We read the coverage destination in from the KUBE_COVERAGE_FILE env var,
// or if it's empty we just use a default in /tmp
coverageFile
=
os
.
Getenv
(
"KUBE_COVERAGE_FILE"
)
if
coverageFile
==
""
{
coverageFile
=
"/tmp/k8s-"
+
name
+
".cov"
}
// Set up the unit test framework with the arguments we want.
flag
.
CommandLine
.
Parse
([]
string
{
"-test.coverprofile="
+
tempCoveragePath
()})
// Begin periodic logging
go
wait
.
Forever
(
FlushCoverage
,
flushInterval
)
}
// FlushCoverage flushes collected coverage information to disk.
// The destination file is configured at startup and cannot be changed.
// Calling this function also sends a line like "coverage: 5% of statements" to stdout.
func
FlushCoverage
()
{
// We're not actually going to run any tests, but we need Go to think we did so it writes
// coverage information to disk. To achieve this, we create a bunch of empty test suites and
// have it "run" them.
tests
:=
[]
testing
.
InternalTest
{}
benchmarks
:=
[]
testing
.
InternalBenchmark
{}
examples
:=
[]
testing
.
InternalExample
{}
var
deps
fakeTestDeps
dummyRun
:=
testing
.
MainStart
(
deps
,
tests
,
benchmarks
,
examples
)
dummyRun
.
Run
()
// Once it writes to the temporary path, we move it to the intended path.
// This gets us atomic updates from the perspective of another process trying to access
// the file.
if
err
:=
os
.
Rename
(
tempCoveragePath
(),
coverageFile
);
err
!=
nil
{
// This should never fail, because we're in the same directory. There's also little that
// we can do if it does.
glog
.
Errorf
(
"Couldn't move coverage file from %s to %s"
,
coverageFile
,
tempCoveragePath
())
}
}
pkg/util/coverage/coverage_disabled.go
0 → 100644
View file @
da4bbd42
// +build !coverage
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
coverage
// InitCoverage is a no-op when not running with coverage.
func
InitCoverage
(
name
string
)
{
}
// FlushCoverage is a no-op when not running with coverage.
func
FlushCoverage
()
{
}
pkg/util/coverage/fake_test_deps.go
0 → 100644
View file @
da4bbd42
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
coverage
import
(
"io"
)
// This is an implementation of testing.testDeps. It doesn't need to do anything, because
// no tests are actually run. It does need a concrete implementation of at least ImportPath,
// which is called unconditionally when running tests.
type
fakeTestDeps
struct
{}
func
(
fakeTestDeps
)
ImportPath
()
string
{
return
""
}
func
(
fakeTestDeps
)
MatchString
(
pat
,
str
string
)
(
bool
,
error
)
{
return
false
,
nil
}
func
(
fakeTestDeps
)
StartCPUProfile
(
io
.
Writer
)
error
{
return
nil
}
func
(
fakeTestDeps
)
StopCPUProfile
()
{}
func
(
fakeTestDeps
)
StartTestLog
(
io
.
Writer
)
{}
func
(
fakeTestDeps
)
StopTestLog
()
error
{
return
nil
}
func
(
fakeTestDeps
)
WriteHeapProfile
(
io
.
Writer
)
error
{
return
nil
}
func
(
fakeTestDeps
)
WriteProfileTo
(
string
,
io
.
Writer
,
int
)
error
{
return
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment