interaction_env_handler_process_ready.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2019 The etcd Authors
  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 rafttest
  15. import (
  16. "testing"
  17. "github.com/cockroachdb/datadriven"
  18. "go.etcd.io/etcd/raft"
  19. "go.etcd.io/etcd/raft/raftpb"
  20. )
  21. func (env *InteractionEnv) handleProcessReady(t *testing.T, d datadriven.TestData) error {
  22. idx := firstAsNodeIdx(t, d)
  23. return env.ProcessReady(idx)
  24. }
  25. // ProcessReady runs Ready handling on the node with the given index.
  26. func (env *InteractionEnv) ProcessReady(idx int) error {
  27. // TODO(tbg): Allow simulating crashes here.
  28. rn, s := env.Nodes[idx].RawNode, env.Nodes[idx].Storage
  29. rd := rn.Ready()
  30. env.Output.WriteString(raft.DescribeReady(rd, defaultEntryFormatter))
  31. // TODO(tbg): the order of operations here is not necessarily safe. See:
  32. // https://github.com/etcd-io/etcd/pull/10861
  33. if !raft.IsEmptyHardState(rd.HardState) {
  34. if err := s.SetHardState(rd.HardState); err != nil {
  35. return err
  36. }
  37. }
  38. if err := s.Append(rd.Entries); err != nil {
  39. return err
  40. }
  41. if !raft.IsEmptySnap(rd.Snapshot) {
  42. if err := s.ApplySnapshot(rd.Snapshot); err != nil {
  43. return err
  44. }
  45. }
  46. for _, ent := range rd.CommittedEntries {
  47. var update []byte
  48. var cs *raftpb.ConfState
  49. switch ent.Type {
  50. case raftpb.EntryConfChange:
  51. var cc raftpb.ConfChange
  52. if err := cc.Unmarshal(ent.Data); err != nil {
  53. return err
  54. }
  55. update = cc.Context
  56. cs = rn.ApplyConfChange(cc)
  57. case raftpb.EntryConfChangeV2:
  58. var cc raftpb.ConfChangeV2
  59. if err := cc.Unmarshal(ent.Data); err != nil {
  60. return err
  61. }
  62. cs = rn.ApplyConfChange(cc)
  63. update = cc.Context
  64. default:
  65. update = ent.Data
  66. }
  67. // Record the new state by starting with the current state and applying
  68. // the command.
  69. lastSnap := env.Nodes[idx].History[len(env.Nodes[idx].History)-1]
  70. var snap raftpb.Snapshot
  71. snap.Data = append(snap.Data, lastSnap.Data...)
  72. // NB: this hard-codes an "appender" state machine.
  73. snap.Data = append(snap.Data, update...)
  74. snap.Metadata.Index = ent.Index
  75. snap.Metadata.Term = ent.Term
  76. if cs == nil {
  77. sl := env.Nodes[idx].History
  78. cs = &sl[len(sl)-1].Metadata.ConfState
  79. }
  80. snap.Metadata.ConfState = *cs
  81. env.Nodes[idx].History = append(env.Nodes[idx].History, snap)
  82. }
  83. for _, msg := range rd.Messages {
  84. env.Messages = append(env.Messages, msg)
  85. }
  86. rn.Advance(rd)
  87. return nil
  88. }