Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 1 | package debug |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 2 | |
| 3 | import ( |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 4 | "fmt" |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 5 | "io" |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 6 | "io/ioutil" |
| 7 | "os" |
| 8 | "path/filepath" |
| 9 | "reflect" |
| 10 | "sort" |
| 11 | "strings" |
| 12 | "testing" |
| 13 | "time" |
| 14 | |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 15 | "veyron.io/veyron/veyron2" |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 16 | "veyron.io/veyron/veyron2/context" |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 17 | "veyron.io/veyron/veyron2/ipc" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 18 | "veyron.io/veyron/veyron2/naming" |
| 19 | "veyron.io/veyron/veyron2/rt" |
| 20 | "veyron.io/veyron/veyron2/services/mgmt/logreader" |
| 21 | "veyron.io/veyron/veyron2/services/mgmt/stats" |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 22 | vtracesvc "veyron.io/veyron/veyron2/services/mgmt/vtrace" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 23 | "veyron.io/veyron/veyron2/verror" |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 24 | "veyron.io/veyron/veyron2/vtrace" |
Cosmos Nicolaou | 43b9535 | 2014-10-14 11:09:52 -0700 | [diff] [blame] | 25 | |
| 26 | libstats "veyron.io/veyron/veyron/lib/stats" |
Robin Thellend | 5c95a6c | 2014-11-10 13:06:56 -0800 | [diff] [blame] | 27 | "veyron.io/veyron/veyron/lib/testutil" |
Cosmos Nicolaou | 43b9535 | 2014-10-14 11:09:52 -0700 | [diff] [blame] | 28 | "veyron.io/veyron/veyron/profiles" |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 29 | ) |
| 30 | |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 31 | // startDebugServer starts a debug server. |
| 32 | func startDebugServer(rt veyron2.Runtime, listenSpec ipc.ListenSpec, logsDir string) (string, func(), error) { |
| 33 | if len(logsDir) == 0 { |
| 34 | return "", nil, fmt.Errorf("logs directory missing") |
| 35 | } |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 36 | disp := NewDispatcher(logsDir, nil, rt.VtraceStore()) |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 37 | server, err := rt.NewServer() |
| 38 | if err != nil { |
| 39 | return "", nil, fmt.Errorf("failed to start debug server: %v", err) |
| 40 | } |
Cosmos Nicolaou | 28dabfc | 2014-12-15 22:51:07 -0800 | [diff] [blame] | 41 | endpoints, err := server.Listen(listenSpec) |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 42 | if err != nil { |
| 43 | return "", nil, fmt.Errorf("failed to listen on %s: %v", listenSpec, err) |
| 44 | } |
| 45 | if err := server.ServeDispatcher("", disp); err != nil { |
| 46 | return "", nil, err |
| 47 | } |
Cosmos Nicolaou | 28dabfc | 2014-12-15 22:51:07 -0800 | [diff] [blame] | 48 | ep := endpoints[0].String() |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 49 | return ep, func() { server.Stop() }, nil |
| 50 | } |
| 51 | |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 52 | func TestDebugServer(t *testing.T) { |
Matt Rosencrantz | 5180d16 | 2014-12-03 13:48:40 -0800 | [diff] [blame] | 53 | runtime, err := rt.New() |
| 54 | if err != nil { |
| 55 | t.Fatalf("Could not initialize runtime: %v", err) |
| 56 | } |
| 57 | defer runtime.Cleanup() |
| 58 | |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 59 | tracedContext := func() context.T { |
| 60 | ctx := runtime.NewContext() |
| 61 | vtrace.FromContext(ctx).Trace().ForceCollect() |
| 62 | return ctx |
| 63 | } |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 64 | rootName = "debug" |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 65 | |
| 66 | workdir, err := ioutil.TempDir("", "logreadertest") |
| 67 | if err != nil { |
| 68 | t.Fatalf("ioutil.TempDir: %v", err) |
| 69 | } |
| 70 | defer os.RemoveAll(workdir) |
| 71 | if err = ioutil.WriteFile(filepath.Join(workdir, "test.INFO"), []byte("test"), os.FileMode(0644)); err != nil { |
| 72 | t.Fatalf("ioutil.WriteFile failed: %v", err) |
| 73 | } |
| 74 | |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 75 | endpoint, stop, err := startDebugServer(runtime, profiles.LocalListenSpec, workdir) |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 76 | if err != nil { |
| 77 | t.Fatalf("StartDebugServer failed: %v", err) |
| 78 | } |
| 79 | defer stop() |
| 80 | |
| 81 | // Access a logs directory that exists. |
| 82 | { |
Matt Rosencrantz | 8a42280 | 2014-11-27 21:36:45 -0800 | [diff] [blame] | 83 | results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs"), "*") |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 84 | if err != nil { |
| 85 | t.Errorf("Glob failed: %v", err) |
| 86 | } |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 87 | if len(results) != 1 || results[0] != "test.INFO" { |
| 88 | t.Errorf("unexpected result. Got %v, want 'test.INFO'", results) |
| 89 | } |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | // Access a logs directory that doesn't exist. |
| 93 | { |
Matt Rosencrantz | 8a42280 | 2014-11-27 21:36:45 -0800 | [diff] [blame] | 94 | results, err := testutil.GlobName(runtime.NewContext(), naming.JoinAddressName(endpoint, "debug/logs/nowheretobefound"), "*") |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 95 | if len(results) != 0 { |
| 96 | t.Errorf("unexpected result. Got %v, want ''", results) |
| 97 | } |
Robin Thellend | ac7128c | 2014-11-11 09:58:28 -0800 | [diff] [blame] | 98 | if err != nil { |
| 99 | t.Errorf("unexpected error value: %v", err) |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 100 | } |
| 101 | } |
| 102 | |
| 103 | // Access a log file that exists. |
| 104 | { |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 105 | lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/test.INFO")) |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 106 | size, err := lf.Size(tracedContext()) |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 107 | if err != nil { |
| 108 | t.Errorf("Size failed: %v", err) |
| 109 | } |
| 110 | if expected := int64(len("test")); size != expected { |
| 111 | t.Errorf("unexpected result. Got %v, want %v", size, expected) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Access a log file that doesn't exist. |
| 116 | { |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 117 | lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/nosuchfile.INFO")) |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 118 | _, err = lf.Size(tracedContext()) |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 119 | if expected := verror.NoExist; !verror.Is(err, expected) { |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 120 | t.Errorf("unexpected error value, got %v, want: %v", err, expected) |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | // Access a stats object that exists. |
| 125 | { |
| 126 | foo := libstats.NewInteger("testing/foo") |
| 127 | foo.Set(123) |
| 128 | |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 129 | st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/foo")) |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 130 | v, err := st.Value(tracedContext()) |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 131 | if err != nil { |
| 132 | t.Errorf("Value failed: %v", err) |
| 133 | } |
| 134 | if expected := int64(123); v != expected { |
| 135 | t.Errorf("unexpected result. Got %v, want %v", v, expected) |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | // Access a stats object that doesn't exists. |
| 140 | { |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 141 | st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/nobodyhome")) |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 142 | _, err = st.Value(tracedContext()) |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 143 | if expected := verror.NoExist; !verror.Is(err, expected) { |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 144 | t.Errorf("unexpected error value, got %v, want: %v", err, expected) |
| 145 | } |
| 146 | } |
| 147 | |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 148 | // Access vtrace. |
| 149 | { |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 150 | vt := vtracesvc.StoreClient(naming.JoinAddressName(endpoint, "debug/vtrace")) |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 151 | call, err := vt.AllTraces(runtime.NewContext()) |
| 152 | if err != nil { |
| 153 | t.Errorf("AllTraces failed: %v", err) |
| 154 | } |
| 155 | ntraces := 0 |
| 156 | stream := call.RecvStream() |
| 157 | for stream.Advance() { |
| 158 | stream.Value() |
| 159 | ntraces++ |
| 160 | } |
| 161 | if err = stream.Err(); err != nil && err != io.EOF { |
| 162 | t.Fatalf("Unexpected error reading trace stream: %s", err) |
| 163 | } |
Matt Rosencrantz | be1a8b5 | 2014-11-21 15:14:06 -0800 | [diff] [blame] | 164 | if ntraces != 4 { |
| 165 | t.Errorf("We expected 4 traces, got: %d", ntraces) |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 166 | } |
| 167 | } |
| 168 | |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 169 | // Glob from the root. |
| 170 | { |
Matt Rosencrantz | 5180d16 | 2014-12-03 13:48:40 -0800 | [diff] [blame] | 171 | ns := runtime.Namespace() |
Robin Thellend | b16d716 | 2014-11-07 13:47:26 -0800 | [diff] [blame] | 172 | ns.SetRoots(naming.JoinAddressName(endpoint, "debug")) |
Matt Rosencrantz | 5180d16 | 2014-12-03 13:48:40 -0800 | [diff] [blame] | 173 | ctx, cancel := runtime.NewContext().WithTimeout(10 * time.Second) |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 174 | defer cancel() |
| 175 | c, err := ns.Glob(ctx, "logs/...") |
| 176 | if err != nil { |
| 177 | t.Errorf("ns.Glob failed: %v", err) |
| 178 | } |
| 179 | results := []string{} |
| 180 | for res := range c { |
| 181 | results = append(results, res.Name) |
| 182 | } |
| 183 | sort.Strings(results) |
| 184 | expected := []string{ |
| 185 | "logs", |
| 186 | "logs/test.INFO", |
| 187 | } |
| 188 | if !reflect.DeepEqual(expected, results) { |
| 189 | t.Errorf("unexpected result. Got %v, want %v", results, expected) |
| 190 | } |
| 191 | |
| 192 | c, err = ns.Glob(ctx, "stats/testing/*") |
| 193 | if err != nil { |
| 194 | t.Errorf("ns.Glob failed: %v", err) |
| 195 | } |
| 196 | results = []string{} |
| 197 | for res := range c { |
| 198 | results = append(results, res.Name) |
| 199 | } |
| 200 | sort.Strings(results) |
| 201 | expected = []string{ |
| 202 | "stats/testing/foo", |
| 203 | } |
| 204 | if !reflect.DeepEqual(expected, results) { |
| 205 | t.Errorf("unexpected result. Got %v, want %v", results, expected) |
| 206 | } |
| 207 | |
Robin Thellend | 1bc409b | 2014-09-23 11:16:38 -0700 | [diff] [blame] | 208 | c, err = ns.Glob(ctx, "*") |
| 209 | if err != nil { |
| 210 | t.Errorf("ns.Glob failed: %v", err) |
| 211 | } |
| 212 | results = []string{} |
| 213 | for res := range c { |
| 214 | results = append(results, res.Name) |
| 215 | } |
| 216 | sort.Strings(results) |
| 217 | expected = []string{ |
| 218 | "logs", |
| 219 | "pprof", |
| 220 | "stats", |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 221 | "vtrace", |
Robin Thellend | 1bc409b | 2014-09-23 11:16:38 -0700 | [diff] [blame] | 222 | } |
| 223 | if !reflect.DeepEqual(expected, results) { |
| 224 | t.Errorf("unexpected result. Got %v, want %v", results, expected) |
| 225 | } |
| 226 | |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 227 | c, err = ns.Glob(ctx, "...") |
| 228 | if err != nil { |
| 229 | t.Errorf("ns.Glob failed: %v", err) |
| 230 | } |
| 231 | results = []string{} |
| 232 | for res := range c { |
| 233 | if strings.HasPrefix(res.Name, "stats/") && !strings.HasPrefix(res.Name, "stats/testing/") { |
| 234 | // Skip any non-testing stats. |
| 235 | continue |
| 236 | } |
| 237 | results = append(results, res.Name) |
| 238 | } |
| 239 | sort.Strings(results) |
| 240 | expected = []string{ |
Robin Thellend | c26c32e | 2014-10-06 17:44:04 -0700 | [diff] [blame] | 241 | "", |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 242 | "logs", |
| 243 | "logs/test.INFO", |
Robin Thellend | 1bc409b | 2014-09-23 11:16:38 -0700 | [diff] [blame] | 244 | "pprof", |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 245 | "stats", |
| 246 | "stats/testing/foo", |
Matt Rosencrantz | b30286b | 2014-11-10 14:52:17 -0800 | [diff] [blame] | 247 | "vtrace", |
Robin Thellend | 738bb08 | 2014-08-25 14:56:58 -0700 | [diff] [blame] | 248 | } |
| 249 | if !reflect.DeepEqual(expected, results) { |
| 250 | t.Errorf("unexpected result. Got %v, want %v", results, expected) |
| 251 | } |
| 252 | } |
| 253 | } |