Procházet zdrojové kódy

Add some unit tests for the RPC client.

Mathias Gottschlag před 5 roky
rodič
revize
0e4f95dd4d
1 změnil soubory, kde provedl 125 přidání a 2 odebrání
  1. 125
    2
      src/network/client.rs

+ 125
- 2
src/network/client.rs Zobrazit soubor

@@ -204,7 +204,7 @@ pub struct RPCInterface<PacketType, ErrorType> {
204 204
 }
205 205
 
206 206
 impl<PacketType, ErrorType> RPCInterface<PacketType, ErrorType> {
207
-    pub async fn call(&mut self, call: PacketType) -> RPC<PacketType, ErrorType> {
207
+    pub fn call(&mut self, call: PacketType) -> RPC<PacketType, ErrorType> {
208 208
         let (sender, receiver) = oneshot::channel();
209 209
         let call_data = CallData {
210 210
             data: call,
@@ -292,13 +292,136 @@ impl<PacketType> Stream for ServerEventStream<PacketType> {
292 292
     }
293 293
 }
294 294
 
295
-#[derive(Debug)]
295
+#[derive(Debug, PartialEq)]
296 296
 pub enum RPCError<StreamError> {
297 297
     Closed,
298 298
     Timeout,
299 299
     Stream(StreamError),
300 300
 }
301 301
 
302
+#[cfg(test)]
303
+mod tests {
304
+    use super::*;
305
+    use crate::network::test_utils::{panic_after, Pipe};
306
+    use crate::network::Packet;
307
+
308
+    type TestPayload = u32;
309
+
310
+    fn serialize_packet<T>(id: u32, response: bool, payload: T) -> Vec<u8>
311
+    where
312
+        T: Serialize,
313
+    {
314
+        let packet = Packet {
315
+            id,
316
+            response,
317
+            payload,
318
+        };
319
+        let mut serialized = Vec::new();
320
+        packet
321
+            .serialize(
322
+                &mut Serializer::new(&mut serialized)
323
+                    .with_struct_map()
324
+                    .with_string_variants(),
325
+            )
326
+            .unwrap();
327
+        serialized
328
+    }
329
+
330
+    /// Test the basic RPC interface.
331
+    #[tokio::test]
332
+    async fn test_rpc_client() {
333
+        panic_after(Duration::from_secs(1), async move {
334
+            let (pipe1, mut pipe2) = Pipe::new();
335
+            let (mut client, events) = create::<_, _, TestPayload>(pipe1);
336
+            println!("init");
337
+
338
+            // Client task.
339
+            let tasks = (
340
+                tokio::spawn(async move {
341
+                    assert_eq!(client.call(42).await, Ok(1337));
342
+                    let delayed = client.call(43);
343
+                    assert_eq!(client.call(44).await, Ok(1339));
344
+                    assert_eq!(delayed.await, Ok(1338));
345
+                }),
346
+                tokio::spawn(async move {
347
+                    // Invalid ID, should be ignored.
348
+                    pipe2.send(serialize_packet(42, true, 42)).await.unwrap();
349
+
350
+                    assert_eq!(pipe2.next().await, Some(Ok(serialize_packet(0, false, 42))));
351
+                    pipe2.send(serialize_packet(0, true, 1337)).await.unwrap();
352
+
353
+                    // Network errors shall be ignored if the stream is not closed.
354
+                    pipe2.inject_error();
355
+
356
+                    // The ID has to be reused, and a second concurrent call has to have a
357
+                    // different ID.
358
+                    assert_eq!(pipe2.next().await, Some(Ok(serialize_packet(0, false, 43))));
359
+                    assert_eq!(pipe2.next().await, Some(Ok(serialize_packet(1, false, 44))));
360
+                    pipe2.send(serialize_packet(1, true, 1339)).await.unwrap();
361
+                    pipe2.send(serialize_packet(0, true, 1338)).await.unwrap();
362
+                }),
363
+            );
364
+
365
+            tasks.0.await.unwrap();
366
+            tasks.1.await.unwrap();
367
+        })
368
+        .await;
369
+    }
370
+
371
+    /// Test correct behaviour if the connection is closed during a call.
372
+    #[tokio::test]
373
+    async fn test_connection_closed() {
374
+        panic_after(Duration::from_secs(1), async move {
375
+            let (pipe1, pipe2) = Pipe::new();
376
+            let (mut client, _events) = create::<_, _, TestPayload>(pipe1);
377
+
378
+            // Client task.
379
+            let tasks = (
380
+                tokio::spawn(async move {
381
+                    assert_eq!(client.call(42).await, Err(RPCError::Closed));
382
+                }),
383
+                tokio::spawn(async move {
384
+                    drop(pipe2);
385
+                }),
386
+            );
387
+
388
+            tasks.0.await.unwrap();
389
+            tasks.1.await.unwrap();
390
+        })
391
+        .await;
392
+    }
393
+
394
+    /// Test server events.
395
+    #[tokio::test]
396
+    async fn test_events() {
397
+        panic_after(Duration::from_secs(1), async move {
398
+            let (pipe1, mut pipe2) = Pipe::new();
399
+            let (client, mut events) = create::<_, _, TestPayload>(pipe1);
400
+
401
+            // Client task.
402
+            let tasks = (
403
+                tokio::spawn(async move {
404
+                    assert_eq!(events.next().await, Some(42));
405
+                    assert_eq!(events.next().await, None);
406
+                }),
407
+                tokio::spawn(async move {
408
+                    pipe2.send(serialize_packet(SERVER_EVENT_ID, false, 42)).await.unwrap();
409
+                    drop(pipe2);
410
+                }),
411
+            );
412
+
413
+            tasks.0.await.unwrap();
414
+            tasks.1.await.unwrap();
415
+        }).await;
416
+    }
417
+
418
+    // TODO:
419
+    // - Test for unparseable response.
420
+    // - Test for server events.
421
+    // - Test wether the client correctly closes the connection and whether futures return an error
422
+    // in this case.
423
+}
424
+
302 425
 pub async fn low_level_integration_test_client(_address: String) {
303 426
     /*use super::websocket::WebSocketConnection;
304 427
 

Loading…
Zrušit
Uložit