---
Sorry, I didn't test for this in the previous patch.
Added tests in the parser module.
src/parser.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 67 insertions(+), 5 deletions(-)
diff --git a/src/parser.rs b/src/parser.rs
index 261356c..8dded8e 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -38,7 +38,7 @@ impl std::error::Error for Error {
}
pub fn document(mut r: impl io::BufRead) -> Result<Scfg, Error> {
- let mut lineno = 1;
+ let mut lineno = 0;
let (block, closing_brace) = read_block(&mut r, &mut lineno)?;
if closing_brace {
return Err(Error {
@@ -54,13 +54,14 @@ pub fn document(mut r: impl io::BufRead) -> Result<Scfg, Error> {
/// Returns `(block, closing_brace)` where `closing_brace` is true if parsing stopped on '}', and
/// false if parsing stopped on EOF.
///
-/// `lineno` must be set the line number of the first line of the block, and is set to the line
-/// number of the closing bracket or EOF.
+/// `lineno` must be set the line number of the first line of the block minus one, and is set to
+/// the line number of the closing bracket or EOF.
fn read_block<R: io::BufRead>(r: &mut R, lineno: &mut usize) -> Result<(Scfg, bool), Error> {
let mut block = Scfg::new();
let mut line = String::new();
loop {
+ *lineno += 1;
line.clear();
let n = r.read_line(&mut line).map_err(|err| Error {
kind: ErrorKind::Io(err),
@@ -95,7 +96,6 @@ fn read_block<R: io::BufRead>(r: &mut R, lineno: &mut usize) -> Result<(Scfg, bo
} else {
words.remove(0)
};
- *lineno += 1;
let (child, closing_brace) = read_block(r, lineno)?;
if !closing_brace {
return Err(Error {
@@ -121,7 +121,69 @@ fn read_block<R: io::BufRead>(r: &mut R, lineno: &mut usize) -> Result<(Scfg, bo
)
};
block.add_directive(name, directive);
+ }
+}
- *lineno += 1;
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::*;
+
+ #[test]
+ fn unexpected_bracket() {
+ let src = r#"domain example.com
+
+# TLS endpoint
+listen 0.0.0.0:6697 {
+ certificate "/etc/letsencrypt/live/example.com/fullchain.pem"
+ key "/etc/letsencrypt/live/example.com/privkey.pem"
+}
+}
+
+listen 127.0.0.1:6667
+"#;
+
+ let err = Scfg::from_str(src).unwrap_err();
+ assert!(matches!(err.kind, ErrorKind::UnexpectedClosingBrace));
+ assert_eq!(err.lineno, 8);
+ }
+
+ #[test]
+ fn unexpected_eof() {
+ let src = r#"domain example.com
+
+# TLS endpoint
+listen 0.0.0.0:6697 {
+ certificate "/etc/letsencrypt/live/example.com/fullchain.pem"
+"#;
+
+ let err = Scfg::from_str(src).unwrap_err();
+ match err.kind {
+ ErrorKind::Io(err) => {
+ assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
+ }
+ _ => {
+ panic!("unexpected error kind {:?}", err.kind);
+ }
+ }
+ assert_eq!(err.lineno, 6);
+ }
+
+ #[test]
+ fn missing_quote() {
+ let src = r#"domain example.com
+
+# TLS endpoint
+listen 0.0.0.0:6697 {
+ certificate "/etc/letsencrypt/live/example.com/fullchain.pem
+ key "/etc/letsencrypt/live/example.com/privkey.pem"
+}
+
+listen 127.0.0.1:6667
+"#;
+
+ let err = Scfg::from_str(src).unwrap_err();
+ assert!(matches!(err.kind, ErrorKind::ShellWords(_)));
+ assert_eq!(err.lineno, 5);
}
}
--
2.31.1