google.golang.org/grpc@v1.72.2/encoding/proto/proto_test.go (about)

     1  /*
     2   *
     3   * Copyright 2018 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package proto
    20  
    21  import (
    22  	"bytes"
    23  	"sync"
    24  	"testing"
    25  
    26  	"google.golang.org/grpc/encoding"
    27  	"google.golang.org/grpc/internal/grpctest"
    28  	"google.golang.org/grpc/mem"
    29  	pb "google.golang.org/grpc/test/codec_perf"
    30  )
    31  
    32  func marshalAndUnmarshal(t *testing.T, codec encoding.CodecV2, expectedBody []byte) {
    33  	p := &pb.Buffer{}
    34  	p.Body = expectedBody
    35  
    36  	marshalledBytes, err := codec.Marshal(p)
    37  	if err != nil {
    38  		t.Errorf("codec.Marshal(_) returned an error")
    39  	}
    40  
    41  	if err := codec.Unmarshal(marshalledBytes, p); err != nil {
    42  		t.Errorf("codec.Unmarshal(_) returned an error")
    43  	}
    44  
    45  	if !bytes.Equal(p.GetBody(), expectedBody) {
    46  		t.Errorf("Unexpected body; got %v; want %v", p.GetBody(), expectedBody)
    47  	}
    48  }
    49  
    50  type s struct {
    51  	grpctest.Tester
    52  }
    53  
    54  func Test(t *testing.T) {
    55  	grpctest.RunSubTests(t, s{})
    56  }
    57  
    58  func (s) TestBasicProtoCodecMarshalAndUnmarshal(t *testing.T) {
    59  	marshalAndUnmarshal(t, &codecV2{}, []byte{1, 2, 3})
    60  }
    61  
    62  // Try to catch possible race conditions around use of pools
    63  func (s) TestConcurrentUsage(t *testing.T) {
    64  	const (
    65  		numGoRoutines   = 100
    66  		numMarshUnmarsh = 1000
    67  	)
    68  
    69  	// small, arbitrary byte slices
    70  	protoBodies := [][]byte{
    71  		[]byte("one"),
    72  		[]byte("two"),
    73  		[]byte("three"),
    74  		[]byte("four"),
    75  		[]byte("five"),
    76  	}
    77  
    78  	var wg sync.WaitGroup
    79  	codec := &codecV2{}
    80  
    81  	for i := 0; i < numGoRoutines; i++ {
    82  		wg.Add(1)
    83  		go func() {
    84  			defer wg.Done()
    85  			for k := 0; k < numMarshUnmarsh; k++ {
    86  				marshalAndUnmarshal(t, codec, protoBodies[k%len(protoBodies)])
    87  			}
    88  		}()
    89  	}
    90  
    91  	wg.Wait()
    92  }
    93  
    94  // TestStaggeredMarshalAndUnmarshalUsingSamePool tries to catch potential errors in which slices get
    95  // stomped on during reuse of a proto.Buffer.
    96  func (s) TestStaggeredMarshalAndUnmarshalUsingSamePool(t *testing.T) {
    97  	codec1 := &codecV2{}
    98  	codec2 := &codecV2{}
    99  
   100  	expectedBody1 := []byte{1, 2, 3}
   101  	expectedBody2 := []byte{4, 5, 6}
   102  
   103  	proto1 := pb.Buffer{Body: expectedBody1}
   104  	proto2 := pb.Buffer{Body: expectedBody2}
   105  
   106  	var m1, m2 mem.BufferSlice
   107  	var err error
   108  
   109  	if m1, err = codec1.Marshal(&proto1); err != nil {
   110  		t.Errorf("codec.Marshal(%s) failed", &proto1)
   111  	}
   112  
   113  	if m2, err = codec2.Marshal(&proto2); err != nil {
   114  		t.Errorf("codec.Marshal(%s) failed", &proto2)
   115  	}
   116  
   117  	if err = codec1.Unmarshal(m1, &proto1); err != nil {
   118  		t.Errorf("codec.Unmarshal(%v) failed", m1)
   119  	}
   120  
   121  	if err = codec2.Unmarshal(m2, &proto2); err != nil {
   122  		t.Errorf("codec.Unmarshal(%v) failed", m2)
   123  	}
   124  
   125  	b1 := proto1.GetBody()
   126  	b2 := proto2.GetBody()
   127  
   128  	for i, v := range b1 {
   129  		if expectedBody1[i] != v {
   130  			t.Errorf("expected %v at index %v but got %v", i, expectedBody1[i], v)
   131  		}
   132  	}
   133  
   134  	for i, v := range b2 {
   135  		if expectedBody2[i] != v {
   136  			t.Errorf("expected %v at index %v but got %v", i, expectedBody2[i], v)
   137  		}
   138  	}
   139  }