go.temporal.io/server@v1.23.0/common/persistence/serialization/serializer_test.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package serialization 26 27 import ( 28 "math/rand" 29 "sync" 30 "testing" 31 "time" 32 33 "github.com/brianvoe/gofakeit/v6" 34 "github.com/stretchr/testify/require" 35 "github.com/stretchr/testify/suite" 36 enumspb "go.temporal.io/api/enums/v1" 37 historypb "go.temporal.io/api/history/v1" 38 "google.golang.org/protobuf/types/known/timestamppb" 39 40 persistencespb "go.temporal.io/server/api/persistence/v1" 41 "go.temporal.io/server/common" 42 "go.temporal.io/server/common/log" 43 "go.temporal.io/server/common/payloads" 44 "go.temporal.io/server/common/testing/protorequire" 45 ) 46 47 type ( 48 temporalSerializerSuite struct { 49 suite.Suite 50 // override suite.Suite.Assertions with require.Assertions; this means that s.NotNil(nil) will stop the test, 51 // not merely log an error 52 *require.Assertions 53 protorequire.ProtoAssertions 54 logger log.Logger 55 56 serializer Serializer 57 } 58 ) 59 60 func TestTemporalSerializerSuite(t *testing.T) { 61 s := new(temporalSerializerSuite) 62 suite.Run(t, s) 63 } 64 65 func (s *temporalSerializerSuite) SetupTest() { 66 s.logger = log.NewTestLogger() 67 // Have to define our overridden assertions in the test setup. If we did it earlier, s.T() will return nil 68 s.Assertions = require.New(s.T()) 69 s.ProtoAssertions = protorequire.New(s.T()) 70 71 s.serializer = NewSerializer() 72 } 73 74 func (s *temporalSerializerSuite) TestSerializer() { 75 concurrency := 1 76 startWG := sync.WaitGroup{} 77 doneWG := sync.WaitGroup{} 78 79 startWG.Add(1) 80 doneWG.Add(concurrency) 81 82 eventType := enumspb.EVENT_TYPE_ACTIVITY_TASK_COMPLETED 83 event0 := &historypb.HistoryEvent{ 84 EventId: 999, 85 EventTime: timestamppb.New(time.Date(2020, 8, 22, 0, 0, 0, 0, time.UTC)), 86 EventType: eventType, 87 Attributes: &historypb.HistoryEvent_ActivityTaskCompletedEventAttributes{ 88 ActivityTaskCompletedEventAttributes: &historypb.ActivityTaskCompletedEventAttributes{ 89 Result: payloads.EncodeString("result-1-event-1"), 90 ScheduledEventId: 4, 91 StartedEventId: 5, 92 Identity: "event-1", 93 }, 94 }, 95 } 96 97 history0 := &historypb.History{Events: []*historypb.HistoryEvent{event0, event0}} 98 99 for i := 0; i < concurrency; i++ { 100 101 go func() { 102 startWG.Wait() 103 defer doneWG.Done() 104 105 // serialize event 106 nilEvent, err := s.serializer.SerializeEvent(nil, enumspb.ENCODING_TYPE_PROTO3) 107 s.Nil(err) 108 s.Nil(nilEvent) 109 110 _, err = s.serializer.SerializeEvent(event0, enumspb.ENCODING_TYPE_UNSPECIFIED) 111 s.NotNil(err) 112 _, ok := err.(*UnknownEncodingTypeError) 113 s.True(ok) 114 115 dProto, err := s.serializer.SerializeEvent(event0, enumspb.ENCODING_TYPE_PROTO3) 116 s.Nil(err) 117 s.NotNil(dProto) 118 119 // serialize batch events 120 nilEvents, err := s.serializer.SerializeEvents(nil, enumspb.ENCODING_TYPE_PROTO3) 121 s.Nil(err) 122 s.NotNil(nilEvents) 123 124 _, err = s.serializer.SerializeEvents(history0.Events, enumspb.ENCODING_TYPE_UNSPECIFIED) 125 s.NotNil(err) 126 _, ok = err.(*UnknownEncodingTypeError) 127 s.True(ok) 128 129 dsProto, err := s.serializer.SerializeEvents(history0.Events, enumspb.ENCODING_TYPE_PROTO3) 130 s.Nil(err) 131 s.NotNil(dsProto) 132 133 // deserialize event 134 dNilEvent, err := s.serializer.DeserializeEvent(nilEvent) 135 s.Nil(err) 136 s.Nil(dNilEvent) 137 138 event2, err := s.serializer.DeserializeEvent(dProto) 139 s.Nil(err) 140 s.ProtoEqual(event0, event2) 141 142 // deserialize events 143 dNilEvents, err := s.serializer.DeserializeEvents(nilEvents) 144 s.Nil(err) 145 s.Nil(dNilEvents) 146 147 events, err := s.serializer.DeserializeEvents(dsProto) 148 history2 := &historypb.History{Events: events} 149 s.Nil(err) 150 s.ProtoEqual(history0, history2) 151 }() 152 } 153 154 startWG.Done() 155 succ := common.AwaitWaitGroup(&doneWG, 10*time.Second) 156 s.True(succ, "test timed out") 157 } 158 159 func (s *temporalSerializerSuite) TestSerializeShardInfo_EmptyMapSlice() { 160 var shardInfo persistencespb.ShardInfo 161 162 shardInfo.ShardId = rand.Int31() 163 shardInfo.RangeId = rand.Int63() 164 165 categoryID := rand.Int31() 166 shardInfo.QueueStates = make(map[int32]*persistencespb.QueueState) 167 shardInfo.QueueStates[categoryID] = &persistencespb.QueueState{ 168 ReaderStates: make(map[int64]*persistencespb.QueueReaderState), 169 } 170 shardInfo.QueueStates[categoryID].ReaderStates[rand.Int63()] = &persistencespb.QueueReaderState{ 171 Scopes: make([]*persistencespb.QueueSliceScope, 0), 172 } 173 shardInfo.ReplicationDlqAckLevel = make(map[string]int64) 174 175 blob, err := s.serializer.ShardInfoToBlob(&shardInfo, enumspb.ENCODING_TYPE_PROTO3) 176 s.NoError(err) 177 178 deserializedShardInfo, err := s.serializer.ShardInfoFromBlob(blob) 179 s.NoError(err) 180 s.NotNil(deserializedShardInfo) 181 182 s.ProtoEqual(&shardInfo, deserializedShardInfo) 183 } 184 185 func (s *temporalSerializerSuite) TestSerializeShardInfo_Random() { 186 var shardInfo persistencespb.ShardInfo 187 err := gofakeit.Struct(&shardInfo) 188 s.NoError(err) 189 190 blob, err := s.serializer.ShardInfoToBlob(&shardInfo, enumspb.ENCODING_TYPE_PROTO3) 191 s.NoError(err) 192 193 deserializedShardInfo, err := s.serializer.ShardInfoFromBlob(blob) 194 s.NoError(err) 195 s.NotNil(deserializedShardInfo) 196 197 s.ProtoEqual(&shardInfo, deserializedShardInfo) 198 }