1// Copyright 2018 Google Inc. All Rights Reserved.
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