1// Copyright 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// +build linux 16 17package peek_test 18 19import ( 20 "flag" 21 "fmt" 22 "log" 23 "os" 24 "os/exec" 25 "reflect" 26 "regexp" 27 "sync" 28 "testing" 29 30 "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug" 31 "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/local" 32 "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/remote" 33) 34 35var expectedVarValues = map[string]interface{}{ 36 `main.Z_bool_false`: false, 37 `main.Z_bool_true`: true, 38 `main.Z_complex128`: complex128(1.987654321 - 2.987654321i), 39 `main.Z_complex64`: complex64(1.54321 + 2.54321i), 40 `main.Z_float32`: float32(1.54321), 41 `main.Z_float64`: float64(1.987654321), 42 `main.Z_int16`: int16(-32321), 43 `main.Z_int32`: int32(-1987654321), 44 `main.Z_int64`: int64(-9012345678987654321), 45 `main.Z_int8`: int8(-121), 46 `main.Z_uint16`: uint16(54321), 47 `main.Z_uint32`: uint32(3217654321), 48 `main.Z_uint64`: uint64(12345678900987654321), 49 `main.Z_uint8`: uint8(231), 50} 51 52// TODO: the string forms of some types we're testing aren't stable 53var expectedVars = map[string]string{ 54 `main.Z_array`: `[5]int8{-121, 121, 3, 2, 1}`, 55 `main.Z_array_empty`: `[0]int8{}`, 56 `main.Z_bool_false`: `false`, 57 `main.Z_bool_true`: `true`, 58 `main.Z_channel`: `(chan int16 0xX)`, 59 `main.Z_channel_2`: `(chan int16 0xX)`, 60 `main.Z_channel_buffered`: `(chan int16 0xX [6/10])`, 61 `main.Z_channel_nil`: `(chan int16 <nil>)`, 62 `main.Z_array_of_empties`: `[2]{}{{} {}, ({} 0xX)}`, 63 `main.Z_complex128`: `(1.987654321-2.987654321i)`, 64 `main.Z_complex64`: `(1.54321+2.54321i)`, 65 `main.Z_float32`: `1.54321`, 66 `main.Z_float64`: `1.987654321`, 67 `main.Z_func_int8_r_int8`: `func(int8, *int8) void @0xX `, 68 `main.Z_func_int8_r_pint8`: `func(int8, **int8) void @0xX `, 69 `main.Z_func_bar`: `func(*main.FooStruct) void @0xX `, 70 `main.Z_func_nil`: `func(int8, *int8) void @0xX `, 71 `main.Z_int`: `-21`, 72 `main.Z_int16`: `-32321`, 73 `main.Z_int32`: `-1987654321`, 74 `main.Z_int64`: `-9012345678987654321`, 75 `main.Z_int8`: `-121`, 76 `main.Z_int_typedef`: `88`, 77 `main.Z_interface`: `("*main.FooStruct", 0xX)`, 78 `main.Z_interface_nil`: `(<nil>, <nil>)`, 79 `main.Z_interface_typed_nil`: `("*main.FooStruct", <nil>)`, 80 `main.Z_map`: `map[-21:3.54321]`, 81 `main.Z_map_2`: `map[1024:1]`, 82 `main.Z_map_3`: `map[1024:1 512:-1]`, 83 `main.Z_map_empty`: `map[]`, 84 `main.Z_map_nil`: `map[]`, 85 `main.Z_pointer`: `0xX`, 86 `main.Z_pointer_nil`: `0x0`, 87 `main.Z_slice`: `[]uint8{115, 108, 105, 99, 101}`, 88 `main.Z_slice_2`: `[]int8{-121, 121}`, 89 `main.Z_slice_nil`: `[]uint8{}`, 90 `main.Z_string`: `"I'm a string"`, 91 `main.Z_struct`: `main.FooStruct {21, "hi"}`, 92 `main.Z_uint`: `21`, 93 `main.Z_uint16`: `54321`, 94 `main.Z_uint32`: `3217654321`, 95 `main.Z_uint64`: `12345678900987654321`, 96 `main.Z_uint8`: `231`, 97 `main.Z_uintptr`: `21`, 98 `main.Z_unsafe_pointer`: `0xX`, 99 `main.Z_unsafe_pointer_nil`: `0x0`, 100} 101 102// expectedEvaluate contains expected results of the debug.Evaluate function. 103// A nil value indicates that an error is expected. 104var expectedEvaluate = map[string]debug.Value{ 105 `x`: int16(42), 106 `local_array`: debug.Array{42, 42, 5, 8}, 107 `local_channel`: debug.Channel{42, 42, 42, 0, 0, 2, 0}, 108 `local_channel_buffered`: debug.Channel{42, 42, 42, 6, 10, 2, 8}, 109 `local_map`: debug.Map{42, 42, 1}, 110 `local_map_2`: debug.Map{42, 42, 1}, 111 `local_map_3`: debug.Map{42, 42, 2}, 112 `local_map_empty`: debug.Map{42, 42, 0}, 113 `x + 5`: int16(47), 114 `x - 5`: int16(37), 115 `x / 5`: int16(8), 116 `x % 5`: int16(2), 117 `x & 2`: int16(2), 118 `x | 1`: int16(43), 119 `x ^ 3`: int16(41), 120 `5 + x`: int16(47), 121 `5 - x`: int16(-37), 122 `100 / x`: int16(2), 123 `100 % x`: int16(16), 124 `2 & x`: int16(2), 125 `1 | x`: int16(43), 126 `3 ^ x`: int16(41), 127 `12`: 12, 128 `+42`: 42, 129 `23i`: 23i, 130 `34.0`: 34.0, 131 `34.5`: 34.5, 132 `1e5`: 100000.0, 133 `0x42`: 66, 134 `'c'`: 'c', 135 `"de"`: debug.String{2, `de`}, 136 "`ef`": debug.String{2, `ef`}, 137 `"de" + "fg"`: debug.String{4, `defg`}, 138 `/* comment */ -5`: -5, 139 `false`: false, 140 `true`: true, 141 `!false`: true, 142 `!true`: false, 143 `5 + 5`: 10, 144 `true || false`: true, 145 `false || false`: false, 146 `true && false`: false, 147 `true && true`: true, 148 `!(5 > 8)`: true, 149 `10 + 'a'`: 'k', 150 `10 + 10.5`: 20.5, 151 `10 + 10.5i`: 10 + 10.5i, 152 `'a' + 10.5`: 107.5, 153 `'a' + 10.5i`: 97 + 10.5i, 154 `10.5 + 20.5i`: 10.5 + 20.5i, 155 `10 * 20`: 200, 156 `10.0 - 20.5`: -10.5, 157 `(6 + 8i) * 4`: 24 + 32i, 158 `(6 + 8i) * (1 + 1i)`: -2 + 14i, 159 `(6 + 8i) * (6 - 8i)`: complex128(100), 160 `(6 + 8i) / (3 + 4i)`: complex128(2), 161 `local_array[2]`: int8(3), 162 `&local_array[1]`: debug.Pointer{42, 42}, 163 `local_map[-21]`: float32(3.54321), 164 `local_map[+21]`: float32(0), 165 `local_map_3[1024]`: int8(1), 166 `local_map_3[512]`: int8(-1), 167 `local_map_empty[21]`: float32(0), 168 `"hello"[2]`: uint8('l'), 169 `local_array[1:3][1]`: int8(3), 170 `local_array[0:4][2:3][0]`: int8(3), 171 `local_array[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5}, 172 `local_array[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5}, 173 `local_array[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3}, 174 `local_array[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4}, 175 `local_array[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4}, 176 `local_array[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3}, 177 `local_array[1:][1:][1:]`: debug.Slice{debug.Array{42, 42, 2, 8}, 2}, 178 `(&local_array)[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5}, 179 `(&local_array)[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5}, 180 `(&local_array)[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3}, 181 `(&local_array)[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4}, 182 `(&local_array)[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4}, 183 `(&local_array)[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3}, 184 `lookup("main.Z_array")`: debug.Array{42, 42, 5, 8}, 185 `lookup("main.Z_array_empty")`: debug.Array{42, 42, 0, 8}, 186 `lookup("main.Z_bool_false")`: false, 187 `lookup("main.Z_bool_true")`: true, 188 `lookup("main.Z_channel")`: debug.Channel{42, 42, 42, 0, 0, 2, 0}, 189 `lookup("main.Z_channel_buffered")`: debug.Channel{42, 42, 42, 6, 10, 2, 8}, 190 `lookup("main.Z_channel_nil")`: debug.Channel{42, 0, 0, 0, 0, 2, 0}, 191 `lookup("main.Z_array_of_empties")`: debug.Array{42, 42, 2, 0}, 192 `lookup("main.Z_complex128")`: complex128(1.987654321 - 2.987654321i), 193 `lookup("main.Z_complex64")`: complex64(1.54321 + 2.54321i), 194 `lookup("main.Z_float32")`: float32(1.54321), 195 `lookup("main.Z_float64")`: float64(1.987654321), 196 `lookup("main.Z_func_int8_r_int8")`: debug.Func{42}, 197 `lookup("main.Z_func_int8_r_pint8")`: debug.Func{42}, 198 `lookup("main.Z_func_bar")`: debug.Func{42}, 199 `lookup("main.Z_func_nil")`: debug.Func{0}, 200 `lookup("main.Z_int")`: -21, 201 `lookup("main.Z_int16")`: int16(-32321), 202 `lookup("main.Z_int32")`: int32(-1987654321), 203 `lookup("main.Z_int64")`: int64(-9012345678987654321), 204 `lookup("main.Z_int8")`: int8(-121), 205 `lookup("main.Z_int_typedef")`: int16(88), 206 `lookup("main.Z_interface")`: debug.Interface{}, 207 `lookup("main.Z_interface_nil")`: debug.Interface{}, 208 `lookup("main.Z_interface_typed_nil")`: debug.Interface{}, 209 `lookup("main.Z_map")`: debug.Map{42, 42, 1}, 210 `lookup("main.Z_map_2")`: debug.Map{42, 42, 1}, 211 `lookup("main.Z_map_3")`: debug.Map{42, 42, 2}, 212 `lookup("main.Z_map_empty")`: debug.Map{42, 42, 0}, 213 `lookup("main.Z_map_nil")`: debug.Map{42, 42, 0}, 214 `lookup("main.Z_pointer")`: debug.Pointer{42, 42}, 215 `lookup("main.Z_pointer_nil")`: debug.Pointer{42, 0}, 216 `lookup("main.Z_slice")`: debug.Slice{debug.Array{42, 42, 5, 8}, 5}, 217 `lookup("main.Z_slice_2")`: debug.Slice{debug.Array{42, 42, 2, 8}, 5}, 218 `lookup("main.Z_slice_nil")`: debug.Slice{debug.Array{42, 0, 0, 8}, 0}, 219 `lookup("main.Z_string")`: debug.String{12, `I'm a string`}, 220 `lookup("main.Z_struct")`: debug.Struct{[]debug.StructField{{"a", debug.Var{}}, {"b", debug.Var{}}}}, 221 `lookup("main.Z_uint")`: uint(21), 222 `lookup("main.Z_uint16")`: uint16(54321), 223 `lookup("main.Z_uint32")`: uint32(3217654321), 224 `lookup("main.Z_uint64")`: uint64(12345678900987654321), 225 `lookup("main.Z_uint8")`: uint8(231), 226 `lookup("main.Z_uintptr")`: uint(21), 227 `lookup("main.Z_unsafe_pointer")`: debug.Pointer{0, 42}, 228 `lookup("main.Z_unsafe_pointer_nil")`: debug.Pointer{0, 0}, 229 `lookup("main.Z_int") + lookup("main.Z_int")`: -42, 230 `lookup("main.Z_int16") < 0`: true, 231 `lookup("main.Z_uint32") + lookup("main.Z_uint32")`: uint32(2140341346), 232 `lookup("main.Z_bool_true") || lookup("main.Z_bool_false")`: true, 233 `lookup("main.Z_bool_true") && lookup("main.Z_bool_false")`: false, 234 `lookup("main.Z_bool_false") || lookup("main.Z_bool_false")`: false, 235 `!lookup("main.Z_bool_true")`: false, 236 `!lookup("main.Z_bool_false")`: true, 237 `lookup("main.Z_array")[2]`: int8(3), 238 `lookup("main.Z_array")[1:3][1]`: int8(3), 239 `lookup("main.Z_array")[0:4][2:3][0]`: int8(3), 240 `lookup("main.Z_array_of_empties")[0]`: debug.Struct{}, 241 `lookup("main.Z_complex128") * 10.0`: complex128(19.87654321 - 29.87654321i), 242 `lookup("main.Z_complex64") * 0.1`: complex64(0.154321 + 0.254321i), 243 `lookup("main.Z_float32") * 10.0`: float32(15.4321), 244 `lookup("main.Z_float64") * 0.1`: float64(0.1987654321), 245 `lookup("main.Z_int") + 1`: int(-20), 246 `lookup("main.Z_int16") - 10`: int16(-32331), 247 `lookup("main.Z_int32") / 10`: int32(-198765432), 248 `lookup("main.Z_int64") / 10`: int64(-901234567898765432), 249 `lookup("main.Z_int8") + 10`: int8(-111), 250 `lookup("main.Z_map")[-21]`: float32(3.54321), 251 `lookup("main.Z_map")[+21]`: float32(0), 252 `lookup("main.Z_map_empty")[21]`: float32(0), 253 `lookup("main.Z_slice")[1]`: uint8(108), 254 `lookup("main.Z_slice_2")[1]`: int8(121), 255 `lookup("main.Z_slice")[1:5][0:3][1]`: uint8('i'), 256 `lookup("main.Z_array")[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3}, 257 `(&lookup("main.Z_array"))[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3}, 258 `lookup("main.Z_string") + "!"`: debug.String{13, `I'm a string!`}, 259 `lookup("main.Z_struct").a`: 21, 260 `(&lookup("main.Z_struct")).a`: 21, 261 `lookup("main.Z_uint")/10`: uint(2), 262 `lookup("main.Z_uint16")/10`: uint16(5432), 263 `lookup("main.Z_uint32")/10`: uint32(321765432), 264 `lookup("main.Z_uint64")/10`: uint64(1234567890098765432), 265 `lookup("main.Z_uint8")/10`: uint8(23), 266 `lookup("main.Z_pointer").a`: 21, 267 `(*lookup("main.Z_pointer")).a`: 21, 268 `(&*lookup("main.Z_pointer")).a`: 21, 269 `lookup("main.Z_pointer").b`: debug.String{2, `hi`}, 270 `(*lookup("main.Z_pointer")).b`: debug.String{2, `hi`}, 271 `(&*lookup("main.Z_pointer")).b`: debug.String{2, `hi`}, 272 `lookup("main.Z_map_nil")[32]`: float32(0), 273 `&lookup("main.Z_int16")`: debug.Pointer{42, 42}, 274 `&lookup("main.Z_array")[1]`: debug.Pointer{42, 42}, 275 `&lookup("main.Z_slice")[1]`: debug.Pointer{42, 42}, 276 `*&lookup("main.Z_int16")`: int16(-32321), 277 `*&*&*&*&lookup("main.Z_int16")`: int16(-32321), 278 `lookup("time.Local")`: debug.Pointer{42, 42}, 279 `5 + false`: nil, 280 ``: nil, 281 `x + ""`: nil, 282 `x / 0`: nil, 283 `0 / 0`: nil, 284 `'a' / ('a'-'a')`: nil, 285 `0.0 / 0.0`: nil, 286 `3i / 0.0`: nil, 287 `x % 0`: nil, 288 `0 % 0`: nil, 289 `'a' % ('a'-'a')`: nil, 290 `local_array[-2] + 1`: nil, 291 `local_array[22] + 1`: nil, 292 `local_slice[-2] + 1`: nil, 293 `local_slice[22] + 1`: nil, 294 `local_string[-2]`: nil, 295 `local_string[22]`: nil, 296 `"hello"[-2]`: nil, 297 `"hello"[22]`: nil, 298 `local_pointer_nil.a`: nil, 299 `(local_struct).c`: nil, 300 `(&local_struct).c`: nil, 301 `(*local_pointer).c`: nil, 302 `lookup("not a real symbol")`: nil, 303 `lookup("x")`: nil, 304 `lookup(x)`: nil, 305 `lookup(42)`: nil, 306} 307 308func isHex(r uint8) bool { 309 switch { 310 case '0' <= r && r <= '9': 311 return true 312 case 'a' <= r && r <= 'f': 313 return true 314 case 'A' <= r && r <= 'F': 315 return true 316 default: 317 return false 318 } 319} 320 321// structRE is used by matches to remove 'struct ' from type names, which is not 322// output by every version of the compiler. 323var structRE = regexp.MustCompile("struct *") 324 325// Check s matches the pattern in p. 326// An 'X' in p greedily matches one or more hex characters in s. 327func matches(p, s string) bool { 328 // Remove 'struct' and following spaces from s. 329 s = structRE.ReplaceAllString(s, "") 330 j := 0 331 for i := 0; i < len(p); i++ { 332 if j == len(s) { 333 return false 334 } 335 c := p[i] 336 if c == 'X' { 337 if !isHex(s[j]) { 338 return false 339 } 340 for j < len(s) && isHex(s[j]) { 341 j++ 342 } 343 continue 344 } 345 if c != s[j] { 346 return false 347 } 348 j++ 349 } 350 return j == len(s) 351} 352 353const ( 354 proxySrc = "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/cmd/debugproxy" 355 traceeSrc = "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/tests/peek/testdata" 356) 357 358var ( 359 // Locations of the proxy and tracee executables. 360 proxyBinary = "./debugproxy.out" 361 traceeBinary = "./tracee.out" 362 // Onces that ensure initProxy and initTracee are called at most once. 363 proxyOnce sync.Once 364 traceeOnce sync.Once 365 // Flags for setting the location of the proxy and tracee, so they don't need to be built. 366 proxyFlag = flag.String("proxy", "", "Location of debugproxy. If empty, proxy will be built.") 367 traceeFlag = flag.String("target", "", "Location of target. If empty, target will be built.") 368 // Executables this test has built, which will be removed on completion of the tests. 369 filesToRemove []string 370) 371 372func TestMain(m *testing.M) { 373 flag.Parse() 374 x := m.Run() 375 for _, f := range filesToRemove { 376 os.Remove(f) 377 } 378 os.Exit(x) 379} 380 381func run(name string, args ...string) error { 382 cmd := exec.Command(name, args...) 383 cmd.Stdout = os.Stdout 384 cmd.Stderr = os.Stderr 385 return cmd.Run() 386} 387 388func initProxy() { 389 if *proxyFlag != "" { 390 proxyBinary = *proxyFlag 391 remote.DebugproxyCmd = proxyBinary 392 return 393 } 394 if err := run("go", "build", "-o", proxyBinary, proxySrc); err != nil { 395 log.Fatalf("couldn't build proxy: %v", err) 396 } 397 filesToRemove = append(filesToRemove, proxyBinary) 398 remote.DebugproxyCmd = proxyBinary 399} 400 401func initTracee() { 402 if *traceeFlag != "" { 403 traceeBinary = *traceeFlag 404 return 405 } 406 if err := run("go", "build", "-o", traceeBinary, traceeSrc); err != nil { 407 log.Fatalf("couldn't build target: %v", err) 408 } 409 filesToRemove = append(filesToRemove, traceeBinary) 410} 411 412func TestLocalProgram(t *testing.T) { 413 t.Skip("Fails looking for runtime.lessstack for some reason") 414 traceeOnce.Do(initTracee) 415 prog, err := local.New(traceeBinary) 416 if err != nil { 417 t.Fatal("local.New:", err) 418 } 419 testProgram(t, prog) 420} 421 422func TestRemoteProgram(t *testing.T) { 423 t.Skip("Fails looking for runtime.lessstack for some reason") 424 traceeOnce.Do(initTracee) 425 proxyOnce.Do(initProxy) 426 prog, err := remote.New("localhost", traceeBinary) 427 if err != nil { 428 t.Fatal("remote.New:", err) 429 } 430 testProgram(t, prog) 431} 432 433func testProgram(t *testing.T, prog debug.Program) { 434 _, err := prog.Run("some", "arguments") 435 if err != nil { 436 log.Fatalf("Run: %v", err) 437 } 438 439 pcs, err := prog.BreakpointAtFunction("main.foo") 440 if err != nil { 441 log.Fatalf("BreakpointAtFunction: %v", err) 442 } 443 fmt.Printf("breakpoints set at %x\n", pcs) 444 445 _, err = prog.Resume() 446 if err != nil { 447 log.Fatalf("Resume: %v", err) 448 } 449 450 gs, err := prog.Goroutines() 451 if err != nil { 452 t.Fatalf("Goroutines(): got error %s", err) 453 } 454 for _, g := range gs { 455 fmt.Println(g) 456 for _, f := range g.StackFrames { 457 fmt.Println(f) 458 } 459 } 460 461 frames, err := prog.Frames(100) 462 if err != nil { 463 log.Fatalf("prog.Frames error: %v", err) 464 } 465 fmt.Printf("%#v\n", frames) 466 if len(frames) == 0 { 467 t.Fatalf("no stack frames returned") 468 } 469 if frames[0].Function != "main.foo" { 470 t.Errorf("function name: got %s expected main.foo", frames[0].Function) 471 } 472 if len(frames[0].Params) != 2 { 473 t.Errorf("got %d parameters, expected 2", len(frames[0].Params)) 474 } else { 475 x := frames[0].Params[0] 476 y := frames[0].Params[1] 477 if x.Name != "x" { 478 x, y = y, x 479 } 480 if x.Name != "x" { 481 t.Errorf("parameter name: got %s expected x", x.Name) 482 } 483 if y.Name != "y" { 484 t.Errorf("parameter name: got %s expected y", y.Name) 485 } 486 if val, err := prog.Value(x.Var); err != nil { 487 t.Errorf("value of x: %s", err) 488 } else if val != int16(42) { 489 t.Errorf("value of x: got %T(%v) expected int16(42)", val, val) 490 } 491 if val, err := prog.Value(y.Var); err != nil { 492 t.Errorf("value of y: %s", err) 493 } else if val != float32(1.5) { 494 t.Errorf("value of y: got %T(%v) expected float32(1.5)", val, val) 495 } 496 } 497 498 varnames, err := prog.Eval(`re:main\.Z_.*`) 499 if err != nil { 500 log.Fatalf("prog.Eval error: %v", err) 501 } 502 503 // Evaluate each of the variables found above, and check they match 504 // expectedVars. 505 seen := make(map[string]bool) 506 for _, v := range varnames { 507 val, err := prog.Eval("val:" + v) 508 if err != nil { 509 log.Fatalf("prog.Eval error for %s: %v", v, err) 510 } else { 511 fmt.Printf("%s = %v\n", v, val) 512 if seen[v] { 513 log.Fatalf("repeated variable %s\n", v) 514 } 515 seen[v] = true 516 if len(val) != 1 { 517 log.Fatalf("should be one value for %s\n", v) 518 } 519 expected, ok := expectedVars[v] 520 if !ok { 521 log.Fatalf("unexpected variable %s\n", v) 522 } else { 523 if !matches(expected, val[0]) { 524 log.Fatalf("expected %s = %s\n", v, expected) 525 } 526 } 527 } 528 } 529 for v, e := range expectedVars { 530 if !seen[v] { 531 log.Fatalf("didn't get %s = %s\n", v, e) 532 } 533 } 534 535 // Remove the breakpoint at main.foo. 536 err = prog.DeleteBreakpoints(pcs) 537 if err != nil { 538 log.Fatalf("DeleteBreakpoints: %v", err) 539 } 540 541 // Set a breakpoint at line 125, resume, and check we stopped there. 542 pcsLine125, err := prog.BreakpointAtLine("testdata/main.go", 125) 543 if err != nil { 544 t.Fatal("BreakpointAtLine:", err) 545 } 546 status, err := prog.Resume() 547 if err != nil { 548 log.Fatalf("Resume: %v", err) 549 } 550 stoppedAt := func(pcs []uint64) bool { 551 for _, pc := range pcs { 552 if status.PC == pc { 553 return true 554 } 555 } 556 return false 557 } 558 if !stoppedAt(pcsLine125) { 559 t.Errorf("stopped at %X; expected one of %X.", status.PC, pcsLine125) 560 } 561 562 for k, v := range expectedEvaluate { 563 val, err := prog.Evaluate(k) 564 if v == nil { 565 if err == nil { 566 t.Errorf("got Evaluate(%s) = %v, expected error", k, val) 567 } 568 continue 569 } 570 if err != nil { 571 t.Errorf("Evaluate(%s): got error %s, expected %v", k, err, v) 572 continue 573 } 574 typ := reflect.TypeOf(v) 575 if typ != reflect.TypeOf(val) && typ != reflect.TypeOf(int(0)) && typ != reflect.TypeOf(uint(0)) { 576 t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v) 577 continue 578 } 579 580 // For types with fields like Address, TypeID, etc., we can't know the exact 581 // value, so we only test whether those fields are zero or not. 582 switch v := v.(type) { 583 default: 584 if v != val { 585 t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v) 586 } 587 case debug.Array: 588 val := val.(debug.Array) 589 if v.ElementTypeID == 0 && val.ElementTypeID != 0 { 590 t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val) 591 } 592 if v.ElementTypeID != 0 && val.ElementTypeID == 0 { 593 t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val) 594 } 595 if v.Address == 0 && val.Address != 0 { 596 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 597 } 598 if v.Address != 0 && val.Address == 0 { 599 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 600 } 601 case debug.Slice: 602 val := val.(debug.Slice) 603 if v.ElementTypeID == 0 && val.ElementTypeID != 0 { 604 t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val) 605 } 606 if v.ElementTypeID != 0 && val.ElementTypeID == 0 { 607 t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val) 608 } 609 if v.Address == 0 && val.Address != 0 { 610 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 611 } 612 if v.Address != 0 && val.Address == 0 { 613 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 614 } 615 case debug.Map: 616 val := val.(debug.Map) 617 if v.TypeID == 0 && val.TypeID != 0 { 618 t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val) 619 } 620 if v.TypeID != 0 && val.TypeID == 0 { 621 t.Errorf("got Evaluate(%s) = %+v, expected non-zero TypeID", k, val) 622 } 623 if v.Address == 0 && val.Address != 0 { 624 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 625 } 626 if v.Address != 0 && val.Address == 0 { 627 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 628 } 629 case debug.Pointer: 630 val := val.(debug.Pointer) 631 if v.TypeID == 0 && val.TypeID != 0 { 632 t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val) 633 } 634 if v.TypeID != 0 && val.TypeID == 0 { 635 t.Errorf("got Evaluate(%s) = %+v, expected non-zero TypeID", k, val) 636 } 637 if v.Address == 0 && val.Address != 0 { 638 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 639 } 640 if v.Address != 0 && val.Address == 0 { 641 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 642 } 643 case debug.Channel: 644 val := val.(debug.Channel) 645 if v.ElementTypeID == 0 && val.ElementTypeID != 0 { 646 t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val) 647 } 648 if v.ElementTypeID != 0 && val.ElementTypeID == 0 { 649 t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val) 650 } 651 if v.Address == 0 && val.Address != 0 { 652 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 653 } 654 if v.Address != 0 && val.Address == 0 { 655 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 656 } 657 if v.Buffer == 0 && val.Buffer != 0 { 658 t.Errorf("got Evaluate(%s) = %+v, expected zero Buffer", k, val) 659 } 660 if v.Buffer != 0 && val.Buffer == 0 { 661 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Buffer", k, val) 662 } 663 case debug.Struct: 664 val := val.(debug.Struct) 665 if len(v.Fields) != len(val.Fields) { 666 t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v) 667 break 668 } 669 for i := range v.Fields { 670 a := v.Fields[i].Name 671 b := val.Fields[i].Name 672 if a != b { 673 t.Errorf("Evaluate(%s): field name mismatch: %s vs %s", k, a, b) 674 break 675 } 676 } 677 case debug.Func: 678 val := val.(debug.Func) 679 if v.Address == 0 && val.Address != 0 { 680 t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val) 681 } 682 if v.Address != 0 && val.Address == 0 { 683 t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val) 684 } 685 case int: 686 // ints in a remote program can be returned as int32 or int64 687 switch val := val.(type) { 688 case int32: 689 if val != int32(v) { 690 t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v) 691 } 692 case int64: 693 if val != int64(v) { 694 t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v) 695 } 696 default: 697 t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v) 698 } 699 case uint: 700 // uints in a remote program can be returned as uint32 or uint64 701 switch val := val.(type) { 702 case uint32: 703 if val != uint32(v) { 704 t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v) 705 } 706 case uint64: 707 if val != uint64(v) { 708 t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v) 709 } 710 default: 711 t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v) 712 } 713 } 714 } 715 716 // Evaluate a struct. 717 v := `lookup("main.Z_struct")` 718 val, err := prog.Evaluate(v) 719 if err != nil { 720 t.Fatalf("Evaluate: %s", err) 721 } 722 s, ok := val.(debug.Struct) 723 if !ok { 724 t.Fatalf("got Evaluate(%q) = %T(%v), expected debug.Struct", v, val, val) 725 } 726 // Check the values of its fields. 727 if len(s.Fields) != 2 { 728 t.Fatalf("got Evaluate(%q) = %+v, expected 2 fields", v, s) 729 } 730 if v0, err := prog.Value(s.Fields[0].Var); err != nil { 731 t.Errorf("Value: %s", err) 732 } else if v0 != int32(21) && v0 != int64(21) { 733 t.Errorf("Value: got %T(%v), expected 21", v0, v0) 734 } 735 if v1, err := prog.Value(s.Fields[1].Var); err != nil { 736 t.Errorf("Value: %s", err) 737 } else if v1 != (debug.String{2, "hi"}) { 738 t.Errorf("Value: got %T(%v), expected `hi`", v1, v1) 739 } 740 741 // Remove the breakpoint at line 125, set a breakpoint at main.f1 and main.f2, 742 // then delete the breakpoint at main.f1. Resume, then check we stopped at 743 // main.f2. 744 err = prog.DeleteBreakpoints(pcsLine125) 745 if err != nil { 746 log.Fatalf("DeleteBreakpoints: %v", err) 747 } 748 pcs1, err := prog.BreakpointAtFunction("main.f1") 749 if err != nil { 750 log.Fatalf("BreakpointAtFunction: %v", err) 751 } 752 pcs2, err := prog.BreakpointAtFunction("main.f2") 753 if err != nil { 754 log.Fatalf("BreakpointAtFunction: %v", err) 755 } 756 err = prog.DeleteBreakpoints(pcs1) 757 if err != nil { 758 log.Fatalf("DeleteBreakpoints: %v", err) 759 } 760 status, err = prog.Resume() 761 if err != nil { 762 log.Fatalf("Resume: %v", err) 763 } 764 if !stoppedAt(pcs2) { 765 t.Errorf("stopped at %X; expected one of %X.", status.PC, pcs2) 766 } 767 768 // Check we get the expected results calling VarByName then Value 769 // for the variables in expectedVarValues. 770 for name, exp := range expectedVarValues { 771 if v, err := prog.VarByName(name); err != nil { 772 t.Errorf("VarByName(%s): %s", name, err) 773 } else if val, err := prog.Value(v); err != nil { 774 t.Errorf("value of %s: %s", name, err) 775 } else if val != exp { 776 t.Errorf("value of %s: got %T(%v) want %T(%v)", name, val, val, exp, exp) 777 } 778 } 779 780 // Check some error cases for VarByName and Value. 781 if _, err = prog.VarByName("not a real name"); err == nil { 782 t.Error("VarByName for invalid name: expected error") 783 } 784 if _, err = prog.Value(debug.Var{}); err == nil { 785 t.Error("value of invalid var: expected error") 786 } 787 if v, err := prog.VarByName("main.Z_int16"); err != nil { 788 t.Error("VarByName(main.Z_int16) error:", err) 789 } else { 790 v.Address = 0 791 // v now has a valid type but a bad address. 792 _, err = prog.Value(v) 793 if err == nil { 794 t.Error("value of invalid location: expected error") 795 } 796 } 797 798 // checkValue tests that we can get a Var for a variable with the given name, 799 // that we can then get the value of that Var, and that calling fn for that 800 // value succeeds. 801 checkValue := func(name string, fn func(val debug.Value) error) { 802 if v, err := prog.VarByName(name); err != nil { 803 t.Errorf("VarByName(%s): %s", name, err) 804 } else if val, err := prog.Value(v); err != nil { 805 t.Errorf("value of %s: %s", name, err) 806 } else if err := fn(val); err != nil { 807 t.Errorf("value of %s: %s", name, err) 808 } 809 } 810 811 checkValue("main.Z_uintptr", func(val debug.Value) error { 812 if val != uint32(21) && val != uint64(21) { 813 // Z_uintptr should be an unsigned integer with size equal to the debugged 814 // program's address size. 815 return fmt.Errorf("got %T(%v) want 21", val, val) 816 } 817 return nil 818 }) 819 820 checkValue("main.Z_int", func(val debug.Value) error { 821 if val != int32(-21) && val != int64(-21) { 822 return fmt.Errorf("got %T(%v) want -21", val, val) 823 } 824 return nil 825 }) 826 827 checkValue("main.Z_uint", func(val debug.Value) error { 828 if val != uint32(21) && val != uint64(21) { 829 return fmt.Errorf("got %T(%v) want 21", val, val) 830 } 831 return nil 832 }) 833 834 checkValue("main.Z_pointer", func(val debug.Value) error { 835 if _, ok := val.(debug.Pointer); !ok { 836 return fmt.Errorf("got %T(%v) expected Pointer", val, val) 837 } 838 return nil 839 }) 840 841 checkValue("main.Z_pointer_nil", func(val debug.Value) error { 842 if p, ok := val.(debug.Pointer); !ok { 843 return fmt.Errorf("got %T(%v) expected Pointer", val, val) 844 } else if p.Address != 0 { 845 return fmt.Errorf("got %T(%v) expected nil pointer", val, val) 846 } 847 return nil 848 }) 849 850 checkValue("main.Z_array", func(val debug.Value) error { 851 a, ok := val.(debug.Array) 852 if !ok { 853 return fmt.Errorf("got %T(%v) expected Array", val, val) 854 } 855 if a.Len() != 5 { 856 return fmt.Errorf("got array length %d expected 5", a.Len()) 857 } 858 expected := [5]int8{-121, 121, 3, 2, 1} 859 for i := uint64(0); i < 5; i++ { 860 if v, err := prog.Value(a.Element(i)); err != nil { 861 return fmt.Errorf("reading element %d: %s", i, err) 862 } else if v != expected[i] { 863 return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i]) 864 } 865 } 866 return nil 867 }) 868 869 checkValue("main.Z_slice", func(val debug.Value) error { 870 s, ok := val.(debug.Slice) 871 if !ok { 872 return fmt.Errorf("got %T(%v) expected Slice", val, val) 873 } 874 if s.Len() != 5 { 875 return fmt.Errorf("got slice length %d expected 5", s.Len()) 876 } 877 expected := []uint8{115, 108, 105, 99, 101} 878 for i := uint64(0); i < 5; i++ { 879 if v, err := prog.Value(s.Element(i)); err != nil { 880 return fmt.Errorf("reading element %d: %s", i, err) 881 } else if v != expected[i] { 882 return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i]) 883 } 884 } 885 return nil 886 }) 887 888 checkValue("main.Z_map_empty", func(val debug.Value) error { 889 m, ok := val.(debug.Map) 890 if !ok { 891 return fmt.Errorf("got %T(%v) expected Map", val, val) 892 } 893 if m.Length != 0 { 894 return fmt.Errorf("got map length %d expected 0", m.Length) 895 } 896 return nil 897 }) 898 899 checkValue("main.Z_map_nil", func(val debug.Value) error { 900 m, ok := val.(debug.Map) 901 if !ok { 902 return fmt.Errorf("got %T(%v) expected Map", val, val) 903 } 904 if m.Length != 0 { 905 return fmt.Errorf("got map length %d expected 0", m.Length) 906 } 907 return nil 908 }) 909 910 checkValue("main.Z_map_3", func(val debug.Value) error { 911 m, ok := val.(debug.Map) 912 if !ok { 913 return fmt.Errorf("got %T(%v) expected Map", val, val) 914 } 915 if m.Length != 2 { 916 return fmt.Errorf("got map length %d expected 2", m.Length) 917 } 918 keyVar0, valVar0, err := prog.MapElement(m, 0) 919 if err != nil { 920 return err 921 } 922 keyVar1, valVar1, err := prog.MapElement(m, 1) 923 if err != nil { 924 return err 925 } 926 key0, err := prog.Value(keyVar0) 927 if err != nil { 928 return err 929 } 930 key1, err := prog.Value(keyVar1) 931 if err != nil { 932 return err 933 } 934 val0, err := prog.Value(valVar0) 935 if err != nil { 936 return err 937 } 938 val1, err := prog.Value(valVar1) 939 if err != nil { 940 return err 941 } 942 // The map should contain 1024,1 and 512,-1 in some order. 943 ok1 := key0 == int16(1024) && val0 == int8(1) && key1 == int16(512) && val1 == int8(-1) 944 ok2 := key1 == int16(1024) && val1 == int8(1) && key0 == int16(512) && val0 == int8(-1) 945 if !ok1 && !ok2 { 946 return fmt.Errorf("got values (%d,%d) and (%d,%d), expected (1024,1) and (512,-1) in some order", key0, val0, key1, val1) 947 } 948 _, _, err = prog.MapElement(m, 2) 949 if err == nil { 950 return fmt.Errorf("MapElement: reading at a bad index succeeded, expected error") 951 } 952 return nil 953 }) 954 955 checkValue("main.Z_string", func(val debug.Value) error { 956 s, ok := val.(debug.String) 957 if !ok { 958 return fmt.Errorf("got %T(%v) expected String", val, val) 959 } 960 if s.Length != 12 { 961 return fmt.Errorf("got string length %d expected 12", s.Length) 962 } 963 expected := "I'm a string" 964 if s.String != expected { 965 return fmt.Errorf("got %s expected %s", s.String, expected) 966 } 967 return nil 968 }) 969 970 checkValue("main.Z_channel", func(val debug.Value) error { 971 c, ok := val.(debug.Channel) 972 if !ok { 973 return fmt.Errorf("got %T(%v) expected Channel", val, val) 974 } 975 if c.Buffer == 0 { 976 return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer) 977 } 978 if c.Length != 0 { 979 return fmt.Errorf("got length %d expected 0", c.Length) 980 } 981 if c.Capacity != 0 { 982 return fmt.Errorf("got capacity %d expected 0", c.Capacity) 983 } 984 return nil 985 }) 986 987 checkValue("main.Z_channel_2", func(val debug.Value) error { 988 c, ok := val.(debug.Channel) 989 if !ok { 990 return fmt.Errorf("got %T(%v) expected Channel", val, val) 991 } 992 if c.Buffer == 0 { 993 return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer) 994 } 995 if c.Length != 0 { 996 return fmt.Errorf("got length %d expected 0", c.Length) 997 } 998 if c.Capacity != 0 { 999 return fmt.Errorf("got capacity %d expected 0", c.Capacity) 1000 } 1001 return nil 1002 }) 1003 1004 checkValue("main.Z_channel_nil", func(val debug.Value) error { 1005 c, ok := val.(debug.Channel) 1006 if !ok { 1007 return fmt.Errorf("got %T(%v) expected Channel", val, val) 1008 } 1009 if c.Buffer != 0 { 1010 return fmt.Errorf("got buffer address %d expected 0", c.Buffer) 1011 } 1012 if c.Length != 0 { 1013 return fmt.Errorf("got length %d expected 0", c.Length) 1014 } 1015 if c.Capacity != 0 { 1016 return fmt.Errorf("got capacity %d expected 0", c.Capacity) 1017 } 1018 return nil 1019 }) 1020 1021 checkValue("main.Z_channel_buffered", func(val debug.Value) error { 1022 c, ok := val.(debug.Channel) 1023 if !ok { 1024 return fmt.Errorf("got %T(%v) expected Channel", val, val) 1025 } 1026 if c.Buffer == 0 { 1027 return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer) 1028 } 1029 if c.Length != 6 { 1030 return fmt.Errorf("got length %d expected 6", c.Length) 1031 } 1032 if c.Capacity != 10 { 1033 return fmt.Errorf("got capacity %d expected 10", c.Capacity) 1034 } 1035 if c.Stride != 2 { 1036 return fmt.Errorf("got stride %d expected 2", c.Stride) 1037 } 1038 expected := []int16{8, 9, 10, 11, 12, 13} 1039 for i := uint64(0); i < 6; i++ { 1040 if v, err := prog.Value(c.Element(i)); err != nil { 1041 return fmt.Errorf("reading element %d: %s", i, err) 1042 } else if v != expected[i] { 1043 return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i]) 1044 } 1045 } 1046 v := c.Element(6) 1047 if v.Address != 0 { 1048 return fmt.Errorf("invalid element returned Var with address %d, expected 0", v.Address) 1049 } 1050 return nil 1051 }) 1052 1053 checkValue("main.Z_func_bar", func(val debug.Value) error { 1054 f, ok := val.(debug.Func) 1055 if !ok { 1056 return fmt.Errorf("got %T(%v) expected Func", val, val) 1057 } 1058 if f.Address == 0 { 1059 return fmt.Errorf("got func address %d expected nonzero", f.Address) 1060 } 1061 return nil 1062 }) 1063 1064 checkValue("main.Z_func_nil", func(val debug.Value) error { 1065 f, ok := val.(debug.Func) 1066 if !ok { 1067 return fmt.Errorf("got %T(%v) expected Func", val, val) 1068 } 1069 if f.Address != 0 { 1070 return fmt.Errorf("got func address %d expected zero", f.Address) 1071 } 1072 return nil 1073 }) 1074} 1075