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

     1  package service_test
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"net"
     9  	"net/rpc"
    10  	"net/rpc/jsonrpc"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"reflect"
    15  	"runtime"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	protest "github.com/go-delve/delve/pkg/proc/test"
    22  	"github.com/go-delve/delve/service/debugger"
    23  
    24  	"github.com/go-delve/delve/pkg/goversion"
    25  	"github.com/go-delve/delve/pkg/logflags"
    26  	"github.com/go-delve/delve/service"
    27  	"github.com/go-delve/delve/service/api"
    28  	"github.com/go-delve/delve/service/rpc2"
    29  	"github.com/go-delve/delve/service/rpccommon"
    30  )
    31  
    32  var normalLoadConfig = api.LoadConfig{
    33  	FollowPointers:     true,
    34  	MaxVariableRecurse: 1,
    35  	MaxStringLen:       64,
    36  	MaxArrayValues:     64,
    37  	MaxStructFields:    -1,
    38  }
    39  
    40  var testBackend, buildMode string
    41  
    42  func TestMain(m *testing.M) {
    43  	flag.StringVar(&testBackend, "backend", "", "selects backend")
    44  	flag.StringVar(&buildMode, "test-buildmode", "", "selects build mode")
    45  	var logOutput string
    46  	flag.StringVar(&logOutput, "log-output", "", "configures log output")
    47  	flag.Parse()
    48  	protest.DefaultTestBackend(&testBackend)
    49  	if buildMode != "" && buildMode != "pie" {
    50  		fmt.Fprintf(os.Stderr, "unknown build mode %q", buildMode)
    51  		os.Exit(1)
    52  	}
    53  	logflags.Setup(logOutput != "", logOutput, "")
    54  	os.Exit(protest.RunTestsWithFixtures(m))
    55  }
    56  
    57  func withTestClient2(name string, t *testing.T, fn func(c service.Client)) {
    58  	withTestClient2Extended(name, t, 0, [3]string{}, func(c service.Client, fixture protest.Fixture) {
    59  		fn(c)
    60  	})
    61  }
    62  
    63  func startServer(name string, buildFlags protest.BuildFlags, t *testing.T, redirects [3]string) (clientConn net.Conn, fixture protest.Fixture) {
    64  	if testBackend == "rr" {
    65  		protest.MustHaveRecordingAllowed(t)
    66  	}
    67  	listener, clientConn := service.ListenerPipe()
    68  	defer listener.Close()
    69  	if buildMode == "pie" {
    70  		buildFlags |= protest.BuildModePIE
    71  	}
    72  	fixture = protest.BuildFixture(name, buildFlags)
    73  	for i := range redirects {
    74  		if redirects[i] != "" {
    75  			redirects[i] = filepath.Join(fixture.BuildDir, redirects[i])
    76  		}
    77  	}
    78  	server := rpccommon.NewServer(&service.Config{
    79  		Listener:    listener,
    80  		ProcessArgs: []string{fixture.Path},
    81  		Debugger: debugger.Config{
    82  			Backend:        testBackend,
    83  			CheckGoVersion: true,
    84  			Packages:       []string{fixture.Source},
    85  			BuildFlags:     "", // build flags can be an empty string here because the only test that uses it, does not set special flags.
    86  			ExecuteKind:    debugger.ExecutingGeneratedFile,
    87  			Redirects:      redirects,
    88  		},
    89  	})
    90  	if err := server.Run(); err != nil {
    91  		t.Fatal(err)
    92  	}
    93  	return clientConn, fixture
    94  }
    95  
    96  func withTestClient2Extended(name string, t *testing.T, buildFlags protest.BuildFlags, redirects [3]string, fn func(c service.Client, fixture protest.Fixture)) {
    97  	clientConn, fixture := startServer(name, buildFlags, t, redirects)
    98  	client := rpc2.NewClientFromConn(clientConn)
    99  	defer func() {
   100  		client.Detach(true)
   101  	}()
   102  
   103  	fn(client, fixture)
   104  }
   105  
   106  func TestRunWithInvalidPath(t *testing.T) {
   107  	if testBackend == "rr" {
   108  		// This test won't work because rr returns an error, after recording, when
   109  		// the recording failed but also when the recording succeeded but the
   110  		// inferior returned an error. Therefore we have to ignore errors from rr.
   111  		return
   112  	}
   113  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   114  	if err != nil {
   115  		t.Fatalf("couldn't start listener: %s\n", err)
   116  	}
   117  	defer listener.Close()
   118  	server := rpccommon.NewServer(&service.Config{
   119  		Listener:    listener,
   120  		ProcessArgs: []string{"invalid_path"},
   121  		APIVersion:  2,
   122  		Debugger: debugger.Config{
   123  			Backend:     testBackend,
   124  			ExecuteKind: debugger.ExecutingGeneratedFile,
   125  		},
   126  	})
   127  	if err := server.Run(); err == nil {
   128  		t.Fatal("Expected Run to return error for invalid program path")
   129  	}
   130  }
   131  
   132  func TestRestart_afterExit(t *testing.T) {
   133  	withTestClient2("continuetestprog", t, func(c service.Client) {
   134  		origPid := c.ProcessPid()
   135  		state := <-c.Continue()
   136  		if !state.Exited {
   137  			t.Fatal("expected initial process to have exited")
   138  		}
   139  		if _, err := c.Restart(false); err != nil {
   140  			t.Fatal(err)
   141  		}
   142  		if c.ProcessPid() == origPid {
   143  			t.Fatal("did not spawn new process, has same PID")
   144  		}
   145  		state = <-c.Continue()
   146  		if !state.Exited {
   147  			t.Fatalf("expected restarted process to have exited %v", state)
   148  		}
   149  	})
   150  }
   151  
   152  func TestRestart_breakpointPreservation(t *testing.T) {
   153  	protest.AllowRecording(t)
   154  	withTestClient2("continuetestprog", t, func(c service.Client) {
   155  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint", Tracepoint: true})
   156  		assertNoError(err, t, "CreateBreakpoint()")
   157  		stateCh := c.Continue()
   158  
   159  		state := <-stateCh
   160  		if state.CurrentThread.Breakpoint.Name != "firstbreakpoint" || !state.CurrentThread.Breakpoint.Tracepoint {
   161  			t.Fatalf("Wrong breakpoint: %#v\n", state.CurrentThread.Breakpoint)
   162  		}
   163  		state = <-stateCh
   164  		if !state.Exited {
   165  			t.Fatal("Did not exit after first tracepoint")
   166  		}
   167  
   168  		t.Log("Restart")
   169  		c.Restart(false)
   170  		stateCh = c.Continue()
   171  		state = <-stateCh
   172  		if state.CurrentThread.Breakpoint.Name != "firstbreakpoint" || !state.CurrentThread.Breakpoint.Tracepoint {
   173  			t.Fatalf("Wrong breakpoint (after restart): %#v\n", state.CurrentThread.Breakpoint)
   174  		}
   175  		state = <-stateCh
   176  		if !state.Exited {
   177  			t.Fatal("Did not exit after first tracepoint (after restart)")
   178  		}
   179  	})
   180  }
   181  
   182  func TestRestart_duringStop(t *testing.T) {
   183  	withTestClient2("continuetestprog", t, func(c service.Client) {
   184  		origPid := c.ProcessPid()
   185  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1})
   186  		if err != nil {
   187  			t.Fatal(err)
   188  		}
   189  		state := <-c.Continue()
   190  		if state.CurrentThread.Breakpoint == nil {
   191  			t.Fatal("did not hit breakpoint")
   192  		}
   193  		if _, err := c.Restart(false); err != nil {
   194  			t.Fatal(err)
   195  		}
   196  		if c.ProcessPid() == origPid {
   197  			t.Fatal("did not spawn new process, has same PID")
   198  		}
   199  		bps, err := c.ListBreakpoints(false)
   200  		if err != nil {
   201  			t.Fatal(err)
   202  		}
   203  		if len(bps) == 0 {
   204  			t.Fatal("breakpoints not preserved")
   205  		}
   206  	})
   207  }
   208  
   209  // This source is a slightly modified version of
   210  // _fixtures/testenv.go. The only difference is that
   211  // the name of the environment variable we are trying to
   212  // read is named differently, so we can assert the code
   213  // was actually changed in the test.
   214  const modifiedSource = `package main
   215  
   216  import (
   217  	"fmt"
   218  	"os"
   219  	"runtime"
   220  )
   221  
   222  func main() {
   223  	x := os.Getenv("SOMEMODIFIEDVAR")
   224  	runtime.Breakpoint()
   225  	fmt.Printf("SOMEMODIFIEDVAR=%s\n", x)
   226  }
   227  `
   228  
   229  func TestRestart_rebuild(t *testing.T) {
   230  	// In the original fixture file the env var tested for is SOMEVAR.
   231  	os.Setenv("SOMEVAR", "bah")
   232  
   233  	withTestClient2Extended("testenv", t, 0, [3]string{}, func(c service.Client, f protest.Fixture) {
   234  		<-c.Continue()
   235  
   236  		var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "x", normalLoadConfig)
   237  		assertNoError(err, t, "EvalVariable")
   238  
   239  		if var1.Value != "bah" {
   240  			t.Fatalf("expected 'bah' got %q", var1.Value)
   241  		}
   242  
   243  		fi, err := os.Stat(f.Source)
   244  		assertNoError(err, t, "Stat fixture.Source")
   245  
   246  		originalSource, err := ioutil.ReadFile(f.Source)
   247  		assertNoError(err, t, "Reading original source")
   248  
   249  		// Ensure we write the original source code back after the test exits.
   250  		defer ioutil.WriteFile(f.Source, originalSource, fi.Mode())
   251  
   252  		// Write modified source code to the fixture file.
   253  		err = ioutil.WriteFile(f.Source, []byte(modifiedSource), fi.Mode())
   254  		assertNoError(err, t, "Writing modified source")
   255  
   256  		// First set our new env var and ensure later that the
   257  		// modified source code picks it up.
   258  		os.Setenv("SOMEMODIFIEDVAR", "foobar")
   259  
   260  		// Restart the program, rebuilding from source.
   261  		_, err = c.Restart(true)
   262  		assertNoError(err, t, "Restart(true)")
   263  
   264  		<-c.Continue()
   265  
   266  		var1, err = c.EvalVariable(api.EvalScope{GoroutineID: -1}, "x", normalLoadConfig)
   267  		assertNoError(err, t, "EvalVariable")
   268  
   269  		if var1.Value != "foobar" {
   270  			t.Fatalf("expected 'foobar' got %q", var1.Value)
   271  		}
   272  	})
   273  }
   274  
   275  func TestClientServer_exit(t *testing.T) {
   276  	protest.AllowRecording(t)
   277  	withTestClient2("continuetestprog", t, func(c service.Client) {
   278  		state, err := c.GetState()
   279  		if err != nil {
   280  			t.Fatalf("Unexpected error: %v", err)
   281  		}
   282  		if e, a := false, state.Exited; e != a {
   283  			t.Fatalf("Expected exited %v, got %v", e, a)
   284  		}
   285  		state = <-c.Continue()
   286  		if state.Err == nil {
   287  			t.Fatalf("Error expected after continue")
   288  		}
   289  		if !state.Exited {
   290  			t.Fatalf("Expected exit after continue: %v", state)
   291  		}
   292  		_, err = c.GetState()
   293  		if err == nil {
   294  			t.Fatal("Expected error on querying state from exited process")
   295  		}
   296  	})
   297  }
   298  
   299  func TestClientServer_step(t *testing.T) {
   300  	protest.AllowRecording(t)
   301  	withTestClient2("testprog", t, func(c service.Client) {
   302  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: -1})
   303  		if err != nil {
   304  			t.Fatalf("Unexpected error: %v", err)
   305  		}
   306  
   307  		stateBefore := <-c.Continue()
   308  		if stateBefore.Err != nil {
   309  			t.Fatalf("Unexpected error: %v", stateBefore.Err)
   310  		}
   311  
   312  		stateAfter, err := c.Step()
   313  		if err != nil {
   314  			t.Fatalf("Unexpected error: %v", err)
   315  		}
   316  
   317  		if before, after := stateBefore.CurrentThread.PC, stateAfter.CurrentThread.PC; before >= after {
   318  			t.Fatalf("Expected %#v to be greater than %#v", after, before)
   319  		}
   320  	})
   321  }
   322  
   323  func TestClientServer_stepout(t *testing.T) {
   324  	protest.AllowRecording(t)
   325  	withTestClient2("testnextprog", t, func(c service.Client) {
   326  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: -1})
   327  		assertNoError(err, t, "CreateBreakpoint()")
   328  		stateBefore := <-c.Continue()
   329  		assertNoError(stateBefore.Err, t, "Continue()")
   330  		if stateBefore.CurrentThread.Line != 13 {
   331  			t.Fatalf("wrong line number %s:%d, expected %d", stateBefore.CurrentThread.File, stateBefore.CurrentThread.Line, 13)
   332  		}
   333  		stateAfter, err := c.StepOut()
   334  		assertNoError(err, t, "StepOut()")
   335  		if stateAfter.CurrentThread.Line != 35 {
   336  			t.Fatalf("wrong line number %s:%d, expected %d", stateAfter.CurrentThread.File, stateAfter.CurrentThread.Line, 13)
   337  		}
   338  	})
   339  }
   340  
   341  func testnext2(testcases []nextTest, initialLocation string, t *testing.T) {
   342  	protest.AllowRecording(t)
   343  	withTestClient2("testnextprog", t, func(c service.Client) {
   344  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: initialLocation, Line: -1})
   345  		if err != nil {
   346  			t.Fatalf("Unexpected error: %v", err)
   347  		}
   348  
   349  		state := <-c.Continue()
   350  		if state.Err != nil {
   351  			t.Fatalf("Unexpected error: %v", state.Err)
   352  		}
   353  
   354  		_, err = c.ClearBreakpoint(bp.ID)
   355  		if err != nil {
   356  			t.Fatalf("Unexpected error: %v", err)
   357  		}
   358  
   359  		for _, tc := range testcases {
   360  			if state.CurrentThread.Line != tc.begin {
   361  				t.Fatalf("Program not stopped at correct spot expected %d was %d", tc.begin, state.CurrentThread.Line)
   362  			}
   363  
   364  			t.Logf("Next for scenario %#v", tc)
   365  			state, err = c.Next()
   366  			if err != nil {
   367  				t.Fatalf("Unexpected error: %v", err)
   368  			}
   369  
   370  			if state.CurrentThread.Line != tc.end {
   371  				t.Fatalf("Program did not continue to correct next location expected %d was %d", tc.end, state.CurrentThread.Line)
   372  			}
   373  		}
   374  	})
   375  }
   376  
   377  func TestNextGeneral(t *testing.T) {
   378  	var testcases []nextTest
   379  
   380  	ver, _ := goversion.Parse(runtime.Version())
   381  
   382  	if ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
   383  		testcases = []nextTest{
   384  			{17, 19},
   385  			{19, 20},
   386  			{20, 23},
   387  			{23, 24},
   388  			{24, 26},
   389  			{26, 31},
   390  			{31, 23},
   391  			{23, 24},
   392  			{24, 26},
   393  			{26, 31},
   394  			{31, 23},
   395  			{23, 24},
   396  			{24, 26},
   397  			{26, 27},
   398  			{27, 28},
   399  			{28, 34},
   400  		}
   401  	} else {
   402  		testcases = []nextTest{
   403  			{17, 19},
   404  			{19, 20},
   405  			{20, 23},
   406  			{23, 24},
   407  			{24, 26},
   408  			{26, 31},
   409  			{31, 23},
   410  			{23, 24},
   411  			{24, 26},
   412  			{26, 31},
   413  			{31, 23},
   414  			{23, 24},
   415  			{24, 26},
   416  			{26, 27},
   417  			{27, 34},
   418  		}
   419  	}
   420  
   421  	testnext2(testcases, "main.testnext", t)
   422  }
   423  
   424  func TestNextFunctionReturn(t *testing.T) {
   425  	testcases := []nextTest{
   426  		{13, 14},
   427  		{14, 15},
   428  		{15, 35},
   429  	}
   430  	testnext2(testcases, "main.helloworld", t)
   431  }
   432  
   433  func TestClientServer_breakpointInMainThread(t *testing.T) {
   434  	protest.AllowRecording(t)
   435  	withTestClient2("testprog", t, func(c service.Client) {
   436  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: 1})
   437  		if err != nil {
   438  			t.Fatalf("Unexpected error: %v", err)
   439  		}
   440  
   441  		state := <-c.Continue()
   442  		if state.Err != nil {
   443  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   444  		}
   445  
   446  		pc := state.CurrentThread.PC
   447  
   448  		if pc-1 != bp.Addr && pc != bp.Addr {
   449  			f, l := state.CurrentThread.File, state.CurrentThread.Line
   450  			t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
   451  		}
   452  	})
   453  }
   454  
   455  func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) {
   456  	protest.AllowRecording(t)
   457  	withTestClient2("testthreads", t, func(c service.Client) {
   458  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.anotherthread", Line: 1})
   459  		if err != nil {
   460  			t.Fatalf("Unexpected error: %v", err)
   461  		}
   462  
   463  		state := <-c.Continue()
   464  		if state.Err != nil {
   465  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   466  		}
   467  
   468  		f, l := state.CurrentThread.File, state.CurrentThread.Line
   469  		if f != "testthreads.go" && l != 9 {
   470  			t.Fatal("Program did not hit breakpoint")
   471  		}
   472  	})
   473  }
   474  
   475  func TestClientServer_breakAtNonexistentPoint(t *testing.T) {
   476  	withTestClient2("testprog", t, func(c service.Client) {
   477  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "nowhere", Line: 1})
   478  		if err == nil {
   479  			t.Fatal("Should not be able to break at non existent function")
   480  		}
   481  	})
   482  }
   483  
   484  func TestClientServer_clearBreakpoint(t *testing.T) {
   485  	withTestClient2("testprog", t, func(c service.Client) {
   486  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sleepytime", Line: 1})
   487  		if err != nil {
   488  			t.Fatalf("Unexpected error: %v", err)
   489  		}
   490  
   491  		if e, a := 1, countBreakpoints(t, c); e != a {
   492  			t.Fatalf("Expected breakpoint count %d, got %d", e, a)
   493  		}
   494  
   495  		deleted, err := c.ClearBreakpoint(bp.ID)
   496  		if err != nil {
   497  			t.Fatalf("Unexpected error: %v", err)
   498  		}
   499  
   500  		if deleted.ID != bp.ID {
   501  			t.Fatalf("Expected deleted breakpoint ID %v, got %v", bp.ID, deleted.ID)
   502  		}
   503  
   504  		if e, a := 0, countBreakpoints(t, c); e != a {
   505  			t.Fatalf("Expected breakpoint count %d, got %d", e, a)
   506  		}
   507  	})
   508  }
   509  
   510  func TestClientServer_toggleBreakpoint(t *testing.T) {
   511  	withTestClient2("testtoggle", t, func(c service.Client) {
   512  		toggle := func(bp *api.Breakpoint) {
   513  			t.Helper()
   514  			dbp, err := c.ToggleBreakpoint(bp.ID)
   515  			if err != nil {
   516  				t.Fatalf("Unexpected error: %v", err)
   517  			}
   518  			if dbp.ID != bp.ID {
   519  				t.Fatalf("The IDs don't match")
   520  			}
   521  		}
   522  
   523  		// This one is toggled twice
   524  		bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.lineOne", Tracepoint: true})
   525  		if err != nil {
   526  			t.Fatalf("Unexpected error: %v\n", err)
   527  		}
   528  
   529  		toggle(bp1)
   530  		toggle(bp1)
   531  
   532  		// This one is toggled once
   533  		bp2, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.lineTwo", Tracepoint: true})
   534  		if err != nil {
   535  			t.Fatalf("Unexpected error: %v\n", err)
   536  		}
   537  
   538  		toggle(bp2)
   539  
   540  		// This one is never toggled
   541  		bp3, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.lineThree", Tracepoint: true})
   542  		if err != nil {
   543  			t.Fatalf("Unexpected error: %v\n", err)
   544  		}
   545  
   546  		if e, a := 3, countBreakpoints(t, c); e != a {
   547  			t.Fatalf("Expected breakpoint count %d, got %d", e, a)
   548  		}
   549  
   550  		enableCount := 0
   551  		disabledCount := 0
   552  
   553  		contChan := c.Continue()
   554  		for state := range contChan {
   555  			if state.CurrentThread != nil && state.CurrentThread.Breakpoint != nil {
   556  				switch state.CurrentThread.Breakpoint.ID {
   557  				case bp1.ID, bp3.ID:
   558  					enableCount++
   559  				case bp2.ID:
   560  					disabledCount++
   561  				}
   562  
   563  				t.Logf("%v", state)
   564  			}
   565  			if state.Exited {
   566  				continue
   567  			}
   568  			if state.Err != nil {
   569  				t.Fatalf("Unexpected error during continue: %v\n", state.Err)
   570  			}
   571  		}
   572  
   573  		if enableCount != 2 {
   574  			t.Fatalf("Wrong number of enabled hits: %d\n", enableCount)
   575  		}
   576  
   577  		if disabledCount != 0 {
   578  			t.Fatalf("A disabled breakpoint was hit: %d\n", disabledCount)
   579  		}
   580  	})
   581  }
   582  
   583  func TestClientServer_toggleAmendedBreakpoint(t *testing.T) {
   584  	withTestClient2("testtoggle", t, func(c service.Client) {
   585  		toggle := func(bp *api.Breakpoint) {
   586  			dbp, err := c.ToggleBreakpoint(bp.ID)
   587  			if err != nil {
   588  				t.Fatalf("Unexpected error: %v", err)
   589  			}
   590  			if dbp.ID != bp.ID {
   591  				t.Fatalf("The IDs don't match")
   592  			}
   593  		}
   594  
   595  		// This one is toggled twice
   596  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.lineOne", Tracepoint: true})
   597  		if err != nil {
   598  			t.Fatalf("Unexpected error: %v\n", err)
   599  		}
   600  		bp.Cond = "n == 7"
   601  		assertNoError(c.AmendBreakpoint(bp), t, "AmendBreakpoint() 1")
   602  
   603  		// Toggle off.
   604  		toggle(bp)
   605  		// Toggle on.
   606  		toggle(bp)
   607  
   608  		amended, err := c.GetBreakpoint(bp.ID)
   609  		if err != nil {
   610  			t.Fatal(err)
   611  		}
   612  		if amended.Cond == "" {
   613  			t.Fatal("breakpoint amendedments not preserved after toggle")
   614  		}
   615  	})
   616  }
   617  
   618  func TestClientServer_disableHitCondLSSBreakpoint(t *testing.T) {
   619  	withTestClient2("break", t, func(c service.Client) {
   620  		fp := testProgPath(t, "break")
   621  		hitCondBp, err := c.CreateBreakpoint(&api.Breakpoint{
   622  			File:    fp,
   623  			Line:    7,
   624  			HitCond: "< 3",
   625  		})
   626  		if err != nil {
   627  			t.Fatalf("Unexpected error: %v", err)
   628  		}
   629  
   630  		state := <-c.Continue()
   631  		if state.Err != nil {
   632  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   633  		}
   634  
   635  		f, l := state.CurrentThread.File, state.CurrentThread.Line
   636  		if f != "break.go" && l != 7 {
   637  			t.Fatal("Program did not hit breakpoint")
   638  		}
   639  
   640  		ivar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
   641  		assertNoError(err, t, "EvalVariable")
   642  
   643  		t.Logf("ivar: %s", ivar.SinglelineString())
   644  
   645  		if ivar.Value != "1" {
   646  			t.Fatalf("Wrong variable value: %s", ivar.Value)
   647  		}
   648  
   649  		bp, err := c.GetBreakpoint(hitCondBp.ID)
   650  		assertNoError(err, t, "GetBreakpoint()")
   651  
   652  		if bp.Disabled {
   653  			t.Fatalf(
   654  				"Hit condition %s is still satisfiable but breakpoint has been disabled",
   655  				bp.HitCond,
   656  			)
   657  		}
   658  
   659  		state = <-c.Continue()
   660  		if state.Err != nil {
   661  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   662  		}
   663  
   664  		f, l = state.CurrentThread.File, state.CurrentThread.Line
   665  		if f != "break.go" && l != 7 {
   666  			t.Fatal("Program did not hit breakpoint")
   667  		}
   668  
   669  		ivar, err = c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
   670  		assertNoError(err, t, "EvalVariable")
   671  
   672  		t.Logf("ivar: %s", ivar.SinglelineString())
   673  
   674  		if ivar.Value != "2" {
   675  			t.Fatalf("Wrong variable value: %s", ivar.Value)
   676  		}
   677  
   678  		bp, err = c.GetBreakpoint(hitCondBp.ID)
   679  		assertNoError(err, t, "GetBreakpoint()")
   680  
   681  		if !bp.Disabled {
   682  			t.Fatalf(
   683  				"Hit condition %s is no more satisfiable but breakpoint has not been disabled",
   684  				bp.HitCond,
   685  			)
   686  		}
   687  	})
   688  }
   689  
   690  func TestClientServer_disableHitEQLCondBreakpoint(t *testing.T) {
   691  	withTestClient2("break", t, func(c service.Client) {
   692  		fp := testProgPath(t, "break")
   693  		hitCondBp, err := c.CreateBreakpoint(&api.Breakpoint{
   694  			File:    fp,
   695  			Line:    7,
   696  			HitCond: "== 3",
   697  		})
   698  		if err != nil {
   699  			t.Fatalf("Unexpected error: %v", err)
   700  		}
   701  
   702  		state := <-c.Continue()
   703  		if state.Err != nil {
   704  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   705  		}
   706  
   707  		f, l := state.CurrentThread.File, state.CurrentThread.Line
   708  		if f != "break.go" && l != 7 {
   709  			t.Fatal("Program did not hit breakpoint")
   710  		}
   711  
   712  		ivar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
   713  		assertNoError(err, t, "EvalVariable")
   714  
   715  		t.Logf("ivar: %s", ivar.SinglelineString())
   716  
   717  		if ivar.Value != "3" {
   718  			t.Fatalf("Wrong variable value: %s", ivar.Value)
   719  		}
   720  
   721  		bp, err := c.GetBreakpoint(hitCondBp.ID)
   722  		assertNoError(err, t, "GetBreakpoint()")
   723  
   724  		if !bp.Disabled {
   725  			t.Fatalf(
   726  				"Hit condition %s is no more satisfiable but breakpoint has not been disabled",
   727  				bp.HitCond,
   728  			)
   729  		}
   730  	})
   731  }
   732  
   733  func TestClientServer_switchThread(t *testing.T) {
   734  	protest.AllowRecording(t)
   735  	withTestClient2("testnextprog", t, func(c service.Client) {
   736  		// With invalid thread id
   737  		_, err := c.SwitchThread(-1)
   738  		if err == nil {
   739  			t.Fatal("Expected error for invalid thread id")
   740  		}
   741  
   742  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1})
   743  		if err != nil {
   744  			t.Fatalf("Unexpected error: %v", err)
   745  		}
   746  		state := <-c.Continue()
   747  		if state.Err != nil {
   748  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   749  		}
   750  
   751  		var nt int
   752  		ct := state.CurrentThread.ID
   753  		threads, err := c.ListThreads()
   754  		if err != nil {
   755  			t.Fatalf("Unexpected error: %v", err)
   756  		}
   757  		for _, th := range threads {
   758  			if th.ID != ct {
   759  				nt = th.ID
   760  				break
   761  			}
   762  		}
   763  		if nt == 0 {
   764  			t.Fatal("could not find thread to switch to")
   765  		}
   766  		// With valid thread id
   767  		state, err = c.SwitchThread(nt)
   768  		if err != nil {
   769  			t.Fatal(err)
   770  		}
   771  		if state.CurrentThread.ID != nt {
   772  			t.Fatal("Did not switch threads")
   773  		}
   774  	})
   775  }
   776  
   777  func TestClientServer_infoLocals(t *testing.T) {
   778  	protest.AllowRecording(t)
   779  	withTestClient2("testnextprog", t, func(c service.Client) {
   780  		fp := testProgPath(t, "testnextprog")
   781  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 24})
   782  		if err != nil {
   783  			t.Fatalf("Unexpected error: %v", err)
   784  		}
   785  		state := <-c.Continue()
   786  		if state.Err != nil {
   787  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   788  		}
   789  		locals, err := c.ListLocalVariables(api.EvalScope{GoroutineID: -1}, normalLoadConfig)
   790  		if err != nil {
   791  			t.Fatalf("Unexpected error: %v", err)
   792  		}
   793  		if len(locals) != 3 {
   794  			t.Fatalf("Expected 3 locals, got %d %#v", len(locals), locals)
   795  		}
   796  	})
   797  }
   798  
   799  func TestClientServer_infoArgs(t *testing.T) {
   800  	protest.AllowRecording(t)
   801  	withTestClient2("testnextprog", t, func(c service.Client) {
   802  		fp := testProgPath(t, "testnextprog")
   803  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 47})
   804  		if err != nil {
   805  			t.Fatalf("Unexpected error: %v", err)
   806  		}
   807  		state := <-c.Continue()
   808  		if state.Err != nil {
   809  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
   810  		}
   811  		regs, err := c.ListThreadRegisters(0, false)
   812  		if err != nil {
   813  			t.Fatalf("Unexpected error: %v", err)
   814  		}
   815  		if len(regs) == 0 {
   816  			t.Fatal("Expected string showing registers values, got empty string")
   817  		}
   818  
   819  		regs, err = c.ListScopeRegisters(api.EvalScope{GoroutineID: -1, Frame: 0}, false)
   820  		assertNoError(err, t, "ListScopeRegisters(-1, 0)")
   821  		if len(regs) == 0 {
   822  			t.Fatal("Expected string showing registers values, got empty string")
   823  		}
   824  		t.Logf("GoroutineID: -1, Frame: 0\n%s", regs.String())
   825  
   826  		regs, err = c.ListScopeRegisters(api.EvalScope{GoroutineID: -1, Frame: 1}, false)
   827  		assertNoError(err, t, "ListScopeRegisters(-1, 1)")
   828  		if len(regs) == 0 {
   829  			t.Fatal("Expected string showing registers values, got empty string")
   830  		}
   831  		t.Logf("GoroutineID: -1, Frame: 1\n%s", regs.String())
   832  
   833  		locals, err := c.ListFunctionArgs(api.EvalScope{GoroutineID: -1}, normalLoadConfig)
   834  		if err != nil {
   835  			t.Fatalf("Unexpected error: %v", err)
   836  		}
   837  		if len(locals) != 2 {
   838  			t.Fatalf("Expected 2 function args, got %d %#v", len(locals), locals)
   839  		}
   840  	})
   841  }
   842  
   843  func TestClientServer_traceContinue(t *testing.T) {
   844  	protest.AllowRecording(t)
   845  	withTestClient2("integrationprog", t, func(c service.Client) {
   846  		fp := testProgPath(t, "integrationprog")
   847  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 15, Tracepoint: true, Goroutine: true, Stacktrace: 5, Variables: []string{"i"}})
   848  		if err != nil {
   849  			t.Fatalf("Unexpected error: %v\n", err)
   850  		}
   851  		count := 0
   852  		contChan := c.Continue()
   853  		for state := range contChan {
   854  			if state.CurrentThread != nil && state.CurrentThread.Breakpoint != nil {
   855  				count++
   856  
   857  				t.Logf("%v", state)
   858  
   859  				bpi := state.CurrentThread.BreakpointInfo
   860  
   861  				if bpi.Goroutine == nil {
   862  					t.Fatalf("No goroutine information")
   863  				}
   864  
   865  				if len(bpi.Stacktrace) <= 0 {
   866  					t.Fatalf("No stacktrace\n")
   867  				}
   868  
   869  				if len(bpi.Variables) != 1 {
   870  					t.Fatalf("Wrong number of variables returned: %d", len(bpi.Variables))
   871  				}
   872  
   873  				if bpi.Variables[0].Name != "i" {
   874  					t.Fatalf("Wrong variable returned %s", bpi.Variables[0].Name)
   875  				}
   876  
   877  				t.Logf("Variable i is %v", bpi.Variables[0])
   878  
   879  				n, err := strconv.Atoi(bpi.Variables[0].Value)
   880  
   881  				if err != nil || n != count-1 {
   882  					t.Fatalf("Wrong variable value %q (%v %d)", bpi.Variables[0].Value, err, count)
   883  				}
   884  			}
   885  			if state.Exited {
   886  				continue
   887  			}
   888  			t.Logf("%v", state)
   889  			if state.Err != nil {
   890  				t.Fatalf("Unexpected error during continue: %v\n", state.Err)
   891  			}
   892  
   893  		}
   894  
   895  		if count != 3 {
   896  			t.Fatalf("Wrong number of continues hit: %d\n", count)
   897  		}
   898  	})
   899  }
   900  
   901  func TestClientServer_traceContinue2(t *testing.T) {
   902  	protest.AllowRecording(t)
   903  	withTestClient2("integrationprog", t, func(c service.Client) {
   904  		bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Tracepoint: true})
   905  		if err != nil {
   906  			t.Fatalf("Unexpected error: %v\n", err)
   907  		}
   908  		bp2, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: 1, Tracepoint: true})
   909  		if err != nil {
   910  			t.Fatalf("Unexpected error: %v\n", err)
   911  		}
   912  		countMain := 0
   913  		countSayhi := 0
   914  		contChan := c.Continue()
   915  		for state := range contChan {
   916  			if state.CurrentThread != nil && state.CurrentThread.Breakpoint != nil {
   917  				switch state.CurrentThread.Breakpoint.ID {
   918  				case bp1.ID:
   919  					countMain++
   920  				case bp2.ID:
   921  					countSayhi++
   922  				}
   923  
   924  				t.Logf("%v", state)
   925  			}
   926  			if state.Exited {
   927  				continue
   928  			}
   929  			if state.Err != nil {
   930  				t.Fatalf("Unexpected error during continue: %v\n", state.Err)
   931  			}
   932  
   933  		}
   934  
   935  		if countMain != 1 {
   936  			t.Fatalf("Wrong number of continues (main.main) hit: %d\n", countMain)
   937  		}
   938  
   939  		if countSayhi != 3 {
   940  			t.Fatalf("Wrong number of continues (main.sayhi) hit: %d\n", countSayhi)
   941  		}
   942  	})
   943  }
   944  
   945  func TestClientServer_FindLocations(t *testing.T) {
   946  	withTestClient2("locationsprog", t, func(c service.Client) {
   947  		someFunctionCallAddr := findLocationHelper(t, c, "locationsprog.go:26", false, 1, 0)[0]
   948  		someFunctionLine1 := findLocationHelper(t, c, "locationsprog.go:27", false, 1, 0)[0]
   949  		findLocationHelper(t, c, "anotherFunction:1", false, 1, someFunctionLine1)
   950  		findLocationHelper(t, c, "main.anotherFunction:1", false, 1, someFunctionLine1)
   951  		findLocationHelper(t, c, "anotherFunction", false, 1, someFunctionCallAddr)
   952  		findLocationHelper(t, c, "main.anotherFunction", false, 1, someFunctionCallAddr)
   953  		findLocationHelper(t, c, fmt.Sprintf("*0x%x", someFunctionCallAddr), false, 1, someFunctionCallAddr)
   954  		findLocationHelper(t, c, "sprog.go:26", true, 0, 0)
   955  
   956  		findLocationHelper(t, c, "String", true, 0, 0)
   957  		findLocationHelper(t, c, "main.String", true, 0, 0)
   958  
   959  		someTypeStringFuncAddr := findLocationHelper(t, c, "locationsprog.go:14", false, 1, 0)[0]
   960  		otherTypeStringFuncAddr := findLocationHelper(t, c, "locationsprog.go:18", false, 1, 0)[0]
   961  		findLocationHelper(t, c, "SomeType.String", false, 1, someTypeStringFuncAddr)
   962  		findLocationHelper(t, c, "(*SomeType).String", false, 1, someTypeStringFuncAddr)
   963  		findLocationHelper(t, c, "main.SomeType.String", false, 1, someTypeStringFuncAddr)
   964  		findLocationHelper(t, c, "main.(*SomeType).String", false, 1, someTypeStringFuncAddr)
   965  
   966  		// Issue #275
   967  		readfile := findLocationHelper(t, c, "io/ioutil.ReadFile", false, 1, 0)[0]
   968  
   969  		// Issue #296
   970  		findLocationHelper(t, c, "/io/ioutil.ReadFile", false, 1, readfile)
   971  		findLocationHelper(t, c, "ioutil.ReadFile", false, 1, readfile)
   972  
   973  		stringAddrs := findLocationHelper(t, c, "/^main.*Type.*String$/", false, 2, 0)
   974  
   975  		if otherTypeStringFuncAddr != stringAddrs[0] && otherTypeStringFuncAddr != stringAddrs[1] {
   976  			t.Fatalf("Wrong locations returned for \"/.*Type.*String/\", got: %v expected: %v and %v\n", stringAddrs, someTypeStringFuncAddr, otherTypeStringFuncAddr)
   977  		}
   978  
   979  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 4, Tracepoint: false})
   980  		if err != nil {
   981  			t.Fatalf("CreateBreakpoint(): %v\n", err)
   982  		}
   983  
   984  		<-c.Continue()
   985  
   986  		locationsprog35Addr := findLocationHelper(t, c, "locationsprog.go:35", false, 1, 0)[0]
   987  		findLocationHelper(t, c, fmt.Sprintf("%s:35", testProgPath(t, "locationsprog")), false, 1, locationsprog35Addr)
   988  		findLocationHelper(t, c, "+1", false, 1, locationsprog35Addr)
   989  		findLocationHelper(t, c, "35", false, 1, locationsprog35Addr)
   990  		findLocationHelper(t, c, "-1", false, 1, findLocationHelper(t, c, "locationsprog.go:33", false, 1, 0)[0])
   991  
   992  		findLocationHelper(t, c, `*amap["k"]`, false, 1, findLocationHelper(t, c, `amap["k"]`, false, 1, 0)[0])
   993  
   994  		locsNoSubst, _ := c.FindLocation(api.EvalScope{GoroutineID: -1}, "_fixtures/locationsprog.go:35", false, nil)
   995  		sep := "/"
   996  		if strings.Contains(locsNoSubst[0].File, "\\") {
   997  			sep = "\\"
   998  		}
   999  		substRules := [][2]string{[2]string{strings.Replace(locsNoSubst[0].File, "locationsprog.go", "", 1), strings.Replace(locsNoSubst[0].File, "_fixtures"+sep+"locationsprog.go", "nonexistent", 1)}}
  1000  		t.Logf("substitute rules: %q -> %q", substRules[0][0], substRules[0][1])
  1001  		locsSubst, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "nonexistent/locationsprog.go:35", false, substRules)
  1002  		if err != nil {
  1003  			t.Fatalf("FindLocation(locationsprog.go:35) with substitute rules: %v", err)
  1004  		}
  1005  		t.Logf("FindLocation(\"/nonexistent/path/locationsprog.go:35\") -> %#v", locsSubst)
  1006  		if locsNoSubst[0].PC != locsSubst[0].PC {
  1007  			t.Fatalf("FindLocation with substitute rules mismatch %#v %#v", locsNoSubst[0], locsSubst[0])
  1008  		}
  1009  
  1010  	})
  1011  
  1012  	withTestClient2("testnextdefer", t, func(c service.Client) {
  1013  		firstMainLine := findLocationHelper(t, c, "testnextdefer.go:5", false, 1, 0)[0]
  1014  		findLocationHelper(t, c, "main.main", false, 1, firstMainLine)
  1015  	})
  1016  
  1017  	withTestClient2("stacktraceprog", t, func(c service.Client) {
  1018  		stacktracemeAddr := findLocationHelper(t, c, "stacktraceprog.go:4", false, 1, 0)[0]
  1019  		findLocationHelper(t, c, "main.stacktraceme", false, 1, stacktracemeAddr)
  1020  	})
  1021  
  1022  	withTestClient2Extended("locationsUpperCase", t, 0, [3]string{}, func(c service.Client, fixture protest.Fixture) {
  1023  		// Upper case
  1024  		findLocationHelper(t, c, "locationsUpperCase.go:6", false, 1, 0)
  1025  
  1026  		// Fully qualified path
  1027  		findLocationHelper(t, c, fixture.Source+":6", false, 1, 0)
  1028  		bp, err := c.CreateBreakpoint(&api.Breakpoint{File: fixture.Source, Line: 6})
  1029  		if err != nil {
  1030  			t.Fatalf("Could not set breakpoint in %s: %v\n", fixture.Source, err)
  1031  		}
  1032  		c.ClearBreakpoint(bp.ID)
  1033  
  1034  		//  Allow `/` or `\` on Windows
  1035  		if runtime.GOOS == "windows" {
  1036  			findLocationHelper(t, c, filepath.FromSlash(fixture.Source)+":6", false, 1, 0)
  1037  			bp, err = c.CreateBreakpoint(&api.Breakpoint{File: filepath.FromSlash(fixture.Source), Line: 6})
  1038  			if err != nil {
  1039  				t.Fatalf("Could not set breakpoint in %s: %v\n", filepath.FromSlash(fixture.Source), err)
  1040  			}
  1041  			c.ClearBreakpoint(bp.ID)
  1042  		}
  1043  
  1044  		// Case-insensitive on Windows, case-sensitive otherwise
  1045  		shouldWrongCaseBeError := true
  1046  		numExpectedMatches := 0
  1047  		if runtime.GOOS == "windows" {
  1048  			shouldWrongCaseBeError = false
  1049  			numExpectedMatches = 1
  1050  		}
  1051  		findLocationHelper(t, c, strings.ToLower(fixture.Source)+":6", shouldWrongCaseBeError, numExpectedMatches, 0)
  1052  		bp, err = c.CreateBreakpoint(&api.Breakpoint{File: strings.ToLower(fixture.Source), Line: 6})
  1053  		if (err == nil) == shouldWrongCaseBeError {
  1054  			t.Fatalf("Could not set breakpoint in %s: %v\n", strings.ToLower(fixture.Source), err)
  1055  		}
  1056  		c.ClearBreakpoint(bp.ID)
  1057  	})
  1058  
  1059  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 13) {
  1060  		withTestClient2("pkgrenames", t, func(c service.Client) {
  1061  			someFuncLoc := findLocationHelper(t, c, "github.com/go-delve/delve/_fixtures/internal/dir%2eio.SomeFunction:0", false, 1, 0)[0]
  1062  			findLocationHelper(t, c, "dirio.SomeFunction:0", false, 1, someFuncLoc)
  1063  		})
  1064  	}
  1065  
  1066  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) {
  1067  		withTestClient2("locationsprog_generic", t, func(c service.Client) {
  1068  			const (
  1069  				methodLine = "locationsprog_generic.go:9"
  1070  				funcLine   = "locationsprog_generic.go:13"
  1071  				funcLine2  = "locationsprog_generic.go:14"
  1072  			)
  1073  			methodLoc := findLocationHelper2(t, c, methodLine, nil)
  1074  			if len(methodLoc.PCs) != 2 {
  1075  				// we didn't get both instantiations of the method
  1076  				t.Errorf("wrong number of PCs for %s: %#x", methodLine, methodLoc.PCs)
  1077  			}
  1078  
  1079  			funcLoc := findLocationHelper2(t, c, funcLine, nil)
  1080  			if len(funcLoc.PCs) != 2 {
  1081  				// we didn't get both instantiations of the function
  1082  				t.Errorf("wrong number of PCs for %s: %#x", funcLine, funcLoc.PCs)
  1083  			}
  1084  
  1085  			funcLoc2 := findLocationHelper2(t, c, funcLine2, nil)
  1086  			if len(funcLoc2.PCs) != 2 {
  1087  				t.Errorf("wrong number of PCs for %s: %#x", funcLine2, funcLoc2.PCs)
  1088  			}
  1089  
  1090  			findLocationHelper2(t, c, "main.ParamFunc", funcLoc)
  1091  
  1092  			findLocationHelper2(t, c, "ParamFunc", funcLoc)
  1093  
  1094  			findLocationHelper2(t, c, "main.ParamReceiver.Amethod", methodLoc)
  1095  			findLocationHelper2(t, c, "main.Amethod", methodLoc)
  1096  			findLocationHelper2(t, c, "ParamReceiver.Amethod", methodLoc)
  1097  			findLocationHelper2(t, c, "Amethod", methodLoc)
  1098  
  1099  			findLocationHelper2(t, c, "main.(*ParamReceiver).Amethod", methodLoc)
  1100  			findLocationHelper2(t, c, "(*ParamReceiver).Amethod", methodLoc)
  1101  
  1102  			findLocationHelper2(t, c, "main.(*ParamReceiver).Amethod", methodLoc)
  1103  			findLocationHelper2(t, c, "(*ParamReceiver).Amethod", methodLoc)
  1104  
  1105  			findLocationHelper2(t, c, "main.ParamFunc:1", funcLoc2)
  1106  		})
  1107  	}
  1108  }
  1109  
  1110  func findLocationHelper2(t *testing.T, c service.Client, loc string, checkLoc *api.Location) *api.Location {
  1111  	locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, loc, false, nil)
  1112  	if err != nil {
  1113  		t.Fatalf("FindLocation(%q) -> error %v", loc, err)
  1114  	}
  1115  	t.Logf("FindLocation(%q) → %v\n", loc, locs)
  1116  	if len(locs) != 1 {
  1117  		t.Logf("Wrong number of locations returned for location %q (got %d expected 1)", loc, len(locs))
  1118  	}
  1119  
  1120  	if checkLoc == nil {
  1121  		return &locs[0]
  1122  	}
  1123  
  1124  	if len(checkLoc.PCs) != len(locs[0].PCs) {
  1125  		t.Fatalf("Wrong number of PCs returned (got %#x expected %#x)", locs[0].PCs, checkLoc.PCs)
  1126  	}
  1127  
  1128  	for i := range checkLoc.PCs {
  1129  		if checkLoc.PCs[i] != locs[0].PCs[i] {
  1130  			t.Fatalf("Wrong PCs returned (got %#x expected %#x)", locs[0].PCs, checkLoc.PCs)
  1131  		}
  1132  	}
  1133  
  1134  	return &locs[0]
  1135  }
  1136  
  1137  func TestClientServer_FindLocationsAddr(t *testing.T) {
  1138  	withTestClient2("locationsprog2", t, func(c service.Client) {
  1139  		<-c.Continue()
  1140  
  1141  		afunction := findLocationHelper(t, c, "main.afunction", false, 1, 0)[0]
  1142  		anonfunc := findLocationHelper(t, c, "main.main.func1", false, 1, 0)[0]
  1143  
  1144  		findLocationHelper(t, c, "*fn1", false, 1, afunction)
  1145  		findLocationHelper(t, c, "*fn3", false, 1, anonfunc)
  1146  	})
  1147  }
  1148  
  1149  func TestClientServer_FindLocationsExactMatch(t *testing.T) {
  1150  	// if an expression matches multiple functions but one of them is an exact
  1151  	// match it should be used anyway.
  1152  	// In this example "math/rand.Intn" would normally match "math/rand.Intn"
  1153  	// and "math/rand.(*Rand).Intn" but since the first match is exact it
  1154  	// should be prioritized.
  1155  	withTestClient2("locationsprog3", t, func(c service.Client) {
  1156  		<-c.Continue()
  1157  		findLocationHelper(t, c, "math/rand.Intn", false, 1, 0)
  1158  	})
  1159  }
  1160  
  1161  func TestClientServer_EvalVariable(t *testing.T) {
  1162  	withTestClient2("testvariables", t, func(c service.Client) {
  1163  		state := <-c.Continue()
  1164  
  1165  		if state.Err != nil {
  1166  			t.Fatalf("Continue(): %v\n", state.Err)
  1167  		}
  1168  
  1169  		var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "a1", normalLoadConfig)
  1170  		assertNoError(err, t, "EvalVariable")
  1171  
  1172  		t.Logf("var1: %s", var1.SinglelineString())
  1173  
  1174  		if var1.Value != "foofoofoofoofoofoo" {
  1175  			t.Fatalf("Wrong variable value: %s", var1.Value)
  1176  		}
  1177  	})
  1178  }
  1179  
  1180  func TestClientServer_SetVariable(t *testing.T) {
  1181  	withTestClient2("testvariables", t, func(c service.Client) {
  1182  		state := <-c.Continue()
  1183  
  1184  		if state.Err != nil {
  1185  			t.Fatalf("Continue(): %v\n", state.Err)
  1186  		}
  1187  
  1188  		assertNoError(c.SetVariable(api.EvalScope{GoroutineID: -1}, "a2", "8"), t, "SetVariable()")
  1189  
  1190  		a2, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "a2", normalLoadConfig)
  1191  		if err != nil {
  1192  			t.Fatalf("Could not evaluate variable: %v", err)
  1193  		}
  1194  
  1195  		t.Logf("a2: %v", a2)
  1196  
  1197  		n, err := strconv.Atoi(a2.Value)
  1198  
  1199  		if err != nil && n != 8 {
  1200  			t.Fatalf("Wrong variable value: %v", a2)
  1201  		}
  1202  	})
  1203  }
  1204  
  1205  func TestClientServer_FullStacktrace(t *testing.T) {
  1206  	protest.AllowRecording(t)
  1207  	if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
  1208  		t.Skip("cgo doesn't work on darwin/arm64")
  1209  	}
  1210  
  1211  	lenient := false
  1212  	if runtime.GOOS == "windows" {
  1213  		lenient = true
  1214  	}
  1215  
  1216  	withTestClient2("goroutinestackprog", t, func(c service.Client) {
  1217  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.stacktraceme", Line: -1})
  1218  		assertNoError(err, t, "CreateBreakpoint()")
  1219  		state := <-c.Continue()
  1220  		if state.Err != nil {
  1221  			t.Fatalf("Continue(): %v\n", state.Err)
  1222  		}
  1223  
  1224  		gs, _, err := c.ListGoroutines(0, 0)
  1225  		assertNoError(err, t, "GoroutinesInfo()")
  1226  		found := make([]bool, 10)
  1227  		for _, g := range gs {
  1228  			frames, err := c.Stacktrace(g.ID, 40, 0, &normalLoadConfig)
  1229  			assertNoError(err, t, fmt.Sprintf("Stacktrace(%d)", g.ID))
  1230  			t.Logf("goroutine %d", g.ID)
  1231  			for i, frame := range frames {
  1232  				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())
  1233  				if frame.Function == nil {
  1234  					continue
  1235  				}
  1236  				if frame.Function.Name() != "main.agoroutine" {
  1237  					continue
  1238  				}
  1239  				for _, arg := range frame.Arguments {
  1240  					if arg.Name != "i" {
  1241  						continue
  1242  					}
  1243  					t.Logf("\tvariable i is %+v\n", arg)
  1244  					argn, err := strconv.Atoi(arg.Value)
  1245  					if err == nil {
  1246  						found[argn] = true
  1247  					}
  1248  				}
  1249  			}
  1250  		}
  1251  
  1252  		for i := range found {
  1253  			if !found[i] {
  1254  				if lenient {
  1255  					lenient = false
  1256  				} else {
  1257  					t.Fatalf("Goroutine %d not found", i)
  1258  				}
  1259  			}
  1260  		}
  1261  
  1262  		t.Logf("continue")
  1263  
  1264  		state = <-c.Continue()
  1265  		if state.Err != nil {
  1266  			t.Fatalf("Continue(): %v\n", state.Err)
  1267  		}
  1268  
  1269  		frames, err := c.Stacktrace(-1, 10, 0, &normalLoadConfig)
  1270  		assertNoError(err, t, "Stacktrace")
  1271  
  1272  		cur := 3
  1273  		for i, frame := range frames {
  1274  			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())
  1275  			if i == 0 {
  1276  				continue
  1277  			}
  1278  			v := frame.Var("n")
  1279  			if v == nil {
  1280  				t.Fatalf("Could not find value of variable n in frame %d", i)
  1281  			}
  1282  			vn, err := strconv.Atoi(v.Value)
  1283  			if err != nil || vn != cur {
  1284  				t.Fatalf("Expected value %d got %d (error: %v)", cur, vn, err)
  1285  			}
  1286  			cur--
  1287  			if cur < 0 {
  1288  				break
  1289  			}
  1290  		}
  1291  	})
  1292  }
  1293  
  1294  func assertErrorOrExited(s *api.DebuggerState, err error, t *testing.T, reason string) {
  1295  	if err != nil {
  1296  		return
  1297  	}
  1298  	if s != nil && s.Exited {
  1299  		return
  1300  	}
  1301  	t.Fatalf("%s (no error and no exited status)", reason)
  1302  }
  1303  
  1304  func TestIssue355(t *testing.T) {
  1305  	// After the target process has terminated should return an error but not crash
  1306  	protest.AllowRecording(t)
  1307  	withTestClient2("continuetestprog", t, func(c service.Client) {
  1308  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1})
  1309  		assertNoError(err, t, "CreateBreakpoint()")
  1310  		ch := c.Continue()
  1311  		state := <-ch
  1312  		tid := state.CurrentThread.ID
  1313  		gid := state.SelectedGoroutine.ID
  1314  		assertNoError(state.Err, t, "First Continue()")
  1315  		ch = c.Continue()
  1316  		state = <-ch
  1317  		if !state.Exited {
  1318  			t.Fatalf("Target did not terminate after second continue")
  1319  		}
  1320  
  1321  		ch = c.Continue()
  1322  		state = <-ch
  1323  		assertError(state.Err, t, "Continue()")
  1324  
  1325  		s, err := c.Next()
  1326  		assertErrorOrExited(s, err, t, "Next()")
  1327  		s, err = c.Step()
  1328  		assertErrorOrExited(s, err, t, "Step()")
  1329  		s, err = c.StepInstruction()
  1330  		assertErrorOrExited(s, err, t, "StepInstruction()")
  1331  		s, err = c.SwitchThread(tid)
  1332  		assertErrorOrExited(s, err, t, "SwitchThread()")
  1333  		s, err = c.SwitchGoroutine(gid)
  1334  		assertErrorOrExited(s, err, t, "SwitchGoroutine()")
  1335  		s, err = c.Halt()
  1336  		assertErrorOrExited(s, err, t, "Halt()")
  1337  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: -1})
  1338  		if testBackend != "rr" {
  1339  			assertError(err, t, "CreateBreakpoint()")
  1340  		}
  1341  		_, err = c.ClearBreakpoint(bp.ID)
  1342  		if testBackend != "rr" {
  1343  			assertError(err, t, "ClearBreakpoint()")
  1344  		}
  1345  		_, err = c.ListThreads()
  1346  		assertError(err, t, "ListThreads()")
  1347  		_, err = c.GetThread(tid)
  1348  		assertError(err, t, "GetThread()")
  1349  		assertError(c.SetVariable(api.EvalScope{GoroutineID: gid}, "a", "10"), t, "SetVariable()")
  1350  		_, err = c.ListLocalVariables(api.EvalScope{GoroutineID: gid}, normalLoadConfig)
  1351  		assertError(err, t, "ListLocalVariables()")
  1352  		_, err = c.ListFunctionArgs(api.EvalScope{GoroutineID: gid}, normalLoadConfig)
  1353  		assertError(err, t, "ListFunctionArgs()")
  1354  		_, err = c.ListThreadRegisters(0, false)
  1355  		assertError(err, t, "ListThreadRegisters()")
  1356  		_, err = c.ListScopeRegisters(api.EvalScope{GoroutineID: gid}, false)
  1357  		assertError(err, t, "ListScopeRegisters()")
  1358  		_, _, err = c.ListGoroutines(0, 0)
  1359  		assertError(err, t, "ListGoroutines()")
  1360  		_, err = c.Stacktrace(gid, 10, 0, &normalLoadConfig)
  1361  		assertError(err, t, "Stacktrace()")
  1362  		_, err = c.FindLocation(api.EvalScope{GoroutineID: gid}, "+1", false, nil)
  1363  		assertError(err, t, "FindLocation()")
  1364  		_, err = c.DisassemblePC(api.EvalScope{GoroutineID: -1}, 0x40100, api.IntelFlavour)
  1365  		assertError(err, t, "DisassemblePC()")
  1366  	})
  1367  }
  1368  
  1369  func TestDisasm(t *testing.T) {
  1370  	// Tests that disassembling by PC, range, and current PC all yeld similar results
  1371  	// Tests that disassembly by current PC will return a disassembly containing the instruction at PC
  1372  	// Tests that stepping on a calculated CALL instruction will yield a disassembly that contains the
  1373  	// effective destination of the CALL instruction
  1374  	withTestClient2("locationsprog2", t, func(c service.Client) {
  1375  		ch := c.Continue()
  1376  		state := <-ch
  1377  		assertNoError(state.Err, t, "Continue()")
  1378  
  1379  		locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "main.main", false, nil)
  1380  		assertNoError(err, t, "FindLocation()")
  1381  		if len(locs) != 1 {
  1382  			t.Fatalf("wrong number of locations for main.main: %d", len(locs))
  1383  		}
  1384  		d1, err := c.DisassemblePC(api.EvalScope{GoroutineID: -1}, locs[0].PC, api.IntelFlavour)
  1385  		assertNoError(err, t, "DisassemblePC()")
  1386  		if len(d1) < 2 {
  1387  			t.Fatalf("wrong size of disassembly: %d", len(d1))
  1388  		}
  1389  
  1390  		pcstart := d1[0].Loc.PC
  1391  		pcend := d1[len(d1)-1].Loc.PC + uint64(len(d1[len(d1)-1].Bytes))
  1392  
  1393  		// start address should be less than end address
  1394  		_, err = c.DisassembleRange(api.EvalScope{GoroutineID: -1}, pcend, pcstart, api.IntelFlavour)
  1395  		assertError(err, t, "DisassembleRange()")
  1396  
  1397  		d2, err := c.DisassembleRange(api.EvalScope{GoroutineID: -1}, pcstart, pcend, api.IntelFlavour)
  1398  		assertNoError(err, t, "DisassembleRange()")
  1399  
  1400  		if len(d1) != len(d2) {
  1401  			t.Logf("d1: %v", d1)
  1402  			t.Logf("d2: %v", d2)
  1403  			t.Fatal("mismatched length between disassemble pc and disassemble range")
  1404  		}
  1405  
  1406  		d3, err := c.DisassemblePC(api.EvalScope{GoroutineID: -1}, state.CurrentThread.PC, api.IntelFlavour)
  1407  		assertNoError(err, t, "DisassemblePC() - second call")
  1408  
  1409  		if len(d1) != len(d3) {
  1410  			t.Logf("d1: %v", d1)
  1411  			t.Logf("d3: %v", d3)
  1412  			t.Fatal("mismatched length between the two calls of disassemble pc")
  1413  		}
  1414  
  1415  		// look for static call to afunction() on line 29
  1416  		found := false
  1417  		for i := range d3 {
  1418  			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" {
  1419  				found = true
  1420  				break
  1421  			}
  1422  		}
  1423  		if !found {
  1424  			t.Fatal("Could not find call to main.afunction on line 29")
  1425  		}
  1426  
  1427  		haspc := false
  1428  		for i := range d3 {
  1429  			if d3[i].AtPC {
  1430  				haspc = true
  1431  				break
  1432  			}
  1433  		}
  1434  
  1435  		if !haspc {
  1436  			t.Logf("d3: %v", d3)
  1437  			t.Fatal("PC instruction not found")
  1438  		}
  1439  
  1440  		if runtime.GOARCH == "386" && buildMode == "pie" {
  1441  			// Skip the rest of the test because on intel 386 with PIE build mode
  1442  			// the compiler will insert calls to __x86.get_pc_thunk which do not have DIEs and we can't resolve.
  1443  			return
  1444  		}
  1445  
  1446  		startinstr := getCurinstr(d3)
  1447  		count := 0
  1448  		for {
  1449  			if count > 20 {
  1450  				t.Fatal("too many step instructions executed without finding a call instruction")
  1451  			}
  1452  			state, err := c.StepInstruction()
  1453  			assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
  1454  
  1455  			d3, err = c.DisassemblePC(api.EvalScope{GoroutineID: -1}, state.CurrentThread.PC, api.IntelFlavour)
  1456  			assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
  1457  
  1458  			curinstr := getCurinstr(d3)
  1459  
  1460  			if curinstr == nil {
  1461  				t.Fatalf("Could not find current instruction %d", count)
  1462  			}
  1463  
  1464  			if curinstr.Loc.Line != startinstr.Loc.Line {
  1465  				t.Fatal("Calling StepInstruction() repeatedly did not find the call instruction")
  1466  			}
  1467  
  1468  			if strings.HasPrefix(curinstr.Text, "call") || strings.HasPrefix(curinstr.Text, "CALL") {
  1469  				t.Logf("call: %v", curinstr)
  1470  				if curinstr.DestLoc == nil || curinstr.DestLoc.Function == nil {
  1471  					t.Fatalf("Call instruction does not have destination: %v", curinstr)
  1472  				}
  1473  				if curinstr.DestLoc.Function.Name() != "main.afunction" {
  1474  					t.Fatalf("Call instruction destination not main.afunction: %v", curinstr)
  1475  				}
  1476  				break
  1477  			}
  1478  
  1479  			count++
  1480  		}
  1481  	})
  1482  }
  1483  
  1484  func TestNegativeStackDepthBug(t *testing.T) {
  1485  	// After the target process has terminated should return an error but not crash
  1486  	protest.AllowRecording(t)
  1487  	withTestClient2("continuetestprog", t, func(c service.Client) {
  1488  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1})
  1489  		assertNoError(err, t, "CreateBreakpoint()")
  1490  		ch := c.Continue()
  1491  		state := <-ch
  1492  		assertNoError(state.Err, t, "Continue()")
  1493  		_, err = c.Stacktrace(-1, -2, 0, &normalLoadConfig)
  1494  		assertError(err, t, "Stacktrace()")
  1495  	})
  1496  }
  1497  
  1498  func TestClientServer_CondBreakpoint(t *testing.T) {
  1499  	if runtime.GOOS == "freebsd" {
  1500  		t.Skip("test is not valid on FreeBSD")
  1501  	}
  1502  	protest.AllowRecording(t)
  1503  	withTestClient2("parallel_next", t, func(c service.Client) {
  1504  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: 1})
  1505  		assertNoError(err, t, "CreateBreakpoint()")
  1506  		bp.Cond = "n == 7"
  1507  		assertNoError(c.AmendBreakpoint(bp), t, "AmendBreakpoint() 1")
  1508  		bp, err = c.GetBreakpoint(bp.ID)
  1509  		assertNoError(err, t, "GetBreakpoint() 1")
  1510  		bp.Variables = append(bp.Variables, "n")
  1511  		assertNoError(c.AmendBreakpoint(bp), t, "AmendBreakpoint() 2")
  1512  		bp, err = c.GetBreakpoint(bp.ID)
  1513  		assertNoError(err, t, "GetBreakpoint() 2")
  1514  		if bp.Cond == "" {
  1515  			t.Fatalf("No condition set on breakpoint %#v", bp)
  1516  		}
  1517  		if len(bp.Variables) != 1 {
  1518  			t.Fatalf("Wrong number of expressions to evaluate on breakpoint %#v", bp)
  1519  		}
  1520  		state := <-c.Continue()
  1521  		assertNoError(state.Err, t, "Continue()")
  1522  
  1523  		nvar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "n", normalLoadConfig)
  1524  		assertNoError(err, t, "EvalVariable()")
  1525  
  1526  		if nvar.SinglelineString() != "7" {
  1527  			t.Fatalf("Stopped on wrong goroutine %s\n", nvar.Value)
  1528  		}
  1529  	})
  1530  }
  1531  
  1532  func clientEvalVariable(t *testing.T, c service.Client, expr string) *api.Variable {
  1533  	v, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, expr, normalLoadConfig)
  1534  	assertNoError(err, t, fmt.Sprintf("EvalVariable(%s)", expr))
  1535  	return v
  1536  }
  1537  
  1538  func TestSkipPrologue(t *testing.T) {
  1539  	withTestClient2("locationsprog2", t, func(c service.Client) {
  1540  		<-c.Continue()
  1541  
  1542  		afunction := findLocationHelper(t, c, "main.afunction", false, 1, 0)[0]
  1543  		findLocationHelper(t, c, "*fn1", false, 1, afunction)
  1544  		findLocationHelper(t, c, "locationsprog2.go:8", false, 1, afunction)
  1545  
  1546  		afunction0 := uint64(clientEvalVariable(t, c, "main.afunction").Addr)
  1547  
  1548  		if afunction == afunction0 {
  1549  			t.Fatal("Skip prologue failed")
  1550  		}
  1551  	})
  1552  }
  1553  
  1554  func TestSkipPrologue2(t *testing.T) {
  1555  	withTestClient2("callme", t, func(c service.Client) {
  1556  		callme := findLocationHelper(t, c, "main.callme", false, 1, 0)[0]
  1557  		callmeZ := uint64(clientEvalVariable(t, c, "main.callme").Addr)
  1558  		findLocationHelper(t, c, "callme.go:5", false, 1, callme)
  1559  		if callme == callmeZ {
  1560  			t.Fatal("Skip prologue failed")
  1561  		}
  1562  
  1563  		callme2 := findLocationHelper(t, c, "main.callme2", false, 1, 0)[0]
  1564  		callme2Z := uint64(clientEvalVariable(t, c, "main.callme2").Addr)
  1565  		findLocationHelper(t, c, "callme.go:12", false, 1, callme2)
  1566  		if callme2 == callme2Z {
  1567  			t.Fatal("Skip prologue failed")
  1568  		}
  1569  
  1570  		callme3 := findLocationHelper(t, c, "main.callme3", false, 1, 0)[0]
  1571  		callme3Z := uint64(clientEvalVariable(t, c, "main.callme3").Addr)
  1572  		ver, _ := goversion.Parse(runtime.Version())
  1573  
  1574  		if (ver.Major < 0 || ver.AfterOrEqual(goversion.GoVer18Beta)) && runtime.GOARCH != "386" {
  1575  			findLocationHelper(t, c, "callme.go:19", false, 1, callme3)
  1576  		} else {
  1577  			// callme3 does not have local variables therefore the first line of the
  1578  			// function is immediately after the prologue
  1579  			// This is only true before go1.8 or on Intel386 where frame pointer chaining
  1580  			// introduced a bit of prologue even for functions without local variables
  1581  			findLocationHelper(t, c, "callme.go:19", false, 1, callme3Z)
  1582  		}
  1583  		if callme3 == callme3Z {
  1584  			t.Fatal("Skip prologue failed")
  1585  		}
  1586  	})
  1587  }
  1588  
  1589  func TestIssue419(t *testing.T) {
  1590  	// Calling service/rpc.(*Client).Halt could cause a crash because both Halt and Continue simultaneously
  1591  	// try to read 'runtime.g' and debug/dwarf.Data.Type is not thread safe
  1592  	finish := make(chan struct{})
  1593  	withTestClient2("issue419", t, func(c service.Client) {
  1594  		go func() {
  1595  			defer close(finish)
  1596  			rand.Seed(time.Now().Unix())
  1597  			d := time.Duration(rand.Intn(4) + 1)
  1598  			time.Sleep(d * time.Second)
  1599  			t.Logf("halt")
  1600  			_, err := c.Halt()
  1601  			assertNoError(err, t, "RequestManualStop()")
  1602  		}()
  1603  		statech := c.Continue()
  1604  		state := <-statech
  1605  		assertNoError(state.Err, t, "Continue()")
  1606  		t.Logf("done")
  1607  		<-finish
  1608  	})
  1609  }
  1610  
  1611  func TestTypesCommand(t *testing.T) {
  1612  	protest.AllowRecording(t)
  1613  	withTestClient2("testvariables2", t, func(c service.Client) {
  1614  		state := <-c.Continue()
  1615  		assertNoError(state.Err, t, "Continue()")
  1616  		types, err := c.ListTypes("")
  1617  		assertNoError(err, t, "ListTypes()")
  1618  
  1619  		found := false
  1620  		for i := range types {
  1621  			if types[i] == "main.astruct" {
  1622  				found = true
  1623  				break
  1624  			}
  1625  		}
  1626  		if !found {
  1627  			t.Fatal("Type astruct not found in ListTypes output")
  1628  		}
  1629  
  1630  		types, err = c.ListTypes("^main.astruct$")
  1631  		assertNoError(err, t, "ListTypes(\"main.astruct\")")
  1632  		if len(types) != 1 {
  1633  			t.Fatalf("ListTypes(\"^main.astruct$\") did not filter properly, expected 1 got %d: %v", len(types), types)
  1634  		}
  1635  	})
  1636  }
  1637  
  1638  func TestIssue406(t *testing.T) {
  1639  	protest.AllowRecording(t)
  1640  	withTestClient2("issue406", t, func(c service.Client) {
  1641  		locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "issue406.go:146", false, nil)
  1642  		assertNoError(err, t, "FindLocation()")
  1643  		_, err = c.CreateBreakpoint(&api.Breakpoint{Addr: locs[0].PC})
  1644  		assertNoError(err, t, "CreateBreakpoint()")
  1645  		ch := c.Continue()
  1646  		state := <-ch
  1647  		assertNoError(state.Err, t, "Continue()")
  1648  		v, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "cfgtree", normalLoadConfig)
  1649  		assertNoError(err, t, "EvalVariable()")
  1650  		vs := v.MultilineString("", "")
  1651  		t.Logf("cfgtree formats to: %s\n", vs)
  1652  	})
  1653  }
  1654  
  1655  func TestEvalExprName(t *testing.T) {
  1656  	withTestClient2("testvariables2", t, func(c service.Client) {
  1657  		state := <-c.Continue()
  1658  		assertNoError(state.Err, t, "Continue()")
  1659  
  1660  		var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i1+1", normalLoadConfig)
  1661  		assertNoError(err, t, "EvalVariable")
  1662  
  1663  		const name = "i1+1"
  1664  
  1665  		t.Logf("i1+1 → %#v", var1)
  1666  
  1667  		if var1.Name != name {
  1668  			t.Fatalf("Wrong variable name %q, expected %q", var1.Name, name)
  1669  		}
  1670  	})
  1671  }
  1672  
  1673  func TestClientServer_Issue528(t *testing.T) {
  1674  	// FindLocation with Receiver.MethodName syntax does not work
  1675  	// on remote package names due to a bug in debug/gosym that
  1676  	// Was fixed in go 1.7 // Commit that fixes the issue in go:
  1677  	// f744717d1924340b8f5e5a385e99078693ad9097
  1678  
  1679  	ver, _ := goversion.Parse(runtime.Version())
  1680  	if ver.Major > 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 7, Rev: -1}) {
  1681  		t.Log("Test skipped")
  1682  		return
  1683  	}
  1684  
  1685  	withTestClient2("issue528", t, func(c service.Client) {
  1686  		findLocationHelper(t, c, "State.Close", false, 1, 0)
  1687  	})
  1688  }
  1689  
  1690  func TestClientServer_FpRegisters(t *testing.T) {
  1691  	if runtime.GOARCH != "amd64" {
  1692  		t.Skip("test is valid only on AMD64")
  1693  	}
  1694  	regtests := []struct{ name, value string }{
  1695  		// x87
  1696  		{"ST(0)", "0x3fffe666660000000000"},
  1697  		{"ST(1)", "0x3fffd9999a0000000000"},
  1698  		{"ST(2)", "0x3fffcccccd0000000000"},
  1699  		{"ST(3)", "0x3fffc000000000000000"},
  1700  		{"ST(4)", "0x3fffb333333333333000"},
  1701  		{"ST(5)", "0x3fffa666666666666800"},
  1702  		{"ST(6)", "0x3fff9999999999999800"},
  1703  		{"ST(7)", "0x3fff8cccccccccccd000"},
  1704  
  1705  		// SSE
  1706  		{"XMM0", "0x3ff33333333333333ff199999999999a	v2_int={ 3ff199999999999a 3ff3333333333333 }	v4_int={ 9999999a 3ff19999 33333333 3ff33333 }	v8_int={ 999a 9999 9999 3ff1 3333 3333 3333 3ff3 }	v16_int={ 9a 99 99 99 99 99 f1 3f 33 33 33 33 33 33 f3 3f }"},
  1707  		{"XMM1", "0x3ff66666666666663ff4cccccccccccd"},
  1708  		{"XMM2", "0x3fe666663fd9999a3fcccccd3fc00000"},
  1709  		{"XMM3", "0x3ff199999999999a3ff3333333333333"},
  1710  		{"XMM4", "0x3ff4cccccccccccd3ff6666666666666"},
  1711  		{"XMM5", "0x3fcccccd3fc000003fe666663fd9999a"},
  1712  		{"XMM6", "0x4004cccccccccccc4003333333333334"},
  1713  		{"XMM7", "0x40026666666666664002666666666666"},
  1714  		{"XMM8", "0x4059999a404ccccd4059999a404ccccd"},
  1715  
  1716  		// AVX 2
  1717  		{"XMM11", "0x3ff66666666666663ff4cccccccccccd"},
  1718  		{"XMM11", "…[YMM11h] 0x3ff66666666666663ff4cccccccccccd"},
  1719  
  1720  		// AVX 512
  1721  		{"XMM12", "0x3ff66666666666663ff4cccccccccccd"},
  1722  		{"XMM12", "…[YMM12h] 0x3ff66666666666663ff4cccccccccccd"},
  1723  		{"XMM12", "…[ZMM12hl] 0x3ff66666666666663ff4cccccccccccd"},
  1724  		{"XMM12", "…[ZMM12hh] 0x3ff66666666666663ff4cccccccccccd"},
  1725  	}
  1726  	protest.AllowRecording(t)
  1727  	withTestClient2Extended("fputest/", t, 0, [3]string{}, func(c service.Client, fixture protest.Fixture) {
  1728  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: filepath.Join(fixture.BuildDir, "fputest.go"), Line: 25})
  1729  		assertNoError(err, t, "CreateBreakpoint")
  1730  
  1731  		state := <-c.Continue()
  1732  		t.Logf("state after continue: %#v", state)
  1733  
  1734  		scope := api.EvalScope{GoroutineID: -1}
  1735  
  1736  		boolvar := func(name string) bool {
  1737  			v, err := c.EvalVariable(scope, name, normalLoadConfig)
  1738  			if err != nil {
  1739  				t.Fatalf("could not read %s variable", name)
  1740  			}
  1741  			t.Logf("%s variable: %#v", name, v)
  1742  			return v.Value != "false"
  1743  		}
  1744  
  1745  		avx2 := boolvar("avx2")
  1746  		avx512 := boolvar("avx512")
  1747  
  1748  		if runtime.GOOS == "windows" {
  1749  			// not supported
  1750  			avx2 = false
  1751  			avx512 = false
  1752  		}
  1753  
  1754  		state = <-c.Continue()
  1755  		t.Logf("state after continue: %#v", state)
  1756  
  1757  		regs, err := c.ListThreadRegisters(0, true)
  1758  		assertNoError(err, t, "ListThreadRegisters()")
  1759  
  1760  		for _, regtest := range regtests {
  1761  			if regtest.name == "XMM11" && !avx2 {
  1762  				continue
  1763  			}
  1764  			if regtest.name == "XMM12" && (!avx512 || testBackend == "rr") {
  1765  				continue
  1766  			}
  1767  			found := false
  1768  			for _, reg := range regs {
  1769  				if reg.Name == regtest.name {
  1770  					found = true
  1771  					if strings.HasPrefix(regtest.value, "…") {
  1772  						if !strings.Contains(reg.Value, regtest.value[len("…"):]) {
  1773  							t.Fatalf("register %s expected to contain %q got %q", reg.Name, regtest.value, reg.Value)
  1774  						}
  1775  					} else {
  1776  						if !strings.HasPrefix(reg.Value, regtest.value) {
  1777  							t.Fatalf("register %s expected %q got %q", reg.Name, regtest.value, reg.Value)
  1778  						}
  1779  					}
  1780  				}
  1781  			}
  1782  			if !found {
  1783  				t.Fatalf("register %s not found: %v", regtest.name, regs)
  1784  			}
  1785  		}
  1786  
  1787  		// Test register expressions
  1788  
  1789  		for _, tc := range []struct{ expr, tgt string }{
  1790  			{"XMM1[:32]", `"cdccccccccccf43f666666666666f63f"`},
  1791  			{"_XMM1[:32]", `"cdccccccccccf43f666666666666f63f"`},
  1792  			{"__XMM1[:32]", `"cdccccccccccf43f666666666666f63f"`},
  1793  			{"XMM1.int8[0]", `-51`},
  1794  			{"XMM1.uint16[0]", `52429`},
  1795  			{"XMM1.float32[0]", `-107374184`},
  1796  			{"XMM1.float64[0]", `1.3`},
  1797  			{"RAX.uint8[0]", "42"},
  1798  		} {
  1799  			v, err := c.EvalVariable(scope, tc.expr, normalLoadConfig)
  1800  			if err != nil {
  1801  				t.Fatalf("could not evalue expression %s: %v", tc.expr, err)
  1802  			}
  1803  			out := v.SinglelineString()
  1804  
  1805  			if out != tc.tgt {
  1806  				t.Fatalf("for %q expected %q got %q\n", tc.expr, tc.tgt, out)
  1807  			}
  1808  		}
  1809  	})
  1810  }
  1811  
  1812  func TestClientServer_RestartBreakpointPosition(t *testing.T) {
  1813  	protest.AllowRecording(t)
  1814  	if buildMode == "pie" || (runtime.GOOS == "darwin" && runtime.GOARCH == "arm64") {
  1815  		t.Skip("not meaningful in PIE mode")
  1816  	}
  1817  	withTestClient2("locationsprog2", t, func(c service.Client) {
  1818  		bpBefore, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.afunction", Line: -1, Tracepoint: true, Name: "this"})
  1819  		addrBefore := bpBefore.Addr
  1820  		t.Logf("%x\n", bpBefore.Addr)
  1821  		assertNoError(err, t, "CreateBreakpoint")
  1822  		stateCh := c.Continue()
  1823  		for range stateCh {
  1824  		}
  1825  		_, err = c.Halt()
  1826  		assertNoError(err, t, "Halt")
  1827  		_, err = c.Restart(false)
  1828  		assertNoError(err, t, "Restart")
  1829  		bps, err := c.ListBreakpoints(false)
  1830  		assertNoError(err, t, "ListBreakpoints")
  1831  		for _, bp := range bps {
  1832  			if bp.Name == bpBefore.Name {
  1833  				if bp.Addr != addrBefore {
  1834  					t.Fatalf("Address changed after restart: %x %x", bp.Addr, addrBefore)
  1835  				}
  1836  				t.Logf("%x %x\n", bp.Addr, addrBefore)
  1837  			}
  1838  		}
  1839  	})
  1840  }
  1841  
  1842  func TestClientServer_SelectedGoroutineLoc(t *testing.T) {
  1843  	// CurrentLocation of SelectedGoroutine should reflect what's happening on
  1844  	// the thread running the goroutine, not the position the goroutine was in
  1845  	// the last time it was parked.
  1846  	protest.AllowRecording(t)
  1847  	withTestClient2("testprog", t, func(c service.Client) {
  1848  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: -11})
  1849  		assertNoError(err, t, "CreateBreakpoint")
  1850  
  1851  		s := <-c.Continue()
  1852  		assertNoError(s.Err, t, "Continue")
  1853  
  1854  		gloc := s.SelectedGoroutine.CurrentLoc
  1855  
  1856  		if gloc.PC != s.CurrentThread.PC {
  1857  			t.Errorf("mismatched PC %#x %#x", gloc.PC, s.CurrentThread.PC)
  1858  		}
  1859  
  1860  		if gloc.File != s.CurrentThread.File || gloc.Line != s.CurrentThread.Line {
  1861  			t.Errorf("mismatched file:lineno: %s:%d %s:%d", gloc.File, gloc.Line, s.CurrentThread.File, s.CurrentThread.Line)
  1862  		}
  1863  	})
  1864  }
  1865  
  1866  func TestClientServer_ReverseContinue(t *testing.T) {
  1867  	protest.AllowRecording(t)
  1868  	if testBackend != "rr" {
  1869  		t.Skip("backend is not rr")
  1870  	}
  1871  	withTestClient2("continuetestprog", t, func(c service.Client) {
  1872  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: -1})
  1873  		assertNoError(err, t, "CreateBreakpoint(main.main)")
  1874  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1})
  1875  		assertNoError(err, t, "CreateBreakpoint(main.sayhi)")
  1876  
  1877  		state := <-c.Continue()
  1878  		assertNoError(state.Err, t, "first continue")
  1879  		mainPC := state.CurrentThread.PC
  1880  		t.Logf("after first continue %#x", mainPC)
  1881  
  1882  		state = <-c.Continue()
  1883  		assertNoError(state.Err, t, "second continue")
  1884  		sayhiPC := state.CurrentThread.PC
  1885  		t.Logf("after second continue %#x", sayhiPC)
  1886  
  1887  		if mainPC == sayhiPC {
  1888  			t.Fatalf("expected different PC after second PC (%#x)", mainPC)
  1889  		}
  1890  
  1891  		state = <-c.Rewind()
  1892  		assertNoError(state.Err, t, "rewind")
  1893  
  1894  		if mainPC != state.CurrentThread.PC {
  1895  			t.Fatalf("Expected rewind to go back to the first breakpoint: %#x", state.CurrentThread.PC)
  1896  		}
  1897  	})
  1898  }
  1899  
  1900  func TestClientServer_collectBreakpointInfoOnNext(t *testing.T) {
  1901  	protest.AllowRecording(t)
  1902  	withTestClient2("testnextprog", t, func(c service.Client) {
  1903  		_, err := c.CreateBreakpoint(&api.Breakpoint{
  1904  			Addr:       findLocationHelper(t, c, "testnextprog.go:23", false, 1, 0)[0],
  1905  			Variables:  []string{"j"},
  1906  			LoadLocals: &normalLoadConfig})
  1907  		assertNoError(err, t, "CreateBreakpoint()")
  1908  		_, err = c.CreateBreakpoint(&api.Breakpoint{
  1909  			Addr:       findLocationHelper(t, c, "testnextprog.go:24", false, 1, 0)[0],
  1910  			Variables:  []string{"j"},
  1911  			LoadLocals: &normalLoadConfig})
  1912  		assertNoError(err, t, "CreateBreakpoint()")
  1913  
  1914  		stateBefore := <-c.Continue()
  1915  		assertNoError(stateBefore.Err, t, "Continue()")
  1916  		if stateBefore.CurrentThread.Line != 23 {
  1917  			t.Fatalf("wrong line number %s:%d, expected %d", stateBefore.CurrentThread.File, stateBefore.CurrentThread.Line, 23)
  1918  		}
  1919  		if bi := stateBefore.CurrentThread.BreakpointInfo; bi == nil || len(bi.Variables) != 1 {
  1920  			t.Fatalf("bad breakpoint info %v", bi)
  1921  		}
  1922  
  1923  		stateAfter, err := c.Next()
  1924  		assertNoError(err, t, "Next()")
  1925  		if stateAfter.CurrentThread.Line != 24 {
  1926  			t.Fatalf("wrong line number %s:%d, expected %d", stateAfter.CurrentThread.File, stateAfter.CurrentThread.Line, 24)
  1927  		}
  1928  		if bi := stateAfter.CurrentThread.BreakpointInfo; bi == nil || len(bi.Variables) != 1 {
  1929  			t.Fatalf("bad breakpoint info %v", bi)
  1930  		}
  1931  	})
  1932  }
  1933  
  1934  func TestClientServer_collectBreakpointInfoError(t *testing.T) {
  1935  	protest.AllowRecording(t)
  1936  	withTestClient2("testnextprog", t, func(c service.Client) {
  1937  		_, err := c.CreateBreakpoint(&api.Breakpoint{
  1938  			Addr:       findLocationHelper(t, c, "testnextprog.go:23", false, 1, 0)[0],
  1939  			Variables:  []string{"nonexistentvariable", "j"},
  1940  			LoadLocals: &normalLoadConfig})
  1941  		assertNoError(err, t, "CreateBreakpoint()")
  1942  		state := <-c.Continue()
  1943  		assertNoError(state.Err, t, "Continue()")
  1944  	})
  1945  }
  1946  
  1947  func TestClientServerConsistentExit(t *testing.T) {
  1948  	// This test is useful because it ensures that Next and Continue operations both
  1949  	// exit with the same exit status and details when the target application terminates.
  1950  	// Other program execution API calls should also behave in the same way.
  1951  	// An error should be present in state.Err.
  1952  	withTestClient2("pr1055", t, func(c service.Client) {
  1953  		fp := testProgPath(t, "pr1055")
  1954  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 12})
  1955  		if err != nil {
  1956  			t.Fatalf("Unexpected error: %v", err)
  1957  		}
  1958  		state := <-c.Continue()
  1959  		if state.Err != nil {
  1960  			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
  1961  		}
  1962  		state, err = c.Next()
  1963  		if err != nil {
  1964  			t.Fatalf("Unexpected error: %v", err)
  1965  		}
  1966  		if !state.Exited {
  1967  			t.Fatal("Process state is not exited")
  1968  		}
  1969  		if state.ExitStatus != 2 {
  1970  			t.Fatalf("Process exit status is not 2, got: %v", state.ExitStatus)
  1971  		}
  1972  
  1973  		// Ensure future commands also return the correct exit status.
  1974  		// Previously there was a bug where the command which prompted the
  1975  		// process to exit (continue, next, etc...) would return the corrent
  1976  		// exit status but subsequent commands would return an incorrect exit
  1977  		// status of 0. To test this we simply repeat the 'next' command and
  1978  		// ensure we get the correct response again.
  1979  		state, err = c.Next()
  1980  		if err != nil {
  1981  			t.Fatalf("Unexpected error: %v", err)
  1982  		}
  1983  		if !state.Exited {
  1984  			t.Fatal("Second process state is not exited")
  1985  		}
  1986  		if state.ExitStatus != 2 {
  1987  			t.Fatalf("Second process exit status is not 2, got: %v", state.ExitStatus)
  1988  		}
  1989  	})
  1990  }
  1991  
  1992  func TestClientServer_StepOutReturn(t *testing.T) {
  1993  	ver, _ := goversion.Parse(runtime.Version())
  1994  	if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) {
  1995  		t.Skip("return variables aren't marked on 1.9 or earlier")
  1996  	}
  1997  	withTestClient2("stepoutret", t, func(c service.Client) {
  1998  		c.SetReturnValuesLoadConfig(&normalLoadConfig)
  1999  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.stepout", Line: -1})
  2000  		assertNoError(err, t, "CreateBreakpoint()")
  2001  		stateBefore := <-c.Continue()
  2002  		assertNoError(stateBefore.Err, t, "Continue()")
  2003  		stateAfter, err := c.StepOut()
  2004  		assertNoError(err, t, "StepOut")
  2005  		ret := stateAfter.CurrentThread.ReturnValues
  2006  
  2007  		if len(ret) != 2 {
  2008  			t.Fatalf("wrong number of return values %v", ret)
  2009  		}
  2010  
  2011  		stridx := 0
  2012  		numidx := 1
  2013  
  2014  		if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 12) {
  2015  			// in 1.11 and earlier the order of return values in DWARF is
  2016  			// unspecified, in 1.11 and later it follows the order of definition
  2017  			// specified by the user
  2018  			for i := range ret {
  2019  				if ret[i].Name == "str" {
  2020  					stridx = i
  2021  					numidx = 1 - i
  2022  					break
  2023  				}
  2024  			}
  2025  		}
  2026  
  2027  		if ret[stridx].Name != "str" {
  2028  			t.Fatalf("(str) bad return value name %s", ret[stridx].Name)
  2029  		}
  2030  		if ret[stridx].Kind != reflect.String {
  2031  			t.Fatalf("(str) bad return value kind %v", ret[stridx].Kind)
  2032  		}
  2033  		if ret[stridx].Value != "return 47" {
  2034  			t.Fatalf("(str) bad return value %q", ret[stridx].Value)
  2035  		}
  2036  
  2037  		if ret[numidx].Name != "num" {
  2038  			t.Fatalf("(num) bad return value name %s", ret[numidx].Name)
  2039  		}
  2040  		if ret[numidx].Kind != reflect.Int {
  2041  			t.Fatalf("(num) bad return value kind %v", ret[numidx].Kind)
  2042  		}
  2043  		if ret[numidx].Value != "48" {
  2044  			t.Fatalf("(num) bad return value %s", ret[numidx].Value)
  2045  		}
  2046  	})
  2047  }
  2048  
  2049  func TestAcceptMulticlient(t *testing.T) {
  2050  	if testBackend == "rr" {
  2051  		t.Skip("recording not allowed for TestAcceptMulticlient")
  2052  	}
  2053  	listener, err := net.Listen("tcp", "127.0.0.1:0")
  2054  	if err != nil {
  2055  		t.Fatalf("couldn't start listener: %s\n", err)
  2056  	}
  2057  	serverDone := make(chan struct{})
  2058  	go func() {
  2059  		defer close(serverDone)
  2060  		defer listener.Close()
  2061  		disconnectChan := make(chan struct{})
  2062  		server := rpccommon.NewServer(&service.Config{
  2063  			Listener:       listener,
  2064  			ProcessArgs:    []string{protest.BuildFixture("testvariables2", 0).Path},
  2065  			AcceptMulti:    true,
  2066  			DisconnectChan: disconnectChan,
  2067  			Debugger: debugger.Config{
  2068  				Backend:     testBackend,
  2069  				ExecuteKind: debugger.ExecutingGeneratedTest,
  2070  			},
  2071  		})
  2072  		if err := server.Run(); err != nil {
  2073  			panic(err)
  2074  		}
  2075  		<-disconnectChan
  2076  		server.Stop()
  2077  	}()
  2078  	client1 := rpc2.NewClient(listener.Addr().String())
  2079  	client1.Disconnect(false)
  2080  
  2081  	client2 := rpc2.NewClient(listener.Addr().String())
  2082  	state := <-client2.Continue()
  2083  	if state.CurrentThread.Function.Name() != "main.main" {
  2084  		t.Fatalf("bad state after continue: %v\n", state)
  2085  	}
  2086  	client2.Detach(true)
  2087  	<-serverDone
  2088  }
  2089  
  2090  func TestForceStopWhileContinue(t *testing.T) {
  2091  	listener, err := net.Listen("tcp", "127.0.0.1:0")
  2092  	if err != nil {
  2093  		t.Fatalf("couldn't start listener: %s\n", err)
  2094  	}
  2095  	serverStopped := make(chan struct{})
  2096  	disconnectChan := make(chan struct{})
  2097  	go func() {
  2098  		defer close(serverStopped)
  2099  		defer listener.Close()
  2100  		server := rpccommon.NewServer(&service.Config{
  2101  			Listener:       listener,
  2102  			ProcessArgs:    []string{protest.BuildFixture("http_server", protest.AllNonOptimized).Path},
  2103  			AcceptMulti:    true,
  2104  			DisconnectChan: disconnectChan,
  2105  			Debugger: debugger.Config{
  2106  				Backend: "default",
  2107  			},
  2108  		})
  2109  		if err := server.Run(); err != nil {
  2110  			panic(err)
  2111  		}
  2112  		<-disconnectChan
  2113  		server.Stop()
  2114  	}()
  2115  
  2116  	client := rpc2.NewClient(listener.Addr().String())
  2117  	client.Disconnect(true /*continue*/)
  2118  	time.Sleep(10 * time.Millisecond) // give server time to start running
  2119  	close(disconnectChan)             // stop the server
  2120  	<-serverStopped                   // Stop() didn't block on detach because we halted first
  2121  }
  2122  
  2123  func TestClientServerFunctionCall(t *testing.T) {
  2124  	protest.MustSupportFunctionCalls(t, testBackend)
  2125  	withTestClient2("fncall", t, func(c service.Client) {
  2126  		c.SetReturnValuesLoadConfig(&normalLoadConfig)
  2127  		state := <-c.Continue()
  2128  		assertNoError(state.Err, t, "Continue()")
  2129  		beforeCallFn := state.CurrentThread.Function.Name()
  2130  		state, err := c.Call(-1, "call1(one, two)", false)
  2131  		assertNoError(err, t, "Call()")
  2132  		t.Logf("returned to %q", state.CurrentThread.Function.Name())
  2133  		if state.CurrentThread.Function.Name() != beforeCallFn {
  2134  			t.Fatalf("did not return to the calling function %q %q", beforeCallFn, state.CurrentThread.Function.Name())
  2135  		}
  2136  		if state.CurrentThread.ReturnValues == nil {
  2137  			t.Fatal("no return values on return from call")
  2138  		}
  2139  		t.Logf("Return values %v", state.CurrentThread.ReturnValues)
  2140  		if len(state.CurrentThread.ReturnValues) != 1 {
  2141  			t.Fatal("not enough return values")
  2142  		}
  2143  		if state.CurrentThread.ReturnValues[0].Value != "3" {
  2144  			t.Fatalf("wrong return value %s", state.CurrentThread.ReturnValues[0].Value)
  2145  		}
  2146  		state = <-c.Continue()
  2147  		if !state.Exited {
  2148  			t.Fatalf("expected process to exit after call %v", state.CurrentThread)
  2149  		}
  2150  	})
  2151  }
  2152  
  2153  func TestClientServerFunctionCallBadPos(t *testing.T) {
  2154  	protest.MustSupportFunctionCalls(t, testBackend)
  2155  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 12) {
  2156  		t.Skip("this is a safe point for Go 1.12")
  2157  	}
  2158  	withTestClient2("fncall", t, func(c service.Client) {
  2159  		loc, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "fmt/print.go:649", false, nil)
  2160  		assertNoError(err, t, "could not find location")
  2161  
  2162  		_, err = c.CreateBreakpoint(&api.Breakpoint{File: loc[0].File, Line: loc[0].Line})
  2163  		assertNoError(err, t, "CreateBreakpoin")
  2164  
  2165  		state := <-c.Continue()
  2166  		assertNoError(state.Err, t, "Continue()")
  2167  
  2168  		state = <-c.Continue()
  2169  		assertNoError(state.Err, t, "Continue()")
  2170  
  2171  		c.SetReturnValuesLoadConfig(&normalLoadConfig)
  2172  		state, err = c.Call(-1, "main.call1(main.zero, main.zero)", false)
  2173  		if err == nil || err.Error() != "call not at safe point" {
  2174  			t.Fatalf("wrong error or no error: %v", err)
  2175  		}
  2176  	})
  2177  }
  2178  
  2179  func TestClientServerFunctionCallPanic(t *testing.T) {
  2180  	protest.MustSupportFunctionCalls(t, testBackend)
  2181  	withTestClient2("fncall", t, func(c service.Client) {
  2182  		c.SetReturnValuesLoadConfig(&normalLoadConfig)
  2183  		state := <-c.Continue()
  2184  		assertNoError(state.Err, t, "Continue()")
  2185  		state, err := c.Call(-1, "callpanic()", false)
  2186  		assertNoError(err, t, "Call()")
  2187  		t.Logf("at: %s:%d", state.CurrentThread.File, state.CurrentThread.Line)
  2188  		if state.CurrentThread.ReturnValues == nil {
  2189  			t.Fatal("no return values on return from call")
  2190  		}
  2191  		t.Logf("Return values %v", state.CurrentThread.ReturnValues)
  2192  		if len(state.CurrentThread.ReturnValues) != 1 {
  2193  			t.Fatal("not enough return values")
  2194  		}
  2195  		if state.CurrentThread.ReturnValues[0].Name != "~panic" {
  2196  			t.Fatal("not a panic")
  2197  		}
  2198  		if state.CurrentThread.ReturnValues[0].Children[0].Value != "callpanic panicked" {
  2199  			t.Fatalf("wrong panic value %s", state.CurrentThread.ReturnValues[0].Children[0].Value)
  2200  		}
  2201  	})
  2202  }
  2203  
  2204  func TestClientServerFunctionCallStacktrace(t *testing.T) {
  2205  	if goversion.VersionAfterOrEqual(runtime.Version(), 1, 15) {
  2206  		t.Skip("Go 1.15 executes function calls in a different goroutine so the stack trace will not contain main.main or runtime.main")
  2207  	}
  2208  	protest.MustSupportFunctionCalls(t, testBackend)
  2209  	withTestClient2("fncall", t, func(c service.Client) {
  2210  		c.SetReturnValuesLoadConfig(&api.LoadConfig{FollowPointers: false, MaxStringLen: 2048})
  2211  		state := <-c.Continue()
  2212  		assertNoError(state.Err, t, "Continue()")
  2213  		state, err := c.Call(-1, "callstacktrace()", false)
  2214  		assertNoError(err, t, "Call()")
  2215  		t.Logf("at: %s:%d", state.CurrentThread.File, state.CurrentThread.Line)
  2216  		if state.CurrentThread.ReturnValues == nil {
  2217  			t.Fatal("no return values on return from call")
  2218  		}
  2219  		if len(state.CurrentThread.ReturnValues) != 1 || state.CurrentThread.ReturnValues[0].Kind != reflect.String {
  2220  			t.Fatal("not enough return values")
  2221  		}
  2222  		st := state.CurrentThread.ReturnValues[0].Value
  2223  		t.Logf("Returned stacktrace:\n%s", st)
  2224  
  2225  		if !strings.Contains(st, "main.callstacktrace") || !strings.Contains(st, "main.main") || !strings.Contains(st, "runtime.main") {
  2226  			t.Fatal("bad stacktrace returned")
  2227  		}
  2228  	})
  2229  }
  2230  
  2231  func TestAncestors(t *testing.T) {
  2232  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) {
  2233  		t.Skip("not supported on Go <= 1.10")
  2234  	}
  2235  	savedGodebug := os.Getenv("GODEBUG")
  2236  	os.Setenv("GODEBUG", "tracebackancestors=100")
  2237  	defer os.Setenv("GODEBUG", savedGodebug)
  2238  	withTestClient2("testnextprog", t, func(c service.Client) {
  2239  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.testgoroutine", Line: -1})
  2240  		assertNoError(err, t, "CreateBreakpoin")
  2241  		state := <-c.Continue()
  2242  		assertNoError(state.Err, t, "Continue()")
  2243  		ancestors, err := c.Ancestors(-1, 1000, 1000)
  2244  		assertNoError(err, t, "Ancestors")
  2245  		t.Logf("ancestors: %#v\n", ancestors)
  2246  		if len(ancestors) != 1 {
  2247  			t.Fatalf("expected only one ancestor got %d", len(ancestors))
  2248  		}
  2249  
  2250  		mainFound := false
  2251  		for _, ancestor := range ancestors {
  2252  			for _, frame := range ancestor.Stack {
  2253  				if frame.Function.Name() == "main.main" {
  2254  					mainFound = true
  2255  				}
  2256  			}
  2257  		}
  2258  		if !mainFound {
  2259  			t.Fatal("function main.main not found in any ancestor")
  2260  		}
  2261  	})
  2262  }
  2263  
  2264  type brokenRPCClient struct {
  2265  	client *rpc.Client
  2266  }
  2267  
  2268  func (c *brokenRPCClient) Detach(kill bool) error {
  2269  	defer c.client.Close()
  2270  	out := new(rpc2.DetachOut)
  2271  	return c.call("Detach", rpc2.DetachIn{Kill: kill}, out)
  2272  }
  2273  
  2274  func (c *brokenRPCClient) call(method string, args, reply interface{}) error {
  2275  	return c.client.Call("RPCServer."+method, args, reply)
  2276  }
  2277  
  2278  func TestUnknownMethodCall(t *testing.T) {
  2279  	clientConn, _ := startServer("continuetestprog", 0, t, [3]string{})
  2280  	client := &brokenRPCClient{jsonrpc.NewClient(clientConn)}
  2281  	client.call("SetApiVersion", api.SetAPIVersionIn{APIVersion: 2}, &api.SetAPIVersionOut{})
  2282  	defer client.Detach(true)
  2283  	var out int
  2284  	err := client.call("NonexistentRPCCall", nil, &out)
  2285  	assertError(err, t, "call()")
  2286  	if !strings.HasPrefix(err.Error(), "unknown method: ") {
  2287  		t.Errorf("wrong error message: %v", err)
  2288  	}
  2289  }
  2290  
  2291  func TestIssue1703(t *testing.T) {
  2292  	// Calling Disassemble when there is no current goroutine should work.
  2293  	withTestClient2("testnextprog", t, func(c service.Client) {
  2294  		locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "main.main", true, nil)
  2295  		assertNoError(err, t, "FindLocation")
  2296  		t.Logf("FindLocation: %#v", locs)
  2297  		text, err := c.DisassemblePC(api.EvalScope{GoroutineID: -1}, locs[0].PC, api.IntelFlavour)
  2298  		assertNoError(err, t, "DisassemblePC")
  2299  		t.Logf("text: %#v\n", text)
  2300  	})
  2301  }
  2302  
  2303  func TestRerecord(t *testing.T) {
  2304  	protest.AllowRecording(t)
  2305  	if testBackend != "rr" {
  2306  		t.Skip("only valid for recorded targets")
  2307  	}
  2308  	withTestClient2("testrerecord", t, func(c service.Client) {
  2309  		fp := testProgPath(t, "testrerecord")
  2310  		_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 10})
  2311  		assertNoError(err, t, "CreateBreakpoin")
  2312  
  2313  		gett := func() int {
  2314  			state := <-c.Continue()
  2315  			if state.Err != nil {
  2316  				t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
  2317  			}
  2318  
  2319  			vart, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "t", normalLoadConfig)
  2320  			assertNoError(err, t, "EvalVariable")
  2321  			if vart.Unreadable != "" {
  2322  				t.Fatalf("Could not read variable 't': %s\n", vart.Unreadable)
  2323  			}
  2324  
  2325  			t.Logf("Value of t is %s\n", vart.Value)
  2326  
  2327  			vartval, err := strconv.Atoi(vart.Value)
  2328  			assertNoError(err, t, "Parsing value of variable t")
  2329  			return vartval
  2330  		}
  2331  
  2332  		t0 := gett()
  2333  
  2334  		_, err = c.RestartFrom(false, "", false, nil, [3]string{}, false)
  2335  		assertNoError(err, t, "First restart")
  2336  		t1 := gett()
  2337  
  2338  		if t0 != t1 {
  2339  			t.Fatalf("Expected same value for t after restarting (without rerecording) %d %d", t0, t1)
  2340  		}
  2341  
  2342  		time.Sleep(2 * time.Second) // make sure that we're not running inside the same second
  2343  
  2344  		_, err = c.RestartFrom(true, "", false, nil, [3]string{}, false)
  2345  		assertNoError(err, t, "Second restart")
  2346  		t2 := gett()
  2347  
  2348  		if t0 == t2 {
  2349  			t.Fatalf("Expected new value for t after restarting (with rerecording) %d %d", t0, t2)
  2350  		}
  2351  	})
  2352  }
  2353  
  2354  func TestIssue1787(t *testing.T) {
  2355  	// Calling FunctionReturnLocations without a selected goroutine should
  2356  	// work.
  2357  	withTestClient2("testnextprog", t, func(c service.Client) {
  2358  		if c, _ := c.(*rpc2.RPCClient); c != nil {
  2359  			c.FunctionReturnLocations("main.main")
  2360  		}
  2361  	})
  2362  }
  2363  
  2364  func TestDoubleCreateBreakpoint(t *testing.T) {
  2365  	withTestClient2("testnextprog", t, func(c service.Client) {
  2366  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint", Tracepoint: true})
  2367  		assertNoError(err, t, "CreateBreakpoint 1")
  2368  
  2369  		bps, err := c.ListBreakpoints(false)
  2370  		assertNoError(err, t, "ListBreakpoints 1")
  2371  
  2372  		t.Logf("breakpoints before second call:")
  2373  		for _, bp := range bps {
  2374  			t.Logf("\t%v", bp)
  2375  		}
  2376  
  2377  		numBreakpoints := len(bps)
  2378  
  2379  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "secondbreakpoint", Tracepoint: true})
  2380  		assertError(err, t, "CreateBreakpoint 2") // breakpoint exists
  2381  
  2382  		bps, err = c.ListBreakpoints(false)
  2383  		assertNoError(err, t, "ListBreakpoints 2")
  2384  
  2385  		t.Logf("breakpoints after second call:")
  2386  		for _, bp := range bps {
  2387  			t.Logf("\t%v", bp)
  2388  		}
  2389  
  2390  		if len(bps) != numBreakpoints {
  2391  			t.Errorf("wrong number of breakpoints, got %d expected %d", len(bps), numBreakpoints)
  2392  		}
  2393  	})
  2394  }
  2395  
  2396  func TestStopRecording(t *testing.T) {
  2397  	protest.AllowRecording(t)
  2398  	if testBackend != "rr" {
  2399  		t.Skip("only for rr backend")
  2400  	}
  2401  	withTestClient2("sleep", t, func(c service.Client) {
  2402  		time.Sleep(time.Second)
  2403  		c.StopRecording()
  2404  		_, err := c.GetState()
  2405  		assertNoError(err, t, "GetState()")
  2406  
  2407  		// try rerecording
  2408  		go func() {
  2409  			c.RestartFrom(true, "", false, nil, [3]string{}, false)
  2410  		}()
  2411  
  2412  		time.Sleep(time.Second) // hopefully the re-recording started...
  2413  		c.StopRecording()
  2414  		_, err = c.GetState()
  2415  		assertNoError(err, t, "GetState()")
  2416  	})
  2417  }
  2418  
  2419  func TestClearLogicalBreakpoint(t *testing.T) {
  2420  	// Clearing a logical breakpoint should clear all associated physical
  2421  	// breakpoints.
  2422  	// Issue #1955.
  2423  	withTestClient2Extended("testinline", t, protest.EnableInlining, [3]string{}, func(c service.Client, fixture protest.Fixture) {
  2424  		bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.inlineThis"})
  2425  		assertNoError(err, t, "CreateBreakpoint()")
  2426  		t.Logf("breakpoint set at %#v", bp.Addrs)
  2427  		if len(bp.Addrs) < 2 {
  2428  			t.Fatal("Wrong number of addresses for main.inlineThis breakpoint")
  2429  		}
  2430  		_, err = c.ClearBreakpoint(bp.ID)
  2431  		assertNoError(err, t, "ClearBreakpoint()")
  2432  		bps, err := c.ListBreakpoints(false)
  2433  		assertNoError(err, t, "ListBreakpoints()")
  2434  		for _, curbp := range bps {
  2435  			if curbp.ID == bp.ID {
  2436  				t.Errorf("logical breakpoint still exists: %#v", curbp)
  2437  				break
  2438  			}
  2439  		}
  2440  	})
  2441  }
  2442  
  2443  func TestRedirects(t *testing.T) {
  2444  	const (
  2445  		infile  = "redirect-input.txt"
  2446  		outfile = "redirect-output.txt"
  2447  	)
  2448  	protest.AllowRecording(t)
  2449  	withTestClient2Extended("redirect", t, 0, [3]string{infile, outfile, ""}, func(c service.Client, fixture protest.Fixture) {
  2450  		outpath := filepath.Join(fixture.BuildDir, outfile)
  2451  		<-c.Continue()
  2452  		buf, err := ioutil.ReadFile(outpath)
  2453  		assertNoError(err, t, "Reading output file")
  2454  		t.Logf("output %q", buf)
  2455  		if !strings.HasPrefix(string(buf), "Redirect test") {
  2456  			t.Fatalf("Wrong output %q", string(buf))
  2457  		}
  2458  		os.Remove(outpath)
  2459  		if testBackend != "rr" {
  2460  			_, err = c.Restart(false)
  2461  			assertNoError(err, t, "Restart")
  2462  			<-c.Continue()
  2463  			buf2, err := ioutil.ReadFile(outpath)
  2464  			t.Logf("output %q", buf2)
  2465  			assertNoError(err, t, "Reading output file (second time)")
  2466  			if !strings.HasPrefix(string(buf2), "Redirect test") {
  2467  				t.Fatalf("Wrong output %q", string(buf2))
  2468  			}
  2469  			if string(buf2) == string(buf) {
  2470  				t.Fatalf("Expected output change got %q and %q", string(buf), string(buf2))
  2471  			}
  2472  			os.Remove(outpath)
  2473  		}
  2474  	})
  2475  }
  2476  
  2477  func TestIssue2162(t *testing.T) {
  2478  	if buildMode == "pie" || runtime.GOOS == "windows" {
  2479  		t.Skip("skip it for stepping into one place where no source for pc when on pie mode or windows")
  2480  	}
  2481  	withTestClient2("issue2162", t, func(c service.Client) {
  2482  		state, err := c.GetState()
  2483  		assertNoError(err, t, "GetState()")
  2484  		if state.CurrentThread.Function == nil {
  2485  			// Can't call Step if we don't have the source code of the current function
  2486  			return
  2487  		}
  2488  
  2489  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main"})
  2490  		if err != nil {
  2491  			t.Fatalf("Unexpected error: %v", err)
  2492  		}
  2493  
  2494  		_, err = c.Step()
  2495  		assertNoError(err, t, "Step()")
  2496  	})
  2497  }
  2498  
  2499  func TestDetachLeaveRunning(t *testing.T) {
  2500  	// See https://github.com/go-delve/delve/issues/2259
  2501  	if testBackend == "rr" {
  2502  		return
  2503  	}
  2504  
  2505  	listener, clientConn := service.ListenerPipe()
  2506  	defer listener.Close()
  2507  	var buildFlags protest.BuildFlags
  2508  	if buildMode == "pie" {
  2509  		buildFlags |= protest.BuildModePIE
  2510  	}
  2511  	fixture := protest.BuildFixture("testnextnethttp", buildFlags)
  2512  
  2513  	cmd := exec.Command(fixture.Path)
  2514  	cmd.Stdout = os.Stdout
  2515  	cmd.Stderr = os.Stderr
  2516  	assertNoError(cmd.Start(), t, "starting fixture")
  2517  	defer cmd.Process.Kill()
  2518  
  2519  	// wait for testnextnethttp to start listening
  2520  	t0 := time.Now()
  2521  	for {
  2522  		conn, err := net.Dial("tcp", "127.0.0.1:9191")
  2523  		if err == nil {
  2524  			conn.Close()
  2525  			break
  2526  		}
  2527  		time.Sleep(50 * time.Millisecond)
  2528  		if time.Since(t0) > 10*time.Second {
  2529  			t.Fatal("fixture did not start")
  2530  		}
  2531  	}
  2532  
  2533  	server := rpccommon.NewServer(&service.Config{
  2534  		Listener:   listener,
  2535  		APIVersion: 2,
  2536  		Debugger: debugger.Config{
  2537  			AttachPid:  cmd.Process.Pid,
  2538  			WorkingDir: ".",
  2539  			Backend:    testBackend,
  2540  		},
  2541  	})
  2542  	if err := server.Run(); err != nil {
  2543  		t.Fatal(err)
  2544  	}
  2545  
  2546  	client := rpc2.NewClientFromConn(clientConn)
  2547  	defer server.Stop()
  2548  	assertNoError(client.Detach(false), t, "Detach")
  2549  }
  2550  
  2551  func assertNoDuplicateBreakpoints(t *testing.T, c service.Client) {
  2552  	t.Helper()
  2553  	bps, _ := c.ListBreakpoints(false)
  2554  	seen := make(map[int]bool)
  2555  	for _, bp := range bps {
  2556  		t.Logf("%#v\n", bp)
  2557  		if seen[bp.ID] {
  2558  			t.Fatalf("duplicate breakpoint ID %d", bp.ID)
  2559  		}
  2560  		seen[bp.ID] = true
  2561  	}
  2562  }
  2563  
  2564  func TestToggleBreakpointRestart(t *testing.T) {
  2565  	// Checks that breakpoints IDs do not overlap after Restart if there are disabled breakpoints.
  2566  	withTestClient2("testtoggle", t, func(c service.Client) {
  2567  		bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint"})
  2568  		assertNoError(err, t, "CreateBreakpoint 1")
  2569  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 2, Name: "secondbreakpoint"})
  2570  		assertNoError(err, t, "CreateBreakpoint 2")
  2571  		_, err = c.ToggleBreakpoint(bp1.ID)
  2572  		assertNoError(err, t, "ToggleBreakpoint")
  2573  		_, err = c.Restart(false)
  2574  		assertNoError(err, t, "Restart")
  2575  		assertNoDuplicateBreakpoints(t, c)
  2576  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 3, Name: "thirdbreakpoint"})
  2577  		assertNoError(err, t, "CreateBreakpoint 3")
  2578  		assertNoDuplicateBreakpoints(t, c)
  2579  	})
  2580  }
  2581  
  2582  func TestStopServerWithClosedListener(t *testing.T) {
  2583  	// Checks that the error erturned by listener.Accept() is ignored when we
  2584  	// are trying to shutdown. See issue #1633.
  2585  	if testBackend == "rr" || buildMode == "pie" {
  2586  		t.Skip("N/A")
  2587  	}
  2588  	listener, err := net.Listen("tcp", "localhost:0")
  2589  	assertNoError(err, t, "listener")
  2590  	fixture := protest.BuildFixture("math", 0)
  2591  	server := rpccommon.NewServer(&service.Config{
  2592  		Listener:           listener,
  2593  		AcceptMulti:        false,
  2594  		APIVersion:         2,
  2595  		CheckLocalConnUser: true,
  2596  		DisconnectChan:     make(chan struct{}),
  2597  		ProcessArgs:        []string{fixture.Path},
  2598  		Debugger: debugger.Config{
  2599  			WorkingDir:  ".",
  2600  			Backend:     "default",
  2601  			Foreground:  false,
  2602  			BuildFlags:  "",
  2603  			ExecuteKind: debugger.ExecutingGeneratedFile,
  2604  		},
  2605  	})
  2606  	assertNoError(server.Run(), t, "blah")
  2607  	time.Sleep(1 * time.Second) // let server start
  2608  	server.Stop()
  2609  	listener.Close()
  2610  	time.Sleep(1 * time.Second) // give time to server to panic
  2611  }
  2612  
  2613  func TestGoroutinesGrouping(t *testing.T) {
  2614  	// Tests the goroutine grouping and filtering feature
  2615  	withTestClient2("goroutinegroup", t, func(c service.Client) {
  2616  		state := <-c.Continue()
  2617  		assertNoError(state.Err, t, "Continue")
  2618  		_, ggrp, _, _, err := c.ListGoroutinesWithFilter(0, 0, nil, &api.GoroutineGroupingOptions{GroupBy: api.GoroutineLabel, GroupByKey: "name", MaxGroupMembers: 5, MaxGroups: 10})
  2619  		assertNoError(err, t, "ListGoroutinesWithFilter (group by label)")
  2620  		t.Logf("%#v\n", ggrp)
  2621  		if len(ggrp) < 5 {
  2622  			t.Errorf("not enough groups %d\n", len(ggrp))
  2623  		}
  2624  		var unnamedCount int
  2625  		for i := range ggrp {
  2626  			if ggrp[i].Name == "name=" {
  2627  				unnamedCount = ggrp[i].Total
  2628  				break
  2629  			}
  2630  		}
  2631  		gs, _, _, _, err := c.ListGoroutinesWithFilter(0, 0, []api.ListGoroutinesFilter{{Kind: api.GoroutineLabel, Arg: "name="}}, nil)
  2632  		assertNoError(err, t, "ListGoroutinesWithFilter (filter unnamed)")
  2633  		if len(gs) != unnamedCount {
  2634  			t.Errorf("wrong number of goroutines returned by filter: %d (expected %d)\n", len(gs), unnamedCount)
  2635  		}
  2636  	})
  2637  }
  2638  
  2639  func TestLongStringArg(t *testing.T) {
  2640  	// Test the ability to load more elements of a string argument, this could
  2641  	// be broken if registerized variables are not handled correctly.
  2642  	withTestClient2("morestringarg", t, func(c service.Client) {
  2643  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.f"})
  2644  		assertNoError(err, t, "CreateBreakpoint")
  2645  		state := <-c.Continue()
  2646  		assertNoError(state.Err, t, "Continue")
  2647  
  2648  		test := func(name, val1, val2 string) uint64 {
  2649  			var1, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, name, normalLoadConfig)
  2650  			assertNoError(err, t, "EvalVariable")
  2651  			t.Logf("%#v\n", var1)
  2652  			if var1.Value != val1 {
  2653  				t.Fatalf("wrong value for variable: %q", var1.Value)
  2654  			}
  2655  			var2, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, fmt.Sprintf("(*(*%q)(%#x))[64:]", var1.Type, var1.Addr), normalLoadConfig)
  2656  			assertNoError(err, t, "EvalVariable")
  2657  			t.Logf("%#v\n", var2)
  2658  			if var2.Value != val2 {
  2659  				t.Fatalf("wrong value for variable: %q", var2.Value)
  2660  
  2661  			}
  2662  			return var1.Addr
  2663  		}
  2664  
  2665  		saddr := test("s", "very long string 01234567890123456789012345678901234567890123456", "7890123456789012345678901234567890123456789X")
  2666  		test("q", "very long string B 012345678901234567890123456789012345678901234", "567890123456789012345678901234567890123456789X2")
  2667  		saddr2 := test("s", "very long string 01234567890123456789012345678901234567890123456", "7890123456789012345678901234567890123456789X")
  2668  		if saddr != saddr2 {
  2669  			t.Fatalf("address of s changed (%#x %#x)", saddr, saddr2)
  2670  		}
  2671  	})
  2672  }
  2673  
  2674  func TestGenericsBreakpoint(t *testing.T) {
  2675  	if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) {
  2676  		t.Skip("generics")
  2677  	}
  2678  	// Tests that setting breakpoints inside a generic function with multiple
  2679  	// instantiations results in a single logical breakpoint with N physical
  2680  	// breakpoints (N = number of instantiations).
  2681  	withTestClient2("genericbp", t, func(c service.Client) {
  2682  		fp := testProgPath(t, "genericbp")
  2683  		bp, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 6})
  2684  		assertNoError(err, t, "CreateBreakpoint")
  2685  		if len(bp.Addrs) != 2 {
  2686  			t.Fatalf("wrong number of physical breakpoints: %d", len(bp.Addrs))
  2687  		}
  2688  
  2689  		frame1Line := func() int {
  2690  			frames, err := c.Stacktrace(-1, 10, 0, nil)
  2691  			assertNoError(err, t, "Stacktrace")
  2692  			return frames[1].Line
  2693  		}
  2694  
  2695  		state := <-c.Continue()
  2696  		assertNoError(state.Err, t, "Continue")
  2697  		if line := frame1Line(); line != 10 {
  2698  			t.Errorf("wrong line after first continue, expected 10, got %d", line)
  2699  		}
  2700  
  2701  		state = <-c.Continue()
  2702  		assertNoError(state.Err, t, "Continue")
  2703  		if line := frame1Line(); line != 11 {
  2704  			t.Errorf("wrong line after first continue, expected 11, got %d", line)
  2705  		}
  2706  
  2707  		if bp.FunctionName != "main.testfn" {
  2708  			t.Errorf("wrong name for breakpoint (CreateBreakpoint): %q", bp.FunctionName)
  2709  		}
  2710  
  2711  		bps, err := c.ListBreakpoints(false)
  2712  		assertNoError(err, t, "ListBreakpoints")
  2713  
  2714  		for _, bp := range bps {
  2715  			if bp.ID > 0 {
  2716  				if bp.FunctionName != "main.testfn" {
  2717  					t.Errorf("wrong name for breakpoint (ListBreakpoints): %q", bp.FunctionName)
  2718  				}
  2719  				break
  2720  			}
  2721  		}
  2722  
  2723  		rmbp, err := c.ClearBreakpoint(bp.ID)
  2724  		assertNoError(err, t, "ClearBreakpoint")
  2725  		if rmbp.FunctionName != "main.testfn" {
  2726  			t.Errorf("wrong name for breakpoint (ClearBreakpoint): %q", rmbp.FunctionName)
  2727  		}
  2728  	})
  2729  }
  2730  
  2731  func TestRestartRewindAfterEnd(t *testing.T) {
  2732  	if testBackend != "rr" {
  2733  		t.Skip("not relevant")
  2734  	}
  2735  	// Check that Restart works after the program has terminated, even if a
  2736  	// Continue is requested just before it.
  2737  	// Also check that Rewind can be used after the program has terminated.
  2738  	protest.AllowRecording(t)
  2739  	withTestClient2("math", t, func(c service.Client) {
  2740  		state := <-c.Continue()
  2741  		if !state.Exited {
  2742  			t.Fatalf("program did not exit")
  2743  		}
  2744  		state = <-c.Continue()
  2745  		if !state.Exited {
  2746  			t.Errorf("bad Continue return state: %v", state)
  2747  		}
  2748  		time.Sleep(1 * time.Second) // bug only happens if there is some time for the server to close the notify channel
  2749  		_, err := c.Restart(false)
  2750  		if err != nil {
  2751  			t.Fatalf("Restart: %v", err)
  2752  		}
  2753  		state = <-c.Continue()
  2754  		if !state.Exited {
  2755  			t.Fatalf("program did not exit exited")
  2756  		}
  2757  		_, err = c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 0})
  2758  		if err != nil {
  2759  			t.Fatalf("CreateBreakpoint: %v", err)
  2760  		}
  2761  		state = <-c.Rewind()
  2762  		if state.Exited || state.Err != nil {
  2763  			t.Errorf("bad Rewind return state: %v", state)
  2764  		}
  2765  		if state.CurrentThread.Line != 7 {
  2766  			t.Errorf("wrong stop location %s:%d", state.CurrentThread.File, state.CurrentThread.Line)
  2767  		}
  2768  	})
  2769  }
  2770  
  2771  func TestClientServer_SinglelineStringFormattedWithBigInts(t *testing.T) {
  2772  	// Check that variables that represent large numbers are represented correctly when using a formatting string
  2773  
  2774  	if runtime.GOARCH != "amd64" {
  2775  		t.Skip("N/A")
  2776  	}
  2777  	withTestClient2Extended("xmm0print/", t, 0, [3]string{}, func(c service.Client, fixture protest.Fixture) {
  2778  		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.VPSLLQ36", Line: 4})
  2779  		assertNoError(err, t, "CreateBreakpoint")
  2780  		state := <-c.Continue()
  2781  		if state.CurrentThread.Line != 8 {
  2782  			t.Fatalf("wrong location after continue %s:%d", state.CurrentThread.File, state.CurrentThread.Line)
  2783  		}
  2784  
  2785  		constvar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "9331634762088972288", normalLoadConfig)
  2786  		assertNoError(err, t, "ErrVariable(9331634762088972288)")
  2787  		out := constvar.SinglelineStringFormatted("%X")
  2788  		t.Logf("constant: %q\n", out)
  2789  		if out != "8180A06000000000" {
  2790  			t.Errorf("expected \"8180A06000000000\" got %q when printing constant", out)
  2791  		}
  2792  
  2793  		xmm0var, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "XMM0.uint64", normalLoadConfig)
  2794  		assertNoError(err, t, "EvalVariable(XMM0.uint64)")
  2795  
  2796  		expected := []string{
  2797  			"9331634762088972288", "8180A06000000000",
  2798  			"9331634762088972288", "8180A06000000000",
  2799  			"9259436018245828608", "8080200000000000",
  2800  			"9259436018245828608", "8080200000000000",
  2801  		}
  2802  
  2803  		for i := range xmm0var.Children {
  2804  			child := &xmm0var.Children[i]
  2805  			if child.Kind != reflect.Uint64 {
  2806  				t.Errorf("wrong kind for variable %s\n", child.Kind)
  2807  			}
  2808  			out1 := child.SinglelineString()
  2809  			out2 := child.SinglelineStringFormatted("%X")
  2810  			t.Logf("%q %q\n", out1, out2)
  2811  			if out1 != expected[i*2] {
  2812  				t.Errorf("for child %d expected %s got %s (decimal)", i, expected[i*2], out1)
  2813  			}
  2814  			if out2 != expected[i*2+1] {
  2815  				t.Errorf("for child %d expected %s got %s (hexadecimal)", i, expected[i*2+1], out2)
  2816  			}
  2817  		}
  2818  	})
  2819  }