...

Source file src/go.etcd.io/etcd/raft/v3/rafttest/interaction_env_handler_deliver_msgs.go

Documentation: go.etcd.io/etcd/raft/v3/rafttest

     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  
    15  package rafttest
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"testing"
    21  
    22  	"github.com/cockroachdb/datadriven"
    23  	"go.etcd.io/etcd/raft/v3"
    24  	"go.etcd.io/etcd/raft/v3/raftpb"
    25  )
    26  
    27  func (env *InteractionEnv) handleDeliverMsgs(t *testing.T, d datadriven.TestData) error {
    28  	var rs []Recipient
    29  	for _, arg := range d.CmdArgs {
    30  		if len(arg.Vals) == 0 {
    31  			id, err := strconv.ParseUint(arg.Key, 10, 64)
    32  			if err != nil {
    33  				t.Fatal(err)
    34  			}
    35  			rs = append(rs, Recipient{ID: id})
    36  		}
    37  		for i := range arg.Vals {
    38  			switch arg.Key {
    39  			case "drop":
    40  				var id uint64
    41  				arg.Scan(t, i, &id)
    42  				var found bool
    43  				for _, r := range rs {
    44  					if r.ID == id {
    45  						found = true
    46  					}
    47  				}
    48  				if found {
    49  					t.Fatalf("can't both deliver and drop msgs to %d", id)
    50  				}
    51  				rs = append(rs, Recipient{ID: id, Drop: true})
    52  			}
    53  		}
    54  	}
    55  
    56  	if n := env.DeliverMsgs(rs...); n == 0 {
    57  		env.Output.WriteString("no messages\n")
    58  	}
    59  	return nil
    60  }
    61  
    62  type Recipient struct {
    63  	ID   uint64
    64  	Drop bool
    65  }
    66  
    67  // DeliverMsgs goes through env.Messages and, depending on the Drop flag,
    68  // delivers or drops messages to the specified Recipients. Returns the
    69  // number of messages handled (i.e. delivered or dropped). A handled message
    70  // is removed from env.Messages.
    71  func (env *InteractionEnv) DeliverMsgs(rs ...Recipient) int {
    72  	var n int
    73  	for _, r := range rs {
    74  		var msgs []raftpb.Message
    75  		msgs, env.Messages = splitMsgs(env.Messages, r.ID)
    76  		n += len(msgs)
    77  		for _, msg := range msgs {
    78  			if r.Drop {
    79  				fmt.Fprint(env.Output, "dropped: ")
    80  			}
    81  			fmt.Fprintln(env.Output, raft.DescribeMessage(msg, defaultEntryFormatter))
    82  			if r.Drop {
    83  				// NB: it's allowed to drop messages to nodes that haven't been instantiated yet,
    84  				// we haven't used msg.To yet.
    85  				continue
    86  			}
    87  			toIdx := int(msg.To - 1)
    88  			if err := env.Nodes[toIdx].Step(msg); err != nil {
    89  				fmt.Fprintln(env.Output, err)
    90  			}
    91  		}
    92  	}
    93  	return n
    94  }
    95  

View as plain text