1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
package driver
import (
"io/ioutil"
"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 := ioutil.TempDir("", "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,
}
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: "/top", Current: false, UserConfig: false},
{Name: "A", URL: "/top?f=foo", Current: true, UserConfig: true},
{Name: "B", URL: "/top?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")
}
}
|