No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

254 líneas
6.8 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 controller
  15. import (
  16. "bytes"
  17. "context"
  18. "errors"
  19. "fmt"
  20. "strconv"
  21. "testing"
  22. "golang.org/x/oauth2"
  23. cd "google.golang.org/api/clouddebugger/v2"
  24. "google.golang.org/api/googleapi"
  25. )
  26. const (
  27. testDebuggeeID = "d12345"
  28. testBreakpointID = "bp12345"
  29. )
  30. var (
  31. // The sequence of wait tokens in List requests and responses.
  32. expectedWaitToken = []string{"init", "token1", "token2", "token1", "token1"}
  33. // The set of breakpoints returned from each List call.
  34. expectedBreakpoints = [][]*cd.Breakpoint{
  35. nil,
  36. {
  37. &cd.Breakpoint{
  38. Id: testBreakpointID,
  39. IsFinalState: false,
  40. Location: &cd.SourceLocation{Line: 42, Path: "foo.go"},
  41. },
  42. },
  43. nil,
  44. }
  45. abortedError error = &googleapi.Error{
  46. Code: 409,
  47. Message: "Conflict",
  48. Body: `{
  49. "error": {
  50. "errors": [
  51. {
  52. "domain": "global",
  53. "reason": "aborted",
  54. "message": "Conflict"
  55. }
  56. ],
  57. "code": 409,
  58. "message": "Conflict"
  59. }
  60. }`,
  61. Errors: []googleapi.ErrorItem{
  62. {Reason: "aborted", Message: "Conflict"},
  63. },
  64. }
  65. backendError error = &googleapi.Error{
  66. Code: 503,
  67. Message: "Backend Error",
  68. Body: `{
  69. "error": {
  70. "errors": [
  71. {
  72. "domain": "global",
  73. "reason": "backendError",
  74. "message": "Backend Error"
  75. }
  76. ],
  77. "code": 503,
  78. "message": "Backend Error"
  79. }
  80. }`,
  81. Errors: []googleapi.ErrorItem{
  82. {Reason: "backendError", Message: "Backend Error"},
  83. },
  84. }
  85. )
  86. type mockService struct {
  87. t *testing.T
  88. listCallsSeen int
  89. registerCallsSeen int
  90. }
  91. func (s *mockService) Register(ctx context.Context, req *cd.RegisterDebuggeeRequest) (*cd.RegisterDebuggeeResponse, error) {
  92. s.registerCallsSeen++
  93. if req.Debuggee == nil {
  94. s.t.Errorf("missing debuggee")
  95. return nil, nil
  96. }
  97. if req.Debuggee.AgentVersion == "" {
  98. s.t.Errorf("missing agent version")
  99. }
  100. if req.Debuggee.Description == "" {
  101. s.t.Errorf("missing debuglet description")
  102. }
  103. if req.Debuggee.Project == "" {
  104. s.t.Errorf("missing project id")
  105. }
  106. if req.Debuggee.Uniquifier == "" {
  107. s.t.Errorf("missing uniquifier")
  108. }
  109. return &cd.RegisterDebuggeeResponse{
  110. Debuggee: &cd.Debuggee{Id: testDebuggeeID},
  111. }, nil
  112. }
  113. func (s *mockService) Update(ctx context.Context, id, breakpointID string, req *cd.UpdateActiveBreakpointRequest) (*cd.UpdateActiveBreakpointResponse, error) {
  114. if id != testDebuggeeID {
  115. s.t.Errorf("got debuggee ID %s want %s", id, testDebuggeeID)
  116. }
  117. if breakpointID != testBreakpointID {
  118. s.t.Errorf("got breakpoint ID %s want %s", breakpointID, testBreakpointID)
  119. }
  120. if !req.Breakpoint.IsFinalState {
  121. s.t.Errorf("got IsFinalState = false, want true")
  122. }
  123. return nil, nil
  124. }
  125. func (s *mockService) List(ctx context.Context, id, waitToken string) (*cd.ListActiveBreakpointsResponse, error) {
  126. if id != testDebuggeeID {
  127. s.t.Errorf("got debuggee ID %s want %s", id, testDebuggeeID)
  128. }
  129. if waitToken != expectedWaitToken[s.listCallsSeen] {
  130. s.t.Errorf("got wait token %s want %s", waitToken, expectedWaitToken[s.listCallsSeen])
  131. }
  132. s.listCallsSeen++
  133. if s.listCallsSeen == 4 {
  134. return nil, backendError
  135. }
  136. if s.listCallsSeen == 5 {
  137. return nil, abortedError
  138. }
  139. resp := &cd.ListActiveBreakpointsResponse{
  140. Breakpoints: expectedBreakpoints[s.listCallsSeen-1],
  141. NextWaitToken: expectedWaitToken[s.listCallsSeen],
  142. }
  143. return resp, nil
  144. }
  145. func TestDebugletControllerClientLibrary(t *testing.T) {
  146. var (
  147. m *mockService
  148. c *Controller
  149. list *cd.ListActiveBreakpointsResponse
  150. err error
  151. )
  152. m = &mockService{t: t}
  153. newService = func(context.Context, oauth2.TokenSource) (serviceInterface, error) { return m, nil }
  154. opts := Options{
  155. ProjectNumber: "5",
  156. ProjectID: "p1",
  157. AppModule: "mod1",
  158. AppVersion: "v1",
  159. }
  160. ctx := context.Background()
  161. if c, err = NewController(ctx, opts); err != nil {
  162. t.Fatal("Initializing Controller client:", err)
  163. }
  164. if err := validateLabels(c, opts); err != nil {
  165. t.Fatalf("Invalid labels:\n%v", err)
  166. }
  167. if list, err = c.List(ctx); err != nil {
  168. t.Fatal("List:", err)
  169. }
  170. if m.registerCallsSeen != 1 {
  171. t.Errorf("saw %d Register calls, want 1", m.registerCallsSeen)
  172. }
  173. if list, err = c.List(ctx); err != nil {
  174. t.Fatal("List:", err)
  175. }
  176. if len(list.Breakpoints) != 1 {
  177. t.Fatalf("got %d breakpoints, want 1", len(list.Breakpoints))
  178. }
  179. if err = c.Update(ctx, list.Breakpoints[0].Id, &cd.Breakpoint{Id: testBreakpointID, IsFinalState: true}); err != nil {
  180. t.Fatal("Update:", err)
  181. }
  182. if list, err = c.List(ctx); err != nil {
  183. t.Fatal("List:", err)
  184. }
  185. if m.registerCallsSeen != 1 {
  186. t.Errorf("saw %d Register calls, want 1", m.registerCallsSeen)
  187. }
  188. // The next List call produces an error that should cause a Register call.
  189. if list, err = c.List(ctx); err == nil {
  190. t.Fatal("List should have returned an error")
  191. }
  192. if m.registerCallsSeen != 2 {
  193. t.Errorf("saw %d Register calls, want 2", m.registerCallsSeen)
  194. }
  195. // The next List call produces an error that should not cause a Register call.
  196. if list, err = c.List(ctx); err == nil {
  197. t.Fatal("List should have returned an error")
  198. }
  199. if m.registerCallsSeen != 2 {
  200. t.Errorf("saw %d Register calls, want 2", m.registerCallsSeen)
  201. }
  202. if m.listCallsSeen != 5 {
  203. t.Errorf("saw %d list calls, want 5", m.listCallsSeen)
  204. }
  205. }
  206. func validateLabels(c *Controller, o Options) error {
  207. errMsg := new(bytes.Buffer)
  208. if m, ok := c.labels["module"]; ok {
  209. if m != o.AppModule {
  210. errMsg.WriteString(fmt.Sprintf("label module: want %s, got %s\n", o.AppModule, m))
  211. }
  212. } else {
  213. errMsg.WriteString("Missing \"module\" label\n")
  214. }
  215. if v, ok := c.labels["version"]; ok {
  216. if v != o.AppVersion {
  217. errMsg.WriteString(fmt.Sprintf("label version: want %s, got %s\n", o.AppVersion, v))
  218. }
  219. } else {
  220. errMsg.WriteString("Missing \"version\" label\n")
  221. }
  222. if mv, ok := c.labels["minorversion"]; ok {
  223. if _, err := strconv.Atoi(mv); err != nil {
  224. errMsg.WriteString(fmt.Sprintln("label minorversion: not a numeric string:", mv))
  225. }
  226. } else {
  227. errMsg.WriteString("Missing \"minorversion\" label\n")
  228. }
  229. if errMsg.Len() != 0 {
  230. return errors.New(errMsg.String())
  231. }
  232. return nil
  233. }
  234. func TestIsAbortedError(t *testing.T) {
  235. if !isAbortedError(abortedError) {
  236. t.Errorf("isAborted(%+v): got false, want true", abortedError)
  237. }
  238. if isAbortedError(backendError) {
  239. t.Errorf("isAborted(%+v): got true, want false", backendError)
  240. }
  241. }