blob: 622818c578f90a9ee9169278c19d87e15d2d5025 [file] [log] [blame]
Damien Neil92f76182019-08-02 16:58:08 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style.
3// license that can be found in the LICENSE file.
4
5package proto_test
6
7import (
8 "fmt"
Damien Neilc70f5d52020-01-29 14:40:11 -08009 "sync"
Damien Neil92f76182019-08-02 16:58:08 -070010 "testing"
11
12 "github.com/google/go-cmp/cmp"
13 "google.golang.org/protobuf/proto"
14 pref "google.golang.org/protobuf/reflect/protoreflect"
15 "google.golang.org/protobuf/runtime/protoimpl"
16
Joe Tsai55f18252020-01-11 00:25:01 -080017 legacy1pb "google.golang.org/protobuf/internal/testprotos/legacy/proto2_20160225_2fc053c5"
Damien Neil92f76182019-08-02 16:58:08 -070018 testpb "google.golang.org/protobuf/internal/testprotos/test"
19)
20
21func TestExtensionFuncs(t *testing.T) {
22 for _, test := range []struct {
23 message proto.Message
24 ext pref.ExtensionType
25 wantDefault interface{}
26 value interface{}
27 }{
28 {
29 message: &testpb.TestAllExtensions{},
Damien Neild025c952020-02-02 00:53:34 -080030 ext: testpb.E_OptionalInt32,
Damien Neil92f76182019-08-02 16:58:08 -070031 wantDefault: int32(0),
32 value: int32(1),
33 },
34 {
Joe Tsai8e9d5f62019-10-04 18:57:48 -070035 message: &testpb.TestAllExtensions{},
Damien Neild025c952020-02-02 00:53:34 -080036 ext: testpb.E_RepeatedString,
Damien Neil293dc762019-08-29 11:42:57 -070037 wantDefault: ([]string)(nil),
38 value: []string{"a", "b", "c"},
Damien Neil92f76182019-08-02 16:58:08 -070039 },
40 {
41 message: protoimpl.X.MessageOf(&legacy1pb.Message{}).Interface(),
42 ext: legacy1pb.E_Message_ExtensionOptionalBool,
43 wantDefault: false,
44 value: true,
45 },
46 } {
Damien Neil79bfdbe2019-08-28 11:08:22 -070047 desc := fmt.Sprintf("Extension %v, value %v", test.ext.TypeDescriptor().FullName(), test.value)
Damien Neil92f76182019-08-02 16:58:08 -070048 if proto.HasExtension(test.message, test.ext) {
49 t.Errorf("%v:\nbefore setting extension HasExtension(...) = true, want false", desc)
50 }
51 got := proto.GetExtension(test.message, test.ext)
52 if d := cmp.Diff(test.wantDefault, got); d != "" {
53 t.Errorf("%v:\nbefore setting extension GetExtension(...) returns unexpected value (-want,+got):\n%v", desc, d)
54 }
55 proto.SetExtension(test.message, test.ext, test.value)
56 if !proto.HasExtension(test.message, test.ext) {
57 t.Errorf("%v:\nafter setting extension HasExtension(...) = false, want true", desc)
58 }
59 got = proto.GetExtension(test.message, test.ext)
60 if d := cmp.Diff(test.value, got); d != "" {
61 t.Errorf("%v:\nafter setting extension GetExtension(...) returns unexpected value (-want,+got):\n%v", desc, d)
62 }
63 proto.ClearExtension(test.message, test.ext)
64 if proto.HasExtension(test.message, test.ext) {
65 t.Errorf("%v:\nafter clearing extension HasExtension(...) = true, want false", desc)
66 }
67
68 }
69}
Damien Neilc70f5d52020-01-29 14:40:11 -080070
71func TestExtensionGetRace(t *testing.T) {
72 // Concurrently fetch an extension value while marshaling the message containing it.
73 // Create the message with proto.Unmarshal to give lazy extension decoding (if present)
74 // a chance to occur.
75 want := int32(42)
76 m1 := &testpb.TestAllExtensions{}
Damien Neild025c952020-02-02 00:53:34 -080077 proto.SetExtension(m1, testpb.E_OptionalNestedMessage, &testpb.TestAllExtensions_NestedMessage{A: proto.Int32(want)})
Damien Neilc70f5d52020-01-29 14:40:11 -080078 b, err := proto.Marshal(m1)
79 if err != nil {
80 t.Fatal(err)
81 }
82 m := &testpb.TestAllExtensions{}
83 if err := proto.Unmarshal(b, m); err != nil {
84 t.Fatal(err)
85 }
86 var wg sync.WaitGroup
87 for i := 0; i < 3; i++ {
88 wg.Add(1)
89 go func() {
90 defer wg.Done()
91 if _, err := proto.Marshal(m); err != nil {
92 t.Error(err)
93 }
94 }()
95 wg.Add(1)
96 go func() {
97 defer wg.Done()
Damien Neild025c952020-02-02 00:53:34 -080098 got := proto.GetExtension(m, testpb.E_OptionalNestedMessage).(*testpb.TestAllExtensions_NestedMessage).GetA()
Damien Neilc70f5d52020-01-29 14:40:11 -080099 if got != want {
100 t.Errorf("GetExtension(optional_nested_message).a = %v, want %v", got, want)
101 }
102 }()
103 }
104 wg.Wait()
105}