暂无描述

settings_test.go 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package driver
  2. import (
  3. "io/ioutil"
  4. "net/url"
  5. "os"
  6. "path/filepath"
  7. "reflect"
  8. "testing"
  9. )
  10. // settingsDirAndFile returns a directory in which settings should be stored
  11. // and the name of the settings file. The caller must delete the directory when
  12. // done.
  13. func settingsDirAndFile(t *testing.T) (string, string) {
  14. tmpDir, err := ioutil.TempDir("", "pprof_settings_test")
  15. if err != nil {
  16. t.Fatalf("error creating temporary directory: %v", err)
  17. }
  18. return tmpDir, filepath.Join(tmpDir, "settings.json")
  19. }
  20. func TestSettings(t *testing.T) {
  21. tmpDir, fname := settingsDirAndFile(t)
  22. defer os.RemoveAll(tmpDir)
  23. s, err := readSettings(fname)
  24. if err != nil {
  25. t.Fatalf("error reading empty settings: %v", err)
  26. }
  27. if len(s.Configs) != 0 {
  28. t.Fatalf("expected empty settings; got %v", s)
  29. }
  30. s.Configs = append(s.Configs, namedConfig{
  31. Name: "Foo",
  32. config: config{
  33. Focus: "focus",
  34. // Ensure that transient fields are not saved/restored.
  35. Output: "output",
  36. SourcePath: "source",
  37. TrimPath: "trim",
  38. DivideBy: -2,
  39. },
  40. })
  41. if err := writeSettings(fname, s); err != nil {
  42. t.Fatal(err)
  43. }
  44. s2, err := readSettings(fname)
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. // Change the transient fields to their expected values.
  49. s.Configs[0].resetTransient()
  50. if !reflect.DeepEqual(s, s2) {
  51. t.Fatalf("ReadSettings = %v; expected %v", s2, s)
  52. }
  53. }
  54. func TestParseConfig(t *testing.T) {
  55. // Use all the fields to check they are saved/restored from URL.
  56. cfg := config{
  57. Output: "",
  58. DropNegative: true,
  59. CallTree: true,
  60. RelativePercentages: true,
  61. Unit: "auto",
  62. CompactLabels: true,
  63. SourcePath: "",
  64. TrimPath: "",
  65. NodeCount: 10,
  66. NodeFraction: 0.1,
  67. EdgeFraction: 0.2,
  68. Trim: true,
  69. Focus: "focus",
  70. Ignore: "ignore",
  71. PruneFrom: "prune_from",
  72. Hide: "hide",
  73. Show: "show",
  74. ShowFrom: "show_from",
  75. TagFocus: "tagfocus",
  76. TagIgnore: "tagignore",
  77. TagShow: "tagshow",
  78. TagHide: "taghide",
  79. DivideBy: 1,
  80. Mean: true,
  81. Normalize: true,
  82. Sort: "cum",
  83. Granularity: "functions",
  84. NoInlines: true,
  85. }
  86. url, changed := cfg.makeURL(url.URL{})
  87. if !changed {
  88. t.Error("applyConfig returned changed=false after applying non-empty config")
  89. }
  90. cfg2 := defaultConfig()
  91. if err := cfg2.applyURL(url.Query()); err != nil {
  92. t.Fatalf("fromURL failed: %v", err)
  93. }
  94. if !reflect.DeepEqual(cfg, cfg2) {
  95. t.Fatalf("parsed config = %+v; expected match with %+v", cfg2, cfg)
  96. }
  97. if url2, changed := cfg.makeURL(url); changed {
  98. t.Errorf("ApplyConfig returned changed=true after applying same config (%q instead of expected %q", url2.String(), url.String())
  99. }
  100. }
  101. // TestDefaultConfig verifies that default config values are omitted from URL.
  102. func TestDefaultConfig(t *testing.T) {
  103. cfg := defaultConfig()
  104. url, changed := cfg.makeURL(url.URL{})
  105. if changed {
  106. t.Error("applyConfig returned changed=true after applying default config")
  107. }
  108. if url.String() != "" {
  109. t.Errorf("applyConfig returned %q; expecting %q", url.String(), "")
  110. }
  111. }
  112. func TestConfigMenu(t *testing.T) {
  113. // Save some test settings.
  114. tmpDir, fname := settingsDirAndFile(t)
  115. defer os.RemoveAll(tmpDir)
  116. a, b := defaultConfig(), defaultConfig()
  117. a.Focus, b.Focus = "foo", "bar"
  118. s := &settings{
  119. Configs: []namedConfig{
  120. {Name: "A", config: a},
  121. {Name: "B", config: b},
  122. },
  123. }
  124. if err := writeSettings(fname, s); err != nil {
  125. t.Fatal("error writing settings", err)
  126. }
  127. pageURL, _ := url.Parse("/top?f=foo")
  128. menu := configMenu(fname, *pageURL)
  129. want := []configMenuEntry{
  130. {Name: "Default", URL: "/top", Current: false, UserConfig: false},
  131. {Name: "A", URL: "/top?f=foo", Current: true, UserConfig: true},
  132. {Name: "B", URL: "/top?f=bar", Current: false, UserConfig: true},
  133. }
  134. if !reflect.DeepEqual(menu, want) {
  135. t.Errorf("ConfigMenu returned %v; want %v", menu, want)
  136. }
  137. }
  138. func TestEditConfig(t *testing.T) {
  139. tmpDir, fname := settingsDirAndFile(t)
  140. defer os.RemoveAll(tmpDir)
  141. type testConfig struct {
  142. name string
  143. focus string
  144. hide string
  145. }
  146. type testCase struct {
  147. remove bool
  148. request string
  149. expect []testConfig
  150. }
  151. for _, c := range []testCase{
  152. // Create setting c1
  153. {false, "/?config=c1&f=foo", []testConfig{
  154. {"c1", "foo", ""},
  155. }},
  156. // Create setting c2
  157. {false, "/?config=c2&h=bar", []testConfig{
  158. {"c1", "foo", ""},
  159. {"c2", "", "bar"},
  160. }},
  161. // Overwrite c1
  162. {false, "/?config=c1&f=baz", []testConfig{
  163. {"c1", "baz", ""},
  164. {"c2", "", "bar"},
  165. }},
  166. // Delete c2
  167. {true, "c2", []testConfig{
  168. {"c1", "baz", ""},
  169. }},
  170. } {
  171. if c.remove {
  172. if err := removeConfig(fname, c.request); err != nil {
  173. t.Errorf("error removing config %s: %v", c.request, err)
  174. continue
  175. }
  176. } else {
  177. req, err := url.Parse(c.request)
  178. if err != nil {
  179. t.Errorf("error parsing request %q: %v", c.request, err)
  180. continue
  181. }
  182. if err := setConfig(fname, *req); err != nil {
  183. t.Errorf("error saving request %q: %v", c.request, err)
  184. continue
  185. }
  186. }
  187. // Check resulting settings.
  188. s, err := readSettings(fname)
  189. if err != nil {
  190. t.Errorf("error reading settings after applying %q: %v", c.request, err)
  191. continue
  192. }
  193. // Convert to a list that can be compared to c.expect
  194. got := make([]testConfig, len(s.Configs))
  195. for i, c := range s.Configs {
  196. got[i] = testConfig{c.Name, c.Focus, c.Hide}
  197. }
  198. if !reflect.DeepEqual(got, c.expect) {
  199. t.Errorf("Settings after applying %q = %v; want %v", c.request, got, c.expect)
  200. }
  201. }
  202. }
  203. func TestAssign(t *testing.T) {
  204. baseConfig := currentConfig()
  205. defer setCurrentConfig(baseConfig)
  206. // Test assigning to a simple field.
  207. if err := configure("nodecount", "20"); err != nil {
  208. t.Errorf("error setting nodecount: %v", err)
  209. }
  210. if n := currentConfig().NodeCount; n != 20 {
  211. t.Errorf("incorrect nodecount; expecting 20, got %d", n)
  212. }
  213. // Test assignment to a group field.
  214. if err := configure("granularity", "files"); err != nil {
  215. t.Errorf("error setting granularity: %v", err)
  216. }
  217. if g := currentConfig().Granularity; g != "files" {
  218. t.Errorf("incorrect granularity; expecting %v, got %v", "files", g)
  219. }
  220. // Test assignment to one choice of a group field.
  221. if err := configure("lines", "t"); err != nil {
  222. t.Errorf("error setting lines: %v", err)
  223. }
  224. if g := currentConfig().Granularity; g != "lines" {
  225. t.Errorf("incorrect granularity; expecting %v, got %v", "lines", g)
  226. }
  227. // Test assignment to invalid choice,
  228. if err := configure("granularity", "cheese"); err == nil {
  229. t.Errorf("allowed assignment of invalid granularity")
  230. }
  231. }