blocking.rs

  1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use try_from::TryFrom;
  8
  9use jid::Jid;
 10use minidom::Element;
 11
 12use error::Error;
 13
 14use ns;
 15use iq::{IqGetPayload, IqSetPayload, IqResultPayload};
 16
 17generate_empty_element!(BlocklistRequest, "blocklist", BLOCKING);
 18
 19impl IqGetPayload for BlocklistRequest {}
 20
 21macro_rules! generate_blocking_element {
 22    ($elem:ident, $name:tt) => (
 23        #[derive(Debug, Clone)]
 24        pub struct $elem {
 25            pub items: Vec<Jid>,
 26        }
 27
 28        impl TryFrom<Element> for $elem {
 29            type Err = Error;
 30
 31            fn try_from(elem: Element) -> Result<$elem, Error> {
 32                check_self!(elem, $name, BLOCKING);
 33                check_no_attributes!(elem, $name);
 34                let mut items = vec!();
 35                for child in elem.children() {
 36                    check_self!(child, "item", BLOCKING);
 37                    check_no_unknown_attributes!(child, "item", ["jid"]);
 38                    check_no_children!(child, "item");
 39                    items.push(get_attr!(child, "jid", required));
 40                }
 41                Ok($elem { items })
 42            }
 43        }
 44
 45        impl From<$elem> for Element {
 46            fn from(elem: $elem) -> Element {
 47                Element::builder($name)
 48                        .ns(ns::BLOCKING)
 49                        .append(elem.items.into_iter().map(|jid| {
 50                             Element::builder("item")
 51                                     .ns(ns::BLOCKING)
 52                                     .attr("jid", jid)
 53                                     .build()
 54                         }).collect::<Vec<_>>())
 55                        .build()
 56            }
 57        }
 58    );
 59}
 60
 61generate_blocking_element!(BlocklistResult, "blocklist");
 62generate_blocking_element!(Block, "block");
 63generate_blocking_element!(Unblock, "unblock");
 64
 65impl IqResultPayload for BlocklistResult {}
 66impl IqSetPayload for Block {}
 67impl IqSetPayload for Unblock {}
 68
 69generate_empty_element!(Blocked, "blocked", BLOCKING_ERRORS);
 70
 71#[cfg(test)]
 72mod tests {
 73    use super::*;
 74
 75    #[test]
 76    fn test_simple() {
 77        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 78        let request_elem = elem.clone();
 79        BlocklistRequest::try_from(request_elem).unwrap();
 80
 81        let result_elem = elem.clone();
 82        let result = BlocklistResult::try_from(result_elem).unwrap();
 83        assert_eq!(result.items, vec!());
 84
 85        let elem: Element = "<block xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 86        let block = Block::try_from(elem).unwrap();
 87        assert_eq!(block.items, vec!());
 88
 89        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 90        let unblock = Unblock::try_from(elem).unwrap();
 91        assert_eq!(unblock.items, vec!());
 92    }
 93
 94    #[test]
 95    fn test_items() {
 96        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
 97        let two_items = vec!(
 98            Jid {
 99                node: Some(String::from("coucou")),
100                domain: String::from("coucou"),
101                resource: None,
102            },
103            Jid {
104                node: None,
105                domain: String::from("domain"),
106                resource: None,
107            },
108        );
109
110        let request_elem = elem.clone();
111        let error = BlocklistRequest::try_from(request_elem).unwrap_err();
112        let message = match error {
113            Error::ParseError(string) => string,
114            _ => panic!(),
115        };
116        assert_eq!(message, "Unknown child in blocklist element.");
117
118        let result_elem = elem.clone();
119        let result = BlocklistResult::try_from(result_elem).unwrap();
120        assert_eq!(result.items, two_items);
121
122        let elem: Element = "<block xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></block>".parse().unwrap();
123        let block = Block::try_from(elem).unwrap();
124        assert_eq!(block.items, two_items);
125
126        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></unblock>".parse().unwrap();
127        let unblock = Unblock::try_from(elem).unwrap();
128        assert_eq!(unblock.items, two_items);
129    }
130
131    #[test]
132    fn test_invalid() {
133        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
134        let request_elem = elem.clone();
135        let error = BlocklistRequest::try_from(request_elem).unwrap_err();
136        let message = match error {
137            Error::ParseError(string) => string,
138            _ => panic!(),
139        };
140        assert_eq!(message, "Unknown attribute in blocklist element.");
141
142        let result_elem = elem.clone();
143        let error = BlocklistResult::try_from(result_elem).unwrap_err();
144        let message = match error {
145            Error::ParseError(string) => string,
146            _ => panic!(),
147        };
148        assert_eq!(message, "Unknown attribute in blocklist element.");
149
150        let elem: Element = "<block xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
151        let error = Block::try_from(elem).unwrap_err();
152        let message = match error {
153            Error::ParseError(string) => string,
154            _ => panic!(),
155        };
156        assert_eq!(message, "Unknown attribute in block element.");
157
158        let elem: Element = "<unblock xmlns='urn:xmpp:blocking' coucou=''/>".parse().unwrap();
159        let error = Unblock::try_from(elem).unwrap_err();
160        let message = match error {
161            Error::ParseError(string) => string,
162            _ => panic!(),
163        };
164        assert_eq!(message, "Unknown attribute in unblock element.");
165    }
166}