LCOV - differential code coverage report
Current view: top level - libs/postgres_backend/tests - simple_select.rs (source / functions) Coverage Total Hit UBC CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 94.1 % 102 96 6 96
Current Date: 2023-10-19 02:04:12 Functions: 100.0 % 14 14 14
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  Line data    Source code
       1                 : /// Test postgres_backend_async with tokio_postgres
       2                 : use once_cell::sync::Lazy;
       3                 : use postgres_backend::{AuthType, Handler, PostgresBackend, QueryError};
       4                 : use pq_proto::{BeMessage, RowDescriptor};
       5                 : use std::io::Cursor;
       6                 : use std::{future, sync::Arc};
       7                 : use tokio::io::{AsyncRead, AsyncWrite};
       8                 : use tokio::net::{TcpListener, TcpStream};
       9                 : use tokio_postgres::config::SslMode;
      10                 : use tokio_postgres::tls::MakeTlsConnect;
      11                 : use tokio_postgres::{Config, NoTls, SimpleQueryMessage};
      12                 : use tokio_postgres_rustls::MakeRustlsConnect;
      13                 : 
      14                 : // generate client, server test streams
      15 CBC           2 : async fn make_tcp_pair() -> (TcpStream, TcpStream) {
      16               2 :     let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
      17               2 :     let addr = listener.local_addr().unwrap();
      18               2 :     let client_stream = TcpStream::connect(addr).await.unwrap();
      19               2 :     let (server_stream, _) = listener.accept().await.unwrap();
      20               2 :     (client_stream, server_stream)
      21               2 : }
      22                 : 
      23                 : struct TestHandler {}
      24                 : 
      25                 : #[async_trait::async_trait]
      26                 : impl<IO: AsyncRead + AsyncWrite + Unpin + Send> Handler<IO> for TestHandler {
      27                 :     // return single col 'hey' for any query
      28               2 :     async fn process_query(
      29               2 :         &mut self,
      30               2 :         pgb: &mut PostgresBackend<IO>,
      31               2 :         _query_string: &str,
      32               2 :     ) -> Result<(), QueryError> {
      33               2 :         pgb.write_message_noflush(&BeMessage::RowDescription(&[RowDescriptor::text_col(
      34               2 :             b"hey",
      35               2 :         )]))?
      36               2 :         .write_message_noflush(&BeMessage::DataRow(&[Some("hey".as_bytes())]))?
      37               2 :         .write_message_noflush(&BeMessage::CommandComplete(b"SELECT 1"))?;
      38               2 :         Ok(())
      39               4 :     }
      40                 : }
      41                 : 
      42                 : // test that basic select works
      43               1 : #[tokio::test]
      44               1 : async fn simple_select() {
      45               1 :     let (client_sock, server_sock) = make_tcp_pair().await;
      46                 : 
      47                 :     // create and run pgbackend
      48               1 :     let pgbackend =
      49               1 :         PostgresBackend::new(server_sock, AuthType::Trust, None).expect("pgbackend creation");
      50               1 : 
      51               1 :     tokio::spawn(async move {
      52               1 :         let mut handler = TestHandler {};
      53               2 :         pgbackend.run(&mut handler, future::pending::<()>).await
      54               1 :     });
      55               1 : 
      56               1 :     let conf = Config::new();
      57               1 :     let (client, connection) = conf.connect_raw(client_sock, NoTls).await.expect("connect");
      58               1 :     // The connection object performs the actual communication with the database,
      59               1 :     // so spawn it off to run on its own.
      60               1 :     tokio::spawn(async move {
      61               1 :         if let Err(e) = connection.await {
      62 UBC           0 :             eprintln!("connection error: {}", e);
      63               0 :         }
      64 CBC           1 :     });
      65                 : 
      66               1 :     let first_val = &(client.simple_query("SELECT 42;").await.expect("select"))[0];
      67               1 :     if let SimpleQueryMessage::Row(row) = first_val {
      68               1 :         let first_col = row.get(0).expect("first column");
      69               1 :         assert_eq!(first_col, "hey");
      70                 :     } else {
      71 UBC           0 :         panic!("expected SimpleQueryMessage::Row");
      72                 :     }
      73                 : }
      74                 : 
      75 CBC           1 : static KEY: Lazy<rustls::PrivateKey> = Lazy::new(|| {
      76               1 :     let mut cursor = Cursor::new(include_bytes!("key.pem"));
      77               1 :     rustls::PrivateKey(rustls_pemfile::rsa_private_keys(&mut cursor).unwrap()[0].clone())
      78               1 : });
      79                 : 
      80               1 : static CERT: Lazy<rustls::Certificate> = Lazy::new(|| {
      81               1 :     let mut cursor = Cursor::new(include_bytes!("cert.pem"));
      82               1 :     rustls::Certificate(rustls_pemfile::certs(&mut cursor).unwrap()[0].clone())
      83               1 : });
      84                 : 
      85                 : // test that basic select with ssl works
      86               1 : #[tokio::test]
      87               1 : async fn simple_select_ssl() {
      88               1 :     let (client_sock, server_sock) = make_tcp_pair().await;
      89                 : 
      90               1 :     let server_cfg = rustls::ServerConfig::builder()
      91               1 :         .with_safe_defaults()
      92               1 :         .with_no_client_auth()
      93               1 :         .with_single_cert(vec![CERT.clone()], KEY.clone())
      94               1 :         .unwrap();
      95               1 :     let tls_config = Some(Arc::new(server_cfg));
      96               1 :     let pgbackend =
      97               1 :         PostgresBackend::new(server_sock, AuthType::Trust, tls_config).expect("pgbackend creation");
      98               1 : 
      99               1 :     tokio::spawn(async move {
     100               1 :         let mut handler = TestHandler {};
     101               5 :         pgbackend.run(&mut handler, future::pending::<()>).await
     102               1 :     });
     103               1 : 
     104               1 :     let client_cfg = rustls::ClientConfig::builder()
     105               1 :         .with_safe_defaults()
     106               1 :         .with_root_certificates({
     107               1 :             let mut store = rustls::RootCertStore::empty();
     108               1 :             store.add(&CERT).unwrap();
     109               1 :             store
     110               1 :         })
     111               1 :         .with_no_client_auth();
     112               1 :     let mut make_tls_connect = tokio_postgres_rustls::MakeRustlsConnect::new(client_cfg);
     113               1 :     let tls_connect = <MakeRustlsConnect as MakeTlsConnect<TcpStream>>::make_tls_connect(
     114               1 :         &mut make_tls_connect,
     115               1 :         "localhost",
     116               1 :     )
     117               1 :     .expect("make_tls_connect");
     118               1 : 
     119               1 :     let mut conf = Config::new();
     120               1 :     conf.ssl_mode(SslMode::Require);
     121               1 :     let (client, connection) = conf
     122               1 :         .connect_raw(client_sock, tls_connect)
     123               4 :         .await
     124               1 :         .expect("connect");
     125               1 :     // The connection object performs the actual communication with the database,
     126               1 :     // so spawn it off to run on its own.
     127               1 :     tokio::spawn(async move {
     128               1 :         if let Err(e) = connection.await {
     129 UBC           0 :             eprintln!("connection error: {}", e);
     130               0 :         }
     131 CBC           1 :     });
     132                 : 
     133               1 :     let first_val = &(client.simple_query("SELECT 42;").await.expect("select"))[0];
     134               1 :     if let SimpleQueryMessage::Row(row) = first_val {
     135               1 :         let first_col = row.get(0).expect("first column");
     136               1 :         assert_eq!(first_col, "hey");
     137                 :     } else {
     138 UBC           0 :         panic!("expected SimpleQueryMessage::Row");
     139                 :     }
     140                 : }
        

Generated by: LCOV version 2.1-beta