-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtimeout_test.go
More file actions
160 lines (134 loc) · 3.6 KB
/
timeout_test.go
File metadata and controls
160 lines (134 loc) · 3.6 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
// Copyright (c) 2017-2026 The ivi developers. All rights reserved.
// Project site: https://github.com/gotmc/ivi
// 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 ivi
import (
"context"
"errors"
"testing"
"time"
)
// mockInstrument simulates an instrument with configurable delays.
type mockInstrument struct {
readDelay time.Duration
writeDelay time.Duration
queryDelay time.Duration
cmdDelay time.Duration
shouldError bool
}
func (m *mockInstrument) ReadBinary(_ context.Context, p []byte) (int, error) {
if m.shouldError {
return 0, errors.New("mock error")
}
time.Sleep(m.readDelay)
copy(p, []byte("test response"))
return len("test response"), nil
}
func (m *mockInstrument) WriteBinary(_ context.Context, p []byte) (int, error) {
if m.shouldError {
return 0, errors.New("mock error")
}
time.Sleep(m.writeDelay)
return len(p), nil
}
func (m *mockInstrument) Close() error { return nil }
func (m *mockInstrument) Command(ctx context.Context, format string, a ...any) error {
if m.shouldError {
return errors.New("mock error")
}
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(m.cmdDelay):
return nil
}
}
func (m *mockInstrument) Query(ctx context.Context, s string) (value string, err error) {
if m.shouldError {
return "", errors.New("mock error")
}
select {
case <-ctx.Done():
return "", ctx.Err()
case <-time.After(m.queryDelay):
return "query response", nil
}
}
func TestQuery_Success(t *testing.T) {
mock := &mockInstrument{
queryDelay: 10 * time.Millisecond,
}
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
response, err := mock.Query(ctx, "*IDN?")
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
if response != "query response" {
t.Errorf("Expected 'query response', got '%s'", response)
}
}
func TestQuery_Timeout(t *testing.T) {
mock := &mockInstrument{
queryDelay: 100 * time.Millisecond,
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
_, err := mock.Query(ctx, "*IDN?")
if err != context.DeadlineExceeded {
t.Errorf("Expected context.DeadlineExceeded, got %v", err)
}
}
func TestCommand_Success(t *testing.T) {
mock := &mockInstrument{
cmdDelay: 10 * time.Millisecond,
}
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
err := mock.Command(ctx, "*RST")
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
}
func TestCommand_Timeout(t *testing.T) {
mock := &mockInstrument{
cmdDelay: 100 * time.Millisecond,
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
err := mock.Command(ctx, "*RST")
if err != context.DeadlineExceeded {
t.Errorf("Expected context.DeadlineExceeded, got %v", err)
}
}
func TestConcurrentOperations(t *testing.T) {
mock := &mockInstrument{
queryDelay: 20 * time.Millisecond,
}
// Run multiple queries concurrently
done := make(chan bool, 3)
for range 3 {
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
response, err := mock.Query(ctx, "*IDN?")
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
if response != "query response" {
t.Errorf("Expected 'query response', got '%s'", response)
}
done <- true
}()
}
// Wait for all goroutines to complete
for range 3 {
select {
case <-done:
// Success
case <-time.After(200 * time.Millisecond):
t.Error("Concurrent operation timed out")
}
}
}