-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathfinalizer_test.go
More file actions
161 lines (137 loc) · 4.37 KB
/
finalizer_test.go
File metadata and controls
161 lines (137 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (c) 2015-2025 The libusb developers. All rights reserved.
// Project site: https://github.com/gotmc/libusb
// Use of this source code is governed by a MIT-style license that
// can be found in the LICENSE.txt file for the project.
package libusb
import (
"runtime"
"testing"
"time"
)
// TestDeviceFinalizer tests that Device objects are properly cleaned up
// by the garbage collector when not explicitly closed.
func TestDeviceFinalizer(t *testing.T) {
// Skip test if no USB devices are connected
ctx, err := NewContext()
if err != nil {
t.Skip("Cannot create context for finalizer test")
}
defer ctx.Close()
devices, err := ctx.DeviceList()
if err != nil {
t.Skip("Cannot get device list for finalizer test")
}
defer func() {
for _, device := range devices {
device.Close()
}
}()
if len(devices) == 0 {
t.Skip("No USB devices connected for finalizer test")
}
// Create a device and let it go out of scope without calling Close()
func() {
// This device will go out of scope and should be finalized
_ = devices[0]
}()
// Force garbage collection and finalization
runtime.GC()
runtime.GC() // Call twice to ensure finalizers run
time.Sleep(100 * time.Millisecond) // Give finalizers time to run
// If we get here without crashing, the finalizer worked correctly
t.Log("Device finalizer test completed successfully")
}
// TestDeviceHandleFinalizer tests that DeviceHandle objects are properly
// cleaned up by the garbage collector when not explicitly closed.
func TestDeviceHandleFinalizer(t *testing.T) {
// Skip test if no USB devices are connected
ctx, err := NewContext()
if err != nil {
t.Skip("Cannot create context for finalizer test")
}
defer ctx.Close()
devices, err := ctx.DeviceList()
if err != nil {
t.Skip("Cannot get device list for finalizer test")
}
defer func() {
for _, device := range devices {
device.Close()
}
}()
if len(devices) == 0 {
t.Skip("No USB devices connected for finalizer test")
}
// Try to open a device handle and let it go out of scope
func() {
handle, err := devices[0].Open()
if err != nil {
t.Skip("Cannot open device for handle finalizer test")
}
// This handle will go out of scope and should be finalized
_ = handle
}()
// Force garbage collection and finalization
runtime.GC()
runtime.GC() // Call twice to ensure finalizers run
time.Sleep(100 * time.Millisecond) // Give finalizers time to run
// If we get here without crashing, the finalizer worked correctly
t.Log("DeviceHandle finalizer test completed successfully")
}
// TestExplicitCloseRemovesFinalizer tests that explicitly calling Close()
// removes the finalizer so it won't be called later.
func TestExplicitCloseRemovesFinalizer(t *testing.T) {
// Skip test if no USB devices are connected
ctx, err := NewContext()
if err != nil {
t.Skip("Cannot create context for finalizer test")
}
defer ctx.Close()
devices, err := ctx.DeviceList()
if err != nil {
t.Skip("Cannot get device list for finalizer test")
}
defer func() {
for _, device := range devices {
device.Close()
}
}()
if len(devices) == 0 {
t.Skip("No USB devices connected for finalizer test")
}
// Create a device, close it explicitly, then force GC
device := devices[0]
device.Close() // This should clear the finalizer
// Force garbage collection - the finalizer should not run
runtime.GC()
runtime.GC()
time.Sleep(100 * time.Millisecond)
t.Log("Explicit close finalizer removal test completed successfully")
}
// TestFinalizerMemoryLeakPrevention tests that finalizers prevent memory leaks
// when objects are not explicitly closed.
func TestFinalizerMemoryLeakPrevention(t *testing.T) {
// This test creates many Device objects without closing them
// and verifies that finalizers clean them up properly
ctx, err := NewContext()
if err != nil {
t.Skip("Cannot create context for finalizer test")
}
defer ctx.Close()
// Create multiple rounds of devices to stress test finalizers
for i := 0; i < 5; i++ {
func() {
devices, err := ctx.DeviceList()
if err != nil {
t.Skip("Cannot get device list for memory leak test")
}
// Let all devices go out of scope without closing them
_ = devices
}()
// Force garbage collection after each round
runtime.GC()
runtime.GC()
time.Sleep(50 * time.Millisecond)
}
t.Log("Memory leak prevention test completed successfully")
}