whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,140 @@
// Copyright 2023 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 config provides methods for loading and querying a
// telemetry upload config file.
package config
import (
"encoding/json"
"os"
"strings"
"golang.org/x/telemetry/internal/telemetry"
)
// Config is a wrapper around telemetry.UploadConfig that provides some
// convenience methods for checking the contents of a report.
type Config struct {
*telemetry.UploadConfig
program map[string]bool
goos map[string]bool
goarch map[string]bool
goversion map[string]bool
pgversion map[pgkey]bool
pgcounter map[pgkey]bool
pgcounterprefix map[pgkey]bool
pgstack map[pgkey]bool
rate map[pgkey]float64
}
type pgkey struct {
program, key string
}
func ReadConfig(file string) (*Config, error) {
data, err := os.ReadFile(file)
if err != nil {
return nil, err
}
var cfg telemetry.UploadConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return NewConfig(&cfg), nil
}
func NewConfig(cfg *telemetry.UploadConfig) *Config {
ucfg := Config{UploadConfig: cfg}
ucfg.goos = set(ucfg.GOOS)
ucfg.goarch = set(ucfg.GOARCH)
ucfg.goversion = set(ucfg.GoVersion)
ucfg.program = make(map[string]bool, len(ucfg.Programs))
ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs))
ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs))
ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs))
ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs))
ucfg.rate = make(map[pgkey]float64)
for _, p := range ucfg.Programs {
ucfg.program[p.Name] = true
for _, v := range p.Versions {
ucfg.pgversion[pgkey{p.Name, v}] = true
}
for _, c := range p.Counters {
for _, e := range Expand(c.Name) {
ucfg.pgcounter[pgkey{p.Name, e}] = true
ucfg.rate[pgkey{p.Name, e}] = c.Rate
}
prefix, _, found := strings.Cut(c.Name, ":")
if found {
ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true
}
}
for _, s := range p.Stacks {
ucfg.pgstack[pgkey{p.Name, s.Name}] = true
ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate
}
}
return &ucfg
}
func (r *Config) HasProgram(s string) bool {
return r.program[s]
}
func (r *Config) HasGOOS(s string) bool {
return r.goos[s]
}
func (r *Config) HasGOARCH(s string) bool {
return r.goarch[s]
}
func (r *Config) HasGoVersion(s string) bool {
return r.goversion[s]
}
func (r *Config) HasVersion(program, version string) bool {
return r.pgversion[pgkey{program, version}]
}
func (r *Config) HasCounter(program, counter string) bool {
return r.pgcounter[pgkey{program, counter}]
}
func (r *Config) HasCounterPrefix(program, prefix string) bool {
return r.pgcounterprefix[pgkey{program, prefix}]
}
func (r *Config) HasStack(program, stack string) bool {
return r.pgstack[pgkey{program, stack}]
}
func (r *Config) Rate(program, name string) float64 {
return r.rate[pgkey{program, name}]
}
func set(slice []string) map[string]bool {
s := make(map[string]bool, len(slice))
for _, v := range slice {
s[v] = true
}
return s
}
// Expand takes a counter defined with buckets and expands it into distinct
// strings for each bucket
func Expand(counter string) []string {
prefix, rest, hasBuckets := strings.Cut(counter, "{")
var counters []string
if hasBuckets {
buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",")
for _, b := range buckets {
counters = append(counters, prefix+b)
}
} else {
counters = append(counters, prefix)
}
return counters
}
@@ -0,0 +1,97 @@
// Copyright 2023 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 config
import (
_ "embed"
"encoding/json"
"os"
"path/filepath"
"testing"
"golang.org/x/telemetry/internal/telemetry"
)
func TestConfig(t *testing.T) {
f, err := os.Open(filepath.FromSlash("../../config/config.json"))
if os.IsNotExist(err) {
t.Skip("config file not found")
}
if err != nil {
t.Fatal(err)
}
defer f.Close()
var cfg telemetry.UploadConfig
d := json.NewDecoder(f)
d.DisallowUnknownFields()
if err := d.Decode(&cfg); err != nil {
t.Fatal(err)
}
}
func TestInternalConfig(t *testing.T) {
got, err := ReadConfig("testdata/config.json")
if err != nil {
t.Fatal(err)
}
wantGOOS := []string{"linux", "darwin"}
wantGOARCH := []string{"amd64", "arm64"}
wantGoVersion := []string{"go1.20", "go1.20.1"}
wantPrograms := []string{"golang.org/x/tools/gopls", "cmd/go"}
wantVersions := [][2]string{
{"golang.org/x/tools/gopls", "v0.10.1"},
{"golang.org/x/tools/gopls", "v0.11.0"},
}
wantCounters := [][2]string{
{"golang.org/x/tools/gopls", "editor:emacs"},
{"golang.org/x/tools/gopls", "editor:vim"},
{"golang.org/x/tools/gopls", "editor:vscode"},
{"golang.org/x/tools/gopls", "editor:other"},
{"cmd/go", "go/buildcache/miss:0"},
{"cmd/go", "go/buildcache/miss:1"},
{"cmd/go", "go/buildcache/miss:10"},
{"cmd/go", "go/buildcache/miss:100"},
}
wantPrefix := [][2]string{
{"golang.org/x/tools/gopls", "editor"},
{"cmd/go", "go/buildcache/miss"},
}
for _, w := range wantGOOS {
if !got.HasGOOS(w) {
t.Errorf("got.HasGOOS(%s) = false: want true", w)
}
}
for _, w := range wantGOARCH {
if !got.HasGOARCH(w) {
t.Errorf("got.HasGOARCH(%s) = false: want true", w)
}
}
for _, w := range wantGoVersion {
if !got.HasGoVersion(w) {
t.Errorf("got.HasGoVersion(%s) = false: want true", w)
}
}
for _, w := range wantPrograms {
if !got.HasProgram(w) {
t.Errorf("got.HasProgram(%s) = false: want true", w)
}
}
for _, w := range wantVersions {
if !got.HasVersion(w[0], w[1]) {
t.Errorf("got.HasVersion(%s, %s) = false: want true", w[0], w)
}
}
for _, w := range wantCounters {
if !got.HasCounter(w[0], w[1]) {
t.Errorf("got.HasCounter(%s, %s) = false: want true", w[0], w[1])
}
}
for _, w := range wantPrefix {
if !got.HasCounterPrefix(w[0], w[1]) {
t.Errorf("got.HasCounterPrefix(%s, %s) = false: want true", w[0], w[1])
}
}
}
@@ -0,0 +1,43 @@
{
"Version": "v0.0.1-test",
"GOOS": [
"linux",
"darwin"
],
"GOARCH": [
"amd64",
"arm64"
],
"GoVersion": [
"go1.20",
"go1.20.1"
],
"Programs": [
{
"Name": "golang.org/x/tools/gopls",
"Versions": [
"v0.10.1",
"v0.11.0"
],
"Counters": [
{
"Name": "editor:{emacs,vim,vscode,other}",
"Rate": 0.01
}
]
},
{
"Name": "cmd/go",
"Versions": [
"v0.10.1",
"v0.11.0"
],
"Counters": [
{
"Name": "go/buildcache/miss:{0,0.1,0.2,0.5,1,10,100,2,20,5,50}",
"Rate": 0.01
}
]
}
]
}