Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

169 rindas
5.0 KiB

  1. // Copyright 2016 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package breakpoints
  15. import (
  16. "testing"
  17. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug"
  18. "cloud.google.com/go/internal/testutil"
  19. cd "google.golang.org/api/clouddebugger/v2"
  20. )
  21. var (
  22. testPC1 uint64 = 0x1234
  23. testPC2 uint64 = 0x5678
  24. testPC3 uint64 = 0x3333
  25. testFile = "foo.go"
  26. testLine uint64 = 42
  27. testLine2 uint64 = 99
  28. testLogPC uint64 = 0x9abc
  29. testLogLine uint64 = 43
  30. testBadPC uint64 = 0xdef0
  31. testBadLine uint64 = 44
  32. testBP = &cd.Breakpoint{
  33. Action: "CAPTURE",
  34. Id: "TestBreakpoint",
  35. IsFinalState: false,
  36. Location: &cd.SourceLocation{Path: testFile, Line: int64(testLine)},
  37. }
  38. testBP2 = &cd.Breakpoint{
  39. Action: "CAPTURE",
  40. Id: "TestBreakpoint2",
  41. IsFinalState: false,
  42. Location: &cd.SourceLocation{Path: testFile, Line: int64(testLine2)},
  43. }
  44. testLogBP = &cd.Breakpoint{
  45. Action: "LOG",
  46. Id: "TestLogBreakpoint",
  47. IsFinalState: false,
  48. Location: &cd.SourceLocation{Path: testFile, Line: int64(testLogLine)},
  49. }
  50. testBadBP = &cd.Breakpoint{
  51. Action: "BEEP",
  52. Id: "TestBadBreakpoint",
  53. IsFinalState: false,
  54. Location: &cd.SourceLocation{Path: testFile, Line: int64(testBadLine)},
  55. }
  56. )
  57. func TestBreakpointStore(t *testing.T) {
  58. p := &Program{breakpointPCs: make(map[uint64]bool)}
  59. bs := NewBreakpointStore(p)
  60. checkPCs := func(expected map[uint64]bool) {
  61. if !testutil.Equal(p.breakpointPCs, expected) {
  62. t.Errorf("got breakpoint map %v want %v", p.breakpointPCs, expected)
  63. }
  64. }
  65. bs.ProcessBreakpointList([]*cd.Breakpoint{testBP, testBP2, testLogBP, testBadBP})
  66. checkPCs(map[uint64]bool{
  67. testPC1: true,
  68. testPC2: true,
  69. testPC3: true,
  70. testLogPC: true,
  71. })
  72. for _, test := range []struct {
  73. pc uint64
  74. expected []*cd.Breakpoint
  75. }{
  76. {testPC1, []*cd.Breakpoint{testBP}},
  77. {testPC2, []*cd.Breakpoint{testBP}},
  78. {testPC3, []*cd.Breakpoint{testBP2}},
  79. {testLogPC, []*cd.Breakpoint{testLogBP}},
  80. } {
  81. if bps := bs.BreakpointsAtPC(test.pc); !testutil.Equal(bps, test.expected) {
  82. t.Errorf("BreakpointsAtPC(%x): got %v want %v", test.pc, bps, test.expected)
  83. }
  84. }
  85. testBP2.IsFinalState = true
  86. bs.ProcessBreakpointList([]*cd.Breakpoint{testBP, testBP2, testLogBP, testBadBP})
  87. checkPCs(map[uint64]bool{
  88. testPC1: true,
  89. testPC2: true,
  90. testPC3: false,
  91. testLogPC: true,
  92. })
  93. bs.RemoveBreakpoint(testBP)
  94. checkPCs(map[uint64]bool{
  95. testPC1: false,
  96. testPC2: false,
  97. testPC3: false,
  98. testLogPC: true,
  99. })
  100. for _, pc := range []uint64{testPC1, testPC2, testPC3} {
  101. if bps := bs.BreakpointsAtPC(pc); len(bps) != 0 {
  102. t.Errorf("BreakpointsAtPC(%x): got %v want []", pc, bps)
  103. }
  104. }
  105. // bs.ErrorBreakpoints should return testBadBP.
  106. errorBps := bs.ErrorBreakpoints()
  107. if len(errorBps) != 1 {
  108. t.Errorf("ErrorBreakpoints: got %d want 1", len(errorBps))
  109. } else {
  110. bp := errorBps[0]
  111. if bp.Id != testBadBP.Id {
  112. t.Errorf("ErrorBreakpoints: got id %q want 1", bp.Id)
  113. }
  114. if bp.Status == nil || !bp.Status.IsError {
  115. t.Errorf("ErrorBreakpoints: got %v, want error", bp.Status)
  116. }
  117. }
  118. // The error should have been removed by the last call to bs.ErrorBreakpoints.
  119. errorBps = bs.ErrorBreakpoints()
  120. if len(errorBps) != 0 {
  121. t.Errorf("ErrorBreakpoints: got %d want 0", len(errorBps))
  122. }
  123. // Even if testBadBP is sent in a new list, it should not be returned again.
  124. bs.ProcessBreakpointList([]*cd.Breakpoint{testBadBP})
  125. errorBps = bs.ErrorBreakpoints()
  126. if len(errorBps) != 0 {
  127. t.Errorf("ErrorBreakpoints: got %d want 0", len(errorBps))
  128. }
  129. }
  130. // Program implements the similarly-named interface in x/debug.
  131. // ValueCollector should only call its BreakpointAtLine and DeleteBreakpoints methods.
  132. type Program struct {
  133. debug.Program
  134. // breakpointPCs contains the state of code breakpoints -- true if the
  135. // breakpoint is currently set, false if it has been deleted.
  136. breakpointPCs map[uint64]bool
  137. }
  138. func (p *Program) BreakpointAtLine(file string, line uint64) ([]uint64, error) {
  139. var pcs []uint64
  140. switch {
  141. case file == testFile && line == testLine:
  142. pcs = []uint64{testPC1, testPC2}
  143. case file == testFile && line == testLine2:
  144. pcs = []uint64{testPC3}
  145. case file == testFile && line == testLogLine:
  146. pcs = []uint64{testLogPC}
  147. default:
  148. pcs = []uint64{0xbad}
  149. }
  150. for _, pc := range pcs {
  151. p.breakpointPCs[pc] = true
  152. }
  153. return pcs, nil
  154. }
  155. func (p *Program) DeleteBreakpoints(pcs []uint64) error {
  156. for _, pc := range pcs {
  157. p.breakpointPCs[pc] = false
  158. }
  159. return nil
  160. }