Revert^2 "Import xml-rs 0.8.3"

2fc140166d67619ad4a9ce3013e2604b8b5845aa

Change-Id: I6fdc0f5dc86abd2b5417e43bae3da28070ad8636
diff --git a/tests/documents/sample_1.xml b/tests/documents/sample_1.xml
new file mode 100644
index 0000000..4d1cbc0
--- /dev/null
+++ b/tests/documents/sample_1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<project name="project-name">
+    <libraries>
+        <library groupId="org.example" artifactId="&lt;name&gt;" version="0.1"/>
+        <library groupId="com.example" artifactId="&quot;cool-lib&amp;" version="999"/>
+    </libraries>
+    <module name="module-1">
+        <files>
+            <file name="somefile.java" type="java">
+                Some &lt;java&gt; class
+            </file>
+            <file name="another_file.java" type="java">
+                Another &quot;java&quot; class
+            </file>
+            <file name="config.xml" type="xml">
+                Weird &apos;XML&apos; config
+            </file>
+        </files>
+        <libraries>
+            <library groupId="junit" artifactId="junit" version="1.9.5"/>
+        </libraries>
+    </module>
+    <module name="module-2">
+        <files>
+            <file name="program.js" type="javascript">
+                JavaScript &amp; program
+            </file>
+            <file name="style.css" type="css">
+                Cascading style sheet: &#xA9; - &#1161;
+            </file>
+        </files>
+    </module>
+</project>
+
diff --git a/tests/documents/sample_1_full.txt b/tests/documents/sample_1_full.txt
new file mode 100644
index 0000000..a8d64d0
--- /dev/null
+++ b/tests/documents/sample_1_full.txt
@@ -0,0 +1,58 @@
+StartDocument(1.0, utf-8)
+StartElement(project [name="project-name"])
+Whitespace("\n    ")
+StartElement(libraries)
+Whitespace("\n        ")
+StartElement(library [groupId="org.example", artifactId="<name>", version="0.1"])
+EndElement(library)
+Whitespace("\n        ")
+StartElement(library [groupId="com.example", artifactId="\"cool-lib&", version="999"])
+EndElement(library)
+Whitespace("\n    ")
+EndElement(libraries)
+Whitespace("\n    ")
+StartElement(module [name="module-1"])
+Whitespace("\n        ")
+StartElement(files)
+Whitespace("\n            ")
+StartElement(file [name="somefile.java", type="java"])
+Characters("\n                Some <java> class\n            ")
+EndElement(file)
+Whitespace("\n            ")
+StartElement(file [name="another_file.java", type="java"])
+Characters("\n                Another \"java\" class\n            ")
+EndElement(file)
+Whitespace("\n            ")
+StartElement(file [name="config.xml", type="xml"])
+Characters("\n                Weird \'XML\' config\n            ")
+EndElement(file)
+Whitespace("\n        ")
+EndElement(files)
+Whitespace("\n        ")
+StartElement(libraries)
+Whitespace("\n            ")
+StartElement(library [groupId="junit", artifactId="junit", version="1.9.5"])
+EndElement(library)
+Whitespace("\n        ")
+EndElement(libraries)
+Whitespace("\n    ")
+EndElement(module)
+Whitespace("\n    ")
+StartElement(module [name="module-2"])
+Whitespace("\n        ")
+StartElement(files)
+Whitespace("\n            ")
+StartElement(file [name="program.js", type="javascript"])
+Characters("\n                JavaScript & program\n            ")
+EndElement(file)
+Whitespace("\n            ")
+StartElement(file [name="style.css", type="css"])
+Characters("\n                Cascading style sheet: © - ҉\n            ")
+EndElement(file)
+Whitespace("\n        ")
+EndElement(files)
+Whitespace("\n    ")
+EndElement(module)
+Whitespace("\n")
+EndElement(project)
+EndDocument
diff --git a/tests/documents/sample_1_short.txt b/tests/documents/sample_1_short.txt
new file mode 100644
index 0000000..4dbe285
--- /dev/null
+++ b/tests/documents/sample_1_short.txt
@@ -0,0 +1,37 @@
+StartDocument(1.0, utf-8)
+StartElement(project [name="project-name"])
+StartElement(libraries)
+StartElement(library [groupId="org.example", artifactId="<name>", version="0.1"])
+EndElement(library)
+StartElement(library [groupId="com.example", artifactId="\"cool-lib&", version="999"])
+EndElement(library)
+EndElement(libraries)
+StartElement(module [name="module-1"])
+StartElement(files)
+StartElement(file [name="somefile.java", type="java"])
+Characters("Some <java> class")
+EndElement(file)
+StartElement(file [name="another_file.java", type="java"])
+Characters("Another \"java\" class")
+EndElement(file)
+StartElement(file [name="config.xml", type="xml"])
+Characters("Weird \'XML\' config")
+EndElement(file)
+EndElement(files)
+StartElement(libraries)
+StartElement(library [groupId="junit", artifactId="junit", version="1.9.5"])
+EndElement(library)
+EndElement(libraries)
+EndElement(module)
+StartElement(module [name="module-2"])
+StartElement(files)
+StartElement(file [name="program.js", type="javascript"])
+Characters("JavaScript & program")
+EndElement(file)
+StartElement(file [name="style.css", type="css"])
+Characters("Cascading style sheet: © - ҉")
+EndElement(file)
+EndElement(files)
+EndElement(module)
+EndElement(project)
+EndDocument
diff --git a/tests/documents/sample_2.xml b/tests/documents/sample_2.xml
new file mode 100644
index 0000000..f9543ac
--- /dev/null
+++ b/tests/documents/sample_2.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<p:data xmlns:d="urn:example:double" xmlns:h="urn:example:header" xmlns:p="urn:example:namespace">
+  <p:datum id="34">
+    <p:name>Name</p:name>
+    <d:name>Another name</d:name>
+    <d:arg>0.3</d:arg>
+    <d:arg>0.2</d:arg>
+    <p:arg>0.1</p:arg>
+    <p:arg>0.01</p:arg>
+    <h:header name="Header-1">header 1 value</h:header>
+    <h:header name="Header-2">
+      Some bigger value
+    </h:header>
+  </p:datum>
+</p:data>
diff --git a/tests/documents/sample_2_full.txt b/tests/documents/sample_2_full.txt
new file mode 100644
index 0000000..75075cd
--- /dev/null
+++ b/tests/documents/sample_2_full.txt
@@ -0,0 +1,41 @@
+StartDocument(1.0, utf-8)
+StartElement({urn:example:namespace}p:data)
+Whitespace("\n  ")
+StartElement({urn:example:namespace}p:datum [id="34"])
+Whitespace("\n    ")
+StartElement({urn:example:namespace}p:name)
+Characters("Name")
+EndElement({urn:example:namespace}p:name)
+Whitespace("\n    ")
+StartElement({urn:example:double}d:name)
+Characters("Another name")
+EndElement({urn:example:double}d:name)
+Whitespace("\n    ")
+StartElement({urn:example:double}d:arg)
+Characters("0.3")
+EndElement({urn:example:double}d:arg)
+Whitespace("\n    ")
+StartElement({urn:example:double}d:arg)
+Characters("0.2")
+EndElement({urn:example:double}d:arg)
+Whitespace("\n    ")
+StartElement({urn:example:namespace}p:arg)
+Characters("0.1")
+EndElement({urn:example:namespace}p:arg)
+Whitespace("\n    ")
+StartElement({urn:example:namespace}p:arg)
+Characters("0.01")
+EndElement({urn:example:namespace}p:arg)
+Whitespace("\n    ")
+StartElement({urn:example:header}h:header [name="Header-1"])
+Characters("header 1 value")
+EndElement({urn:example:header}h:header)
+Whitespace("\n    ")
+StartElement({urn:example:header}h:header [name="Header-2"])
+Characters("\n      Some bigger value\n    ")
+EndElement({urn:example:header}h:header)
+Whitespace("\n  ")
+EndElement({urn:example:namespace}p:datum)
+Whitespace("\n")
+EndElement({urn:example:namespace}p:data)
+EndDocument
diff --git a/tests/documents/sample_2_short.txt b/tests/documents/sample_2_short.txt
new file mode 100644
index 0000000..2368025
--- /dev/null
+++ b/tests/documents/sample_2_short.txt
@@ -0,0 +1,30 @@
+StartDocument(1.0, utf-8)
+StartElement({urn:example:namespace}p:data)
+StartElement({urn:example:namespace}p:datum [id="34"])
+StartElement({urn:example:namespace}p:name)
+Characters("Name")
+EndElement({urn:example:namespace}p:name)
+StartElement({urn:example:double}d:name)
+Characters("Another name")
+EndElement({urn:example:double}d:name)
+StartElement({urn:example:double}d:arg)
+Characters("0.3")
+EndElement({urn:example:double}d:arg)
+StartElement({urn:example:double}d:arg)
+Characters("0.2")
+EndElement({urn:example:double}d:arg)
+StartElement({urn:example:namespace}p:arg)
+Characters("0.1")
+EndElement({urn:example:namespace}p:arg)
+StartElement({urn:example:namespace}p:arg)
+Characters("0.01")
+EndElement({urn:example:namespace}p:arg)
+StartElement({urn:example:header}h:header [name="Header-1"])
+Characters("header 1 value")
+EndElement({urn:example:header}h:header)
+StartElement({urn:example:header}h:header [name="Header-2"])
+Characters("Some bigger value")
+EndElement({urn:example:header}h:header)
+EndElement({urn:example:namespace}p:datum)
+EndElement({urn:example:namespace}p:data)
+EndDocument
diff --git a/tests/documents/sample_3.xml b/tests/documents/sample_3.xml
new file mode 100644
index 0000000..657e37d
--- /dev/null
+++ b/tests/documents/sample_3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<p:data xmlns:p="urn:x" z=">">
+    <!-- abcd &lt; &gt; &amp; -->
+    <a>test</a>
+    <b>kkss" = ddd' ></b>
+    <![CDATA[
+            <a>ddddd</b>!e3--><!-- ddckx
+    ]]>
+    <c/>
+    <![CDATA[
+    <![CDATA[zzzz]]]]><![CDATA[>]]>
+</p:data>
+
diff --git a/tests/documents/sample_3_full.txt b/tests/documents/sample_3_full.txt
new file mode 100644
index 0000000..e9a0f7e
--- /dev/null
+++ b/tests/documents/sample_3_full.txt
@@ -0,0 +1,23 @@
+1:1 StartDocument(1.0, utf-8)
+2:1 StartElement({urn:x}p:data [z=">"])
+2:31 Whitespace("\n    ")
+3:5 Comment(" abcd &lt; &gt; &amp; ")
+3:34 Whitespace("\n    ")
+4:5 StartElement(a)
+4:8 Characters("test")
+4:12 EndElement(a)
+4:16 Whitespace("\n    ")
+5:5 StartElement(b)
+5:8 Characters("kkss\" = ddd\' >")
+5:22 EndElement(b)
+5:26 Whitespace("\n    ")
+6:5 CData("\n            <a>ddddd</b>!e3--><!-- ddckx\n    ")
+8:8 Characters("\n    ")
+9:5 StartElement(c)
+9:5 EndElement(c)
+9:9 Whitespace("\n    ")
+10:5 CData("\n    <![CDATA[zzzz]]")
+11:23 CData(">")
+11:36 Characters("\n")
+12:1 EndElement({urn:x}p:data)
+14:1 EndDocument
diff --git a/tests/documents/sample_3_short.txt b/tests/documents/sample_3_short.txt
new file mode 100644
index 0000000..2582f33
--- /dev/null
+++ b/tests/documents/sample_3_short.txt
@@ -0,0 +1,14 @@
+1:1 StartDocument(1.0, utf-8)
+2:1 StartElement({urn:x}p:data [z=">"])
+4:5 StartElement(a)
+4:8 Characters("test")
+4:12 EndElement(a)
+5:5 StartElement(b)
+5:8 Characters("kkss\" = ddd\' >")
+5:22 EndElement(b)
+6:5 Characters("<a>ddddd</b>!e3--><!-- ddckx")
+9:5 StartElement(c)
+9:5 EndElement(c)
+10:5 Characters("<![CDATA[zzzz]]>")
+12:1 EndElement({urn:x}p:data)
+14:1 EndDocument
diff --git a/tests/documents/sample_4.xml b/tests/documents/sample_4.xml
new file mode 100644
index 0000000..fb915ff
--- /dev/null
+++ b/tests/documents/sample_4.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE data SYSTEM "abcd.dtd">
+<p:data xmlns:p="urn:x" z=">">
+    <!-- abcd &lt; &gt; &amp; -->
+    <a>test</a>
+    <b>kkss" = ddd' ></b>
+    <![CDATA[
+            <a>ddddd</b>!e3--><!-- ddckx
+    ]]>
+    <c/>
+    <![CDATA[
+    <![CDATA[zzzz]]]]><![CDATA[>]]>
+</p:data>
+
+
diff --git a/tests/documents/sample_4_full.txt b/tests/documents/sample_4_full.txt
new file mode 100644
index 0000000..4bdadfb
--- /dev/null
+++ b/tests/documents/sample_4_full.txt
@@ -0,0 +1,23 @@
+StartDocument(1.0, utf-8)
+StartElement({urn:x}p:data [z=">"])
+Whitespace("\n    ")
+Comment(" abcd &lt; &gt; &amp; ")
+Whitespace("\n    ")
+StartElement(a)
+Characters("test")
+EndElement(a)
+Whitespace("\n    ")
+StartElement(b)
+Characters("kkss\" = ddd\' >")
+EndElement(b)
+Whitespace("\n    ")
+CData("\n            <a>ddddd</b>!e3--><!-- ddckx\n    ")
+Characters("\n    ")
+StartElement(c)
+EndElement(c)
+Whitespace("\n    ")
+CData("\n    <![CDATA[zzzz]]")
+CData(">")
+Characters("\n")
+EndElement({urn:x}p:data)
+EndDocument
diff --git a/tests/documents/sample_4_short.txt b/tests/documents/sample_4_short.txt
new file mode 100644
index 0000000..52e4b83
--- /dev/null
+++ b/tests/documents/sample_4_short.txt
@@ -0,0 +1,14 @@
+StartDocument(1.0, utf-8)
+StartElement({urn:x}p:data [z=">"])
+StartElement(a)
+Characters("test")
+EndElement(a)
+StartElement(b)
+Characters("kkss\" = ddd\' >")
+EndElement(b)
+Characters("<a>ddddd</b>!e3--><!-- ddckx")
+StartElement(c)
+EndElement(c)
+Characters("<![CDATA[zzzz]]>")
+EndElement({urn:x}p:data)
+EndDocument
diff --git a/tests/documents/sample_5.xml b/tests/documents/sample_5.xml
new file mode 100644
index 0000000..92aa31d
--- /dev/null
+++ b/tests/documents/sample_5.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE data SYSTEM "abcd.dtd">
+<p>
+    <a>test&nbsp;&copy;&NotEqualTilde;</a>
+</p>
+
+
diff --git a/tests/documents/sample_5_short.txt b/tests/documents/sample_5_short.txt
new file mode 100644
index 0000000..3079811
--- /dev/null
+++ b/tests/documents/sample_5_short.txt
@@ -0,0 +1,7 @@
+StartDocument(1.0, utf-8)
+StartElement(p)
+StartElement(a)
+Characters("test ©≂̸")
+EndElement(a)
+EndElement(p)
+EndDocument
diff --git a/tests/documents/sample_6.xml b/tests/documents/sample_6.xml
new file mode 100644
index 0000000..943c02d
--- /dev/null
+++ b/tests/documents/sample_6.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="doc.xsl"?>
+
+<doc>Hello</doc>
diff --git a/tests/documents/sample_6_full.txt b/tests/documents/sample_6_full.txt
new file mode 100644
index 0000000..debb366
--- /dev/null
+++ b/tests/documents/sample_6_full.txt
@@ -0,0 +1,8 @@
+StartDocument(1.0, UTF-8)
+Whitespace("\n")
+ProcessingInstruction(xml-stylesheet="href=\"doc.xsl\"")
+Whitespace("\n\n")
+StartElement(doc)
+Characters("Hello")
+EndElement(doc)
+EndDocument
diff --git a/tests/event_reader.rs b/tests/event_reader.rs
new file mode 100644
index 0000000..80ed331
--- /dev/null
+++ b/tests/event_reader.rs
@@ -0,0 +1,539 @@
+#![forbid(unsafe_code)]
+
+extern crate xml;
+#[macro_use]
+extern crate lazy_static;
+
+use std::env;
+use std::fmt;
+use std::fs::File;
+use std::io::{BufRead, BufReader, Write, stderr};
+use std::path::Path;
+
+use xml::name::OwnedName;
+use xml::common::Position;
+use xml::reader::{Result, XmlEvent, ParserConfig, EventReader};
+
+/// Dummy function that opens a file, parses it, and returns a `Result`.
+/// There can be IO errors (from `File::open`) and XML errors (from the parser).
+/// Having `impl From<std::io::Error> for xml::reader::Error` allows the user to
+/// do this without defining their own error type.
+#[allow(dead_code)]
+fn count_event_in_file(name: &Path) -> Result<usize> {
+    let mut event_count = 0;
+    for event in EventReader::new(BufReader::new(try!(File::open(name)))) {
+        try!(event);
+        event_count += 1;
+    }
+    Ok(event_count)
+}
+
+#[test]
+fn sample_1_short() {
+    test(
+        include_bytes!("documents/sample_1.xml"),
+        include_bytes!("documents/sample_1_short.txt"),
+        ParserConfig::new()
+            .ignore_comments(true)
+            .whitespace_to_characters(true)
+            .cdata_to_characters(true)
+            .trim_whitespace(true)
+            .coalesce_characters(true),
+        false
+    );
+}
+
+#[test]
+fn sample_1_full() {
+    test(
+        include_bytes!("documents/sample_1.xml"),
+        include_bytes!("documents/sample_1_full.txt"),
+        ParserConfig::new()
+            .ignore_comments(false)
+            .whitespace_to_characters(false)
+            .cdata_to_characters(false)
+            .trim_whitespace(false)
+            .coalesce_characters(false),
+        false
+    );
+}
+
+#[test]
+fn sample_2_short() {
+    test(
+        include_bytes!("documents/sample_2.xml"),
+        include_bytes!("documents/sample_2_short.txt"),
+        ParserConfig::new()
+            .ignore_comments(true)
+            .whitespace_to_characters(true)
+            .cdata_to_characters(true)
+            .trim_whitespace(true)
+            .coalesce_characters(true),
+        false
+    );
+}
+
+#[test]
+fn sample_2_full() {
+    test(
+        include_bytes!("documents/sample_2.xml"),
+        include_bytes!("documents/sample_2_full.txt"),
+        ParserConfig::new()
+            .ignore_comments(false)
+            .whitespace_to_characters(false)
+            .cdata_to_characters(false)
+            .trim_whitespace(false)
+            .coalesce_characters(false),
+        false
+    );
+}
+
+#[test]
+fn sample_3_short() {
+    test(
+        include_bytes!("documents/sample_3.xml"),
+        include_bytes!("documents/sample_3_short.txt"),
+        ParserConfig::new()
+            .ignore_comments(true)
+            .whitespace_to_characters(true)
+            .cdata_to_characters(true)
+            .trim_whitespace(true)
+            .coalesce_characters(true),
+        true
+    );
+}
+
+#[test]
+fn sample_3_full() {
+    test(
+        include_bytes!("documents/sample_3.xml"),
+        include_bytes!("documents/sample_3_full.txt"),
+        ParserConfig::new()
+            .ignore_comments(false)
+            .whitespace_to_characters(false)
+            .cdata_to_characters(false)
+            .trim_whitespace(false)
+            .coalesce_characters(false),
+        true
+    );
+}
+
+#[test]
+fn sample_4_short() {
+    test(
+        include_bytes!("documents/sample_4.xml"),
+        include_bytes!("documents/sample_4_short.txt"),
+        ParserConfig::new()
+            .ignore_comments(true)
+            .whitespace_to_characters(true)
+            .cdata_to_characters(true)
+            .trim_whitespace(true)
+            .coalesce_characters(true),
+        false
+    );
+}
+
+#[test]
+fn sample_4_full() {
+    test(
+        include_bytes!("documents/sample_4.xml"),
+        include_bytes!("documents/sample_4_full.txt"),
+        ParserConfig::new()
+            .ignore_comments(false)
+            .whitespace_to_characters(false)
+            .cdata_to_characters(false)
+            .trim_whitespace(false)
+            .coalesce_characters(false),
+        false
+    );
+
+}
+
+#[test]
+fn sample_5_short() {
+    test(
+        include_bytes!("documents/sample_5.xml"),
+        include_bytes!("documents/sample_5_short.txt"),
+        ParserConfig::new()
+            .ignore_comments(true)
+            .whitespace_to_characters(true)
+            .cdata_to_characters(true)
+            .trim_whitespace(true)
+            .coalesce_characters(true)
+            .add_entity("nbsp", " ")
+            .add_entity("copy", "©")
+            .add_entity("NotEqualTilde", "≂̸"),
+        false
+    );
+}
+
+#[test]
+fn sample_6_full() {
+    test(
+        include_bytes!("documents/sample_6.xml"),
+        include_bytes!("documents/sample_6_full.txt"),
+        ParserConfig::new()
+            .ignore_root_level_whitespace(false)
+            .ignore_comments(false)
+            .whitespace_to_characters(false)
+            .cdata_to_characters(false)
+            .trim_whitespace(false)
+            .coalesce_characters(false),
+        false
+    );
+}
+
+#[test]
+fn eof_1() {
+    test(
+        br#"<?xml"#,
+        br#"1:6 Unexpected end of stream: no root element found"#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn bad_1() {
+    test(
+        br#"<?xml&.,"#,
+        br#"1:6 Unexpected token: <?xml&"#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn dashes_in_comments() {
+    test(
+        br#"<!-- comment -- --><hello/>"#,
+        br#"
+            |1:14 Unexpected token '--' before ' '
+        "#,
+        ParserConfig::new(),
+        false
+    );
+
+    test(
+        br#"<!-- comment ---><hello/>"#,
+        br#"
+            |1:14 Unexpected token '--' before '-'
+        "#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn tabs_1() {
+    test(
+        b"\t<a>\t<b/></a>",
+        br#"
+            |1:2 StartDocument(1.0, UTF-8)
+            |1:2 StartElement(a)
+            |1:6 StartElement(b)
+            |1:6 EndElement(b)
+            |1:10 EndElement(a)
+            |1:14 EndDocument
+        "#,
+        ParserConfig::new()
+            .trim_whitespace(true),
+        true
+    );
+}
+
+#[test]
+fn issue_83_duplicate_attributes() {
+    test(
+        br#"<hello><some-tag a='10' a="20"></hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |1:30 Attribute 'a' is redefined
+        "#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn issue_93_large_characters_in_entity_references() {
+    test(
+        r#"<hello>&𤶼;</hello>"#.as_bytes(),
+        r#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |1:10 Unexpected entity: 𤶼
+        "#.as_bytes(),  // FIXME: it shouldn't be 10, looks like indices are off slightly
+        ParserConfig::new(),
+        false
+    )
+}
+
+#[test]
+fn issue_98_cdata_ending_with_right_bracket() {
+    test(
+        br#"<hello><![CDATA[Foo [Bar]]]></hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |CData("Foo [Bar]")
+            |EndElement(hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    )
+}
+
+#[test]
+fn issue_105_unexpected_double_dash() {
+    test(
+        br#"<hello>-- </hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |Characters("-- ")
+            |EndElement(hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    );
+
+    test(
+        br#"<hello>--</hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |Characters("--")
+            |EndElement(hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    );
+
+    test(
+        br#"<hello>--></hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |Characters("-->")
+            |EndElement(hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    );
+
+    test(
+        br#"<hello><![CDATA[--]]></hello>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(hello)
+            |CData("--")
+            |EndElement(hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn issue_attribues_have_no_default_namespace () {
+    test(
+        br#"<hello xmlns="urn:foo" x="y"/>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement({urn:foo}hello [x="y"])
+            |EndElement({urn:foo}hello)
+            |EndDocument
+        "#,
+        ParserConfig::new(),
+        false
+    );
+}
+
+#[test]
+fn issue_replacement_character_entity_reference() {
+    test(
+        br#"<doc>&#55357;&#56628;</doc>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(doc)
+            |1:13 Invalid decimal character number in an entity: #55357
+        "#,
+        ParserConfig::new(),
+        false,
+    );
+
+    test(
+        br#"<doc>&#xd83d;&#xdd34;</doc>"#,
+        br#"
+            |StartDocument(1.0, UTF-8)
+            |StartElement(doc)
+            |1:13 Invalid hexadecimal character number in an entity: #xd83d
+        "#,
+        ParserConfig::new(),
+        false,
+    );
+
+    test(
+        br#"<doc>&#55357;&#56628;</doc>"#,
+        format!(
+            r#"
+                |StartDocument(1.0, UTF-8)
+                |StartElement(doc)
+                |Characters("{replacement_character}{replacement_character}")
+                |EndElement(doc)
+                |EndDocument
+            "#,
+            replacement_character = "\u{fffd}"
+        )
+        .as_bytes(),
+        ParserConfig::new()
+            .replace_unknown_entity_references(true),
+        false,
+    );
+
+    test(
+        br#"<doc>&#xd83d;&#xdd34;</doc>"#,
+        format!(
+            r#"
+                |StartDocument(1.0, UTF-8)
+                |StartElement(doc)
+                |Characters("{replacement_character}{replacement_character}")
+                |EndElement(doc)
+                |EndDocument
+            "#,
+            replacement_character = "\u{fffd}"
+        )
+        .as_bytes(),
+        ParserConfig::new()
+            .replace_unknown_entity_references(true),
+        false,
+    );
+}
+
+lazy_static! {
+    // If PRINT_SPEC env variable is set, print the lines
+    // to stderr instead of comparing with the output
+    // it can be used like this:
+    // PRINT_SPEC=1 cargo test --test event_reader sample_1_full 2> sample_1_full.txt
+    static ref PRINT: bool = {
+        for (key, value) in env::vars() {
+            if key == "PRINT_SPEC" && value == "1" {
+                return true;
+            }
+        }
+        false
+    };
+}
+
+// clones a lot but that's fine
+fn trim_until_bar(s: String) -> String {
+    match s.trim() {
+        ts if ts.starts_with('|') => return ts[1..].to_owned(),
+        _ => {}
+    }
+    s
+}
+
+fn test(input: &[u8], output: &[u8], config: ParserConfig, test_position: bool) {
+    let mut reader = config.create_reader(input);
+    let mut spec_lines = BufReader::new(output).lines()
+        .map(|line| line.unwrap())
+        .enumerate()
+        .map(|(i, line)| (i, trim_until_bar(line)))
+        .filter(|&(_, ref line)| !line.trim().is_empty());
+
+    loop {
+        let e = reader.next();
+        let line =
+            if test_position {
+                format!("{} {}", reader.position(), Event(&e))
+            } else {
+                format!("{}", Event(&e))
+            };
+
+        if *PRINT {
+            writeln!(&mut stderr(), "{}", line).unwrap();
+        } else {
+            if let Some((n, spec)) = spec_lines.next() {
+                if line != spec {
+                    const SPLITTER: &'static str = "-------------------";
+                    panic!("\n{}\nUnexpected event at line {}:\nExpected: {}\nFound:    {}\n{}\n",
+                           SPLITTER, n + 1, spec, line, std::str::from_utf8(output).unwrap());
+                }
+            } else {
+                panic!("Unexpected event: {}", line);
+            }
+        }
+
+        match e {
+            Ok(XmlEvent::EndDocument) | Err(_) => break,
+            _ => {},
+        }
+    }
+}
+
+// Here we define our own string representation of events so we don't depend
+// on the specifics of Display implementation for XmlEvent and OwnedName.
+
+struct Name<'a>(&'a OwnedName);
+
+impl <'a> fmt::Display for Name<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let Some(ref namespace) = self.0.namespace {
+            try! { write!(f, "{{{}}}", namespace) }
+        }
+
+        if let Some(ref prefix) = self.0.prefix {
+            try! { write!(f, "{}:", prefix) }
+        }
+
+        write!(f, "{}", self.0.local_name)
+    }
+}
+
+struct Event<'a>(&'a Result<XmlEvent>);
+
+impl<'a> fmt::Display for Event<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let empty = String::new();
+        match *self.0 {
+            Ok(ref e) => match *e {
+                XmlEvent::StartDocument { ref version, ref encoding, .. } =>
+                    write!(f, "StartDocument({}, {})", version, encoding),
+                XmlEvent::EndDocument =>
+                    write!(f, "EndDocument"),
+                XmlEvent::ProcessingInstruction { ref name, ref data } =>
+                    write!(f, "ProcessingInstruction({}={:?})", name,
+                        data.as_ref().unwrap_or(&empty)),
+                XmlEvent::StartElement { ref name, ref attributes, .. } => {
+                    if attributes.is_empty() {
+                        write!(f, "StartElement({})", Name(name))
+                    }
+                    else {
+                        let attrs: Vec<_> = attributes.iter()
+                            .map(|a| format!("{}={:?}", Name(&a.name), a.value)) .collect();
+                        write!(f, "StartElement({} [{}])", Name(name), attrs.join(", "))
+                    }
+                },
+                XmlEvent::EndElement { ref name } =>
+                    write!(f, "EndElement({})", Name(name)),
+                XmlEvent::Comment(ref data) =>
+                    write!(f, r#"Comment("{}")"#, data.escape_debug()),
+                XmlEvent::CData(ref data) =>
+                    write!(f, r#"CData("{}")"#, data.escape_debug()),
+                XmlEvent::Characters(ref data) =>
+                    write!(f, r#"Characters("{}")"#, data.escape_debug()),
+                XmlEvent::Whitespace(ref data) =>
+                    write!(f, r#"Whitespace("{}")"#, data.escape_debug()),
+            },
+            Err(ref e) => e.fmt(f),
+        }
+    }
+}
diff --git a/tests/event_writer.rs b/tests/event_writer.rs
new file mode 100644
index 0000000..dd64a43
--- /dev/null
+++ b/tests/event_writer.rs
@@ -0,0 +1,269 @@
+#![forbid(unsafe_code)]
+
+extern crate xml;
+
+use std::io::{BufReader, SeekFrom};
+use std::io::prelude::*;
+use std::fs::File;
+use std::str;
+
+use xml::reader::EventReader;
+use xml::writer::EmitterConfig;
+
+macro_rules! unwrap_all {
+    ($($e:expr);+) => {{
+        $($e.unwrap();)+
+    }}
+}
+
+#[test]
+fn reading_writing_equal_with_namespaces() {
+    let mut f = File::open("tests/documents/sample_2.xml").unwrap();
+    let mut b = Vec::new();
+
+    {
+        let r = EventReader::new(BufReader::new(&mut f));
+        let mut w = EmitterConfig::default().perform_indent(true).create_writer(&mut b);
+
+        for e in r {
+            match e {
+                Ok(e) => if let Some(e) = e.as_writer_event() {
+                    match w.write(e) {
+                        Ok(_) => {},
+                        Err(e) => panic!("Writer error: {:?}", e)
+                    }
+                },
+                Err(e) => panic!("Error: {}", e)
+            }
+        }
+    }
+
+    f.seek(SeekFrom::Start(0)).unwrap();
+    let mut fs = String::new();
+    f.read_to_string(&mut fs).unwrap();
+
+    let bs = String::from_utf8(b).unwrap();
+
+    assert_eq!(fs.trim(), bs.trim());
+}
+
+#[test]
+fn writing_simple() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new().write_document_declaration(false).create_writer(&mut b);
+
+        w.write(XmlEvent::start_element("h:hello").ns("h", "urn:hello-world")).unwrap();
+        w.write("hello world").unwrap();
+        w.write(XmlEvent::end_element()).unwrap();
+    }
+
+    assert_eq!(
+        str::from_utf8(&b).unwrap(),
+        r#"<h:hello xmlns:h="urn:hello-world">hello world</h:hello>"#
+    );
+}
+
+#[test]
+fn writing_empty_elements_with_normalizing() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new().write_document_declaration(false).create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("hello"));
+            w.write(XmlEvent::start_element("world"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(str::from_utf8(&b).unwrap(), r#"<hello><world /></hello>"#);
+}
+
+#[test]
+fn writing_empty_elements_without_normalizing() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .normalize_empty_elements(false)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("hello"));
+            w.write(XmlEvent::start_element("world"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(str::from_utf8(&b).unwrap(), r#"<hello><world></world></hello>"#);
+}
+
+#[test]
+fn writing_empty_elements_without_pad_self_closing() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .pad_self_closing(false)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("hello"));
+            w.write(XmlEvent::start_element("world"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(str::from_utf8(&b).unwrap(), r#"<hello><world/></hello>"#);
+}
+#[test]
+fn writing_empty_elements_pad_self_closing_explicit() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .pad_self_closing(true)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("hello"));
+            w.write(XmlEvent::start_element("world"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(str::from_utf8(&b).unwrap(), r#"<hello><world /></hello>"#);
+}
+
+#[test]
+fn writing_comments_with_indentation() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .perform_indent(true)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("hello"));
+            w.write(XmlEvent::start_element("world"));
+            w.write(XmlEvent::comment("  this is a manually padded comment\t"));
+            w.write(XmlEvent::comment("this is an unpadded comment"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(
+        str::from_utf8(&b).unwrap(),
+        "<hello>
+  <world>
+    <!--  this is a manually padded comment\t-->
+    <!-- this is an unpadded comment -->
+  </world>
+</hello>");
+}
+
+#[test]
+fn issue_112_overriding_namepace_prefix() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(XmlEvent::start_element("iq").ns("", "jabber:client").ns("a", "urn:A"));
+            w.write(XmlEvent::start_element("bind").ns("", "urn:ietf:params:xml:ns:xmpp-bind"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::start_element("whatever").ns("a", "urn:X"));
+            w.write(XmlEvent::end_element());
+            w.write(XmlEvent::end_element())
+        }
+    }
+
+    assert_eq!(
+        str::from_utf8(&b).unwrap(),
+        r#"<iq xmlns="jabber:client" xmlns:a="urn:A"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind" /><whatever xmlns:a="urn:X" /></iq>"#
+    )
+}
+
+#[test]
+fn attribute_escaping() {
+    use xml::writer::XmlEvent;
+
+    let mut b = Vec::new();
+
+    {
+        let mut w = EmitterConfig::new()
+            .write_document_declaration(false)
+            .perform_indent(true)
+            .create_writer(&mut b);
+
+        unwrap_all! {
+            w.write(
+                XmlEvent::start_element("hello")
+                    .attr("testLt", "<")
+                    .attr("testGt", ">")
+            );
+            w.write(XmlEvent::end_element());
+            w.write(
+                XmlEvent::start_element("hello")
+                    .attr("testQuot", "\"")
+                    .attr("testApos", "\'")
+            );
+            w.write(XmlEvent::end_element());
+            w.write(
+                XmlEvent::start_element("hello")
+                    .attr("testAmp", "&")
+            );
+            w.write(XmlEvent::end_element());
+            w.write(
+                XmlEvent::start_element("hello")
+                    .attr("testNl", "\n")
+                    .attr("testCr", "\r")
+            );
+            w.write(XmlEvent::end_element());
+            w.write(
+                XmlEvent::start_element("hello")
+                    .attr("testNl", "\\n")
+                    .attr("testCr", "\\r")
+            );
+            w.write(XmlEvent::end_element())
+        }
+    }
+    assert_eq!(
+        str::from_utf8(&b).unwrap(),
+        "<hello testLt=\"&lt;\" testGt=\"&gt;\" />
+<hello testQuot=\"&quot;\" testApos=\"&apos;\" />
+<hello testAmp=\"&amp;\" />
+<hello testNl=\"&#xA;\" testCr=\"&#xD;\" />
+<hello testNl=\"\\n\" testCr=\"\\r\" />"
+    );
+}
\ No newline at end of file
diff --git a/tests/streaming.rs b/tests/streaming.rs
new file mode 100644
index 0000000..a577a00
--- /dev/null
+++ b/tests/streaming.rs
@@ -0,0 +1,103 @@
+#![forbid(unsafe_code)]
+
+extern crate xml;
+
+use std::io::{Cursor, Write};
+
+use xml::EventReader;
+use xml::reader::ParserConfig;
+use xml::reader::XmlEvent;
+
+macro_rules! assert_match {
+    ($actual:expr, $expected:pat) => {
+        match $actual {
+            $expected => {},
+            _ => panic!("assertion failed: `(left matches right)` \
+                        (left: `{:?}`, right: `{}`", $actual, stringify!($expected))
+        }
+    };
+    ($actual:expr, $expected:pat if $guard:expr) => {
+        match $actual {
+            $expected if $guard => {},
+            _ => panic!("assertion failed: `(left matches right)` \
+                        (left: `{:?}`, right: `{} if {}`",
+                        $actual, stringify!($expected), stringify!($guard))
+        }
+    }
+}
+
+fn write_and_reset_position<W>(c: &mut Cursor<W>, data: &[u8]) where Cursor<W>: Write {
+    let p = c.position();
+    c.write_all(data).unwrap();
+    c.set_position(p);
+}
+
+#[test]
+fn reading_streamed_content() {
+    let buf = Cursor::new(b"<root>".to_vec());
+    let reader = EventReader::new(buf);
+
+    let mut it = reader.into_iter();
+
+    assert_match!(it.next(), Some(Ok(XmlEvent::StartDocument { .. })));
+    assert_match!(it.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "root");
+
+    write_and_reset_position(it.source_mut(), b"<child-1>content</child-1>");
+    assert_match!(it.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-1");
+    assert_match!(it.next(), Some(Ok(XmlEvent::Characters(ref c))) if c == "content");
+    assert_match!(it.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "child-1");
+
+    write_and_reset_position(it.source_mut(), b"<child-2/>");
+    assert_match!(it.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-2");
+    assert_match!(it.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "child-2");
+
+    write_and_reset_position(it.source_mut(), b"<child-3/>");
+    assert_match!(it.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-3");
+    assert_match!(it.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "child-3");
+    // doesn't seem to work because of how tags parsing is done
+//    write_and_reset_position(it.source_mut(), b"some text");
+   // assert_match!(it.next(), Some(Ok(XmlEvent::Characters(ref c))) if c == "some text");
+
+    write_and_reset_position(it.source_mut(), b"</root>");
+    assert_match!(it.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "root");
+    assert_match!(it.next(), Some(Ok(XmlEvent::EndDocument)));
+    assert_match!(it.next(), None);
+}
+
+#[test]
+fn reading_streamed_content2() {
+    let buf = Cursor::new(b"<root>".to_vec());
+    let mut config = ParserConfig::new();
+    config.ignore_end_of_stream = true;
+    let readerb = EventReader::new_with_config(buf, config);
+
+    let mut reader = readerb.into_iter();
+
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartDocument { .. })));
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "root");
+
+    write_and_reset_position(reader.source_mut(), b"<child-1>content</child-1>");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-1");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::Characters(ref c))) if c == "content");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "child-1");
+
+    write_and_reset_position(reader.source_mut(), b"<child-2>content</child-2>");
+
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-2");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::Characters(ref c))) if c == "content");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "child-2");
+    assert_match!(reader.next(), Some(Err(_)));
+    write_and_reset_position(reader.source_mut(), b"<child-3></child-3>");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-3");
+    write_and_reset_position(reader.source_mut(), b"<child-4 type='get'");
+    match reader.next() {
+       None |
+       Some(Ok(_)) => {
+          panic!("At this point, parser must not detect something.");
+       },
+       Some(Err(_)) => {}
+    };
+    write_and_reset_position(reader.source_mut(), b" />");
+    assert_match!(reader.next(), Some(Ok(XmlEvent::StartElement { ref name, .. })) if name.local_name == "child-4");
+}
+