您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

565 行
13 KiB

  1. // Copyright 2017 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 rpcreplay
  15. import (
  16. "bytes"
  17. "errors"
  18. "io"
  19. "strings"
  20. "testing"
  21. "cloud.google.com/go/internal/testutil"
  22. ipb "cloud.google.com/go/rpcreplay/proto/intstore"
  23. rpb "cloud.google.com/go/rpcreplay/proto/rpcreplay"
  24. "github.com/golang/protobuf/proto"
  25. "github.com/google/go-cmp/cmp"
  26. "golang.org/x/net/context"
  27. "google.golang.org/grpc"
  28. "google.golang.org/grpc/codes"
  29. "google.golang.org/grpc/status"
  30. )
  31. func TestRecordIO(t *testing.T) {
  32. buf := &bytes.Buffer{}
  33. want := []byte{1, 2, 3}
  34. if err := writeRecord(buf, want); err != nil {
  35. t.Fatal(err)
  36. }
  37. got, err := readRecord(buf)
  38. if err != nil {
  39. t.Fatal(err)
  40. }
  41. if !bytes.Equal(got, want) {
  42. t.Errorf("got %v, want %v", got, want)
  43. }
  44. }
  45. func TestHeaderIO(t *testing.T) {
  46. buf := &bytes.Buffer{}
  47. want := []byte{1, 2, 3}
  48. if err := writeHeader(buf, want); err != nil {
  49. t.Fatal(err)
  50. }
  51. got, err := readHeader(buf)
  52. if err != nil {
  53. t.Fatal(err)
  54. }
  55. if !testutil.Equal(got, want) {
  56. t.Errorf("got %v, want %v", got, want)
  57. }
  58. // readHeader errors
  59. for _, contents := range []string{"", "badmagic", "gRPCReplay"} {
  60. if _, err := readHeader(bytes.NewBufferString(contents)); err == nil {
  61. t.Errorf("%q: got nil, want error", contents)
  62. }
  63. }
  64. }
  65. func TestEntryIO(t *testing.T) {
  66. for i, want := range []*entry{
  67. {
  68. kind: rpb.Entry_REQUEST,
  69. method: "method",
  70. msg: message{msg: &rpb.Entry{}},
  71. refIndex: 7,
  72. },
  73. {
  74. kind: rpb.Entry_RESPONSE,
  75. method: "method",
  76. msg: message{err: status.Error(codes.NotFound, "not found")},
  77. refIndex: 8,
  78. },
  79. {
  80. kind: rpb.Entry_RECV,
  81. method: "method",
  82. msg: message{err: io.EOF},
  83. refIndex: 3,
  84. },
  85. } {
  86. buf := &bytes.Buffer{}
  87. if err := writeEntry(buf, want); err != nil {
  88. t.Fatal(err)
  89. }
  90. got, err := readEntry(buf)
  91. if err != nil {
  92. t.Fatal(err)
  93. }
  94. if !got.equal(want) {
  95. t.Errorf("#%d: got %v, want %v", i, got, want)
  96. }
  97. }
  98. }
  99. var initialState = []byte{1, 2, 3}
  100. func TestRecord(t *testing.T) {
  101. srv := newIntStoreServer()
  102. defer srv.stop()
  103. buf := record(t, srv)
  104. gotIstate, err := readHeader(buf)
  105. if err != nil {
  106. t.Fatal(err)
  107. }
  108. if !testutil.Equal(gotIstate, initialState) {
  109. t.Fatalf("got %v, want %v", gotIstate, initialState)
  110. }
  111. item := &ipb.Item{Name: "a", Value: 1}
  112. wantEntries := []*entry{
  113. // Set
  114. {
  115. kind: rpb.Entry_REQUEST,
  116. method: "/intstore.IntStore/Set",
  117. msg: message{msg: item},
  118. },
  119. {
  120. kind: rpb.Entry_RESPONSE,
  121. msg: message{msg: &ipb.SetResponse{PrevValue: 0}},
  122. refIndex: 1,
  123. },
  124. // Get
  125. {
  126. kind: rpb.Entry_REQUEST,
  127. method: "/intstore.IntStore/Get",
  128. msg: message{msg: &ipb.GetRequest{Name: "a"}},
  129. },
  130. {
  131. kind: rpb.Entry_RESPONSE,
  132. msg: message{msg: item},
  133. refIndex: 3,
  134. },
  135. {
  136. kind: rpb.Entry_REQUEST,
  137. method: "/intstore.IntStore/Get",
  138. msg: message{msg: &ipb.GetRequest{Name: "x"}},
  139. },
  140. {
  141. kind: rpb.Entry_RESPONSE,
  142. msg: message{err: status.Error(codes.NotFound, `"x"`)},
  143. refIndex: 5,
  144. },
  145. // ListItems
  146. { // entry #7
  147. kind: rpb.Entry_CREATE_STREAM,
  148. method: "/intstore.IntStore/ListItems",
  149. },
  150. {
  151. kind: rpb.Entry_SEND,
  152. msg: message{msg: &ipb.ListItemsRequest{}},
  153. refIndex: 7,
  154. },
  155. {
  156. kind: rpb.Entry_RECV,
  157. msg: message{msg: item},
  158. refIndex: 7,
  159. },
  160. {
  161. kind: rpb.Entry_RECV,
  162. msg: message{err: io.EOF},
  163. refIndex: 7,
  164. },
  165. // SetStream
  166. { // entry #11
  167. kind: rpb.Entry_CREATE_STREAM,
  168. method: "/intstore.IntStore/SetStream",
  169. },
  170. {
  171. kind: rpb.Entry_SEND,
  172. msg: message{msg: &ipb.Item{Name: "b", Value: 2}},
  173. refIndex: 11,
  174. },
  175. {
  176. kind: rpb.Entry_SEND,
  177. msg: message{msg: &ipb.Item{Name: "c", Value: 3}},
  178. refIndex: 11,
  179. },
  180. {
  181. kind: rpb.Entry_RECV,
  182. msg: message{msg: &ipb.Summary{Count: 2}},
  183. refIndex: 11,
  184. },
  185. // StreamChat
  186. { // entry #15
  187. kind: rpb.Entry_CREATE_STREAM,
  188. method: "/intstore.IntStore/StreamChat",
  189. },
  190. {
  191. kind: rpb.Entry_SEND,
  192. msg: message{msg: &ipb.Item{Name: "d", Value: 4}},
  193. refIndex: 15,
  194. },
  195. {
  196. kind: rpb.Entry_RECV,
  197. msg: message{msg: &ipb.Item{Name: "d", Value: 4}},
  198. refIndex: 15,
  199. },
  200. {
  201. kind: rpb.Entry_SEND,
  202. msg: message{msg: &ipb.Item{Name: "e", Value: 5}},
  203. refIndex: 15,
  204. },
  205. {
  206. kind: rpb.Entry_RECV,
  207. msg: message{msg: &ipb.Item{Name: "e", Value: 5}},
  208. refIndex: 15,
  209. },
  210. {
  211. kind: rpb.Entry_RECV,
  212. msg: message{err: io.EOF},
  213. refIndex: 15,
  214. },
  215. }
  216. for i, w := range wantEntries {
  217. g, err := readEntry(buf)
  218. if err != nil {
  219. t.Fatalf("#%d: %v", i+1, err)
  220. }
  221. if !g.equal(w) {
  222. t.Errorf("#%d:\ngot %+v\nwant %+v", i+1, g, w)
  223. }
  224. }
  225. g, err := readEntry(buf)
  226. if err != nil {
  227. t.Fatal(err)
  228. }
  229. if g != nil {
  230. t.Errorf("\ngot %+v\nwant nil", g)
  231. }
  232. }
  233. func TestReplay(t *testing.T) {
  234. srv := newIntStoreServer()
  235. defer srv.stop()
  236. buf := record(t, srv)
  237. rep, err := NewReplayerReader(buf)
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. if got, want := rep.Initial(), initialState; !testutil.Equal(got, want) {
  242. t.Fatalf("got %v, want %v", got, want)
  243. }
  244. // Replay the test.
  245. testService(t, srv.Addr, rep.DialOptions())
  246. }
  247. func record(t *testing.T, srv *intStoreServer) *bytes.Buffer {
  248. buf := &bytes.Buffer{}
  249. rec, err := NewRecorderWriter(buf, initialState)
  250. if err != nil {
  251. t.Fatal(err)
  252. }
  253. testService(t, srv.Addr, rec.DialOptions())
  254. if err := rec.Close(); err != nil {
  255. t.Fatal(err)
  256. }
  257. return buf
  258. }
  259. func testService(t *testing.T, addr string, opts []grpc.DialOption) {
  260. conn, err := grpc.Dial(addr,
  261. append([]grpc.DialOption{grpc.WithInsecure()}, opts...)...)
  262. if err != nil {
  263. t.Fatal(err)
  264. }
  265. defer conn.Close()
  266. client := ipb.NewIntStoreClient(conn)
  267. ctx := context.Background()
  268. item := &ipb.Item{Name: "a", Value: 1}
  269. res, err := client.Set(ctx, item)
  270. if err != nil {
  271. t.Fatal(err)
  272. }
  273. if res.PrevValue != 0 {
  274. t.Errorf("got %d, want 0", res.PrevValue)
  275. }
  276. got, err := client.Get(ctx, &ipb.GetRequest{Name: "a"})
  277. if err != nil {
  278. t.Fatal(err)
  279. }
  280. if !proto.Equal(got, item) {
  281. t.Errorf("got %v, want %v", got, item)
  282. }
  283. _, err = client.Get(ctx, &ipb.GetRequest{Name: "x"})
  284. if err == nil {
  285. t.Fatal("got nil, want error")
  286. }
  287. if _, ok := status.FromError(err); !ok {
  288. t.Errorf("got error type %T, want a grpc/status.Status", err)
  289. }
  290. wantItems := []*ipb.Item{item}
  291. lic, err := client.ListItems(ctx, &ipb.ListItemsRequest{})
  292. if err != nil {
  293. t.Fatal(err)
  294. }
  295. for i := 0; ; i++ {
  296. item, err := lic.Recv()
  297. if err == io.EOF {
  298. break
  299. }
  300. if err != nil {
  301. t.Fatal(err)
  302. }
  303. if i >= len(wantItems) || !proto.Equal(item, wantItems[i]) {
  304. t.Fatalf("%d: bad item", i)
  305. }
  306. }
  307. ssc, err := client.SetStream(ctx)
  308. if err != nil {
  309. t.Fatal(err)
  310. }
  311. must := func(err error) {
  312. if err != nil {
  313. t.Fatal(err)
  314. }
  315. }
  316. for i, name := range []string{"b", "c"} {
  317. must(ssc.Send(&ipb.Item{Name: name, Value: int32(i + 2)}))
  318. }
  319. summary, err := ssc.CloseAndRecv()
  320. if err != nil {
  321. t.Fatal(err)
  322. }
  323. if got, want := summary.Count, int32(2); got != want {
  324. t.Fatalf("got %d, want %d", got, want)
  325. }
  326. chatc, err := client.StreamChat(ctx)
  327. if err != nil {
  328. t.Fatal(err)
  329. }
  330. for i, name := range []string{"d", "e"} {
  331. item := &ipb.Item{Name: name, Value: int32(i + 4)}
  332. must(chatc.Send(item))
  333. got, err := chatc.Recv()
  334. if err != nil {
  335. t.Fatal(err)
  336. }
  337. if !proto.Equal(got, item) {
  338. t.Errorf("got %v, want %v", got, item)
  339. }
  340. }
  341. must(chatc.CloseSend())
  342. if _, err := chatc.Recv(); err != io.EOF {
  343. t.Fatalf("got %v, want EOF", err)
  344. }
  345. }
  346. func TestRecorderBeforeFunc(t *testing.T) {
  347. var tests = []struct {
  348. name string
  349. msg, wantRespMsg, wantEntryMsg *ipb.Item
  350. f func(string, proto.Message) error
  351. wantErr bool
  352. }{
  353. {
  354. name: "BeforeFunc should modify messages saved, but not alter what is sent/received to/from services",
  355. msg: &ipb.Item{Name: "foo", Value: 1},
  356. wantEntryMsg: &ipb.Item{Name: "bar", Value: 2},
  357. wantRespMsg: &ipb.Item{Name: "foo", Value: 1},
  358. f: func(method string, m proto.Message) error {
  359. // This callback only runs when Set is called.
  360. if !strings.HasSuffix(method, "Set") {
  361. return nil
  362. }
  363. if _, ok := m.(*ipb.Item); !ok {
  364. return nil
  365. }
  366. item := m.(*ipb.Item)
  367. item.Name = "bar"
  368. item.Value = 2
  369. return nil
  370. },
  371. },
  372. {
  373. name: "BeforeFunc should not be able to alter returned responses",
  374. msg: &ipb.Item{Name: "foo", Value: 1},
  375. wantRespMsg: &ipb.Item{Name: "foo", Value: 1},
  376. f: func(method string, m proto.Message) error {
  377. // This callback only runs when Get is called.
  378. if !strings.HasSuffix(method, "Get") {
  379. return nil
  380. }
  381. if _, ok := m.(*ipb.Item); !ok {
  382. return nil
  383. }
  384. item := m.(*ipb.Item)
  385. item.Value = 2
  386. return nil
  387. },
  388. },
  389. {
  390. name: "Errors should cause the RPC send to fail",
  391. msg: &ipb.Item{},
  392. f: func(_ string, _ proto.Message) error {
  393. return errors.New("err")
  394. },
  395. wantErr: true,
  396. },
  397. }
  398. for _, tc := range tests {
  399. // Wrap test cases in a func so defers execute correctly.
  400. func() {
  401. srv := newIntStoreServer()
  402. defer srv.stop()
  403. var b bytes.Buffer
  404. r, err := NewRecorderWriter(&b, nil)
  405. if err != nil {
  406. t.Error(err)
  407. return
  408. }
  409. r.BeforeFunc = tc.f
  410. ctx := context.Background()
  411. conn, err := grpc.DialContext(ctx, srv.Addr, append([]grpc.DialOption{grpc.WithInsecure()}, r.DialOptions()...)...)
  412. if err != nil {
  413. t.Error(err)
  414. return
  415. }
  416. defer conn.Close()
  417. client := ipb.NewIntStoreClient(conn)
  418. _, err = client.Set(ctx, tc.msg)
  419. switch {
  420. case err != nil && !tc.wantErr:
  421. t.Error(err)
  422. return
  423. case err == nil && tc.wantErr:
  424. t.Errorf("got nil; want error")
  425. return
  426. case err != nil:
  427. // Error found as expected, don't check Get().
  428. return
  429. }
  430. if tc.wantRespMsg != nil {
  431. got, err := client.Get(ctx, &ipb.GetRequest{Name: tc.msg.GetName()})
  432. if err != nil {
  433. t.Error(err)
  434. return
  435. }
  436. if !cmp.Equal(got, tc.wantRespMsg) {
  437. t.Errorf("got %+v; want %+v", got, tc.wantRespMsg)
  438. }
  439. }
  440. r.Close()
  441. if tc.wantEntryMsg != nil {
  442. _, _ = readHeader(&b)
  443. e, err := readEntry(&b)
  444. if err != nil {
  445. t.Error(err)
  446. return
  447. }
  448. got := e.msg.msg.(*ipb.Item)
  449. if !cmp.Equal(got, tc.wantEntryMsg) {
  450. t.Errorf("got %v; want %v", got, tc.wantEntryMsg)
  451. }
  452. }
  453. }()
  454. }
  455. }
  456. func TestReplayerBeforeFunc(t *testing.T) {
  457. var tests = []struct {
  458. name string
  459. msg, reqMsg *ipb.Item
  460. f func(string, proto.Message) error
  461. wantErr bool
  462. }{
  463. {
  464. name: "BeforeFunc should modify messages sent before they are passed to the replayer",
  465. msg: &ipb.Item{Name: "foo", Value: 1},
  466. reqMsg: &ipb.Item{Name: "bar", Value: 1},
  467. f: func(method string, m proto.Message) error {
  468. item := m.(*ipb.Item)
  469. item.Name = "foo"
  470. return nil
  471. },
  472. },
  473. {
  474. name: "Errors should cause the RPC send to fail",
  475. msg: &ipb.Item{},
  476. f: func(_ string, _ proto.Message) error {
  477. return errors.New("err")
  478. },
  479. wantErr: true,
  480. },
  481. }
  482. for _, tc := range tests {
  483. // Wrap test cases in a func so defers execute correctly.
  484. func() {
  485. srv := newIntStoreServer()
  486. defer srv.stop()
  487. var b bytes.Buffer
  488. rec, err := NewRecorderWriter(&b, nil)
  489. if err != nil {
  490. t.Error(err)
  491. return
  492. }
  493. ctx := context.Background()
  494. conn, err := grpc.DialContext(ctx, srv.Addr, append([]grpc.DialOption{grpc.WithInsecure()}, rec.DialOptions()...)...)
  495. if err != nil {
  496. t.Error(err)
  497. return
  498. }
  499. defer conn.Close()
  500. client := ipb.NewIntStoreClient(conn)
  501. _, err = client.Set(ctx, tc.msg)
  502. if err != nil {
  503. t.Error(err)
  504. return
  505. }
  506. rec.Close()
  507. rep, err := NewReplayerReader(&b)
  508. if err != nil {
  509. t.Error(err)
  510. return
  511. }
  512. rep.BeforeFunc = tc.f
  513. conn, err = grpc.DialContext(ctx, srv.Addr, append([]grpc.DialOption{grpc.WithInsecure()}, rep.DialOptions()...)...)
  514. if err != nil {
  515. t.Error(err)
  516. return
  517. }
  518. defer conn.Close()
  519. client = ipb.NewIntStoreClient(conn)
  520. _, err = client.Set(ctx, tc.reqMsg)
  521. switch {
  522. case err != nil && !tc.wantErr:
  523. t.Error(err)
  524. case err == nil && tc.wantErr:
  525. t.Errorf("got nil; want error")
  526. }
  527. }()
  528. }
  529. }