Repository: Marwes/combine (language: rust)

Issue:
Move/copy examples to examples/
It more standard, and it allows to easily run them.



Discussion / hints:
The reason for having them in `tests` is so that they get built and run automatically with `cargo test` but I will look into moving them to examples as you are right that they should really be there!

Oh yeah, didn't see `test/` ^^. I was talking about the examples in the doc.

Aha, well I don't know what benefit there is to copy them to `examples`. I guess they could print out they result in (what they assert on)? Otherwise running them would not do anything that `cargo test test_name` does now?

`cargo run --example`, with a `println!` of the result, I think. It's a standard directory, so people automatically go see what's in it if they want examples.

You can add to Cargo.toml to run it automatically.

Cargo guide:

cargo test runs additional checks as well. For example, it will compile any examples you’ve included and will also test the examples in your documentation. Please see the testing guide in the Rust documentation for more details.

(I'm on mobile, sorry for the link)

And assert_eq! works fine with it. Test fails when assertion in example failed
@kdy1997 That is only when running the examples manually. Just running `cargo test` only builds the examples and does not run them.

I think the way to fix this properly though is to have the examples in examples/ directory and then also have separate tests which runs the example executable, feeding it input to its stdin and reading its stdout to compare with the expected result. Did that for https://github.com/gluon-lang/gluon/pull/226 (though it reads/writes to tcp stream).

Fix patch:
diff --git a/tests/date.rs b/examples/date.rs
similarity index 85%
rename from tests/date.rs
rename to examples/date.rs
index 6b94e304..cce60895 100644
--- a/tests/date.rs
+++ b/examples/date.rs
@@ -4,8 +4,14 @@
 #[macro_use]
 extern crate combine;
 
+use std::env;
+use std::error::Error as StdError;
+use std::fs::File;
+use std::io::{self, Read};
+
 use combine::char::{char, digit};
 use combine::{choice, many, optional, Parser, Stream};
+use combine::state::State;
 
 #[derive(PartialEq, Debug)]
 pub struct Date {
@@ -172,3 +178,26 @@ fn test() {
     };
     assert_eq!(result, Ok((d, "")));
 }
+
+fn main() {
+    let result = match env::args().nth(1) {
+        Some(file) => File::open(file).map_err(From::from).and_then(main_),
+        None => main_(io::stdin()),
+    };
+    match result {
+        Ok(_) => println!("OK"),
+        Err(err) => println!("{}", err),
+    }
+}
+
+fn main_<R>(mut read: R) -> Result<(), Box<StdError>>
+where
+    R: Read,
+{
+    let mut text = String::new();
+    read.read_to_string(&mut text)?;
+    date_time()
+        .parse(State::new(&*text))
+        .map_err(|err| err.map_range(|s| s.to_string()))?;
+    Ok(())
+}
diff --git a/tests/ini.rs b/examples/ini.rs
similarity index 82%
rename from tests/ini.rs
rename to examples/ini.rs
index adbcba06..46344649 100644
--- a/tests/ini.rs
+++ b/examples/ini.rs
@@ -3,11 +3,14 @@
 extern crate combine;
 
 use std::collections::HashMap;
+use std::env;
+use std::error::Error as StdError;
+use std::fs::File;
+use std::io::{self, Read};
 
 use combine::*;
 use combine::char::space;
-use combine::primitives::Error;
-use combine::state::SourcePosition;
+use combine::state::State;
 
 #[derive(PartialEq, Debug)]
 pub struct Ini {
@@ -124,3 +127,26 @@ fn ini_error() {
         })
     );
 }
+
+fn main() {
+    let result = match env::args().nth(1) {
+        Some(file) => File::open(file).map_err(From::from).and_then(main_),
+        None => main_(io::stdin()),
+    };
+    match result {
+        Ok(_) => println!("OK"),
+        Err(err) => println!("{}", err),
+    }
+}
+
+fn main_<R>(mut read: R) -> Result<(), Box<StdError>>
+where
+    R: Read,
+{
+    let mut text = String::new();
+    read.read_to_string(&mut text)?;
+    ini()
+        .parse(State::new(&*text))
+        .map_err(|err| err.map_range(|s| s.to_string()))?;
+    Ok(())
+}
diff --git a/tests/readme.rs b/examples/readme.rs
similarity index 59%
rename from tests/readme.rs
rename to examples/readme.rs
index 7932ba0e..40e36d4d 100644
--- a/tests/readme.rs
+++ b/examples/readme.rs
@@ -1,13 +1,16 @@
 extern crate combine;
-use combine::{many1, Parser, sep_by};
+use combine::{sep_by, Parser, many1};
 use combine::char::{letter, space};
 
 #[test]
 fn readme() {
+    main();
+}
+
+fn main() {
     let word = many1(letter());
 
-    let mut parser = sep_by(word, space())
-        .map(|mut words: Vec<String>| words.pop());
+    let mut parser = sep_by(word, space()).map(|mut words: Vec<String>| words.pop());
     let result = parser.parse("Pick up that word!");
     assert_eq!(result, Ok((Some("word".to_string()), "!")));
-}
\ No newline at end of file
+}
diff --git a/src/combinator.rs b/src/combinator.rs
index 3dc7d6c8..1363c820 100644
--- a/src/combinator.rs
+++ b/src/combinator.rs
@@ -785,12 +785,10 @@ where
                                 self[i - 1].add_error(&mut prev_err);
                                 last_parser_having_non_1_offset = i;
                             }
-                            Some(
-                                Tracked {
-                                    error: prev_err.error.merge(err.error),
-                                    offset: err.offset,
-                                }
-                            )
+                            Some(Tracked {
+                                error: prev_err.error.merge(err.error),
+                                offset: err.offset,
+                            })
                         }
                     };
                 }
@@ -3082,11 +3080,8 @@ mod tests {
     #[test]
     fn sequence_in_choice_array_parser_empty_err_where_first_parser_delay_errors() {
         let mut p1 = char('1');
-        let mut p2 = (optional(char('b')), char('2')).map(|t| t. 1);
-        let mut parser = choice::<[&mut Parser<Input = _, Output = _>; 2]>([
-            &mut p1,
-            &mut p2,
-        ]);
+        let mut p2 = (optional(char('b')), char('2')).map(|t| t.1);
+        let mut parser = choice::<[&mut Parser<Input = _, Output = _>; 2]>([&mut p1, &mut p2]);
 
         assert_eq!(
             parser.parse(State::new("c")),
diff --git a/src/regex.rs b/src/regex.rs
index c0ea0e88..287c79e1 100644
--- a/src/regex.rs
+++ b/src/regex.rs
@@ -221,7 +221,9 @@ where
         }
     }
     fn add_error(&mut self, error: &mut Tracked<StreamError<Self::Input>>) {
-        error.error.add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
+        error
+            .error
+            .add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
     }
 }
 
@@ -272,7 +274,9 @@ where
         }
     }
     fn add_error(&mut self, error: &mut Tracked<StreamError<Self::Input>>) {
-        error.error.add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
+        error
+            .error
+            .add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
     }
 }
 
@@ -325,7 +329,9 @@ where
         take(end).parse_lazy(input).map(|_| value)
     }
     fn add_error(&mut self, error: &mut Tracked<StreamError<Self::Input>>) {
-        error.error.add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
+        error
+            .error
+            .add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
     }
 }
 
@@ -380,7 +386,9 @@ where
         }
     }
     fn add_error(&mut self, error: &mut Tracked<StreamError<Self::Input>>) {
-        error.error.add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
+        error
+            .error
+            .add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
     }
 }
 
@@ -440,7 +448,9 @@ where
         take(end).parse_lazy(input).map(|_| value)
     }
     fn add_error(&mut self, error: &mut Tracked<StreamError<Self::Input>>) {
-        error.error.add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
+        error
+            .error
+            .add_error(Error::Expected(format!("/{}/", self.0.as_str()).into()))
     }
 }
 
diff --git a/travis.sh b/travis.sh
index d974e1e3..bfe2be97 100755
--- a/travis.sh
+++ b/travis.sh
@@ -2,6 +2,7 @@
 
 cargo build &&
     cargo test --features regex &&
+    cargo test --features regex --examples &&
     cargo check --bench json &&
     cargo check --bench http &&
     cargo check --bench mp4 --features mp4
\ No newline at end of file


Test patch: