diff --git a/tx-parser/src/lib.rs b/tx-parser/src/lib.rs index 0cbc400c..050f4768 100644 --- a/tx-parser/src/lib.rs +++ b/tx-parser/src/lib.rs @@ -16,8 +16,7 @@ extern crate mentat_tx; use combine::{any, eof, many, optional, parser, satisfy_map, token, Parser, ParseResult, Stream}; use combine::combinator::{Expected, FnParser}; -// TODO: understand why this is self::edn rather than just edn. -use self::edn::types::Value; +use edn::types::Value; use mentat_tx::entities::*; // TODO: implement combine::Positioner on Value. We can't do this @@ -45,7 +44,7 @@ use mentat_tx::entities::*; // } // } -struct Tx(::std::marker::PhantomData I>); +pub struct Tx(::std::marker::PhantomData I>); type TxParser = Expected ParseResult>>; @@ -252,7 +251,7 @@ impl Tx p.parse_stream(input) } - fn entity() -> TxParser { + pub fn entity() -> TxParser { fn_parser(Tx::::entity_, "[:db/add|:db/retract|:db/retractAttribute|:db/retractEntity ...]") } @@ -274,105 +273,8 @@ impl Tx .parse_stream(input); } - fn entities() -> TxParser, I> { + pub fn entities() -> TxParser, I> { fn_parser(Tx::::entities_, "[[:db/add|:db/retract|:db/retractAttribute|:db/retractEntity ...]*]") } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_add() { - let input = [Value::Vector(vec![Value::Keyword("db/add".into()), - Value::Keyword("ident".into()), - Value::Keyword("a".into()), - Value::Text("v".into())])]; - let mut parser = Tx::entity(); - let result = parser.parse(&input[..]); - assert_eq!(result, - Ok((Entity::Add { - e: EntIdOrLookupRef::EntId(EntId::Ident("ident".into())), - a: EntId::Ident("a".into()), - v: ValueOrLookupRef::Value(Value::Text("v".into())), - tx: None, - }, - &[][..]))); - } - - #[test] - fn test_retract() { - let input = [Value::Vector(vec![Value::Keyword("db/retract".into()), - Value::Integer(101), - Value::Keyword("a".into()), - Value::Text("v".into())])]; - let mut parser = Tx::entity(); - let result = parser.parse(&input[..]); - assert_eq!(result, - Ok((Entity::Retract { - e: EntIdOrLookupRef::EntId(EntId::EntId(101)), - a: EntId::Ident("a".into()), - v: ValueOrLookupRef::Value(Value::Text("v".into())), - }, - &[][..]))); - } - - #[test] - fn test_entities() { - let input = [Value::Vector(vec![ - Value::Vector(vec![Value::Keyword("db/add".into()), - Value::Integer(101), - Value::Keyword("a".into()), - Value::Text("v".into())]), - Value::Vector(vec![Value::Keyword("db/retract".into()), - Value::Integer(102), - Value::Keyword("b".into()), - Value::Text("w".into())])])]; - - let mut parser = Tx::entities(); - let result = parser.parse(&input[..]); - assert_eq!(result, - Ok((vec![ - Entity::Add { - e: EntIdOrLookupRef::EntId(EntId::EntId(101)), - a: EntId::Ident("a".into()), - v: ValueOrLookupRef::Value(Value::Text("v".into())), - tx: None, - }, - Entity::Retract { - e: EntIdOrLookupRef::EntId(EntId::EntId(102)), - a: EntId::Ident("b".into()), - v: ValueOrLookupRef::Value(Value::Text("w".into())), - }, - ], - &[][..]))); - } - - #[test] - fn test_lookup_ref() { - let input = [Value::Vector(vec![Value::Keyword("db/add".into()), - Value::Vector(vec![Value::Keyword("a1".into()), - Value::Text("v1".into())]), - Value::Keyword("a".into()), - Value::Text("v".into())])]; - let mut parser = Tx::entity(); - let result = parser.parse(&input[..]); - assert_eq!(result, - Ok((Entity::Add { - e: EntIdOrLookupRef::LookupRef(LookupRef { - a: EntId::Ident("a1".into()), - v: Value::Text("v1".into()), - }), - a: EntId::Ident("a".into()), - v: ValueOrLookupRef::Value(Value::Text("v".into())), - tx: None, - }, - &[][..]))); - } - - // TODO: test error handling in select cases. It's tricky to do - // this without combine::Positioner; see the TODO at the top of - // the file. -} diff --git a/tx-parser/tests/parser.rs b/tx-parser/tests/parser.rs new file mode 100644 index 00000000..98ac039d --- /dev/null +++ b/tx-parser/tests/parser.rs @@ -0,0 +1,112 @@ +// Copyright 2016 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +extern crate edn; +extern crate combine; +extern crate mentat_tx; +extern crate mentat_tx_parser; + +use combine::Parser; +use edn::types::Value; +use mentat_tx::entities::*; +use mentat_tx_parser::Tx; + +#[test] +fn test_add() { + let input = [Value::Vector(vec![Value::Keyword("db/add".into()), + Value::Keyword("ident".into()), + Value::Keyword("a".into()), + Value::Text("v".into())])]; + let mut parser = Tx::entity(); + let result = parser.parse(&input[..]); + assert_eq!(result, + Ok((Entity::Add { + e: EntIdOrLookupRef::EntId(EntId::Ident("ident".into())), + a: EntId::Ident("a".into()), + v: ValueOrLookupRef::Value(Value::Text("v".into())), + tx: None, + }, + &[][..]))); +} + +#[test] +fn test_retract() { + let input = [Value::Vector(vec![Value::Keyword("db/retract".into()), + Value::Integer(101), + Value::Keyword("a".into()), + Value::Text("v".into())])]; + let mut parser = Tx::entity(); + let result = parser.parse(&input[..]); + assert_eq!(result, + Ok((Entity::Retract { + e: EntIdOrLookupRef::EntId(EntId::EntId(101)), + a: EntId::Ident("a".into()), + v: ValueOrLookupRef::Value(Value::Text("v".into())), + }, + &[][..]))); +} + +#[test] +fn test_entities() { + let input = [Value::Vector(vec![ + Value::Vector(vec![Value::Keyword("db/add".into()), + Value::Integer(101), + Value::Keyword("a".into()), + Value::Text("v".into())]), + Value::Vector(vec![Value::Keyword("db/retract".into()), + Value::Integer(102), + Value::Keyword("b".into()), + Value::Text("w".into())])])]; + + let mut parser = Tx::entities(); + let result = parser.parse(&input[..]); + assert_eq!(result, + Ok((vec![ + Entity::Add { + e: EntIdOrLookupRef::EntId(EntId::EntId(101)), + a: EntId::Ident("a".into()), + v: ValueOrLookupRef::Value(Value::Text("v".into())), + tx: None, + }, + Entity::Retract { + e: EntIdOrLookupRef::EntId(EntId::EntId(102)), + a: EntId::Ident("b".into()), + v: ValueOrLookupRef::Value(Value::Text("w".into())), + }, + ], + &[][..]))); +} + +#[test] +fn test_lookup_ref() { + let input = [Value::Vector(vec![Value::Keyword("db/add".into()), + Value::Vector(vec![Value::Keyword("a1".into()), + Value::Text("v1".into())]), + Value::Keyword("a".into()), + Value::Text("v".into())])]; + let mut parser = Tx::entity(); + let result = parser.parse(&input[..]); + assert_eq!(result, + Ok((Entity::Add { + e: EntIdOrLookupRef::LookupRef(LookupRef { + a: EntId::Ident("a1".into()), + v: Value::Text("v1".into()), + }), + a: EntId::Ident("a".into()), + v: ValueOrLookupRef::Value(Value::Text("v".into())), + tx: None, + }, + &[][..]))); +} + +// TODO: test error handling in select cases. It's tricky to do +// this without combine::Positioner; see the TODO at the top of +// the file. +