Merge branch 'tests' into 'master'

lumi created

Add more error cases and corresponding tests, and bump minidom

See merge request xmpp-rs/jid-rs!12

Change summary

CHANGELOG.md |  5 +++++
Cargo.toml   |  4 ++--
src/lib.rs   | 46 +++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 52 insertions(+), 3 deletions(-)

Detailed changes

CHANGELOG.md 🔗

@@ -1,3 +1,8 @@
+Version 0.5.0, released 2018-02-18:
+  * Updates
+    - Link Mauve has updated the optional `minidom` dependency.
+    - Link Mauve has added tests for invalid JIDs, which adds more error cases.
+
 Version 0.4.0, released 2017-12-27:
   * Updates
     - Maxime Buquet has updated the optional `minidom` dependency.

Cargo.toml 🔗

@@ -1,6 +1,6 @@
 [package]
 name = "jid"
-version = "0.4.0"
+version = "0.5.0"
 authors = [
   "lumi <lumi@pew.im>",
   "Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>",
@@ -18,4 +18,4 @@ license = "LGPL-3.0+"
 gitlab = { repository = "xmpp-rs/jid-rs" }
 
 [dependencies]
-minidom = { version = "0.7", optional = true }
+minidom = { version = "0.8.0", optional = true }

src/lib.rs 🔗

@@ -13,8 +13,13 @@ use std::str::FromStr;
 /// An error that signifies that a `Jid` cannot be parsed from a string.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum JidParseError {
-    /// Happens when there is no domain. (really, only happens when the string is empty)
+    /// Happens when there is no domain, that is either the string is empty,
+    /// starts with a /, or contains the @/ sequence.
     NoDomain,
+    /// Happens when the node is empty, that is the string starts with a @.
+    EmptyNode,
+    /// Happens when the resource is empty, that is the string ends with a /.
+    EmptyResource,
 }
 
 /// A struct representing a Jabber ID.
@@ -86,11 +91,17 @@ impl FromStr for Jid {
                 ParserState::Node => {
                     match c {
                         '@' => {
+                            if buf == "" {
+                                return Err(JidParseError::EmptyNode);
+                            }
                             state = ParserState::Domain;
                             node = Some(buf.clone()); // TODO: performance tweaks, do not need to copy it
                             buf.clear();
                         },
                         '/' => {
+                            if buf == "" {
+                                return Err(JidParseError::NoDomain);
+                            }
                             state = ParserState::Resource;
                             domain = Some(buf.clone()); // TODO: performance tweaks
                             buf.clear();
@@ -103,6 +114,9 @@ impl FromStr for Jid {
                 ParserState::Domain => {
                     match c {
                         '/' => {
+                            if buf == "" {
+                                return Err(JidParseError::NoDomain);
+                            }
                             state = ParserState::Resource;
                             domain = Some(buf.clone()); // TODO: performance tweaks
                             buf.clear();
@@ -129,6 +143,8 @@ impl FromStr for Jid {
                     resource = Some(buf);
                 },
             }
+        } else if let ParserState::Resource = state {
+            return Err(JidParseError::EmptyResource);
         }
         Ok(Jid {
             node: node,
@@ -401,6 +417,34 @@ mod tests {
         assert_eq!(String::from(Jid::full("a", "b", "c")), String::from("a@b/c"));
     }
 
+    #[test]
+    fn invalid() {
+        match Jid::from_str("") {
+            Err(JidParseError::NoDomain) => (),
+            err => panic!("Invalid error: {:?}", err)
+        }
+
+        match Jid::from_str("a@/c") {
+            Err(JidParseError::NoDomain) => (),
+            err => panic!("Invalid error: {:?}", err)
+        }
+
+        match Jid::from_str("/c") {
+            Err(JidParseError::NoDomain) => (),
+            err => panic!("Invalid error: {:?}", err)
+        }
+
+        match Jid::from_str("@b") {
+            Err(JidParseError::EmptyNode) => (),
+            err => panic!("Invalid error: {:?}", err)
+        }
+
+        match Jid::from_str("b/") {
+            Err(JidParseError::EmptyResource) => (),
+            err => panic!("Invalid error: {:?}", err)
+        }
+    }
+
     #[cfg(feature = "minidom")]
     #[test]
     fn minidom() {