1
+ package hivesim
2
+
3
+ import (
4
+ "encoding/json"
5
+ "net"
6
+ "net/http"
7
+ "net/http/httptest"
8
+ "testing"
9
+
10
+ "github.com/ethereum/hive/internal/fakes"
11
+ "github.com/ethereum/hive/internal/libhive"
12
+ "github.com/ethereum/hive/internal/simapi"
13
+ )
14
+
15
+ // Tests shared client functionality by mocking server responses.
16
+ func TestStartSharedClient (t * testing.T ) {
17
+ // This test creates a test HTTP server that mocks the simulation API.
18
+ // It responds to just the calls we need for this test, ignoring others.
19
+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
20
+ switch r .URL .Path {
21
+ case "/testsuite" :
22
+ // StartSuite
23
+ json .NewEncoder (w ).Encode (0 ) // Return suite ID
24
+ case "/testsuite/0/shared-client" :
25
+ // StartSharedClient
26
+ json .NewEncoder (w ).Encode (simapi.StartNodeResponse {
27
+ ID : "container1" ,
28
+ IP : "192.0.2.1" ,
29
+ })
30
+ case "/testsuite/0/shared-client/container1" :
31
+ // GetSharedClientInfo
32
+ json .NewEncoder (w ).Encode (simapi.NodeResponse {
33
+ ID : "container1" ,
34
+ Name : "client-1" ,
35
+ })
36
+ default :
37
+ http .NotFound (w , r )
38
+ }
39
+ }))
40
+ defer srv .Close ()
41
+
42
+ sim := NewAt (srv .URL )
43
+
44
+ // Start a test suite
45
+ suiteID , err := sim .StartSuite (& simapi.TestRequest {Name : "shared-client-test-suite" }, "Testing shared clients" )
46
+ if err != nil {
47
+ t .Fatal ("can't start suite:" , err )
48
+ }
49
+
50
+ // Start a shared client
51
+ containerID , ip , err := sim .StartSharedClient (suiteID , "client-1" , Params (map [string ]string {
52
+ "HIVE_PARAM" : "value" ,
53
+ }))
54
+ if err != nil {
55
+ t .Fatal ("can't start shared client:" , err )
56
+ }
57
+
58
+ if containerID != "container1" {
59
+ t .Errorf ("wrong container ID: got %q, want %q" , containerID , "container1" )
60
+ }
61
+ expected := net .ParseIP ("192.0.2.1" )
62
+ if ! ip .Equal (expected ) {
63
+ t .Errorf ("wrong IP returned: got %v, want %v" , ip , expected )
64
+ }
65
+
66
+ // Get client info
67
+ info , err := sim .GetSharedClientInfo (suiteID , containerID )
68
+ if err != nil {
69
+ t .Fatal ("can't get shared client info:" , err )
70
+ }
71
+
72
+ if info .ID != "container1" {
73
+ t .Errorf ("wrong container ID in info: got %q, want %q" , info .ID , "container1" )
74
+ }
75
+ }
76
+
77
+ // Tests AddSharedClient method in Suite.
78
+ func TestAddSharedClient (t * testing.T ) {
79
+ var startedContainers int
80
+
81
+ tm , srv := newFakeAPI (& fakes.BackendHooks {
82
+ StartContainer : func (image , containerID string , opt libhive.ContainerOptions ) (* libhive.ContainerInfo , error ) {
83
+ startedContainers ++
84
+ return & libhive.ContainerInfo {
85
+ ID : containerID ,
86
+ IP : "192.0.2.1" ,
87
+ }, nil
88
+ },
89
+ })
90
+ defer srv .Close ()
91
+ defer tm .Terminate ()
92
+
93
+ suite := Suite {
94
+ Name : "shared-client-suite" ,
95
+ Description : "Testing shared client registration" ,
96
+ }
97
+ suite .AddSharedClient ("shared1" , "client-1" , Params (map [string ]string {
98
+ "PARAM1" : "value1" ,
99
+ }))
100
+
101
+ suite .Add (TestSpec {
102
+ Name : "test-using-shared-client" ,
103
+ Run : func (t * T ) {
104
+ client := t .GetSharedClient ("shared1" )
105
+ if client == nil {
106
+ t .Fatal ("shared client not found" )
107
+ }
108
+
109
+ if client .Type != "client-1" {
110
+ t .Errorf ("wrong client type: got %q, want %q" , client .Type , "client-1" )
111
+ }
112
+ if ! client .IsShared {
113
+ t .Error ("IsShared flag not set on client" )
114
+ }
115
+ },
116
+ })
117
+
118
+ sim := NewAt (srv .URL )
119
+ err := RunSuite (sim , suite )
120
+ if err != nil {
121
+ t .Fatal ("suite run failed:" , err )
122
+ }
123
+
124
+ if startedContainers == 0 {
125
+ t .Error ("no containers were started" )
126
+ }
127
+
128
+ tm .Terminate ()
129
+ results := tm .Results ()
130
+ removeTimestamps (results )
131
+
132
+ if len (results ) == 0 {
133
+ t .Fatal ("no test results" )
134
+ }
135
+
136
+ suiteResult := results [0 ]
137
+ if suiteResult .SharedClients == nil || len (suiteResult .SharedClients ) == 0 {
138
+ t .Error ("no shared clients in test results" )
139
+ }
140
+ }
141
+
142
+ // Tests log offset tracking.
143
+ func TestSharedClientLogOffset (t * testing.T ) {
144
+ // Mock HTTP server for testing the log offset API
145
+ var offsetValue int64 = 0
146
+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
147
+ switch r .URL .Path {
148
+ case "/testsuite" :
149
+ // StartSuite
150
+ json .NewEncoder (w ).Encode (0 ) // Return suite ID
151
+ case "/testsuite/0/shared-client" :
152
+ // StartSharedClient
153
+ json .NewEncoder (w ).Encode (simapi.StartNodeResponse {
154
+ ID : "container1" ,
155
+ IP : "192.0.2.1" ,
156
+ })
157
+ case "/testsuite/0/shared-client/container1/log-offset" :
158
+ // GetClientLogOffset - increment the offset each time it's called
159
+ currentOffset := offsetValue
160
+ offsetValue += 100 // Simulate log growth
161
+ json .NewEncoder (w ).Encode (currentOffset )
162
+ case "/testsuite/0/shared-client/container1/exec" :
163
+ // ExecSharedClient
164
+ json .NewEncoder (w ).Encode (& ExecInfo {
165
+ Stdout : "test output" ,
166
+ ExitCode : 0 ,
167
+ })
168
+ default :
169
+ http .NotFound (w , r )
170
+ }
171
+ }))
172
+ defer srv .Close ()
173
+
174
+ sim := NewAt (srv .URL )
175
+ suiteID , err := sim .StartSuite (& simapi.TestRequest {Name : "log-offset-suite" }, "Testing log offset" )
176
+ if err != nil {
177
+ t .Fatal ("can't start suite:" , err )
178
+ }
179
+
180
+ containerID , _ , err := sim .StartSharedClient (suiteID , "client-1" )
181
+ if err != nil {
182
+ t .Fatal ("can't start shared client:" , err )
183
+ }
184
+
185
+ // Get initial offset
186
+ initialOffset , err := sim .GetClientLogOffset (suiteID , containerID )
187
+ if err != nil {
188
+ t .Fatal ("can't get initial log offset:" , err )
189
+ }
190
+ if initialOffset != 0 {
191
+ t .Errorf ("wrong initial offset: got %d, want 0" , initialOffset )
192
+ }
193
+
194
+ // Simulate a command that generates logs
195
+ _ , err = sim .ExecSharedClient (suiteID , containerID , []string {"/bin/echo" , "test1" })
196
+ if err != nil {
197
+ t .Fatal ("exec failed:" , err )
198
+ }
199
+
200
+ // Get new offset - should have increased
201
+ newOffset , err := sim .GetClientLogOffset (suiteID , containerID )
202
+ if err != nil {
203
+ t .Fatal ("can't get new log offset:" , err )
204
+ }
205
+ if newOffset <= initialOffset {
206
+ t .Errorf ("offset didn't increase: got %d, want > %d" , newOffset , initialOffset )
207
+ }
208
+ }
209
+
210
+ // Tests log extraction functionality.
211
+ func TestSharedClientLogExtraction (t * testing.T ) {
212
+ // We can't fully test the log extraction in unit tests because it depends on file I/O.
213
+ // However, we can verify that the API endpoints are called correctly.
214
+ // The actual file operations are tested in integration tests.
215
+
216
+ // This test ensures that:
217
+ // 1. We use a MockSuite instead of real test cases
218
+ // 2. We verify that the ClientLogs structure is correctly set up
219
+
220
+ // Create a mock ClientLogs map for our test result
221
+ clientLogs := make (map [string ]* libhive.ClientLogSegment )
222
+ clientLogs ["shared1" ] = & libhive.ClientLogSegment {
223
+ Start : 0 ,
224
+ End : 100 ,
225
+ ClientID : "container1" ,
226
+ }
227
+
228
+ // Create a mock test result
229
+ mockResult := & libhive.TestResult {
230
+ Pass : true ,
231
+ ClientLogs : clientLogs ,
232
+ }
233
+
234
+ // Verify the test result has client logs
235
+ if mockResult .ClientLogs == nil {
236
+ t .Error ("no client logs in test results" )
237
+ }
238
+
239
+ if len (mockResult .ClientLogs ) == 0 {
240
+ t .Error ("empty client logs map" )
241
+ }
242
+
243
+ // Verify the log segment values
244
+ logSegment := mockResult .ClientLogs ["shared1" ]
245
+ if logSegment .Start != 0 || logSegment .End != 100 || logSegment .ClientID != "container1" {
246
+ t .Errorf ("unexpected log segment values: got %+v" , logSegment )
247
+ }
248
+ }
249
+
250
+ // Tests GetClientLogOffset function.
251
+ func TestGetClientLogOffset (t * testing.T ) {
252
+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
253
+ switch r .URL .Path {
254
+ case "/testsuite" :
255
+ // StartSuite
256
+ json .NewEncoder (w ).Encode (0 ) // Return suite ID
257
+ case "/testsuite/0/shared-client" :
258
+ // StartSharedClient
259
+ json .NewEncoder (w ).Encode (simapi.StartNodeResponse {
260
+ ID : "container1" ,
261
+ IP : "192.0.2.1" ,
262
+ })
263
+ case "/testsuite/0/shared-client/container1/log-offset" :
264
+ // GetClientLogOffset
265
+ json .NewEncoder (w ).Encode (int64 (0 )) // Initial log offset
266
+ default :
267
+ http .NotFound (w , r )
268
+ }
269
+ }))
270
+ defer srv .Close ()
271
+
272
+ sim := NewAt (srv .URL )
273
+ suiteID , err := sim .StartSuite (& simapi.TestRequest {Name : "log-offset-test" }, "Test GetClientLogOffset" )
274
+ if err != nil {
275
+ t .Fatal ("can't start suite:" , err )
276
+ }
277
+
278
+ containerID , _ , err := sim .StartSharedClient (suiteID , "client-1" )
279
+ if err != nil {
280
+ t .Fatal ("can't start shared client:" , err )
281
+ }
282
+
283
+ offset , err := sim .GetClientLogOffset (suiteID , containerID )
284
+ if err != nil {
285
+ t .Fatal ("get log offset failed:" , err )
286
+ }
287
+
288
+ if offset != 0 {
289
+ t .Errorf ("wrong initial log offset: got %d, want 0" , offset )
290
+ }
291
+ }
0 commit comments