Skip to content

Commit 8c933b2

Browse files
test: improve test coverage across multiple packages (#39)
* test: improve test coverage across multiple packages * test
1 parent fb2b971 commit 8c933b2

16 files changed

Lines changed: 6511 additions & 2 deletions

errors/errors_test.go

Lines changed: 411 additions & 0 deletions
Large diffs are not rendered by default.

marshaller/factory_test.go

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
package marshaller
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestIsRegistered_Success(t *testing.T) {
12+
t.Parallel()
13+
14+
tests := []struct {
15+
name string
16+
typ reflect.Type
17+
expected bool
18+
}{
19+
{
20+
name: "registered string type returns true",
21+
typ: reflect.TypeOf(""),
22+
expected: true,
23+
},
24+
{
25+
name: "registered pointer string type returns true",
26+
typ: reflect.TypeOf((*string)(nil)),
27+
expected: true,
28+
},
29+
{
30+
name: "registered int type returns true",
31+
typ: reflect.TypeOf(0),
32+
expected: true,
33+
},
34+
{
35+
name: "unregistered custom struct returns false",
36+
typ: reflect.TypeOf(struct{ Name string }{}),
37+
expected: false,
38+
},
39+
}
40+
41+
for _, tt := range tests {
42+
t.Run(tt.name, func(t *testing.T) {
43+
t.Parallel()
44+
actual := IsRegistered(tt.typ)
45+
assert.Equal(t, tt.expected, actual)
46+
})
47+
}
48+
}
49+
50+
func TestCreateInstance_Success(t *testing.T) {
51+
t.Parallel()
52+
53+
tests := []struct {
54+
name string
55+
typ reflect.Type
56+
expected reflect.Type
57+
}{
58+
{
59+
name: "create string instance",
60+
typ: reflect.TypeOf(""),
61+
expected: reflect.TypeOf((*string)(nil)),
62+
},
63+
{
64+
name: "create pointer string instance",
65+
typ: reflect.TypeOf((*string)(nil)),
66+
expected: reflect.TypeOf((*string)(nil)),
67+
},
68+
{
69+
name: "create int instance",
70+
typ: reflect.TypeOf(0),
71+
expected: reflect.TypeOf((*int)(nil)),
72+
},
73+
{
74+
name: "create bool instance",
75+
typ: reflect.TypeOf(false),
76+
expected: reflect.TypeOf((*bool)(nil)),
77+
},
78+
}
79+
80+
for _, tt := range tests {
81+
t.Run(tt.name, func(t *testing.T) {
82+
t.Parallel()
83+
actual := CreateInstance(tt.typ)
84+
assert.Equal(t, tt.expected, actual.Type())
85+
assert.NotNil(t, actual.Interface())
86+
})
87+
}
88+
}
89+
90+
func TestCreateInstance_UnregisteredType_Success(t *testing.T) {
91+
t.Parallel()
92+
93+
// Test with an unregistered struct type
94+
type UnregisteredStruct struct {
95+
Name string
96+
Age int
97+
}
98+
99+
typ := reflect.TypeOf(UnregisteredStruct{})
100+
result := CreateInstance(typ)
101+
102+
assert.Equal(t, reflect.TypeOf((*UnregisteredStruct)(nil)), result.Type())
103+
assert.NotNil(t, result.Interface())
104+
}
105+
106+
func TestRegisterType_Success(t *testing.T) {
107+
t.Parallel()
108+
109+
// Define a custom type for testing
110+
type TestCustomType struct {
111+
Value string
112+
}
113+
114+
// Register the type
115+
RegisterType(func() *TestCustomType {
116+
return &TestCustomType{Value: "test"}
117+
})
118+
119+
// Verify it's registered
120+
typ := reflect.TypeOf(TestCustomType{})
121+
assert.True(t, IsRegistered(typ))
122+
123+
// Verify we can create instances
124+
instance := CreateInstance(typ)
125+
assert.Equal(t, reflect.TypeOf((*TestCustomType)(nil)), instance.Type())
126+
127+
// Verify the factory function is used
128+
customInstance := instance.Interface().(*TestCustomType)
129+
assert.Equal(t, "test", customInstance.Value)
130+
}
131+
132+
func TestClearGlobalFieldCache_Success(t *testing.T) {
133+
t.Parallel()
134+
135+
// Define a test struct to build cache for
136+
type TestStruct struct {
137+
Name string `key:"name"`
138+
Age int `key:"age"`
139+
}
140+
141+
// Register the type to build field cache
142+
RegisterType(func() *TestStruct {
143+
return &TestStruct{}
144+
})
145+
146+
// Verify cache has entries
147+
stats := GetFieldCacheStats()
148+
initialSize := stats.Size
149+
150+
// Clear the cache
151+
ClearGlobalFieldCache()
152+
153+
// Verify cache is empty
154+
stats = GetFieldCacheStats()
155+
assert.Equal(t, int64(0), stats.Size)
156+
assert.True(t, stats.Size < initialSize || initialSize == 0)
157+
}
158+
159+
func TestGetFieldCacheStats_Success(t *testing.T) {
160+
t.Parallel()
161+
162+
// Clear cache first to get a clean state
163+
ClearGlobalFieldCache()
164+
165+
// Define test structs to build cache for
166+
type TestStruct1 struct {
167+
Name string `key:"name"`
168+
}
169+
type TestStruct2 struct {
170+
Value int `key:"value"`
171+
}
172+
173+
// Register types to build field cache
174+
RegisterType(func() *TestStruct1 {
175+
return &TestStruct1{}
176+
})
177+
RegisterType(func() *TestStruct2 {
178+
return &TestStruct2{}
179+
})
180+
181+
// Get stats
182+
stats := GetFieldCacheStats()
183+
184+
// Should have at least 2 entries (our test structs)
185+
assert.GreaterOrEqual(t, stats.Size, int64(2))
186+
}
187+
188+
func TestBuildFieldCacheForType_Success(t *testing.T) {
189+
t.Parallel()
190+
191+
// Define a test struct with various field types
192+
type TestStruct struct {
193+
Name string `key:"name" required:"true"`
194+
Age int `key:"age"`
195+
OptionalField *string `key:"optional"`
196+
// Extensions field (special handling)
197+
Extensions interface{} `key:"extensions"`
198+
}
199+
200+
structType := reflect.TypeOf(TestStruct{})
201+
202+
// Build cache for the type
203+
buildFieldCacheForType(structType)
204+
205+
// Verify cache was built
206+
cached := getFieldMapCached(structType)
207+
208+
assert.NotEmpty(t, cached.Fields)
209+
assert.Contains(t, cached.Fields, "name")
210+
assert.Contains(t, cached.Fields, "age")
211+
assert.Contains(t, cached.Fields, "optional")
212+
213+
// Verify required field detection
214+
assert.True(t, cached.Fields["name"].Required)
215+
assert.False(t, cached.Fields["age"].Required) // no required tag
216+
assert.False(t, cached.Fields["optional"].Required) // pointer type
217+
}
218+
219+
func TestBuildFieldCacheForType_NonStruct_Success(t *testing.T) {
220+
t.Parallel()
221+
222+
// Test with non-struct type (should not panic)
223+
intType := reflect.TypeOf(0)
224+
buildFieldCacheForType(intType)
225+
226+
// Should not create cache entry for non-struct
227+
_, ok := fieldCache.Load(intType)
228+
assert.False(t, ok)
229+
}
230+
231+
func TestGetFieldMapCached_CacheMiss_Success(t *testing.T) {
232+
t.Parallel()
233+
234+
// Define a struct that hasn't been registered
235+
type UnregisteredStruct struct {
236+
Name string `key:"name"`
237+
}
238+
239+
structType := reflect.TypeOf(UnregisteredStruct{})
240+
241+
// This should build cache on-demand
242+
cached := getFieldMapCached(structType)
243+
244+
assert.NotEmpty(t, cached.Fields)
245+
assert.Contains(t, cached.Fields, "name")
246+
}
247+
248+
func TestIsTesting_Success(t *testing.T) {
249+
t.Parallel()
250+
251+
// During test execution, isTesting() should return true
252+
result := isTesting()
253+
assert.True(t, result)
254+
}
255+
256+
func TestCachedFieldInfo_Success(t *testing.T) {
257+
t.Parallel()
258+
259+
// Test CachedFieldInfo struct creation
260+
info := CachedFieldInfo{
261+
Name: "TestField",
262+
Index: 0,
263+
Required: true,
264+
Tag: "test",
265+
IsExported: true,
266+
IsExtensions: false,
267+
}
268+
269+
assert.Equal(t, "TestField", info.Name)
270+
assert.Equal(t, 0, info.Index)
271+
assert.True(t, info.Required)
272+
assert.Equal(t, "test", info.Tag)
273+
assert.True(t, info.IsExported)
274+
assert.False(t, info.IsExtensions)
275+
}
276+
277+
func TestCachedFieldMaps_Success(t *testing.T) {
278+
t.Parallel()
279+
280+
// Test CachedFieldMaps struct creation
281+
maps := CachedFieldMaps{
282+
Fields: map[string]CachedFieldInfo{
283+
"test": {
284+
Name: "TestField",
285+
Index: 0,
286+
Required: true,
287+
Tag: "test",
288+
},
289+
},
290+
ExtensionIndex: -1,
291+
HasExtensions: false,
292+
FieldIndexes: map[string]int{
293+
"test": 0,
294+
},
295+
RequiredFields: map[string]bool{
296+
"test": true,
297+
},
298+
}
299+
300+
assert.NotEmpty(t, maps.Fields)
301+
assert.Contains(t, maps.Fields, "test")
302+
assert.Equal(t, -1, maps.ExtensionIndex)
303+
assert.False(t, maps.HasExtensions)
304+
assert.NotEmpty(t, maps.FieldIndexes)
305+
assert.NotEmpty(t, maps.RequiredFields)
306+
}
307+
308+
func TestFieldCacheStats_Success(t *testing.T) {
309+
t.Parallel()
310+
311+
// Test FieldCacheStats struct
312+
stats := FieldCacheStats{
313+
Size: 42,
314+
}
315+
316+
assert.Equal(t, int64(42), stats.Size)
317+
}
318+
319+
func TestRegisterType_PointerType_Success(t *testing.T) {
320+
t.Parallel()
321+
322+
// Test registering a pointer type
323+
type TestPointerType struct {
324+
Value string
325+
}
326+
327+
// Register with pointer type
328+
RegisterType(func() *TestPointerType {
329+
return &TestPointerType{Value: "pointer-test"}
330+
})
331+
332+
// Should be registered for the element type
333+
elemType := reflect.TypeOf(TestPointerType{})
334+
assert.True(t, IsRegistered(elemType))
335+
336+
// Should also work with pointer type
337+
ptrType := reflect.TypeOf((*TestPointerType)(nil))
338+
assert.True(t, IsRegistered(ptrType))
339+
}
340+
341+
func TestTypeFactory_Success(t *testing.T) {
342+
t.Parallel()
343+
344+
// Test TypeFactory function type
345+
factory := TypeFactory(func() interface{} {
346+
return &struct{ Name string }{Name: "test"}
347+
})
348+
349+
result := factory()
350+
assert.NotNil(t, result)
351+
352+
// Verify the result is the expected type
353+
structPtr, ok := result.(*struct{ Name string })
354+
require.True(t, ok)
355+
assert.Equal(t, "test", structPtr.Name)
356+
}

0 commit comments

Comments
 (0)