proctl_test.go 5.2 KB
Newer Older
D
Derek Parker 已提交
1
package proctl_test
D
Derek Parker 已提交
2 3

import (
4
	"bytes"
5
	"path/filepath"
D
Derek Parker 已提交
6 7
	"testing"

D
Derek Parker 已提交
8 9
	"github.com/derekparker/delve/helper"
	"github.com/derekparker/delve/proctl"
D
Derek Parker 已提交
10
)
11

12 13
func dataAtAddr(pid int, addr uint64) ([]byte, error) {
	data := make([]byte, 1)
D
Derek Parker 已提交
14
	_, err := proctl.ReadMemory(pid, uintptr(addr), data)
15 16 17 18 19 20 21
	if err != nil {
		return nil, err
	}

	return data, nil
}

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
func assertNoError(err error, t *testing.T, s string) {
	if err != nil {
		t.Fatal(s, ":", err)
	}
}

func currentPC(p *proctl.DebuggedProcess, t *testing.T) uint64 {
	pc, err := p.CurrentPC()
	if err != nil {
		t.Fatal(err)
	}

	return pc
}

D
Derek Parker 已提交
37
func currentLineNumber(p *proctl.DebuggedProcess, t *testing.T) (string, int) {
38
	pc := currentPC(p, t)
D
Derek Parker 已提交
39
	f, l, _ := p.GoSymTable.PCToLine(pc)
40

D
Derek Parker 已提交
41
	return f, l
42 43
}

44
func TestStep(t *testing.T) {
45
	helper.WithTestProcess("../_fixtures/testprog", t, func(p *proctl.DebuggedProcess) {
46 47 48 49 50 51 52
		helloworldfunc := p.GoSymTable.LookupFunc("main.helloworld")
		helloworldaddr := helloworldfunc.Entry

		_, err := p.Break(uintptr(helloworldaddr))
		assertNoError(err, t, "Break()")
		assertNoError(p.Continue(), t, "Continue()")

D
Derek Parker 已提交
53
		regs := helper.GetRegisters(p, t)
54
		rip := regs.PC()
55

56
		err = p.Step()
D
Derek Parker 已提交
57
		assertNoError(err, t, "Step()")
58

D
Derek Parker 已提交
59
		regs = helper.GetRegisters(p, t)
60 61 62 63 64
		if rip >= regs.PC() {
			t.Errorf("Expected %#v to be greater than %#v", regs.PC(), rip)
		}
	})
}
65

66
func TestContinue(t *testing.T) {
67
	helper.WithTestProcess("../_fixtures/continuetestprog", t, func(p *proctl.DebuggedProcess) {
68
		err := p.Continue()
69 70 71 72 73
		if err != nil {
			if _, ok := err.(proctl.ProcessExitedError); !ok {
				t.Fatal(err)
			}
		}
74

75 76
		if p.Status().ExitStatus() != 0 {
			t.Fatal("Process did not exit successfully", p.Status().ExitStatus())
77 78
		}
	})
79
}
80 81

func TestBreakPoint(t *testing.T) {
82
	helper.WithTestProcess("../_fixtures/testprog", t, func(p *proctl.DebuggedProcess) {
83
		sleepytimefunc := p.GoSymTable.LookupFunc("main.helloworld")
84 85 86
		sleepyaddr := sleepytimefunc.Entry

		bp, err := p.Break(uintptr(sleepyaddr))
D
Derek Parker 已提交
87
		assertNoError(err, t, "Break()")
88 89 90

		breakpc := bp.Addr + 1
		err = p.Continue()
D
Derek Parker 已提交
91
		assertNoError(err, t, "Continue()")
92

93 94 95 96
		pc, err := p.CurrentPC()
		if err != nil {
			t.Fatal(err)
		}
97 98

		if pc != breakpc {
99 100
			f, l, _ := p.GoSymTable.PCToLine(pc)
			t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, breakpc)
101 102 103
		}

		err = p.Step()
104
		assertNoError(err, t, "Step()")
105

106 107 108 109
		pc, err = p.CurrentPC()
		if err != nil {
			t.Fatal(err)
		}
110 111 112 113 114

		if pc == breakpc {
			t.Fatalf("Step not respected:\nPC:%d\nFN:%d\n", pc, breakpc)
		}
	})
115
}
116

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
func TestBreakPointInSeperateGoRoutine(t *testing.T) {
	helper.WithTestProcess("../_fixtures/testthreads", t, func(p *proctl.DebuggedProcess) {
		fn := p.GoSymTable.LookupFunc("main.anotherthread")
		if fn == nil {
			t.Fatal("No fn exists")
		}

		_, err := p.Break(uintptr(fn.Entry))
		if err != nil {
			t.Fatal(err)
		}

		err = p.Continue()
		if err != nil {
			t.Fatal(err)
		}

		pc, err := p.CurrentPC()
		if err != nil {
			t.Fatal(err)
		}

		f, l, _ := p.GoSymTable.PCToLine(pc)
		if f != "testthreads.go" && l != 8 {
			t.Fatal("Program did not hit breakpoint")
		}
	})
}

146
func TestBreakPointWithNonExistantFunction(t *testing.T) {
147
	helper.WithTestProcess("../_fixtures/testprog", t, func(p *proctl.DebuggedProcess) {
148 149 150 151 152
		_, err := p.Break(uintptr(0))
		if err == nil {
			t.Fatal("Should not be able to break at non existant function")
		}
	})
153
}
154 155

func TestClearBreakPoint(t *testing.T) {
156
	helper.WithTestProcess("../_fixtures/testprog", t, func(p *proctl.DebuggedProcess) {
157 158
		fn := p.GoSymTable.LookupFunc("main.sleepytime")
		bp, err := p.Break(uintptr(fn.Entry))
D
Derek Parker 已提交
159
		assertNoError(err, t, "Break()")
160 161 162 163 164 165 166

		int3, err := dataAtAddr(p.Pid, bp.Addr)
		if err != nil {
			t.Fatal(err)
		}

		bp, err = p.Clear(fn.Entry)
D
Derek Parker 已提交
167
		assertNoError(err, t, "Clear()")
168 169 170 171 172 173 174 175 176 177

		data, err := dataAtAddr(p.Pid, bp.Addr)
		if err != nil {
			t.Fatal(err)
		}

		if bytes.Equal(data, int3) {
			t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
		}

178
		if len(p.BreakPoints) != 0 {
179 180 181
			t.Fatal("Breakpoint not removed internally")
		}
	})
182
}
183 184 185

func TestNext(t *testing.T) {
	var (
186 187
		err            error
		executablePath = "../_fixtures/testnextprog"
188 189 190 191 192
	)

	testcases := []struct {
		begin, end int
	}{
D
Derek Parker 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
		{19, 20},
		{20, 23},
		{23, 24},
		{24, 26},
		{26, 31},
		{31, 23},
		{23, 24},
		{24, 26},
		{26, 31},
		{31, 23},
		{23, 24},
		{24, 26},
		{26, 27},
		{27, 34},
		{34, 35},
D
Derek Parker 已提交
208
		{35, 41},
209
		{41, 40},
D
Derek Parker 已提交
210
		{40, 41},
211 212 213 214 215 216 217
	}

	fp, err := filepath.Abs("../_fixtures/testnextprog.go")
	if err != nil {
		t.Fatal(err)
	}

218
	helper.WithTestProcess(executablePath, t, func(p *proctl.DebuggedProcess) {
219
		pc, _, _ := p.GoSymTable.LineToPC(fp, testcases[0].begin)
D
Derek Parker 已提交
220
		_, err := p.Break(uintptr(pc))
221 222
		assertNoError(err, t, "Break()")
		assertNoError(p.Continue(), t, "Continue()")
223 224

		for _, tc := range testcases {
D
Derek Parker 已提交
225
			f, ln := currentLineNumber(p, t)
226
			if ln != tc.begin {
D
Derek Parker 已提交
227
				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, f, ln)
228 229 230 231
			}

			assertNoError(p.Next(), t, "Next() returned an error")

D
Derek Parker 已提交
232
			f, ln = currentLineNumber(p, t)
233
			if ln != tc.end {
D
Derek Parker 已提交
234
				t.Fatalf("Program did not continue to correct next location expected %d was %s:%d", tc.end, f, ln)
235 236
			}
		}
237

238
		if len(p.BreakPoints) != 1 {
D
Derek Parker 已提交
239
			t.Fatal("Not all breakpoints were cleaned up", len(p.BreakPoints))
240
		}
241 242
	})
}