mirror of
https://github.com/langhuihui/monibuca.git
synced 2026-04-25 10:16:42 +08:00
feat: add pprof
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
package driver
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// settingsDirAndFile returns a directory in which settings should be stored
|
||||
// and the name of the settings file. The caller must delete the directory when
|
||||
// done.
|
||||
func settingsDirAndFile(t *testing.T) (string, string) {
|
||||
tmpDir, err := os.MkdirTemp("", "pprof_settings_test")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temporary directory: %v", err)
|
||||
}
|
||||
return tmpDir, filepath.Join(tmpDir, "settings.json")
|
||||
}
|
||||
|
||||
func TestSettings(t *testing.T) {
|
||||
tmpDir, fname := settingsDirAndFile(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
s, err := readSettings(fname)
|
||||
if err != nil {
|
||||
t.Fatalf("error reading empty settings: %v", err)
|
||||
}
|
||||
if len(s.Configs) != 0 {
|
||||
t.Fatalf("expected empty settings; got %v", s)
|
||||
}
|
||||
s.Configs = append(s.Configs, namedConfig{
|
||||
Name: "Foo",
|
||||
config: config{
|
||||
Focus: "focus",
|
||||
// Ensure that transient fields are not saved/restored.
|
||||
Output: "output",
|
||||
SourcePath: "source",
|
||||
TrimPath: "trim",
|
||||
DivideBy: -2,
|
||||
},
|
||||
})
|
||||
if err := writeSettings(fname, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s2, err := readSettings(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Change the transient fields to their expected values.
|
||||
s.Configs[0].resetTransient()
|
||||
if !reflect.DeepEqual(s, s2) {
|
||||
t.Fatalf("ReadSettings = %v; expected %v", s2, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseConfig(t *testing.T) {
|
||||
// Use all the fields to check they are saved/restored from URL.
|
||||
cfg := config{
|
||||
Output: "",
|
||||
DropNegative: true,
|
||||
CallTree: true,
|
||||
RelativePercentages: true,
|
||||
Unit: "auto",
|
||||
CompactLabels: true,
|
||||
SourcePath: "",
|
||||
TrimPath: "",
|
||||
NodeCount: 10,
|
||||
NodeFraction: 0.1,
|
||||
EdgeFraction: 0.2,
|
||||
Trim: true,
|
||||
Focus: "focus",
|
||||
Ignore: "ignore",
|
||||
PruneFrom: "prune_from",
|
||||
Hide: "hide",
|
||||
Show: "show",
|
||||
ShowFrom: "show_from",
|
||||
TagFocus: "tagfocus",
|
||||
TagIgnore: "tagignore",
|
||||
TagShow: "tagshow",
|
||||
TagHide: "taghide",
|
||||
DivideBy: 1,
|
||||
Mean: true,
|
||||
Normalize: true,
|
||||
Sort: "cum",
|
||||
Granularity: "functions",
|
||||
NoInlines: true,
|
||||
ShowColumns: true,
|
||||
}
|
||||
url, changed := cfg.makeURL(url.URL{})
|
||||
if !changed {
|
||||
t.Error("applyConfig returned changed=false after applying non-empty config")
|
||||
}
|
||||
cfg2 := defaultConfig()
|
||||
if err := cfg2.applyURL(url.Query()); err != nil {
|
||||
t.Fatalf("fromURL failed: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(cfg, cfg2) {
|
||||
t.Fatalf("parsed config = %+v; expected match with %+v", cfg2, cfg)
|
||||
}
|
||||
if url2, changed := cfg.makeURL(url); changed {
|
||||
t.Errorf("ApplyConfig returned changed=true after applying same config (%q instead of expected %q", url2.String(), url.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestDefaultConfig verifies that default config values are omitted from URL.
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
cfg := defaultConfig()
|
||||
url, changed := cfg.makeURL(url.URL{})
|
||||
if changed {
|
||||
t.Error("applyConfig returned changed=true after applying default config")
|
||||
}
|
||||
if url.String() != "" {
|
||||
t.Errorf("applyConfig returned %q; expecting %q", url.String(), "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigMenu(t *testing.T) {
|
||||
// Save some test settings.
|
||||
tmpDir, fname := settingsDirAndFile(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
a, b := defaultConfig(), defaultConfig()
|
||||
a.Focus, b.Focus = "foo", "bar"
|
||||
s := &settings{
|
||||
Configs: []namedConfig{
|
||||
{Name: "A", config: a},
|
||||
{Name: "B", config: b},
|
||||
},
|
||||
}
|
||||
if err := writeSettings(fname, s); err != nil {
|
||||
t.Fatal("error writing settings", err)
|
||||
}
|
||||
|
||||
pageURL, _ := url.Parse("/top?f=foo")
|
||||
menu := configMenu(fname, *pageURL)
|
||||
want := []configMenuEntry{
|
||||
{Name: "Default", URL: "?", Current: false, UserConfig: false},
|
||||
{Name: "A", URL: "?f=foo", Current: true, UserConfig: true},
|
||||
{Name: "B", URL: "?f=bar", Current: false, UserConfig: true},
|
||||
}
|
||||
if !reflect.DeepEqual(menu, want) {
|
||||
t.Errorf("ConfigMenu returned %v; want %v", menu, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEditConfig(t *testing.T) {
|
||||
tmpDir, fname := settingsDirAndFile(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
type testConfig struct {
|
||||
name string
|
||||
focus string
|
||||
hide string
|
||||
}
|
||||
type testCase struct {
|
||||
remove bool
|
||||
request string
|
||||
expect []testConfig
|
||||
}
|
||||
for _, c := range []testCase{
|
||||
// Create setting c1
|
||||
{false, "/?config=c1&f=foo", []testConfig{
|
||||
{"c1", "foo", ""},
|
||||
}},
|
||||
// Create setting c2
|
||||
{false, "/?config=c2&h=bar", []testConfig{
|
||||
{"c1", "foo", ""},
|
||||
{"c2", "", "bar"},
|
||||
}},
|
||||
// Overwrite c1
|
||||
{false, "/?config=c1&f=baz", []testConfig{
|
||||
{"c1", "baz", ""},
|
||||
{"c2", "", "bar"},
|
||||
}},
|
||||
// Delete c2
|
||||
{true, "c2", []testConfig{
|
||||
{"c1", "baz", ""},
|
||||
}},
|
||||
} {
|
||||
if c.remove {
|
||||
if err := removeConfig(fname, c.request); err != nil {
|
||||
t.Errorf("error removing config %s: %v", c.request, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
req, err := url.Parse(c.request)
|
||||
if err != nil {
|
||||
t.Errorf("error parsing request %q: %v", c.request, err)
|
||||
continue
|
||||
}
|
||||
if err := setConfig(fname, *req); err != nil {
|
||||
t.Errorf("error saving request %q: %v", c.request, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Check resulting settings.
|
||||
s, err := readSettings(fname)
|
||||
if err != nil {
|
||||
t.Errorf("error reading settings after applying %q: %v", c.request, err)
|
||||
continue
|
||||
}
|
||||
// Convert to a list that can be compared to c.expect
|
||||
got := make([]testConfig, len(s.Configs))
|
||||
for i, c := range s.Configs {
|
||||
got[i] = testConfig{c.Name, c.Focus, c.Hide}
|
||||
}
|
||||
if !reflect.DeepEqual(got, c.expect) {
|
||||
t.Errorf("Settings after applying %q = %v; want %v", c.request, got, c.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssign(t *testing.T) {
|
||||
baseConfig := currentConfig()
|
||||
defer setCurrentConfig(baseConfig)
|
||||
|
||||
// Test assigning to a simple field.
|
||||
if err := configure("nodecount", "20"); err != nil {
|
||||
t.Errorf("error setting nodecount: %v", err)
|
||||
}
|
||||
if n := currentConfig().NodeCount; n != 20 {
|
||||
t.Errorf("incorrect nodecount; expecting 20, got %d", n)
|
||||
}
|
||||
|
||||
// Test assignment to a group field.
|
||||
if err := configure("granularity", "files"); err != nil {
|
||||
t.Errorf("error setting granularity: %v", err)
|
||||
}
|
||||
if g := currentConfig().Granularity; g != "files" {
|
||||
t.Errorf("incorrect granularity; expecting %v, got %v", "files", g)
|
||||
}
|
||||
|
||||
// Test assignment to one choice of a group field.
|
||||
if err := configure("lines", "t"); err != nil {
|
||||
t.Errorf("error setting lines: %v", err)
|
||||
}
|
||||
if g := currentConfig().Granularity; g != "lines" {
|
||||
t.Errorf("incorrect granularity; expecting %v, got %v", "lines", g)
|
||||
}
|
||||
|
||||
// Test assignment to invalid choice,
|
||||
if err := configure("granularity", "cheese"); err == nil {
|
||||
t.Errorf("allowed assignment of invalid granularity")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user