...

Source file src/cloud.google.com/go/storage/grpc_client_test.go

Documentation: cloud.google.com/go/storage

     1  // Copyright 2024 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  
    15  package storage
    16  
    17  import (
    18  	"crypto/md5"
    19  	"hash/crc32"
    20  	"math/rand"
    21  	"testing"
    22  	"time"
    23  
    24  	"cloud.google.com/go/storage/internal/apiv2/storagepb"
    25  	"github.com/google/go-cmp/cmp"
    26  	"google.golang.org/protobuf/proto"
    27  	"google.golang.org/protobuf/testing/protocmp"
    28  )
    29  
    30  func TestBytesCodec(t *testing.T) {
    31  	// Generate some random content.
    32  	content := make([]byte, 1<<10+1) // 1 kib + 1 byte
    33  	rand.New(rand.NewSource(0)).Read(content)
    34  
    35  	// Calculate full content hashes.
    36  	crc32c := crc32.Checksum(content, crc32.MakeTable(crc32.Castagnoli))
    37  	hasher := md5.New()
    38  	if _, err := hasher.Write(content); err != nil {
    39  		t.Errorf("hasher.Write: %v", err)
    40  	}
    41  	md5 := hasher.Sum(nil)
    42  
    43  	trueBool := true
    44  	metadata := &storagepb.Object{
    45  		Name:               "object-name",
    46  		Bucket:             "bucket-name",
    47  		Etag:               "etag",
    48  		Generation:         100,
    49  		Metageneration:     907,
    50  		StorageClass:       "Standard",
    51  		Size:               1025,
    52  		ContentEncoding:    "none",
    53  		ContentDisposition: "inline",
    54  		CacheControl:       "public, max-age=3600",
    55  		Acl: []*storagepb.ObjectAccessControl{{
    56  			Role:   "role",
    57  			Id:     "id",
    58  			Entity: "allUsers",
    59  			Etag:   "tag",
    60  			Email:  "email@foo.com",
    61  		}},
    62  		ContentLanguage: "mi, en",
    63  		DeleteTime:      toProtoTimestamp(time.Now()),
    64  		ContentType:     "application/octet-stream",
    65  		CreateTime:      toProtoTimestamp(time.Now()),
    66  		ComponentCount:  1,
    67  		Checksums: &storagepb.ObjectChecksums{
    68  			Crc32C:  &crc32c,
    69  			Md5Hash: md5,
    70  		},
    71  		TemporaryHold: true,
    72  		Metadata: map[string]string{
    73  			"a-key": "a-value",
    74  		},
    75  		EventBasedHold: &trueBool,
    76  		Owner: &storagepb.Owner{
    77  			Entity:   "user-1",
    78  			EntityId: "1",
    79  		},
    80  		CustomerEncryption: &storagepb.CustomerEncryption{
    81  			EncryptionAlgorithm: "alg",
    82  			KeySha256Bytes:      []byte("bytes"),
    83  		},
    84  		HardDeleteTime: toProtoTimestamp(time.Now()),
    85  	}
    86  
    87  	for _, test := range []struct {
    88  		desc string
    89  		resp *storagepb.ReadObjectResponse
    90  	}{
    91  		{
    92  			desc: "filled object response",
    93  			resp: &storagepb.ReadObjectResponse{
    94  				ChecksummedData: &storagepb.ChecksummedData{
    95  					Content: content,
    96  					Crc32C:  &crc32c,
    97  				},
    98  				ObjectChecksums: &storagepb.ObjectChecksums{
    99  					Crc32C:  &crc32c,
   100  					Md5Hash: md5,
   101  				},
   102  				ContentRange: &storagepb.ContentRange{
   103  					Start:          0,
   104  					End:            1025,
   105  					CompleteLength: 1025,
   106  				},
   107  				Metadata: metadata,
   108  			},
   109  		},
   110  		{
   111  			desc: "empty object response",
   112  			resp: &storagepb.ReadObjectResponse{},
   113  		},
   114  		{
   115  			desc: "partially empty",
   116  			resp: &storagepb.ReadObjectResponse{
   117  				ChecksummedData: &storagepb.ChecksummedData{},
   118  				ObjectChecksums: &storagepb.ObjectChecksums{Md5Hash: md5},
   119  				Metadata:        &storagepb.Object{},
   120  			},
   121  		},
   122  	} {
   123  		t.Run(test.desc, func(t *testing.T) {
   124  			// Encode the response.
   125  			encodedResp, err := proto.Marshal(test.resp)
   126  			if err != nil {
   127  				t.Fatalf("proto.Marshal: %v", err)
   128  			}
   129  
   130  			// Unmarshal and decode response using custom decoding.
   131  			encodedBytes := &[]byte{}
   132  			if err := bytesCodec.Unmarshal(bytesCodec{}, encodedResp, encodedBytes); err != nil {
   133  				t.Fatalf("unmarshal: %v", err)
   134  			}
   135  
   136  			got, err := readFullObjectResponse(*encodedBytes)
   137  			if err != nil {
   138  				t.Fatalf("readFullObjectResponse: %v", err)
   139  			}
   140  
   141  			// Compare the result with the original ReadObjectResponse.
   142  			if diff := cmp.Diff(got, test.resp, protocmp.Transform()); diff != "" {
   143  				t.Errorf("cmp.Diff got(-),want(+):\n%s", diff)
   144  			}
   145  		})
   146  	}
   147  }
   148  

View as plain text