go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/api/v3rpc/watch_test.go (about)

     1  // Copyright 2018 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 v3rpc
    16  
    17  import (
    18  	"bytes"
    19  	"math"
    20  	"testing"
    21  
    22  	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    23  	"github.com/coreos/etcd/mvcc/mvccpb"
    24  )
    25  
    26  func TestSendFragment(t *testing.T) {
    27  	tt := []struct {
    28  		wr              *pb.WatchResponse
    29  		maxRequestBytes int
    30  		fragments       int
    31  		werr            error
    32  	}{
    33  		{ // large limit should not fragment
    34  			wr:              createResponse(100, 1),
    35  			maxRequestBytes: math.MaxInt32,
    36  			fragments:       1,
    37  		},
    38  		{ // large limit for two messages, expect no fragment
    39  			wr:              createResponse(10, 2),
    40  			maxRequestBytes: 50,
    41  			fragments:       1,
    42  		},
    43  		{ // limit is small but only one message, expect no fragment
    44  			wr:              createResponse(1024, 1),
    45  			maxRequestBytes: 1,
    46  			fragments:       1,
    47  		},
    48  		{ // exceed limit only when combined, expect fragments
    49  			wr:              createResponse(11, 5),
    50  			maxRequestBytes: 20,
    51  			fragments:       5,
    52  		},
    53  		{ // 5 events with each event exceeding limits, expect fragments
    54  			wr:              createResponse(15, 5),
    55  			maxRequestBytes: 10,
    56  			fragments:       5,
    57  		},
    58  		{ // 4 events with some combined events exceeding limits
    59  			wr:              createResponse(10, 4),
    60  			maxRequestBytes: 35,
    61  			fragments:       2,
    62  		},
    63  	}
    64  
    65  	for i := range tt {
    66  		fragmentedResp := make([]*pb.WatchResponse, 0)
    67  		testSend := func(wr *pb.WatchResponse) error {
    68  			fragmentedResp = append(fragmentedResp, wr)
    69  			return nil
    70  		}
    71  		err := sendFragments(tt[i].wr, tt[i].maxRequestBytes, testSend)
    72  		if err != tt[i].werr {
    73  			t.Errorf("#%d: expected error %v, got %v", i, tt[i].werr, err)
    74  		}
    75  		got := len(fragmentedResp)
    76  		if got != tt[i].fragments {
    77  			t.Errorf("#%d: expected response number %d, got %d", i, tt[i].fragments, got)
    78  		}
    79  		if got > 0 && fragmentedResp[got-1].Fragment {
    80  			t.Errorf("#%d: expected fragment=false in last response, got %+v", i, fragmentedResp[got-1])
    81  		}
    82  	}
    83  }
    84  
    85  func createResponse(dataSize, events int) (resp *pb.WatchResponse) {
    86  	resp = &pb.WatchResponse{Events: make([]*mvccpb.Event, events)}
    87  	for i := range resp.Events {
    88  		resp.Events[i] = &mvccpb.Event{
    89  			Kv: &mvccpb.KeyValue{
    90  				Key: bytes.Repeat([]byte("a"), dataSize),
    91  			},
    92  		}
    93  	}
    94  	return resp
    95  }