Skip to content

Commit 7a3beaa

Browse files
authored
[common] Add unit test for convertions (#1395)
* [common] Add unit test for convertions
1 parent 2d4612d commit 7a3beaa

File tree

4 files changed

+238
-50
lines changed

4 files changed

+238
-50
lines changed

internal/common/convert.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,55 +38,60 @@ func Int64Ceil(v float64) int64 {
3838

3939
// Int32Ptr makes a copy and returns the pointer to an int32.
4040
func Int32Ptr(v int32) *int32 {
41-
return &v
41+
return PtrOf(v)
4242
}
4343

4444
// Float64Ptr makes a copy and returns the pointer to a float64.
4545
func Float64Ptr(v float64) *float64 {
46-
return &v
46+
return PtrOf(v)
4747
}
4848

4949
// Int64Ptr makes a copy and returns the pointer to an int64.
5050
func Int64Ptr(v int64) *int64 {
51-
return &v
51+
return PtrOf(v)
5252
}
5353

5454
// StringPtr makes a copy and returns the pointer to a string.
5555
func StringPtr(v string) *string {
56-
return &v
56+
return PtrOf(v)
5757
}
5858

5959
// BoolPtr makes a copy and returns the pointer to a string.
6060
func BoolPtr(v bool) *bool {
61-
return &v
61+
return PtrOf(v)
6262
}
6363

6464
// TaskListPtr makes a copy and returns the pointer to a TaskList.
6565
func TaskListPtr(v s.TaskList) *s.TaskList {
66-
return &v
66+
return PtrOf(v)
6767
}
6868

6969
// DecisionTypePtr makes a copy and returns the pointer to a DecisionType.
7070
func DecisionTypePtr(t s.DecisionType) *s.DecisionType {
71-
return &t
71+
return PtrOf(t)
7272
}
7373

7474
// EventTypePtr makes a copy and returns the pointer to a EventType.
7575
func EventTypePtr(t s.EventType) *s.EventType {
76-
return &t
76+
return PtrOf(t)
7777
}
7878

7979
// QueryTaskCompletedTypePtr makes a copy and returns the pointer to a QueryTaskCompletedType.
8080
func QueryTaskCompletedTypePtr(t s.QueryTaskCompletedType) *s.QueryTaskCompletedType {
81-
return &t
81+
return PtrOf(t)
8282
}
8383

8484
// TaskListKindPtr makes a copy and returns the pointer to a TaskListKind.
8585
func TaskListKindPtr(t s.TaskListKind) *s.TaskListKind {
86-
return &t
86+
return PtrOf(t)
8787
}
8888

8989
// QueryResultTypePtr makes a copy and returns the pointer to a QueryResultType.
9090
func QueryResultTypePtr(t s.QueryResultType) *s.QueryResultType {
91-
return &t
91+
return PtrOf(t)
92+
}
93+
94+
// PtrOf makes a copy and returns the pointer to a value.
95+
func PtrOf[T any](v T) *T {
96+
return &v
9297
}

internal/common/convert_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) 2017-2021 Uber Technologies Inc.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package common
22+
23+
import (
24+
"testing"
25+
26+
s "go.uber.org/cadence/.gen/go/shared"
27+
28+
"github.com/stretchr/testify/assert"
29+
)
30+
31+
func TestPtrOf(t *testing.T) {
32+
assert.Equal(t, "a", *PtrOf("a"))
33+
assert.Equal(t, 1, *PtrOf(1))
34+
assert.Equal(t, int32(1), *PtrOf(int32(1)))
35+
assert.Equal(t, int64(1), *PtrOf(int64(1)))
36+
assert.Equal(t, float64(1.1), *PtrOf(float64(1.1)))
37+
assert.Equal(t, true, *PtrOf(true))
38+
}
39+
40+
func TestPtrHelpers(t *testing.T) {
41+
assert.Equal(t, int32(1), *Int32Ptr(1))
42+
assert.Equal(t, int64(1), *Int64Ptr(1))
43+
assert.Equal(t, 1.1, *Float64Ptr(1.1))
44+
assert.Equal(t, true, *BoolPtr(true))
45+
assert.Equal(t, "a", *StringPtr("a"))
46+
assert.Equal(t, s.TaskList{Name: PtrOf("a")}, *TaskListPtr(s.TaskList{Name: PtrOf("a")}))
47+
assert.Equal(t, s.DecisionTypeScheduleActivityTask, *DecisionTypePtr(s.DecisionTypeScheduleActivityTask))
48+
assert.Equal(t, s.EventTypeWorkflowExecutionStarted, *EventTypePtr(s.EventTypeWorkflowExecutionStarted))
49+
assert.Equal(t, s.QueryTaskCompletedTypeCompleted, *QueryTaskCompletedTypePtr(s.QueryTaskCompletedTypeCompleted))
50+
assert.Equal(t, s.TaskListKindNormal, *TaskListKindPtr(s.TaskListKindNormal))
51+
assert.Equal(t, s.QueryResultTypeFailed, *QueryResultTypePtr(s.QueryResultTypeFailed))
52+
}
53+
54+
func TestCeilHelpers(t *testing.T) {
55+
assert.Equal(t, int32(2), Int32Ceil(1.1))
56+
assert.Equal(t, int64(2), Int64Ceil(1.1))
57+
}

internal/common/thrift_util.go

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,13 @@ import (
2727
"github.com/apache/thrift/lib/go/thrift"
2828
)
2929

30-
// TSerialize is used to serialize thrift TStruct to []byte
31-
func TSerialize(ctx context.Context, t thrift.TStruct) (b []byte, err error) {
32-
return thrift.NewTSerializer().Write(ctx, t)
33-
}
34-
3530
// TListSerialize is used to serialize list of thrift TStruct to []byte
36-
func TListSerialize(ts []thrift.TStruct) (b []byte, err error) {
31+
func TListSerialize(ts []thrift.TStruct) ([]byte, error) {
3732
if ts == nil {
38-
return
33+
return nil, nil
3934
}
4035

4136
t := thrift.NewTSerializer()
42-
t.Transport.Reset()
4337

4438
// NOTE: we don't write any markers as thrift by design being a streaming protocol doesn't
4539
// recommend writing length.
@@ -48,26 +42,11 @@ func TListSerialize(ts []thrift.TStruct) (b []byte, err error) {
4842
ctx := context.Background()
4943
for _, v := range ts {
5044
if e := v.Write(ctx, t.Protocol); e != nil {
51-
err = thrift.PrependError("error writing TStruct: ", e)
52-
return
45+
return nil, thrift.PrependError("error writing TStruct: ", e)
5346
}
5447
}
5548

56-
if err = t.Protocol.Flush(ctx); err != nil {
57-
return
58-
}
59-
60-
if err = t.Transport.Flush(ctx); err != nil {
61-
return
62-
}
63-
64-
b = t.Transport.Bytes()
65-
return
66-
}
67-
68-
// TDeserialize is used to deserialize []byte to thrift TStruct
69-
func TDeserialize(ctx context.Context, t thrift.TStruct, b []byte) (err error) {
70-
return thrift.NewTDeserializer().Read(ctx, t, b)
49+
return t.Transport.Bytes(), t.Protocol.Flush(ctx)
7150
}
7251

7352
// TListDeserialize is used to deserialize []byte to list of thrift TStruct
@@ -92,15 +71,13 @@ func TListDeserialize(ts []thrift.TStruct, b []byte) (err error) {
9271

9372
// IsUseThriftEncoding checks if the objects passed in are all encoded using thrift.
9473
func IsUseThriftEncoding(objs []interface{}) bool {
95-
// NOTE: our criteria to use which encoder is simple if all the types are serializable using thrift then we use
96-
// thrift encoder. For everything else we default to gob.
97-
9874
if len(objs) == 0 {
9975
return false
10076
}
101-
102-
for i := 0; i < len(objs); i++ {
103-
if !IsThriftType(objs[i]) {
77+
// NOTE: our criteria to use which encoder is simple if all the types are serializable using thrift then we use
78+
// thrift encoder. For everything else we default to gob.
79+
for _, obj := range objs {
80+
if !IsThriftType(obj) {
10481
return false
10582
}
10683
}
@@ -109,15 +86,13 @@ func IsUseThriftEncoding(objs []interface{}) bool {
10986

11087
// IsUseThriftDecoding checks if the objects passed in are all de-serializable using thrift.
11188
func IsUseThriftDecoding(objs []interface{}) bool {
112-
// NOTE: our criteria to use which encoder is simple if all the types are de-serializable using thrift then we use
113-
// thrift decoder. For everything else we default to gob.
114-
11589
if len(objs) == 0 {
11690
return false
11791
}
118-
119-
for i := 0; i < len(objs); i++ {
120-
rVal := reflect.ValueOf(objs[i])
92+
// NOTE: our criteria to use which encoder is simple if all the types are de-serializable using thrift then we use
93+
// thrift decoder. For everything else we default to gob.
94+
for _, obj := range objs {
95+
rVal := reflect.ValueOf(obj)
12196
if rVal.Kind() != reflect.Ptr || !IsThriftType(reflect.Indirect(rVal).Interface()) {
12297
return false
12398
}
@@ -133,6 +108,7 @@ func IsThriftType(v interface{}) bool {
133108
if reflect.ValueOf(v).Kind() != reflect.Ptr {
134109
return false
135110
}
136-
t := reflect.TypeOf((*thrift.TStruct)(nil)).Elem()
137-
return reflect.TypeOf(v).Implements(t)
111+
return reflect.TypeOf(v).Implements(tStructType)
138112
}
113+
114+
var tStructType = reflect.TypeOf((*thrift.TStruct)(nil)).Elem()

internal/common/thrift_util_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright (c) 2017-2021 Uber Technologies Inc.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package common
22+
23+
import (
24+
"context"
25+
"testing"
26+
27+
"github.com/apache/thrift/lib/go/thrift"
28+
"github.com/stretchr/testify/assert"
29+
)
30+
31+
func TestTListSerialize(t *testing.T) {
32+
t.Run("nil", func(t *testing.T) {
33+
data, err := TListSerialize(nil)
34+
assert.NoError(t, err)
35+
assert.Nil(t, data)
36+
})
37+
t.Run("normal", func(t *testing.T) {
38+
ts := []thrift.TStruct{
39+
&mockThriftStruct{Field1: "value1", Field2: 1},
40+
&mockThriftStruct{Field1: "value2", Field2: 2},
41+
}
42+
43+
_, err := TListSerialize(ts)
44+
assert.NoError(t, err)
45+
})
46+
}
47+
48+
func TestTListDeserialize(t *testing.T) {
49+
ts := []thrift.TStruct{
50+
&mockThriftStruct{},
51+
&mockThriftStruct{},
52+
}
53+
54+
data, err := TListSerialize(ts)
55+
assert.NoError(t, err)
56+
57+
err = TListDeserialize(ts, data)
58+
assert.NoError(t, err)
59+
}
60+
61+
func TestIsUseThriftEncoding(t *testing.T) {
62+
for _, tc := range []struct {
63+
name string
64+
input []interface{}
65+
expected bool
66+
}{
67+
{
68+
name: "nil",
69+
input: nil,
70+
expected: false,
71+
},
72+
{
73+
name: "success",
74+
input: []interface{}{
75+
&mockThriftStruct{},
76+
&mockThriftStruct{},
77+
},
78+
expected: true,
79+
},
80+
{
81+
name: "fail",
82+
input: []interface{}{
83+
&mockThriftStruct{},
84+
PtrOf("string"),
85+
},
86+
expected: false,
87+
},
88+
} {
89+
t.Run(tc.name, func(t *testing.T) {
90+
assert.Equal(t, tc.expected, IsUseThriftEncoding(tc.input))
91+
})
92+
}
93+
}
94+
95+
func TestIsUseThriftDecoding(t *testing.T) {
96+
for _, tc := range []struct {
97+
name string
98+
input []interface{}
99+
expected bool
100+
}{
101+
{
102+
name: "nil",
103+
input: nil,
104+
expected: false,
105+
},
106+
{
107+
name: "success",
108+
input: []interface{}{
109+
PtrOf(&mockThriftStruct{}),
110+
PtrOf(&mockThriftStruct{}),
111+
},
112+
expected: true,
113+
},
114+
{
115+
name: "fail",
116+
input: []interface{}{
117+
PtrOf(&mockThriftStruct{}),
118+
PtrOf("string"),
119+
},
120+
expected: false,
121+
},
122+
} {
123+
t.Run(tc.name, func(t *testing.T) {
124+
assert.Equal(t, tc.expected, IsUseThriftDecoding(tc.input))
125+
})
126+
}
127+
}
128+
129+
func TestIsThriftType(t *testing.T) {
130+
assert.True(t, IsThriftType(&mockThriftStruct{}))
131+
132+
assert.False(t, IsThriftType(mockThriftStruct{}))
133+
}
134+
135+
type mockThriftStruct struct {
136+
Field1 string
137+
Field2 int
138+
}
139+
140+
func (m *mockThriftStruct) Read(ctx context.Context, iprot thrift.TProtocol) error {
141+
return nil
142+
}
143+
144+
func (m *mockThriftStruct) Write(ctx context.Context, oprot thrift.TProtocol) error {
145+
return nil
146+
}
147+
148+
func (m *mockThriftStruct) String() string {
149+
return ""
150+
}

0 commit comments

Comments
 (0)