1
1
use serde:: { Deserialize , Serialize } ;
2
2
use soketto:: connection:: { Receiver , Sender } ;
3
3
use soketto:: handshake:: { self , ServerResponse } ;
4
+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
4
5
use thiserror:: Error ;
5
6
6
7
/// Basic synchronization client enabling one to send signals and await barriers.
@@ -57,6 +58,7 @@ impl Client {
57
58
state : contextualized_state,
58
59
} ) ,
59
60
barrier : None ,
61
+ publish : None ,
60
62
} ;
61
63
62
64
self . send ( request) . await ?;
@@ -83,6 +85,7 @@ impl Client {
83
85
let request = Request {
84
86
id : id. clone ( ) ,
85
87
signal_entry : None ,
88
+ publish : None ,
86
89
barrier : Some ( BarrierRequest {
87
90
state : contextualized_state,
88
91
target,
@@ -100,13 +103,62 @@ impl Client {
100
103
Ok ( ( ) )
101
104
}
102
105
106
+ pub async fn publish_success ( & mut self ) -> Result < u64 , PublishSuccessError > {
107
+ let id = self . next_id ( ) . to_string ( ) ;
108
+
109
+ let event = Event {
110
+ success_event : SuccessEvent {
111
+ group : std:: env:: var ( "TEST_GROUP_ID" ) . unwrap ( ) ,
112
+ } ,
113
+ } ;
114
+
115
+ let request = Request {
116
+ id : id. clone ( ) ,
117
+ signal_entry : None ,
118
+ barrier : None ,
119
+ publish : Some ( PublishRequest {
120
+ topic : topic ( ) ,
121
+ payload : event. clone ( ) ,
122
+ } ) ,
123
+ } ;
124
+
125
+ self . send ( request) . await ?;
126
+ let resp = self . receive ( ) . await ?;
127
+ if resp. id != id {
128
+ return Err ( PublishSuccessError :: UnexpectedId ( resp. id ) ) ;
129
+ }
130
+ if !resp. error . is_empty ( ) {
131
+ return Err ( PublishSuccessError :: Remote ( resp. error ) ) ;
132
+ }
133
+ let seq = resp
134
+ . publish
135
+ . ok_or ( PublishSuccessError :: ExpectedPublishInResponse )
136
+ . map ( |resp| resp. seq ) ?;
137
+
138
+ // The Testground daemon determines the success or failure of a test
139
+ // instance by parsing stdout for runtime events.
140
+ println ! (
141
+ "{}" ,
142
+ serde_json:: to_string( & LogLine {
143
+ ts: SystemTime :: now( )
144
+ . duration_since( UNIX_EPOCH )
145
+ . unwrap( )
146
+ . as_nanos( ) ,
147
+ event,
148
+ } ) ?
149
+ ) ;
150
+
151
+ Ok ( seq)
152
+ }
153
+
103
154
fn next_id ( & mut self ) -> u64 {
104
155
let next_id = self . next_id ;
105
156
self . next_id += 1 ;
106
157
next_id
107
158
}
108
159
109
160
async fn send ( & mut self , req : Request ) -> Result < ( ) , SendError > {
161
+ log:: debug!( "Sending request: {:?}" , req) ;
110
162
self . sender . send_text ( serde_json:: to_string ( & req) ?) . await ?;
111
163
self . sender . flush ( ) . await ?;
112
164
Ok ( ( ) )
@@ -116,20 +168,28 @@ impl Client {
116
168
let mut data = Vec :: new ( ) ;
117
169
self . receiver . receive_data ( & mut data) . await ?;
118
170
let resp = serde_json:: from_str ( & String :: from_utf8 ( data) ?) ?;
171
+ log:: debug!( "Received response: {:?}" , resp) ;
119
172
Ok ( resp)
120
173
}
121
174
}
122
175
123
- fn contextualize_state ( state : String ) -> String {
176
+ fn context_from_env ( ) -> String {
124
177
format ! (
125
- "run:{}:plan:{}:case:{}:states:{} " ,
178
+ "run:{}:plan:{}:case:{}" ,
126
179
std:: env:: var( "TEST_RUN" ) . unwrap( ) ,
127
180
std:: env:: var( "TEST_PLAN" ) . unwrap( ) ,
128
181
std:: env:: var( "TEST_CASE" ) . unwrap( ) ,
129
- state
130
182
)
131
183
}
132
184
185
+ fn contextualize_state ( state : String ) -> String {
186
+ format ! ( "{}:states:{}" , context_from_env( ) , state, )
187
+ }
188
+
189
+ fn topic ( ) -> String {
190
+ format ! ( "{}:run_events" , context_from_env( ) , )
191
+ }
192
+
133
193
#[ derive( Error , Debug ) ]
134
194
pub enum SignalError {
135
195
#[ error( "Remote returned error {0}." ) ]
@@ -156,6 +216,22 @@ pub enum BarrierError {
156
216
Receive ( #[ from] ReceiveError ) ,
157
217
}
158
218
219
+ #[ derive( Error , Debug ) ]
220
+ pub enum PublishSuccessError {
221
+ #[ error( "Serde: {0}" ) ]
222
+ Serde ( #[ from] serde_json:: error:: Error ) ,
223
+ #[ error( "Remote returned error {0}." ) ]
224
+ Remote ( String ) ,
225
+ #[ error( "Remote returned response with unexpected ID {0}." ) ]
226
+ UnexpectedId ( String ) ,
227
+ #[ error( "Expected remote to return publish entry in response." ) ]
228
+ ExpectedPublishInResponse ,
229
+ #[ error( "Error sending request {0}" ) ]
230
+ Send ( #[ from] SendError ) ,
231
+ #[ error( "Error receiving response: {0}" ) ]
232
+ Receive ( #[ from] ReceiveError ) ,
233
+ }
234
+
159
235
#[ derive( Error , Debug ) ]
160
236
pub enum SendError {
161
237
#[ error( "Soketto: {0}" ) ]
@@ -174,32 +250,61 @@ pub enum ReceiveError {
174
250
FromUtf8 ( #[ from] std:: string:: FromUtf8Error ) ,
175
251
}
176
252
177
- #[ derive( Serialize ) ]
253
+ #[ derive( Debug , Serialize ) ]
178
254
struct Request {
179
255
id : String ,
180
256
signal_entry : Option < SignalEntryRequest > ,
181
257
barrier : Option < BarrierRequest > ,
258
+ publish : Option < PublishRequest > ,
182
259
}
183
260
184
- #[ derive( Serialize ) ]
261
+ #[ derive( Debug , Serialize ) ]
185
262
struct SignalEntryRequest {
186
263
state : String ,
187
264
}
188
265
189
- #[ derive( Serialize ) ]
266
+ #[ derive( Debug , Serialize ) ]
190
267
struct BarrierRequest {
191
268
state : String ,
192
269
target : u64 ,
193
270
}
194
271
272
+ #[ derive( Debug , Serialize ) ]
273
+ struct PublishRequest {
274
+ topic : String ,
275
+ payload : Event ,
276
+ }
277
+
278
+ #[ derive( Debug , Serialize ) ]
279
+ struct LogLine {
280
+ ts : u128 ,
281
+ event : Event ,
282
+ }
283
+
284
+ #[ derive( Clone , Debug , Serialize ) ]
285
+ struct Event {
286
+ success_event : SuccessEvent ,
287
+ }
288
+
289
+ #[ derive( Clone , Debug , Serialize ) ]
290
+ struct SuccessEvent {
291
+ group : String ,
292
+ }
293
+
195
294
#[ derive( Deserialize , Debug ) ]
196
295
struct Response {
197
296
id : String ,
198
297
signal_entry : Option < SignalEntryResponse > ,
199
298
error : String ,
299
+ publish : Option < PublishResponse > ,
200
300
}
201
301
202
302
#[ derive( Deserialize , Debug ) ]
203
303
struct SignalEntryResponse {
204
304
seq : u64 ,
205
305
}
306
+
307
+ #[ derive( Deserialize , Debug ) ]
308
+ struct PublishResponse {
309
+ seq : u64 ,
310
+ }
0 commit comments