|  | // Copyright 2020 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package proto_test | 
|  |  | 
|  | import ( | 
|  | "testing" | 
|  |  | 
|  | "google.golang.org/protobuf/proto" | 
|  | "google.golang.org/protobuf/reflect/protoreflect" | 
|  |  | 
|  | testpb "google.golang.org/protobuf/internal/testprotos/test" | 
|  | ) | 
|  |  | 
|  | // TestNil tests for boundary conditions when nil and typed-nil messages | 
|  | // are passed to various top-level functions. | 
|  | // These tests are not necessarily a statement of proper behavior, | 
|  | // but exist to detect accidental changes in behavior. | 
|  | func TestNil(t *testing.T) { | 
|  | nilMsg := (*testpb.TestAllExtensions)(nil) | 
|  | extType := testpb.E_OptionalBool | 
|  | extRanger := func(protoreflect.ExtensionType, any) bool { return true } | 
|  |  | 
|  | tests := []struct { | 
|  | label string | 
|  | test  func() | 
|  | panic bool | 
|  | }{{ | 
|  | label: "Size", | 
|  | test:  func() { proto.Size(nil) }, | 
|  | }, { | 
|  | label: "Size", | 
|  | test:  func() { proto.Size(nilMsg) }, | 
|  | }, { | 
|  | label: "Marshal", | 
|  | test:  func() { proto.Marshal(nil) }, | 
|  | }, { | 
|  | label: "Marshal", | 
|  | test:  func() { proto.Marshal(nilMsg) }, | 
|  | }, { | 
|  | label: "Unmarshal", | 
|  | test:  func() { proto.Unmarshal(nil, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Unmarshal", | 
|  | test:  func() { proto.Unmarshal(nil, nilMsg) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Merge", | 
|  | test:  func() { proto.Merge(nil, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Merge", | 
|  | test:  func() { proto.Merge(nil, nilMsg) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Merge", | 
|  | test:  func() { proto.Merge(nilMsg, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Merge", | 
|  | test:  func() { proto.Merge(nilMsg, nilMsg) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Clone", | 
|  | test:  func() { proto.Clone(nil) }, | 
|  | }, { | 
|  | label: "Clone", | 
|  | test:  func() { proto.Clone(nilMsg) }, | 
|  | }, { | 
|  | label: "Equal", | 
|  | test:  func() { proto.Equal(nil, nil) }, | 
|  | }, { | 
|  | label: "Equal", | 
|  | test:  func() { proto.Equal(nil, nilMsg) }, | 
|  | }, { | 
|  | label: "Equal", | 
|  | test:  func() { proto.Equal(nilMsg, nil) }, | 
|  | }, { | 
|  | label: "Equal", | 
|  | test:  func() { proto.Equal(nilMsg, nilMsg) }, | 
|  | }, { | 
|  | label: "Reset", | 
|  | test:  func() { proto.Reset(nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "Reset", | 
|  | test:  func() { proto.Reset(nilMsg) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "HasExtension", | 
|  | test:  func() { proto.HasExtension(nil, nil) }, | 
|  | }, { | 
|  | label: "HasExtension", | 
|  | test:  func() { proto.HasExtension(nil, extType) }, | 
|  | }, { | 
|  | label: "HasExtension", | 
|  | test:  func() { proto.HasExtension(nilMsg, nil) }, | 
|  | }, { | 
|  | label: "HasExtension", | 
|  | test:  func() { proto.HasExtension(nilMsg, extType) }, | 
|  | }, { | 
|  | label: "GetExtension", | 
|  | test:  func() { proto.GetExtension(nil, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "GetExtension", | 
|  | test:  func() { proto.GetExtension(nil, extType) }, | 
|  | }, { | 
|  | label: "GetExtension", | 
|  | test:  func() { proto.GetExtension(nilMsg, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "GetExtension", | 
|  | test:  func() { proto.GetExtension(nilMsg, extType) }, | 
|  | }, { | 
|  | label: "SetExtension", | 
|  | test:  func() { proto.SetExtension(nil, nil, true) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "SetExtension", | 
|  | test:  func() { proto.SetExtension(nil, extType, true) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "SetExtension", | 
|  | test:  func() { proto.SetExtension(nilMsg, nil, true) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "SetExtension", | 
|  | test:  func() { proto.SetExtension(nilMsg, extType, true) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "ClearExtension", | 
|  | test:  func() { proto.ClearExtension(nil, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "ClearExtension", | 
|  | test:  func() { proto.ClearExtension(nil, extType) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "ClearExtension", | 
|  | test:  func() { proto.ClearExtension(nilMsg, nil) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "ClearExtension", | 
|  | test:  func() { proto.ClearExtension(nilMsg, extType) }, | 
|  | panic: true, | 
|  | }, { | 
|  | label: "RangeExtensions", | 
|  | test:  func() { proto.RangeExtensions(nil, nil) }, | 
|  | }, { | 
|  | label: "RangeExtensions", | 
|  | test:  func() { proto.RangeExtensions(nil, extRanger) }, | 
|  | }, { | 
|  | label: "RangeExtensions", | 
|  | test:  func() { proto.RangeExtensions(nilMsg, nil) }, | 
|  | }, { | 
|  | label: "RangeExtensions", | 
|  | test:  func() { proto.RangeExtensions(nilMsg, extRanger) }, | 
|  | }} | 
|  |  | 
|  | for _, tt := range tests { | 
|  | t.Run(tt.label, func(t *testing.T) { | 
|  | defer func() { | 
|  | switch gotPanic := recover() != nil; { | 
|  | case gotPanic && !tt.panic: | 
|  | t.Errorf("unexpected panic") | 
|  | case !gotPanic && tt.panic: | 
|  | t.Errorf("expected panic") | 
|  | } | 
|  | }() | 
|  | tt.test() | 
|  | }) | 
|  | } | 
|  | } |