component: Split into submodules test/xmpp

This way I don't have to guard everything with #[cfg(test)]..

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2022-09-26 14:22:11 +02:00
parent 1f7112616a
commit cc1c1609e3
3 changed files with 124 additions and 92 deletions

34
src/component/mod.rs Normal file
View file

@ -0,0 +1,34 @@
// Copyright (C) 2022-2099 The crate authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
// for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#[cfg(test)]
mod test;
mod xmpp;
use crate::error::Error;
use async_trait::async_trait;
use futures::Stream;
use xmpp_parsers::Element;
// Testable interface
#[async_trait]
pub trait ComponentTrait: Stream<Item = Element> + Unpin {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error>;
}
#[cfg(test)]
pub use crate::component::test::Component as TestComponent;
pub use crate::component::xmpp::Component;

View file

@ -13,86 +13,21 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::component::ComponentTrait;
use crate::error::Error;
#[cfg(test)]
use std::collections::VecDeque;
#[cfg(test)]
use std::fmt;
use std::marker::Send;
use std::ops::{Deref, DerefMut};
use std::ops::Deref;
use std::pin::Pin;
use std::task::Context;
#[cfg(test)]
use std::thread;
use async_trait::async_trait;
use futures::{task::Poll, Stream};
use log::debug;
use tokio_xmpp::Component as TokioXMPPComponent;
use xmpp_parsers::Element;
#[cfg(test)]
use xmpp_parsers::{iq::Iq, message::Message, presence::Presence};
use xmpp_parsers::{iq::Iq, message::Message, presence::Presence, Element};
// Testable interface
#[async_trait]
pub trait ComponentTrait: Stream<Item = Element> + Unpin {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error>;
}
pub struct Component(TokioXMPPComponent);
impl Stream for Component {
type Item = Element;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.0).poll_next(cx)
}
}
#[async_trait]
impl ComponentTrait for Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
let el: Element = el.into();
debug!("SEND: {}", String::from(&el));
self.0.send_stanza(el).await?;
Ok(())
}
}
#[async_trait]
impl ComponentTrait for &mut Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
let el: Element = el.into();
debug!("SEND: {}", String::from(&el));
self.0.send_stanza(el).await?;
Ok(())
}
}
impl Deref for Component {
type Target = TokioXMPPComponent;
fn deref(&self) -> &TokioXMPPComponent {
&self.0
}
}
impl DerefMut for Component {
fn deref_mut(&mut self) -> &mut TokioXMPPComponent {
&mut self.0
}
}
impl Component {
pub async fn new(jid: &str, password: &str, server: &str, port: u16) -> Result<Self, Error> {
Ok(Component(
TokioXMPPComponent::new(jid, password, server, port).await?,
))
}
}
#[cfg(test)]
enum Expect {
/// Simple Element
Element(TestElement),
@ -104,7 +39,6 @@ enum Expect {
Message(Box<dyn FnOnce(Message) + Send + 'static>, String),
}
#[cfg(test)]
impl fmt::Debug for Expect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Expect::")?;
@ -117,11 +51,9 @@ impl fmt::Debug for Expect {
}
}
#[cfg(test)]
#[derive(Clone, Eq, PartialEq)]
pub struct TestElement(pub Element);
#[cfg(test)]
impl Deref for TestElement {
type Target = Element;
@ -130,73 +62,63 @@ impl Deref for TestElement {
}
}
#[cfg(test)]
impl fmt::Debug for TestElement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", String::from(&self.0))
}
}
#[cfg(test)]
impl fmt::Display for TestElement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", String::from(&self.0))
}
}
#[cfg(test)]
impl From<&TestElement> for String {
fn from(elem: &TestElement) -> Self {
format!("{}", elem)
}
}
#[cfg(test)]
impl From<Element> for TestElement {
fn from(elem: Element) -> Self {
Self(elem)
}
}
#[cfg(test)]
impl From<TestElement> for Element {
fn from(elem: TestElement) -> Self {
elem.0
}
}
#[cfg(test)]
impl From<Iq> for TestElement {
fn from(elem: Iq) -> Self {
Self(Element::from(elem))
}
}
#[cfg(test)]
impl From<Presence> for TestElement {
fn from(elem: Presence) -> Self {
Self(Element::from(elem))
}
}
#[cfg(test)]
impl From<Message> for TestElement {
fn from(elem: Message) -> Self {
Self(Element::from(elem))
}
}
#[cfg(test)]
#[derive(Debug)]
pub struct TestComponent {
pub struct Component {
in_buffer: VecDeque<TestElement>,
expect_buffer: VecDeque<Expect>,
}
#[cfg(test)]
impl TestComponent {
impl Component {
pub fn new(in_buffer: Vec<Element>) -> Self {
TestComponent {
Component {
in_buffer: VecDeque::from(
in_buffer
.into_iter()
@ -275,8 +197,7 @@ impl TestComponent {
}
}
#[cfg(test)]
impl Stream for TestComponent {
impl Stream for Component {
type Item = Element;
fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
@ -288,8 +209,7 @@ impl Stream for TestComponent {
}
}
#[cfg(test)]
impl Drop for TestComponent {
impl Drop for Component {
fn drop(&mut self) {
// Don't assert if we're already panicking. Rustc displays a huge backtrace when "panicked
// while panicking" even when nobody asks for it (RUST_BACKTRACE unset). Let the error
@ -303,17 +223,15 @@ impl Drop for TestComponent {
}
}
#[cfg(test)]
#[async_trait]
impl ComponentTrait for TestComponent {
impl ComponentTrait for Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
self.send_stanza_inner(el.into())
}
}
#[cfg(test)]
#[async_trait]
impl ComponentTrait for &mut TestComponent {
impl ComponentTrait for &mut Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
self.send_stanza_inner(el.into())
}

80
src/component/xmpp.rs Normal file
View file

@ -0,0 +1,80 @@
// Copyright (C) 2022-2099 The crate authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
// for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::component::ComponentTrait;
use crate::error::Error;
use std::marker::Send;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::task::Context;
use async_trait::async_trait;
use futures::{task::Poll, Stream};
use log::debug;
use tokio_xmpp::Component as TokioXMPPComponent;
use xmpp_parsers::Element;
pub struct Component(TokioXMPPComponent);
impl Stream for Component {
type Item = Element;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.0).poll_next(cx)
}
}
#[async_trait]
impl ComponentTrait for Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
let el: Element = el.into();
debug!("SEND: {}", String::from(&el));
self.0.send_stanza(el).await?;
Ok(())
}
}
#[async_trait]
impl ComponentTrait for &mut Component {
async fn send_stanza<E: Into<Element> + Send>(&mut self, el: E) -> Result<(), Error> {
let el: Element = el.into();
debug!("SEND: {}", String::from(&el));
self.0.send_stanza(el).await?;
Ok(())
}
}
impl Deref for Component {
type Target = TokioXMPPComponent;
fn deref(&self) -> &TokioXMPPComponent {
&self.0
}
}
impl DerefMut for Component {
fn deref_mut(&mut self) -> &mut TokioXMPPComponent {
&mut self.0
}
}
impl Component {
pub async fn new(jid: &str, password: &str, server: &str, port: u16) -> Result<Self, Error> {
Ok(Component(
TokioXMPPComponent::new(jid, password, server, port).await?,
))
}
}