Joe Tsai | b936504 | 2019-03-19 14:14:29 -0700 | [diff] [blame^] | 1 | // 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 | |
| 5 | package legacy |
| 6 | |
| 7 | import ( |
| 8 | "sync" |
| 9 | "testing" |
| 10 | |
| 11 | "github.com/golang/protobuf/v2/reflect/protoreflect" |
| 12 | ) |
| 13 | |
| 14 | type ( |
| 15 | MessageA struct { |
| 16 | A1 *MessageA `protobuf:"bytes,1,req,name=a1"` |
| 17 | A2 *MessageB `protobuf:"bytes,2,req,name=a2"` |
| 18 | A3 Enum `protobuf:"varint,3,opt,name=a3,enum=legacy.Enum"` |
| 19 | } |
| 20 | MessageB struct { |
| 21 | B1 *MessageA `protobuf:"bytes,1,req,name=b1"` |
| 22 | B2 *MessageB `protobuf:"bytes,2,req,name=b2"` |
| 23 | B3 Enum `protobuf:"varint,3,opt,name=b3,enum=legacy.Enum"` |
| 24 | } |
| 25 | Enum int32 |
| 26 | ) |
| 27 | |
| 28 | // TestConcurrentInit tests that concurrent wrapping of multiple legacy types |
| 29 | // results in the exact same descriptor being created. |
| 30 | func TestConcurrentInit(t *testing.T) { |
| 31 | const numParallel = 5 |
| 32 | var messageATypes [numParallel]protoreflect.MessageType |
| 33 | var messageBTypes [numParallel]protoreflect.MessageType |
| 34 | var enumTypes [numParallel]protoreflect.EnumType |
| 35 | |
| 36 | // Concurrently load message and enum types. |
| 37 | var wg sync.WaitGroup |
| 38 | for i := 0; i < numParallel; i++ { |
| 39 | i := i |
| 40 | wg.Add(3) |
| 41 | go func() { |
| 42 | defer wg.Done() |
| 43 | messageATypes[i] = Export{}.MessageTypeOf((*MessageA)(nil)) |
| 44 | }() |
| 45 | go func() { |
| 46 | defer wg.Done() |
| 47 | messageBTypes[i] = Export{}.MessageTypeOf((*MessageB)(nil)) |
| 48 | }() |
| 49 | go func() { |
| 50 | defer wg.Done() |
| 51 | enumTypes[i] = Export{}.EnumTypeOf(Enum(0)) |
| 52 | }() |
| 53 | } |
| 54 | wg.Wait() |
| 55 | |
| 56 | var ( |
| 57 | wantMTA = messageATypes[0] |
| 58 | wantMDA = messageATypes[0].Fields().ByNumber(1).MessageType() |
| 59 | wantMTB = messageBTypes[0] |
| 60 | wantMDB = messageBTypes[0].Fields().ByNumber(2).MessageType() |
| 61 | wantET = enumTypes[0] |
| 62 | wantED = messageATypes[0].Fields().ByNumber(3).EnumType() |
| 63 | ) |
| 64 | |
| 65 | for _, gotMT := range messageATypes[1:] { |
| 66 | if gotMT != wantMTA { |
| 67 | t.Error("MessageType(MessageA) mismatch") |
| 68 | } |
| 69 | if gotMDA := gotMT.Fields().ByNumber(1).MessageType(); gotMDA != wantMDA { |
| 70 | t.Error("MessageDescriptor(MessageA) mismatch") |
| 71 | } |
| 72 | if gotMDB := gotMT.Fields().ByNumber(2).MessageType(); gotMDB != wantMDB { |
| 73 | t.Error("MessageDescriptor(MessageB) mismatch") |
| 74 | } |
| 75 | if gotED := gotMT.Fields().ByNumber(3).EnumType(); gotED != wantED { |
| 76 | t.Error("EnumDescriptor(Enum) mismatch") |
| 77 | } |
| 78 | } |
| 79 | for _, gotMT := range messageBTypes[1:] { |
| 80 | if gotMT != wantMTB { |
| 81 | t.Error("MessageType(MessageB) mismatch") |
| 82 | } |
| 83 | if gotMDA := gotMT.Fields().ByNumber(1).MessageType(); gotMDA != wantMDA { |
| 84 | t.Error("MessageDescriptor(MessageA) mismatch") |
| 85 | } |
| 86 | if gotMDB := gotMT.Fields().ByNumber(2).MessageType(); gotMDB != wantMDB { |
| 87 | t.Error("MessageDescriptor(MessageB) mismatch") |
| 88 | } |
| 89 | if gotED := gotMT.Fields().ByNumber(3).EnumType(); gotED != wantED { |
| 90 | t.Error("EnumDescriptor(Enum) mismatch") |
| 91 | } |
| 92 | } |
| 93 | for _, gotET := range enumTypes[1:] { |
| 94 | if gotET != wantET { |
| 95 | t.Error("EnumType(Enum) mismatch") |
| 96 | } |
| 97 | } |
| 98 | } |