mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
[tooling] add benchfind (#62981)
This commit adds benchfind, a cli utility which can be used to discover Benchmark test targets in a golang tree. The reason this is useful in a large codebase is that to run `go test -bench ./...` would require the linking of every test target binary. This can take 1h+. Previously a `grep` expression was used to find targets: ```sh grep --exclude-dir api --include "*_test.go" -lr testing.B . | xargs dirname | xargs go list | sort -u ``` The issue with this is that it can break when the tree contains other go modules and requires handling of pipefail. Instead a single utility is provided. This can now be replaced with: ```sh benchfind ./... ``` Note that the tool will respect module boundaries, instead of having to explicitly exclude them, call the CLI multiple times with `-d` flag.
This commit is contained in:
@@ -887,6 +887,10 @@ DIFF_TEST := $(TOOLINGDIR)/bin/difftest
|
||||
$(DIFF_TEST): $(wildcard $(TOOLINGDIR)/cmd/difftest/*.go)
|
||||
cd $(TOOLINGDIR) && go build -o "$@" ./cmd/difftest
|
||||
|
||||
BENCHFIND := $(TOOLINGDIR)/bin/benchfind
|
||||
$(BENCHFIND): $(wildcard $(TOOLINGDIR)/cmd/benchfind/*.go)
|
||||
cd $(TOOLINGDIR) && go build -o "$@" ./cmd/benchfind
|
||||
|
||||
RERUN := $(TOOLINGDIR)/bin/rerun
|
||||
$(RERUN): $(wildcard $(TOOLINGDIR)/cmd/rerun/*.go)
|
||||
cd $(TOOLINGDIR) && go build -o "$@" ./cmd/rerun
|
||||
@@ -1003,17 +1007,26 @@ endif
|
||||
# Race detection is not enabled because it significantly slows down benchmarks.
|
||||
# todo: Use gotestsum when it is compatible with benchmark output. Currently will consider all benchmarks failed.
|
||||
.PHONY: test-go-bench
|
||||
test-go-bench: PACKAGES = $(shell grep --exclude-dir api --exclude-dir gen --include "*_test.go" -lr testing.B . | xargs dirname | xargs go list | sort -u)
|
||||
test-go-bench: BENCHMARK_SKIP_PATTERN = "^BenchmarkRoot"
|
||||
test-go-bench: | $(TEST_LOG_DIR)
|
||||
go test -run ^$$ -bench . -skip $(BENCHMARK_SKIP_PATTERN) -benchtime 1x $(PACKAGES) \
|
||||
test-go-bench: $(BENCHFIND) | $(TEST_LOG_DIR)
|
||||
@PKGS=$$($(BENCHFIND) --tags=$(BUILD_TAGS)) ; \
|
||||
if [ -z "$$PKGS" ]; then \
|
||||
echo "No benchmark packages found"; \
|
||||
exit 1; \
|
||||
fi ; \
|
||||
go test -run ^$$ -bench . -skip $(BENCHMARK_SKIP_PATTERN) -benchtime 1x $$PKGS \
|
||||
| tee $(TEST_LOG_DIR)/bench.txt
|
||||
|
||||
test-go-bench-root: PACKAGES = $(shell grep --exclude-dir api --exclude-dir gen --include "*_test.go" -lr BenchmarkRoot . | xargs dirname | xargs go list | sort -u)
|
||||
.PHONY: test-go-bench-root
|
||||
test-go-bench-root: BENCHMARK_PATTERN = "^BenchmarkRoot"
|
||||
test-go-bench-root: BENCHMARK_SKIP_PATTERN = ""
|
||||
test-go-bench-root: | $(TEST_LOG_DIR)
|
||||
go test -run ^$$ -bench $(BENCHMARK_PATTERN) -skip $(BENCHMARK_SKIP_PATTERN) -benchtime 1x $(PACKAGES) \
|
||||
test-go-bench-root: $(BENCHFIND) | $(TEST_LOG_DIR)
|
||||
@PKGS=$$($(BENCHFIND) --tags=$(BUILD_TAGS)) ; \
|
||||
if [ -z "$$PKGS" ]; then \
|
||||
echo "No benchmark packages found"; \
|
||||
exit 1; \
|
||||
fi ; \
|
||||
go test -run ^$$ -bench $(BENCHMARK_PATTERN) -skip $(BENCHMARK_SKIP_PATTERN) -benchtime 1x $$PKGS \
|
||||
| tee $(TEST_LOG_DIR)/bench.txt
|
||||
|
||||
# Make sure untagged vnetdaemon code build/tests.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# benchfind
|
||||
|
||||
A CLI utility to discover modules with Benchmarks without compilation/linking.
|
||||
|
||||
Example useage:
|
||||
|
||||
```sh
|
||||
# Find all Benchmark packages in the current dir:
|
||||
benchfind
|
||||
|
||||
# Find all Benchmark packages matching ./lib/...:
|
||||
benchfind ./lib/...
|
||||
|
||||
# Find all Benchmark packages matching given tags:
|
||||
benchfind --tags=integration,linux
|
||||
|
||||
# Find all Benchmark packages and exclude a given package:
|
||||
benchfind -e github.com/gravitational/teleport/foo/bar
|
||||
```
|
||||
|
||||
The reason this is useful in a large codebase is that to run `go test -bench ./...` would require the linking of every test target binary. This can be very computationally heavy. Instead `benchfind` relies on the golang AST to find the relevant packages.
|
||||
|
||||
Example use:
|
||||
```sh
|
||||
go test -run ^$$ -bench . $(benchfind)
|
||||
```
|
||||
@@ -0,0 +1,163 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// Config specifies configuration for finding benchmark packages.
|
||||
type Config struct {
|
||||
// Patterns specifies package patterns to search. Defaults to './...' if empty.
|
||||
Patterns []string
|
||||
// BuildTags specifies build tags to use when loading packages.
|
||||
BuildTags string
|
||||
// Dir specifies the working directory to run package discovery from.
|
||||
Dir string
|
||||
// Excludes specifies package path prefixes to exclude.
|
||||
Excludes []string
|
||||
}
|
||||
|
||||
// Loader abstracts package loading.
|
||||
type Loader interface {
|
||||
Load(cfg *packages.Config, patterns ...string) ([]*packages.Package, error)
|
||||
}
|
||||
|
||||
// PackagesLoader is the default Loader using go/packages.
|
||||
type PackagesLoader struct{}
|
||||
|
||||
func (PackagesLoader) Load(cfg *packages.Config, patterns ...string) ([]*packages.Package, error) {
|
||||
return packages.Load(cfg, patterns...)
|
||||
}
|
||||
|
||||
// Find finds all packages matching the given patterns that contain benchmarks.
|
||||
func Find(cfg Config) ([]string, error) {
|
||||
return findWithLoader(cfg, PackagesLoader{})
|
||||
}
|
||||
|
||||
func findWithLoader(cfg Config, loader Loader) ([]string, error) {
|
||||
if len(cfg.Patterns) == 0 {
|
||||
cfg.Patterns = []string{"./..."}
|
||||
}
|
||||
|
||||
pkgs, err := loader.Load(&packages.Config{
|
||||
Dir: cfg.Dir,
|
||||
Mode: packages.NeedName |
|
||||
packages.NeedFiles |
|
||||
packages.NeedSyntax, // requires [packages.NeedFiles] to be set.
|
||||
Tests: true,
|
||||
BuildFlags: buildFlags(cfg.BuildTags),
|
||||
}, cfg.Patterns...)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if packages.PrintErrors(pkgs) > 0 {
|
||||
return nil, trace.BadParameter("failed to load packages")
|
||||
}
|
||||
|
||||
return findBenchmarks(pkgs, cfg.Excludes), nil
|
||||
}
|
||||
|
||||
func findBenchmarks(pkgs []*packages.Package, excludes []string) []string {
|
||||
seen := make(map[string]struct{})
|
||||
var result []string
|
||||
|
||||
packages.Visit(pkgs, nil, func(p *packages.Package) {
|
||||
path := strings.TrimSuffix(p.PkgPath, ".test")
|
||||
path = strings.TrimSuffix(path, "_test")
|
||||
|
||||
if matchesAnyPrefix(path, excludes) {
|
||||
return
|
||||
}
|
||||
|
||||
if pkgsContainBenchmarks(p) {
|
||||
if _, ok := seen[path]; !ok {
|
||||
seen[path] = struct{}{}
|
||||
result = append(result, path)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func buildFlags(tags string) []string {
|
||||
if tags == "" {
|
||||
return nil
|
||||
}
|
||||
return []string{"-tags=" + tags}
|
||||
}
|
||||
|
||||
func pkgsContainBenchmarks(pkg *packages.Package) bool {
|
||||
return slices.ContainsFunc(pkg.Syntax, filepkgsContainBenchmarks)
|
||||
}
|
||||
|
||||
func filepkgsContainBenchmarks(file *ast.File) bool {
|
||||
for _, decl := range file.Decls {
|
||||
fn, ok := decl.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if isBenchmark(fn) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func matchesAnyPrefix(path string, prefixes []string) bool {
|
||||
for _, p := range prefixes {
|
||||
if strings.HasPrefix(path, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isBenchmark(fn *ast.FuncDecl) bool {
|
||||
if fn.Recv != nil {
|
||||
return false
|
||||
}
|
||||
if fn.Name == nil || !strings.HasPrefix(fn.Name.Name, "Benchmark") {
|
||||
return false
|
||||
}
|
||||
if fn.Type == nil || fn.Type.Params == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
params := fn.Type.Params.List
|
||||
if len(params) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
star, ok := params[0].Type.(*ast.StarExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
sel, ok := star.X.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return sel.Sel.Name == "B"
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type fakeLoader struct {
|
||||
pkgs []*packages.Package
|
||||
err error
|
||||
}
|
||||
|
||||
func (f fakeLoader) Load(_ *packages.Config, _ ...string) ([]*packages.Package, error) {
|
||||
return f.pkgs, f.err
|
||||
}
|
||||
|
||||
func mustParseFile(t *testing.T, src string) *ast.File {
|
||||
t.Helper()
|
||||
|
||||
fset := token.NewFileSet()
|
||||
file, err := parser.ParseFile(fset, "test.go", src, 0)
|
||||
require.NoError(t, err)
|
||||
return file
|
||||
}
|
||||
|
||||
func TestFindWithLoader(t *testing.T) {
|
||||
benchFile := mustParseFile(t, `
|
||||
package p
|
||||
import "testing"
|
||||
func BenchmarkFoo(b *testing.B) {}
|
||||
`)
|
||||
|
||||
nonBenchFile := mustParseFile(t, `
|
||||
package p
|
||||
func Foo() {}
|
||||
`)
|
||||
|
||||
loader := fakeLoader{
|
||||
pkgs: []*packages.Package{
|
||||
{
|
||||
PkgPath: "github.com/foo/bar",
|
||||
Syntax: []*ast.File{benchFile},
|
||||
},
|
||||
{
|
||||
PkgPath: "github.com/baz/bar",
|
||||
Syntax: []*ast.File{nonBenchFile},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
Patterns: []string{"./..."},
|
||||
}
|
||||
|
||||
result, err := findWithLoader(cfg, loader)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []string{"github.com/foo/bar"}, result)
|
||||
}
|
||||
|
||||
func TestFindWithLoader_Excludes(t *testing.T) {
|
||||
benchFile := mustParseFile(t, `
|
||||
package p
|
||||
import "testing"
|
||||
func BenchmarkFoo(b *testing.B) {}
|
||||
`)
|
||||
|
||||
loader := fakeLoader{
|
||||
pkgs: []*packages.Package{
|
||||
{
|
||||
PkgPath: "github.com/foo/bar",
|
||||
Syntax: []*ast.File{benchFile},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
Excludes: []string{"github.com/foo"},
|
||||
}
|
||||
|
||||
result, err := findWithLoader(cfg, loader)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestFindBenchmarks_DeduplicatesTestPackages(t *testing.T) {
|
||||
benchFile := mustParseFile(t, `
|
||||
package p
|
||||
import "testing"
|
||||
func BenchmarkFoo(b *testing.B) {}
|
||||
`)
|
||||
|
||||
pkgs := []*packages.Package{
|
||||
{
|
||||
PkgPath: "github.com/foo/bar",
|
||||
Syntax: []*ast.File{benchFile},
|
||||
},
|
||||
{
|
||||
PkgPath: "github.com/foo/bar.test",
|
||||
Syntax: []*ast.File{benchFile},
|
||||
},
|
||||
}
|
||||
|
||||
result := findBenchmarks(pkgs, nil)
|
||||
require.Equal(t, []string{"github.com/foo/bar"}, result)
|
||||
}
|
||||
|
||||
func TestIsBenchmark(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
src string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
src: `
|
||||
package p
|
||||
import "testing"
|
||||
func BenchmarkFoo(b *testing.B) {}
|
||||
`,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "wrong name",
|
||||
src: `
|
||||
package p
|
||||
import "testing"
|
||||
func TestFoo(b *testing.B) {}
|
||||
`,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "wrong param type",
|
||||
src: `
|
||||
package p
|
||||
func BenchmarkFoo(i int) {}
|
||||
`,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "too many params",
|
||||
src: `
|
||||
package p
|
||||
import "testing"
|
||||
func BenchmarkFoo(b *testing.B, i int) {}
|
||||
`,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "missing params",
|
||||
src: `
|
||||
package p
|
||||
func Foo() {}
|
||||
`,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "cannot be a method",
|
||||
src: `
|
||||
package p
|
||||
import "testing"
|
||||
type T struct{}
|
||||
func (T) BenchmarkFoo(b *testing.B) {}
|
||||
`,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
file := mustParseFile(t, tt.src)
|
||||
|
||||
var fn *ast.FuncDecl
|
||||
for _, d := range file.Decls {
|
||||
if f, ok := d.(*ast.FuncDecl); ok {
|
||||
fn = f
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, fn)
|
||||
assert.Equal(t, tt.want, isBenchmark(fn))
|
||||
|
||||
pkg := &packages.Package{
|
||||
Syntax: []*ast.File{file},
|
||||
}
|
||||
assert.Equal(t, tt.want, pkgsContainBenchmarks(pkg))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchesAnyPrefix(t *testing.T) {
|
||||
require.False(t, matchesAnyPrefix("github.com/foo/bar", nil))
|
||||
require.True(t, matchesAnyPrefix("github.com/foo/bar", []string{"github.com/foo"}))
|
||||
require.False(t, matchesAnyPrefix("github.com/foo/bar", []string{"github.com/other"}))
|
||||
}
|
||||
|
||||
func TestBuildFlags(t *testing.T) {
|
||||
require.Nil(t, buildFlags(""))
|
||||
require.Equal(t, []string{"-tags=foo"}, buildFlags("foo"))
|
||||
require.Equal(t, []string{"-tags=foo,bar"}, buildFlags("foo,bar"))
|
||||
}
|
||||
|
||||
// TestFind is a smoketest that ensures Find works end-to-end.
|
||||
func TestFind(t *testing.T) {
|
||||
dir := filepath.Join(".", "testdata")
|
||||
expected := []string{
|
||||
"github.com/gravitational/teleport/build.assets/tooling/cmd/benchfind/testdata",
|
||||
"github.com/gravitational/teleport/build.assets/tooling/cmd/benchfind/testdata/nested",
|
||||
}
|
||||
|
||||
pkgs, err := Find(Config{
|
||||
Dir: dir,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, pkgs)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
func run() error {
|
||||
app := kingpin.New(
|
||||
"benchfind",
|
||||
"Find Go packages that define benchmarks without compiling test binaries.",
|
||||
)
|
||||
app.HelpFlag.Short('h')
|
||||
|
||||
tags := app.Flag("tags", "Comma-separated build tags.").Short('t').String()
|
||||
cwd := app.Flag("directory", "Working directory to run package discovery from. (Default: current directory)").Short('d').ExistingDir()
|
||||
excludes := app.Flag("exclude", "List of package prefixes to skip.").Short('e').Strings()
|
||||
patterns := app.Arg("patterns", `Package patterns. (Default: "./...")`).Default("./...").Strings()
|
||||
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
|
||||
dir := *cwd
|
||||
if dir == "" {
|
||||
var err error
|
||||
dir, err = os.Getwd()
|
||||
if err != nil {
|
||||
return trace.Wrap(err, "failed to get current working directory")
|
||||
}
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
Patterns: *patterns,
|
||||
BuildTags: *tags,
|
||||
Dir: dir,
|
||||
Excludes: *excludes,
|
||||
}
|
||||
|
||||
pkgs, err := Find(cfg)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
for _, p := range pkgs {
|
||||
fmt.Println(p)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
if trace.IsBadParameter(err) {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, trace.DebugReport(err))
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package testdata
|
||||
|
||||
import "testing"
|
||||
|
||||
// BenchmarkExample is a simple benchmark for testing discovery.
|
||||
func BenchmarkExample(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = i * i
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package nested
|
||||
|
||||
import "testing"
|
||||
|
||||
func BenchmarkAnother(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = i * i
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Teleport
|
||||
// Copyright (C) 2026 Gravitational, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package nobench
|
||||
|
||||
// This file intentionally left blank to represent a package with no benchmarks.
|
||||
+47
-50
@@ -17,7 +17,9 @@ require (
|
||||
github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d
|
||||
golang.org/x/mod v0.31.0
|
||||
golang.org/x/oauth2 v0.34.0
|
||||
golang.org/x/tools v0.40.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
helm.sh/helm/v3 v3.19.2
|
||||
howett.net/plist v1.0.1
|
||||
k8s.io/apiextensions-apiserver v0.34.2
|
||||
@@ -30,60 +32,11 @@ require (
|
||||
buf.build/go/protovalidate v1.1.0 // indirect
|
||||
buf.build/go/spdx v0.2.0 // indirect
|
||||
cel.dev/expr v0.25.1 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/bufbuild/protocompile v0.14.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
github.com/google/go-querystring v1.2.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kisielk/gotool v1.0.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
golang.org/x/crypto v0.46.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/tools v0.40.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/apimachinery v0.35.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||
pluginrpc.com/pluginrpc v0.5.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/auth v0.18.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
connectrpc.com/connect v1.19.1 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
filippo.io/age v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
|
||||
@@ -91,6 +44,10 @@ require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.0 // indirect
|
||||
@@ -126,6 +83,7 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/bufbuild/protocompile v0.14.1 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
@@ -134,6 +92,7 @@ require (
|
||||
github.com/crewjam/httperr v0.2.0 // indirect
|
||||
github.com/crewjam/saml v0.4.14 // indirect
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/di-wu/parser v0.3.0 // indirect
|
||||
github.com/di-wu/xsd-datetime v1.0.0 // indirect
|
||||
github.com/digitorus/pkcs7 v0.0.0-20250730155240-ffadbf3f398c // indirect
|
||||
@@ -144,10 +103,12 @@ require (
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.24.1 // indirect
|
||||
github.com/go-openapi/errors v0.22.6 // indirect
|
||||
@@ -182,16 +143,19 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
github.com/google/certificate-transparency-go v1.3.2 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-attestation v0.6.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.7 // indirect
|
||||
github.com/google/go-github/v70 v70.0.0 // indirect
|
||||
github.com/google/go-querystring v1.2.0 // indirect
|
||||
github.com/google/go-tpm v0.9.7 // indirect
|
||||
github.com/google/go-tpm-tools v0.4.7 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.9 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.16.0 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
@@ -203,6 +167,7 @@ require (
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/in-toto/attestation v1.1.2 // indirect
|
||||
github.com/in-toto/in-toto-golang v0.9.0 // indirect
|
||||
github.com/invopop/jsonschema v0.13.0 // indirect
|
||||
@@ -217,16 +182,23 @@ require (
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||
github.com/kisielk/gotool v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/muhlemmer/gu v0.3.1 // indirect
|
||||
github.com/muhlemmer/httpforwarded v0.1.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
@@ -237,7 +209,9 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkoukk/tiktoken-go v0.1.8 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/pquerna/otp v1.5.0 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
@@ -250,6 +224,7 @@ require (
|
||||
github.com/scim2/filter-parser/v2 v2.2.0 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect
|
||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sigstore/protobuf-specs v0.5.0 // indirect
|
||||
github.com/sigstore/rekor v1.5.0 // indirect
|
||||
github.com/sigstore/rekor-tiles/v2 v2.0.1 // indirect
|
||||
@@ -258,7 +233,10 @@ require (
|
||||
github.com/sigstore/timestamp-authority/v2 v2.0.4 // indirect
|
||||
github.com/sijms/go-ora/v2 v2.9.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/theupdateframework/go-tuf/v2 v2.4.1 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
@@ -269,9 +247,11 @@ require (
|
||||
github.com/transparency-dev/merkle v0.0.2 // indirect
|
||||
github.com/vulcand/predicate v1.2.0 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
github.com/zitadel/logging v0.6.2 // indirect
|
||||
github.com/zitadel/oidc/v3 v3.45.0 // indirect
|
||||
github.com/zitadel/schema v1.3.1 // indirect
|
||||
@@ -290,18 +270,35 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.46.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/term v0.38.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
google.golang.org/api v0.260.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
|
||||
google.golang.org/grpc v1.78.0 // indirect
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/api v0.35.0 // indirect
|
||||
k8s.io/apimachinery v0.35.0 // indirect
|
||||
k8s.io/client-go v0.35.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||
mvdan.cc/sh/v3 v3.7.0 // indirect
|
||||
pluginrpc.com/pluginrpc v0.5.0 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.22.4 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
|
||||
|
||||
Reference in New Issue
Block a user