github.com/neilgarb/delve@v1.9.2-nobreaks/service/test/integration1_test.go (about)

     1  package service_test
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"net"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	protest "github.com/go-delve/delve/pkg/proc/test"
    15  	"github.com/go-delve/delve/service/debugger"
    16  
    17  	"github.com/go-delve/delve/pkg/goversion"
    18  	"github.com/go-delve/delve/service"
    19  	"github.com/go-delve/delve/service/api"
    20  	"github.com/go-delve/delve/service/rpc1"
    21  	"github.com/go-delve/delve/service/rpccommon"
    22  )
    23  
    24  func withTestClient1(name string, t *testing.T, fn func(c *rpc1.RPCClient)) {
    25  	withTestClient1Extended(name, t, func(c *rpc1.RPCClient, fixture protest.Fixture) {
    26  		fn(c)
    27  	})
    28  }
    29  
    30  func withTestClient1Extended(name string, t *testing.T, fn func(c *rpc1.RPCClient, fixture protest.Fixture)) {
    31  	if testBackend == "rr" {
    32  		protest.MustHaveRecordingAllowed(t)
    33  	}
    34  	listener, err := net.Listen("tcp", "127.0.0.1:0")
    35  	if err != nil {
    36  		t.Fatalf("couldn't start listener: %s\n", err)
    37  	}
    38  	defer listener.Close()
    39  	var buildFlags protest.BuildFlags
    40  	if buildMode == "pie" {
    41  		buildFlags = protest.BuildModePIE
    42  	}
    43  	fixture := protest.BuildFixture(name, buildFlags)
    44  	server := rpccommon.NewServer(&service.Config{
    45  		Listener:    listener,
    46  		ProcessArgs: []string{fixture.Path},
    47  		Debugger: debugger.Config{
    48  			Backend: testBackend,
    49  		},
    50  	})
    51  	if err := server.Run(); err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	client := rpc1.NewClient(listener.Addr().String())
    55  	defer func() {
    56  		client.Detach(true)
    57  	}()
    58  
    59  	fn(client, fixture)
    60  }
    61  
    62  func Test1RunWithInvalidPath(t *testing.T) {
    63  	if testBackend == "rr" {
    64  		// This test won't work because rr returns an error, after recording, when
    65  		// the recording failed but also when the recording succeeded but the
    66  		// inferior returned an error. Therefore we have to ignore errors from rr.
    67  		return
    68  	}
    69  	listener, err := net.Listen("tcp", "127.0.0.1:0")
    70  	if err != nil {
    71  		t.Fatalf("couldn't start listener: %s\n", err)
    72  	}
    73  	defer listener.Close()
    74  	server := rpccommon.NewServer(&service.Config{
    75  		Listener:    listener,
    76  		ProcessArgs: []string{"invalid_path"},
    77  		Debugger: debugger.Config{
    78  			Backend: testBackend,
    79  		},
    80  	})
    81  	if err := server.Run(); err == nil {
    82  		t.Fatal("Expected Run to return error for invalid program path")
    83  	}
    84  }
    85  
    86  func Test1Restart_afterExit(t *testing.T) {
    87  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
    88  		origPid := c.ProcessPid()
    89  		state := <-c.Continue()
    90  		if !state.Exited {
    91  			t.Fatal("expected initial process to have exited")
    92  		}
    93  		if err := c.Restart(); err != nil {
    94  			t.Fatal(err)
    95  		}
    96  		if c.ProcessPid() == origPid {
    97  			t.Fatal("did not spawn new process, has same PID")
    98  		}
    99  		state = <-c.Continue()
   100  		if !state.Exited {
   101  			t.Fatalf("expected restarted process to have exited %v", state)
   102  		}
   103  	})
   104  }
   105  
   106  func Test1Restart_breakpointPreservation(t *testing.T) {
   107  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
   108  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint", Tracepoint: true})
   109  		assertNoError(err, t, "CreateBreakpoint()")
   110  		stateCh := c.Continue()
   111  
   112  		state := <-stateCh
   113  		if state.CurrentThread.Breakpoint.Name != "firstbreakpoint" || !state.CurrentThread.Breakpoint.Tracepoint {
   114  			t.Fatalf("Wrong breakpoint: %#v\n", state.CurrentThread.Breakpoint)
   115  		}
   116  		state = <-stateCh
   117  		if !state.Exited {
   118  			t.Fatal("Did not exit after first tracepoint")
   119  		}
   120  
   121  		t.Log("Restart")
   122  		c.Restart()
   123  		stateCh = c.Continue()
   124  		state = <-stateCh
   125  		if state.CurrentThread.Breakpoint.Name != "firstbreakpoint" || !state.CurrentThread.Breakpoint.Tracepoint {
   126  			t.Fatalf("Wrong breakpoint (after restart): %#v\n", state.CurrentThread.Breakpoint)
   127  		}
   128  		state = <-stateCh
   129  		if !state.Exited {
   130  			t.Fatal("Did not exit after first tracepoint (after restart)")
   131  		}
   132  	})
   133  }
   134  
   135  func Test1Restart_duringStop(t *testing.T) {
   136  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
   137  		origPid := c.ProcessPid()
   138  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1})
   139  		if err != nil {
   140  			t.Fatal(err)
   141  		}
   142  		state := <-c.Continue()
   143  		if state.CurrentThread.Breakpoint == nil {
   144  			t.Fatal("did not hit breakpoint")
   145  		}
   146  		if err := c.Restart(); err != nil {
   147  			t.Fatal(err)
   148  		}
   149  		if c.ProcessPid() == origPid {
   150  			t.Fatal("did not spawn new process, has same PID")
   151  		}
   152  		bps, err := c.ListBreakpoints()
   153  		if err != nil {
   154  			t.Fatal(err)
   155  		}
   156  		if len(bps) == 0 {
   157  			t.Fatal("breakpoints not preserved")
   158  		}
   159  	})
   160  }
   161  
   162  func Test1ClientServer_exit(t *testing.T) {
   163  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
   164  		state, err := c.GetState()
   165  		if err != nil {
   166  			t.Fatalf("Unexpected error: %v", err)
   167  		}
   168  		if e, a := false, state.Exited; e != a {
   169  			t.Fatalf("Expected exited %v, got %v", e, a)
   170  		}
   171  		state = <-c.Continue()
   172  		if state.Err == nil {
   173  			t.Fatalf("Error expected after continue")
   174  		}
   175  		if !state.Exited {
   176  			t.Fatalf("Expected exit after continue: %v", state)
   177  		}
   178  		_, err = c.GetState()
   179  		if err == nil {
   180  			t.Fatal("Expected error on querying state from exited process")
   181  		}
   182  	})
   183  }
   184  
   185  func Test1ClientServer_step(t *testing.T) {
   186  	withTestClient1("testprog", t, func(c *rpc1.RPCClient) {
   187  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: -1})
   188  		if err != nil {
   189  			t.Fatalf("Unexpected error: %v", err)
   190  		}
   191  
   192  		stateBefore := <-c.Continue()
   193  		if stateBefore.Err != nil {
   194  			t.Fatalf("Unexpected error: %v", stateBefore.Err)
   195  		}
   196  
   197  		stateAfter, err := c.Step()
   198  		if err != nil {
   199  			t.Fatalf("Unexpected error: %v", err)
   200  		}
   201  
   202  		if before, after := stateBefore.CurrentThread.PC, stateAfter.CurrentThread.PC; before >= after {
   203  			t.Fatalf("Expected %#v to be greater than %#v", after, before)
   204  		}
   205  	})
   206  }
   207  
   208  func testnext(testcases []nextTest, initialLocation string, t *testing.T) {
   209  	withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) {
   210  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: initialLocation, Line: -1})
   211  		if err != nil {
   212  			t.Fatalf("Unexpected error: %v", err)
   213  		}
   214  
   215  		state := <-c.Continue()
   216  		if state.Err != nil {
   217  			t.Fatalf("Unexpected error: %v", state.Err)
   218  		}
   219  
   220  		_, err = c.ClearBreakpoint(bp.ID)
   221  		if err != nil {
   222  			t.Fatalf("Unexpected error: %v", err)
   223  		}
   224  
   225  		for _, tc := range testcases {
   226  			if state.CurrentThread.Line != tc.begin {
   227  				t.Fatalf("Program not stopped at correct spot expected %d was %d", tc.begin, state.CurrentThread.Line)
   228  			}
   229  
   230  			t.Logf("Next for scenario %#v", tc)
   231  			state, err = c.Next()
   232  			if err != nil {
   233  				t.Fatalf("Unexpected error: %v", err)
   234  			}
   235  
   236  			if state.CurrentThread.Line != tc.end {
   237  				t.Fatalf("Program did not continue to correct next location expected %d was %d", tc.end, state.CurrentThread.Line)
   238  			}
   239  		}
   240  	})
   241  }
   242  
   243  func Test1NextGeneral(t *testing.T) {
   244  	var testcases []nextTest
   245  
   246  	ver, _ := goversion.Parse(runtime.Version())
   247  
   248  	if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
   249  		testcases = []nextTest{
   250  			{17, 19},
   251  			{19, 20},
   252  			{20, 23},
   253  			{23, 24},
   254  			{24, 26},
   255  			{26, 31},
   256  			{31, 23},
   257  			{23, 24},
   258  			{24, 26},
   259  			{26, 31},
   260  			{31, 23},
   261  			{23, 24},
   262  			{24, 26},
   263  			{26, 27},
   264  			{27, 28},
   265  			{28, 34},
   266  		}
   267  	} else {
   268  		testcases = []nextTest{
   269  			{17, 19},
   270  			{19, 20},
   271  			{20, 23},
   272  			{23, 24},
   273  			{24, 26},
   274  			{26, 31},
   275  			{31, 23},
   276  			{23, 24},
   277  			{24, 26},
   278  			{26, 31},
   279  			{31, 23},
   280  			{23, 24},
   281  			{24, 26},
   282  			{26, 27},
   283  			{27, 34},
   284  		}
   285  	}
   286  
   287  	testnext(testcases, "main.testnext", t)
   288  }
   289  
   290  func Test1NextFunctionReturn(t *testing.T) {
   291  	testcases := []nextTest{
   292  		{13, 14},
   293  		{14, 15},
   294  		{15, 35},
   295  	}
   296  	testnext(testcases, "main.helloworld", t)
   297  }
   298  
   299  func Test1ClientServer_breakpointInMainThread(t *testing.T) {
   300  	withTestClient1("testprog", t, func(c *rpc1.RPCClient) {
   301  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: 1})
   302  		if err != nil {
   303  			t.Fatalf("Unexpected error: %v", err)
   304  		}
   305  
   306  		state := <-c.Continue()
   307  		if err != nil {
   308  			t.Fatalf("Unexpected error: %v, state: %#v", err, state)
   309  		}
   310  
   311  		pc := state.CurrentThread.PC
   312  
   313  		if pc-1 != bp.Addr && pc != bp.Addr {
   314  			f, l := state.CurrentThread.File, state.CurrentThread.Line
   315  			t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
   316  		}
   317  	})
   318  }
   319  
   320  func Test1ClientServer_breakpointInSeparateGoroutine(t *testing.T) {
   321  	withTestClient1("testthreads", t, func(c *rpc1.RPCClient) {
   322  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.anotherthread", Line: 1})
   323  		if err != nil {
   324  			t.Fatalf("Unexpected error: %v", err)
   325  		}
   326  
   327  		state := <-c.Continue()
   328  		if state.Err != nil {
   329  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   330  		}
   331  
   332  		f, l := state.CurrentThread.File, state.CurrentThread.Line
   333  		if f != "testthreads.go" && l != 9 {
   334  			t.Fatal("Program did not hit breakpoint")
   335  		}
   336  	})
   337  }
   338  
   339  func Test1ClientServer_breakAtNonexistentPoint(t *testing.T) {
   340  	withTestClient1("testprog", t, func(c *rpc1.RPCClient) {
   341  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "nowhere", Line: 1})
   342  		if err == nil {
   343  			t.Fatal("Should not be able to break at non existent function")
   344  		}
   345  	})
   346  }
   347  
   348  func Test1ClientServer_clearBreakpoint(t *testing.T) {
   349  	withTestClient1("testprog", t, func(c *rpc1.RPCClient) {
   350  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sleepytime", Line: 1})
   351  		if err != nil {
   352  			t.Fatalf("Unexpected error: %v", err)
   353  		}
   354  
   355  		if e, a := 1, countBreakpoints(t, c); e != a {
   356  			t.Fatalf("Expected breakpoint count %d, got %d", e, a)
   357  		}
   358  
   359  		deleted, err := c.ClearBreakpoint(bp.ID)
   360  		if err != nil {
   361  			t.Fatalf("Unexpected error: %v", err)
   362  		}
   363  
   364  		if deleted.ID != bp.ID {
   365  			t.Fatalf("Expected deleted breakpoint ID %v, got %v", bp.ID, deleted.ID)
   366  		}
   367  
   368  		if e, a := 0, countBreakpoints(t, c); e != a {
   369  			t.Fatalf("Expected breakpoint count %d, got %d", e, a)
   370  		}
   371  	})
   372  }
   373  
   374  func Test1ClientServer_switchThread(t *testing.T) {
   375  	withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) {
   376  		// With invalid thread id
   377  		_, err := c.SwitchThread(-1)
   378  		if err == nil {
   379  			t.Fatal("Expected error for invalid thread id")
   380  		}
   381  
   382  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1})
   383  		if err != nil {
   384  			t.Fatalf("Unexpected error: %v", err)
   385  		}
   386  		state := <-c.Continue()
   387  		if state.Err != nil {
   388  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   389  		}
   390  
   391  		var nt int
   392  		ct := state.CurrentThread.ID
   393  		threads, err := c.ListThreads()
   394  		if err != nil {
   395  			t.Fatalf("Unexpected error: %v", err)
   396  		}
   397  		for _, th := range threads {
   398  			if th.ID != ct {
   399  				nt = th.ID
   400  				break
   401  			}
   402  		}
   403  		if nt == 0 {
   404  			t.Fatal("could not find thread to switch to")
   405  		}
   406  		// With valid thread id
   407  		state, err = c.SwitchThread(nt)
   408  		if err != nil {
   409  			t.Fatal(err)
   410  		}
   411  		if state.CurrentThread.ID != nt {
   412  			t.Fatal("Did not switch threads")
   413  		}
   414  	})
   415  }
   416  
   417  func Test1ClientServer_infoLocals(t *testing.T) {
   418  	withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) {
   419  		fp := testProgPath(t, "testnextprog")
   420  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 24})
   421  		if err != nil {
   422  			t.Fatalf("Unexpected error: %v", err)
   423  		}
   424  		state := <-c.Continue()
   425  		if state.Err != nil {
   426  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   427  		}
   428  		locals, err := c.ListLocalVariables(api.EvalScope{GoroutineID: -1})
   429  		if err != nil {
   430  			t.Fatalf("Unexpected error: %v", err)
   431  		}
   432  		if len(locals) != 3 {
   433  			t.Fatalf("Expected 3 locals, got %d %#v", len(locals), locals)
   434  		}
   435  	})
   436  }
   437  
   438  func Test1ClientServer_infoArgs(t *testing.T) {
   439  	withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) {
   440  		fp := testProgPath(t, "testnextprog")
   441  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 47})
   442  		if err != nil {
   443  			t.Fatalf("Unexpected error: %v", err)
   444  		}
   445  		state := <-c.Continue()
   446  		if state.Err != nil {
   447  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   448  		}
   449  		regs, err := c.ListRegisters()
   450  		if err != nil {
   451  			t.Fatalf("Unexpected error: %v", err)
   452  		}
   453  		if regs == "" {
   454  			t.Fatal("Expected string showing registers values, got empty string")
   455  		}
   456  		locals, err := c.ListFunctionArgs(api.EvalScope{GoroutineID: -1})
   457  		if err != nil {
   458  			t.Fatalf("Unexpected error: %v", err)
   459  		}
   460  		if len(locals) != 2 {
   461  			t.Fatalf("Expected 2 function args, got %d %#v", len(locals), locals)
   462  		}
   463  	})
   464  }
   465  
   466  func Test1ClientServer_traceContinue(t *testing.T) {
   467  	withTestClient1("integrationprog", t, func(c *rpc1.RPCClient) {
   468  		fp := testProgPath(t, "integrationprog")
   469  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 15, Tracepoint: true, Goroutine: true, Stacktrace: 5, Variables: []string{"i"}})
   470  		if err != nil {
   471  			t.Fatalf("Unexpected error: %v\n", err)
   472  		}
   473  		count := 0
   474  		contChan := c.Continue()
   475  		for state := range contChan {
   476  			if state.CurrentThread != nil && state.CurrentThread.Breakpoint != nil {
   477  				count++
   478  
   479  				t.Logf("%v", state)
   480  
   481  				bpi := state.CurrentThread.BreakpointInfo
   482  
   483  				if bpi.Goroutine == nil {
   484  					t.Fatalf("No goroutine information")
   485  				}
   486  
   487  				if len(bpi.Stacktrace) <= 0 {
   488  					t.Fatalf("No stacktrace\n")
   489  				}
   490  
   491  				if len(bpi.Variables) != 1 {
   492  					t.Fatalf("Wrong number of variables returned: %d", len(bpi.Variables))
   493  				}
   494  
   495  				if bpi.Variables[0].Name != "i" {
   496  					t.Fatalf("Wrong variable returned %s", bpi.Variables[0].Name)
   497  				}
   498  
   499  				t.Logf("Variable i is %v", bpi.Variables[0])
   500  
   501  				n, err := strconv.Atoi(bpi.Variables[0].Value)
   502  
   503  				if err != nil || n != count-1 {
   504  					t.Fatalf("Wrong variable value %q (%v %d)", bpi.Variables[0].Value, err, count)
   505  				}
   506  			}
   507  			if state.Exited {
   508  				continue
   509  			}
   510  			t.Logf("%v", state)
   511  			if state.Err != nil {
   512  				t.Fatalf("Unexpected error during continue: %v\n", state.Err)
   513  			}
   514  
   515  		}
   516  
   517  		if count != 3 {
   518  			t.Fatalf("Wrong number of continues hit: %d\n", count)
   519  		}
   520  	})
   521  }
   522  
   523  func Test1ClientServer_traceContinue2(t *testing.T) {
   524  	withTestClient1("integrationprog", t, func(c *rpc1.RPCClient) {
   525  		bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Tracepoint: true})
   526  		if err != nil {
   527  			t.Fatalf("Unexpected error: %v\n", err)
   528  		}
   529  		bp2, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: 1, Tracepoint: true})
   530  		if err != nil {
   531  			t.Fatalf("Unexpected error: %v\n", err)
   532  		}
   533  		countMain := 0
   534  		countSayhi := 0
   535  		contChan := c.Continue()
   536  		for state := range contChan {
   537  			if state.CurrentThread != nil && state.CurrentThread.Breakpoint != nil {
   538  				switch state.CurrentThread.Breakpoint.ID {
   539  				case bp1.ID:
   540  					countMain++
   541  				case bp2.ID:
   542  					countSayhi++
   543  				}
   544  
   545  				t.Logf("%v", state)
   546  			}
   547  			if state.Exited {
   548  				continue
   549  			}
   550  			if state.Err != nil {
   551  				t.Fatalf("Unexpected error during continue: %v\n", state.Err)
   552  			}
   553  
   554  		}
   555  
   556  		if countMain != 1 {
   557  			t.Fatalf("Wrong number of continues (main.main) hit: %d\n", countMain)
   558  		}
   559  
   560  		if countSayhi != 3 {
   561  			t.Fatalf("Wrong number of continues (main.sayhi) hit: %d\n", countSayhi)
   562  		}
   563  	})
   564  }
   565  
   566  func Test1ClientServer_FindLocations(t *testing.T) {
   567  	withTestClient1("locationsprog", t, func(c *rpc1.RPCClient) {
   568  		someFunctionCallAddr := findLocationHelper(t, c, "locationsprog.go:26", false, 1, 0)[0]
   569  		someFunctionLine1 := findLocationHelper(t, c, "locationsprog.go:27", false, 1, 0)[0]
   570  		findLocationHelper(t, c, "anotherFunction:1", false, 1, someFunctionLine1)
   571  		findLocationHelper(t, c, "main.anotherFunction:1", false, 1, someFunctionLine1)
   572  		findLocationHelper(t, c, "anotherFunction", false, 1, someFunctionCallAddr)
   573  		findLocationHelper(t, c, "main.anotherFunction", false, 1, someFunctionCallAddr)
   574  		findLocationHelper(t, c, fmt.Sprintf("*0x%x", someFunctionCallAddr), false, 1, someFunctionCallAddr)
   575  		findLocationHelper(t, c, "sprog.go:26", true, 0, 0)
   576  
   577  		findLocationHelper(t, c, "String", true, 0, 0)
   578  		findLocationHelper(t, c, "main.String", true, 0, 0)
   579  
   580  		someTypeStringFuncAddr := findLocationHelper(t, c, "locationsprog.go:14", false, 1, 0)[0]
   581  		otherTypeStringFuncAddr := findLocationHelper(t, c, "locationsprog.go:18", false, 1, 0)[0]
   582  		findLocationHelper(t, c, "SomeType.String", false, 1, someTypeStringFuncAddr)
   583  		findLocationHelper(t, c, "(*SomeType).String", false, 1, someTypeStringFuncAddr)
   584  		findLocationHelper(t, c, "main.SomeType.String", false, 1, someTypeStringFuncAddr)
   585  		findLocationHelper(t, c, "main.(*SomeType).String", false, 1, someTypeStringFuncAddr)
   586  
   587  		// Issue #275
   588  		readfile := findLocationHelper(t, c, "io/ioutil.ReadFile", false, 1, 0)[0]
   589  
   590  		// Issue #296
   591  		findLocationHelper(t, c, "/io/ioutil.ReadFile", false, 1, readfile)
   592  		findLocationHelper(t, c, "ioutil.ReadFile", false, 1, readfile)
   593  
   594  		stringAddrs := findLocationHelper(t, c, "/^main.*Type.*String$/", false, 2, 0)
   595  
   596  		if otherTypeStringFuncAddr != stringAddrs[0] && otherTypeStringFuncAddr != stringAddrs[1] {
   597  			t.Fatalf("Wrong locations returned for \"/.*Type.*String/\", got: %v expected: %v and %v\n", stringAddrs, someTypeStringFuncAddr, otherTypeStringFuncAddr)
   598  		}
   599  
   600  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 4, Tracepoint: false})
   601  		if err != nil {
   602  			t.Fatalf("CreateBreakpoint(): %v\n", err)
   603  		}
   604  
   605  		<-c.Continue()
   606  
   607  		locationsprog35Addr := findLocationHelper(t, c, "locationsprog.go:35", false, 1, 0)[0]
   608  		findLocationHelper(t, c, fmt.Sprintf("%s:35", testProgPath(t, "locationsprog")), false, 1, locationsprog35Addr)
   609  		findLocationHelper(t, c, "+1", false, 1, locationsprog35Addr)
   610  		findLocationHelper(t, c, "35", false, 1, locationsprog35Addr)
   611  		findLocationHelper(t, c, "-1", false, 1, findLocationHelper(t, c, "locationsprog.go:33", false, 1, 0)[0])
   612  	})
   613  
   614  	withTestClient1("testnextdefer", t, func(c *rpc1.RPCClient) {
   615  		firstMainLine := findLocationHelper(t, c, "testnextdefer.go:5", false, 1, 0)[0]
   616  		findLocationHelper(t, c, "main.main", false, 1, firstMainLine)
   617  	})
   618  
   619  	withTestClient1("stacktraceprog", t, func(c *rpc1.RPCClient) {
   620  		stacktracemeAddr := findLocationHelper(t, c, "stacktraceprog.go:4", false, 1, 0)[0]
   621  		findLocationHelper(t, c, "main.stacktraceme", false, 1, stacktracemeAddr)
   622  	})
   623  
   624  	withTestClient1Extended("locationsUpperCase", t, func(c *rpc1.RPCClient, fixture protest.Fixture) {
   625  		// Upper case
   626  		findLocationHelper(t, c, "locationsUpperCase.go:6", false, 1, 0)
   627  
   628  		// Fully qualified path
   629  		findLocationHelper(t, c, fixture.Source+":6", false, 1, 0)
   630  		bp, err := c.CreateBreakpoint(&api.Breakpoint{File: fixture.Source, Line: 6})
   631  		if err != nil {
   632  			t.Fatalf("Could not set breakpoint in %s: %v\n", fixture.Source, err)
   633  		}
   634  		c.ClearBreakpoint(bp.ID)
   635  
   636  		//  Allow `/` or `\` on Windows
   637  		if runtime.GOOS == "windows" {
   638  			findLocationHelper(t, c, filepath.FromSlash(fixture.Source)+":6", false, 1, 0)
   639  			bp, err = c.CreateBreakpoint(&api.Breakpoint{File: filepath.FromSlash(fixture.Source), Line: 6})
   640  			if err != nil {
   641  				t.Fatalf("Could not set breakpoint in %s: %v\n", filepath.FromSlash(fixture.Source), err)
   642  			}
   643  			c.ClearBreakpoint(bp.ID)
   644  		}
   645  
   646  		// Case-insensitive on Windows, case-sensitive otherwise
   647  		shouldWrongCaseBeError := true
   648  		numExpectedMatches := 0
   649  		if runtime.GOOS == "windows" {
   650  			shouldWrongCaseBeError = false
   651  			numExpectedMatches = 1
   652  		}
   653  		findLocationHelper(t, c, strings.ToLower(fixture.Source)+":6", shouldWrongCaseBeError, numExpectedMatches, 0)
   654  		bp, err = c.CreateBreakpoint(&api.Breakpoint{File: strings.ToLower(fixture.Source), Line: 6})
   655  		if (err == nil) == shouldWrongCaseBeError {
   656  			t.Fatalf("Could not set breakpoint in %s: %v\n", strings.ToLower(fixture.Source), err)
   657  		}
   658  		c.ClearBreakpoint(bp.ID)
   659  	})
   660  }
   661  
   662  func Test1ClientServer_FindLocationsAddr(t *testing.T) {
   663  	withTestClient1("locationsprog2", t, func(c *rpc1.RPCClient) {
   664  		<-c.Continue()
   665  
   666  		afunction := findLocationHelper(t, c, "main.afunction", false, 1, 0)[0]
   667  		anonfunc := findLocationHelper(t, c, "main.main.func1", false, 1, 0)[0]
   668  
   669  		findLocationHelper(t, c, "*fn1", false, 1, afunction)
   670  		findLocationHelper(t, c, "*fn3", false, 1, anonfunc)
   671  	})
   672  }
   673  
   674  func Test1ClientServer_EvalVariable(t *testing.T) {
   675  	withTestClient1("testvariables", t, func(c *rpc1.RPCClient) {
   676  		state := <-c.Continue()
   677  
   678  		if state.Err != nil {
   679  			t.Fatalf("Continue(): %v\n", state.Err)
   680  		}
   681  
   682  		var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "a1")
   683  		assertNoError(err, t, "EvalVariable")
   684  
   685  		t.Logf("var1: %s", var1.SinglelineString())
   686  
   687  		if var1.Value != "foofoofoofoofoofoo" {
   688  			t.Fatalf("Wrong variable value: %s", var1.Value)
   689  		}
   690  	})
   691  }
   692  
   693  func Test1ClientServer_SetVariable(t *testing.T) {
   694  	withTestClient1("testvariables", t, func(c *rpc1.RPCClient) {
   695  		state := <-c.Continue()
   696  
   697  		if state.Err != nil {
   698  			t.Fatalf("Continue(): %v\n", state.Err)
   699  		}
   700  
   701  		assertNoError(c.SetVariable(api.EvalScope{GoroutineID: -1}, "a2", "8"), t, "SetVariable()")
   702  
   703  		a2, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "a2")
   704  		if err != nil {
   705  			t.Fatalf("Could not evaluate variable: %v", err)
   706  		}
   707  
   708  		t.Logf("a2: %v", a2)
   709  
   710  		n, err := strconv.Atoi(a2.Value)
   711  
   712  		if err != nil && n != 8 {
   713  			t.Fatalf("Wrong variable value: %v", a2)
   714  		}
   715  	})
   716  }
   717  
   718  func Test1ClientServer_FullStacktrace(t *testing.T) {
   719  	if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
   720  		t.Skip("cgo doesn't work on darwin/arm64")
   721  	}
   722  
   723  	lenient := false
   724  	if runtime.GOOS == "windows" {
   725  		lenient = true
   726  	}
   727  
   728  	withTestClient1("goroutinestackprog", t, func(c *rpc1.RPCClient) {
   729  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.stacktraceme", Line: -1})
   730  		assertNoError(err, t, "CreateBreakpoint()")
   731  		state := <-c.Continue()
   732  		if state.Err != nil {
   733  			t.Fatalf("Continue(): %v\n", state.Err)
   734  		}
   735  
   736  		gs, err := c.ListGoroutines()
   737  		assertNoError(err, t, "GoroutinesInfo()")
   738  		found := make([]bool, 10)
   739  		for _, g := range gs {
   740  			frames, err := c.Stacktrace(g.ID, 40, true)
   741  			assertNoError(err, t, fmt.Sprintf("Stacktrace(%d)", g.ID))
   742  			t.Logf("goroutine %d", g.ID)
   743  			for i, frame := range frames {
   744  				t.Logf("\tframe %d off=%#x bpoff=%#x pc=%#x %s:%d %s", i, frame.FrameOffset, frame.FramePointerOffset, frame.PC, frame.File, frame.Line, frame.Function.Name())
   745  				if frame.Function == nil {
   746  					continue
   747  				}
   748  				if frame.Function.Name() != "main.agoroutine" {
   749  					continue
   750  				}
   751  				for _, arg := range frame.Arguments {
   752  					if arg.Name != "i" {
   753  						continue
   754  					}
   755  					t.Logf("\tvariable i is %+v\n", arg)
   756  					argn, err := strconv.Atoi(arg.Value)
   757  					if err == nil {
   758  						found[argn] = true
   759  					}
   760  				}
   761  			}
   762  		}
   763  
   764  		for i := range found {
   765  			if !found[i] {
   766  				if lenient {
   767  					lenient = false
   768  				} else {
   769  					t.Fatalf("Goroutine %d not found", i)
   770  				}
   771  			}
   772  		}
   773  
   774  		t.Logf("continue")
   775  
   776  		state = <-c.Continue()
   777  		if state.Err != nil {
   778  			t.Fatalf("Continue(): %v\n", state.Err)
   779  		}
   780  
   781  		frames, err := c.Stacktrace(-1, 10, true)
   782  		assertNoError(err, t, "Stacktrace")
   783  
   784  		cur := 3
   785  		for i, frame := range frames {
   786  			t.Logf("\tframe %d off=%#x bpoff=%#x pc=%#x %s:%d %s", i, frame.FrameOffset, frame.FramePointerOffset, frame.PC, frame.File, frame.Line, frame.Function.Name())
   787  			if i == 0 {
   788  				continue
   789  			}
   790  			v := frame.Var("n")
   791  			if v == nil {
   792  				t.Fatalf("Could not find value of variable n in frame %d", i)
   793  			}
   794  			vn, err := strconv.Atoi(v.Value)
   795  			if err != nil || vn != cur {
   796  				t.Fatalf("Expected value %d got %d (error: %v)", cur, vn, err)
   797  			}
   798  			cur--
   799  			if cur < 0 {
   800  				break
   801  			}
   802  		}
   803  	})
   804  }
   805  
   806  func Test1Issue355(t *testing.T) {
   807  	// After the target process has terminated should return an error but not crash
   808  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
   809  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1})
   810  		assertNoError(err, t, "CreateBreakpoint()")
   811  		ch := c.Continue()
   812  		state := <-ch
   813  		tid := state.CurrentThread.ID
   814  		gid := state.SelectedGoroutine.ID
   815  		assertNoError(state.Err, t, "First Continue()")
   816  		ch = c.Continue()
   817  		state = <-ch
   818  		if !state.Exited {
   819  			t.Fatalf("Target did not terminate after second continue")
   820  		}
   821  
   822  		ch = c.Continue()
   823  		state = <-ch
   824  		assertError(state.Err, t, "Continue()")
   825  
   826  		s, err := c.Next()
   827  		assertErrorOrExited(s, err, t, "Next()")
   828  		s, err = c.Step()
   829  		assertErrorOrExited(s, err, t, "Step()")
   830  		s, err = c.StepInstruction()
   831  		assertErrorOrExited(s, err, t, "StepInstruction()")
   832  		s, err = c.SwitchThread(tid)
   833  		assertErrorOrExited(s, err, t, "SwitchThread()")
   834  		s, err = c.SwitchGoroutine(gid)
   835  		assertErrorOrExited(s, err, t, "SwitchGoroutine()")
   836  		s, err = c.Halt()
   837  		assertErrorOrExited(s, err, t, "Halt()")
   838  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: -1})
   839  		assertError(err, t, "CreateBreakpoint()")
   840  		_, err = c.ClearBreakpoint(bp.ID)
   841  		assertError(err, t, "ClearBreakpoint()")
   842  		_, err = c.ListThreads()
   843  		assertError(err, t, "ListThreads()")
   844  		_, err = c.GetThread(tid)
   845  		assertError(err, t, "GetThread()")
   846  		assertError(c.SetVariable(api.EvalScope{GoroutineID: gid}, "a", "10"), t, "SetVariable()")
   847  		_, err = c.ListLocalVariables(api.EvalScope{GoroutineID: gid})
   848  		assertError(err, t, "ListLocalVariables()")
   849  		_, err = c.ListFunctionArgs(api.EvalScope{GoroutineID: gid})
   850  		assertError(err, t, "ListFunctionArgs()")
   851  		_, err = c.ListRegisters()
   852  		assertError(err, t, "ListRegisters()")
   853  		_, err = c.ListGoroutines()
   854  		assertError(err, t, "ListGoroutines()")
   855  		_, err = c.Stacktrace(gid, 10, false)
   856  		assertError(err, t, "Stacktrace()")
   857  		_, err = c.FindLocation(api.EvalScope{GoroutineID: gid}, "+1")
   858  		assertError(err, t, "FindLocation()")
   859  		_, err = c.DisassemblePC(api.EvalScope{GoroutineID: -1}, 0x40100, api.IntelFlavour)
   860  		assertError(err, t, "DisassemblePC()")
   861  	})
   862  }
   863  
   864  func Test1Disasm(t *testing.T) {
   865  	// Tests that disassembling by PC, range, and current PC all yeld similar results
   866  	// Tests that disassembly by current PC will return a disassembly containing the instruction at PC
   867  	// Tests that stepping on a calculated CALL instruction will yield a disassembly that contains the
   868  	// effective destination of the CALL instruction
   869  	withTestClient1("locationsprog2", t, func(c *rpc1.RPCClient) {
   870  		ch := c.Continue()
   871  		state := <-ch
   872  		assertNoError(state.Err, t, "Continue()")
   873  
   874  		locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "main.main")
   875  		assertNoError(err, t, "FindLocation()")
   876  		if len(locs) != 1 {
   877  			t.Fatalf("wrong number of locations for main.main: %d", len(locs))
   878  		}
   879  		d1, err := c.DisassemblePC(api.EvalScope{GoroutineID: -1}, locs[0].PC, api.IntelFlavour)
   880  		assertNoError(err, t, "DisassemblePC()")
   881  		if len(d1) < 2 {
   882  			t.Fatalf("wrong size of disassembly: %d", len(d1))
   883  		}
   884  
   885  		pcstart := d1[0].Loc.PC
   886  		pcend := d1[len(d1)-1].Loc.PC + uint64(len(d1[len(d1)-1].Bytes))
   887  		d2, err := c.DisassembleRange(api.EvalScope{GoroutineID: -1}, pcstart, pcend, api.IntelFlavour)
   888  		assertNoError(err, t, "DisassembleRange()")
   889  
   890  		if len(d1) != len(d2) {
   891  			t.Logf("d1: %v", d1)
   892  			t.Logf("d2: %v", d2)
   893  			t.Fatal("mismatched length between disassemble pc and disassemble range")
   894  		}
   895  
   896  		d3, err := c.DisassemblePC(api.EvalScope{GoroutineID: -1}, state.CurrentThread.PC, api.IntelFlavour)
   897  		assertNoError(err, t, "DisassemblePC() - second call")
   898  
   899  		if len(d1) != len(d3) {
   900  			t.Logf("d1: %v", d1)
   901  			t.Logf("d3: %v", d3)
   902  			t.Fatal("mismatched length between the two calls of disassemble pc")
   903  		}
   904  
   905  		// look for static call to afunction() on line 29
   906  		found := false
   907  		for i := range d3 {
   908  			if d3[i].Loc.Line == 29 && (strings.HasPrefix(d3[i].Text, "call") || strings.HasPrefix(d3[i].Text, "CALL")) && d3[i].DestLoc != nil && d3[i].DestLoc.Function != nil && d3[i].DestLoc.Function.Name() == "main.afunction" {
   909  				found = true
   910  				break
   911  			}
   912  		}
   913  		if !found {
   914  			t.Fatal("Could not find call to main.afunction on line 29")
   915  		}
   916  
   917  		haspc := false
   918  		for i := range d3 {
   919  			if d3[i].AtPC {
   920  				haspc = true
   921  				break
   922  			}
   923  		}
   924  
   925  		if !haspc {
   926  			t.Logf("d3: %v", d3)
   927  			t.Fatal("PC instruction not found")
   928  		}
   929  
   930  		if runtime.GOARCH == "386" && buildMode == "pie" {
   931  			// Skip the rest of the test because on intel 386 with PIE build mode
   932  			// the compiler will insert calls to __x86.get_pc_thunk which do not have DIEs and we can't resolve.
   933  			return
   934  		}
   935  
   936  		startinstr := getCurinstr(d3)
   937  		count := 0
   938  		for {
   939  			if count > 20 {
   940  				t.Fatal("too many step instructions executed without finding a call instruction")
   941  			}
   942  			state, err := c.StepInstruction()
   943  			assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
   944  
   945  			d3, err = c.DisassemblePC(api.EvalScope{GoroutineID: -1}, state.CurrentThread.PC, api.IntelFlavour)
   946  			assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
   947  
   948  			curinstr := getCurinstr(d3)
   949  
   950  			if curinstr == nil {
   951  				t.Fatalf("Could not find current instruction %d", count)
   952  			}
   953  
   954  			if curinstr.Loc.Line != startinstr.Loc.Line {
   955  				t.Fatal("Calling StepInstruction() repeatedly did not find the call instruction")
   956  			}
   957  
   958  			if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") {
   959  				t.Logf("call: %v", curinstr)
   960  				if curinstr.DestLoc == nil || curinstr.DestLoc.Function == nil {
   961  					t.Fatalf("Call instruction does not have destination: %v", curinstr)
   962  				}
   963  				if curinstr.DestLoc.Function.Name() != "main.afunction" {
   964  					t.Fatalf("Call instruction destination not main.afunction: %v", curinstr)
   965  				}
   966  				break
   967  			}
   968  
   969  			count++
   970  		}
   971  	})
   972  }
   973  
   974  func Test1NegativeStackDepthBug(t *testing.T) {
   975  	// After the target process has terminated should return an error but not crash
   976  	withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) {
   977  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1})
   978  		assertNoError(err, t, "CreateBreakpoint()")
   979  		ch := c.Continue()
   980  		state := <-ch
   981  		assertNoError(state.Err, t, "Continue()")
   982  		_, err = c.Stacktrace(-1, -2, true)
   983  		assertError(err, t, "Stacktrace()")
   984  	})
   985  }
   986  
   987  func Test1ClientServer_CondBreakpoint(t *testing.T) {
   988  	if runtime.GOOS == "freebsd" {
   989  		t.Skip("test is not valid on FreeBSD")
   990  	}
   991  	withTestClient1("parallel_next", t, func(c *rpc1.RPCClient) {
   992  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: 1})
   993  		assertNoError(err, t, "CreateBreakpoint()")
   994  		bp.Cond = "n == 7"
   995  		assertNoError(c.AmendBreakpoint(bp), t, "AmendBreakpoint() 1")
   996  		bp, err = c.GetBreakpoint(bp.ID)
   997  		assertNoError(err, t, "GetBreakpoint() 1")
   998  		bp.Variables = append(bp.Variables, "n")
   999  		assertNoError(c.AmendBreakpoint(bp), t, "AmendBreakpoint() 2")
  1000  		bp, err = c.GetBreakpoint(bp.ID)
  1001  		assertNoError(err, t, "GetBreakpoint() 2")
  1002  		if bp.Cond == "" {
  1003  			t.Fatalf("No condition set on breakpoint %#v", bp)
  1004  		}
  1005  		if len(bp.Variables) != 1 {
  1006  			t.Fatalf("Wrong number of expressions to evaluate on breakpoint %#v", bp)
  1007  		}
  1008  		state := <-c.Continue()
  1009  		assertNoError(state.Err, t, "Continue()")
  1010  
  1011  		nvar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "n")
  1012  		assertNoError(err, t, "EvalVariable()")
  1013  
  1014  		if nvar.SinglelineString() != "7" {
  1015  			t.Fatalf("Stopped on wrong goroutine %s\n", nvar.Value)
  1016  		}
  1017  	})
  1018  }
  1019  
  1020  func Test1Issue419(t *testing.T) {
  1021  	// Calling service/rpc.(*Client).Halt could cause a crash because both Halt and Continue simultaneously
  1022  	// try to read 'runtime.g' and debug/dwarf.Data.Type is not thread safe
  1023  	withTestClient1("issue419", t, func(c *rpc1.RPCClient) {
  1024  		go func() {
  1025  			rand.Seed(time.Now().Unix())
  1026  			d := time.Duration(rand.Intn(4) + 1)
  1027  			time.Sleep(d * time.Second)
  1028  			_, err := c.Halt()
  1029  			assertNoError(err, t, "RequestManualStop()")
  1030  		}()
  1031  		statech := c.Continue()
  1032  		state := <-statech
  1033  		assertNoError(state.Err, t, "Continue()")
  1034  	})
  1035  }
  1036  
  1037  func Test1TypesCommand(t *testing.T) {
  1038  	withTestClient1("testvariables2", t, func(c *rpc1.RPCClient) {
  1039  		state := <-c.Continue()
  1040  		assertNoError(state.Err, t, "Continue()")
  1041  		types, err := c.ListTypes("")
  1042  		assertNoError(err, t, "ListTypes()")
  1043  
  1044  		found := false
  1045  		for i := range types {
  1046  			if types[i] == "main.astruct" {
  1047  				found = true
  1048  				break
  1049  			}
  1050  		}
  1051  		if !found {
  1052  			t.Fatal("Type astruct not found in ListTypes output")
  1053  		}
  1054  
  1055  		types, err = c.ListTypes("^main.astruct$")
  1056  		assertNoError(err, t, "ListTypes(\"main.astruct\")")
  1057  		if len(types) != 1 {
  1058  			t.Fatalf("ListTypes(\"^main.astruct$\") did not filter properly, expected 1 got %d: %v", len(types), types)
  1059  		}
  1060  	})
  1061  }
  1062  
  1063  func Test1Issue406(t *testing.T) {
  1064  	withTestClient1("issue406", t, func(c *rpc1.RPCClient) {
  1065  		locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "issue406.go:146")
  1066  		assertNoError(err, t, "FindLocation()")
  1067  		_, err = c.CreateBreakpoint(&api.Breakpoint{Addr: locs[0].PC})
  1068  		assertNoError(err, t, "CreateBreakpoint()")
  1069  		ch := c.Continue()
  1070  		state := <-ch
  1071  		assertNoError(state.Err, t, "Continue()")
  1072  		v, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "cfgtree")
  1073  		assertNoError(err, t, "EvalVariable()")
  1074  		vs := v.MultilineString("", "")
  1075  		t.Logf("cfgtree formats to: %s\n", vs)
  1076  	})
  1077  }