diff options
-rw-r--r-- | tests/basic_match.rs | 92 | ||||
-rw-r--r-- | tests/common/mod.rs | 175 |
2 files changed, 267 insertions, 0 deletions
diff --git a/tests/basic_match.rs b/tests/basic_match.rs new file mode 100644 index 0000000..2f65451 --- /dev/null +++ b/tests/basic_match.rs @@ -0,0 +1,92 @@ +/* + * This file is part of Datafu + * Copyright (C) 2021 Soni L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +extern crate datafu; + +mod common; + +use common::Value; + +#[test] +fn test_basic_example() { + let tree = Value::M(vec![ + ("foo".into(), Value::U(1)), + ("bar".into(), Value::M(vec![ + ("baz".into(), Value::U(2)), + ].into_iter().collect())), + ].into_iter().collect()); + let pat = datafu::Pattern::<Value>::compile("->X:?$dict->Y", None).ok().unwrap(); + let mut matcher = pat.attempt_match(&tree); + let m = matcher.next(); + // TODO + todo!(); + //assert m['X'][0] == 'bar' + //assert m['Y'][0] == 'baz' + //assert m['Y'][1] == 2 +} + +#[test] +fn test_basic_2() { + let tree = Value::M(vec![ + ("projects".into(), Value::M(vec![ + ("385e734a52e13949a7a5c71827f6de920dbfea43".into(), Value::M(vec![ + ("https://soniex2.autistic.space/git-repos/ganarchy.git".into(), Value::M(vec![ + ("HEAD".into(), Value::M(vec![ + ("active".into(), Value::B(true)), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect()); + let pat = datafu::Pattern::<Value>::compile("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", None).ok().unwrap(); + let mut matcher = pat.attempt_match(&tree); + let m = matcher.next(); + // TODO + todo!(); + //assert m['P'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" + //assert m['U'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" + //assert m['B'][0] == "HEAD" + //assert m['B'][1] == {"active": True} +} + +#[test] +fn test_spaces() { + let tree = Value::M(vec![ + ("projects".into(), Value::M(vec![ + ("385e734a52e13949a7a5c71827f6de920dbfea43".into(), Value::M(vec![ + ("https://soniex2.autistic.space/git-repos/ganarchy.git".into(), Value::M(vec![ + ("HEAD".into(), Value::M(vec![ + ("active".into(), Value::B(true)), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect())), + ].into_iter().collect()); + let pat = datafu::Pattern::<Value>::compile("-> 'projects'? + -> commit /[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/? :?$dict + -> url :?$dict + -> branch :?$dict", None).ok().unwrap(); + let mut matcher = pat.attempt_match(&tree); + let m = matcher.next(); + // TODO + todo!(); + //assert m['commit'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" + //assert m['url'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" + //assert m['branch'][0] == "HEAD" + //assert m['branch'][1] == {"active": True} +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..48153af --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,175 @@ +/* + * This file is part of Datafu + * Copyright (C) 2021 Soni L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use std::borrow::Borrow; +use std::borrow::Cow; +use std::collections::BTreeMap; + +use datafu::RefOwn; +use datafu::PatternTypes; +use datafu::KVPair; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum Value { + U(usize), + B(bool), + M(BTreeMap<Value, Value>), + S(Cow<'static, str>), +} + +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum Dummy { +} + +trait ValueHelper { + fn as_value(&self) -> Result<&Value, &str>; +} + +impl ValueHelper for Value { + fn as_value(&self) -> Result<&Value, &str> { + Ok(self) + } +} + +impl ValueHelper for &str { + fn as_value(&self) -> Result<&Value, &str> { + Err(self) + } +} + +impl PartialEq<str> for Value { + fn eq(&self, other: &str) -> bool { + matches!(self, Value::S(l) if l == other) + } +} + +impl PartialEq<Value> for str { + fn eq(&self, other: &Value) -> bool { + matches!(other, Value::S(r) if self == r) + } +} + +impl PartialEq<Dummy> for Value { + fn eq(&self, other: &Dummy) -> bool { + unreachable!() + } +} + +impl PartialEq<Value> for Dummy { + fn eq(&self, other: &Value) -> bool { + unreachable!() + } +} + +impl PartialEq<str> for Dummy { + fn eq(&self, other: &str) -> bool { + unreachable!() + } +} + +impl PartialEq<Dummy> for str { + fn eq(&self, other: &Dummy) -> bool { + unreachable!() + } +} + +impl<'a> PartialEq for dyn ValueHelper + 'a { + fn eq(&self, other: &(dyn ValueHelper + 'a)) -> bool { + match (self.as_value(), other.as_value()) { + (a, b) if a == b => true, + (Ok(Value::S(a)), Err(b)) | (Err(b), Ok(Value::S(a))) => { + a.eq(b) + }, + _ => false, + } + } +} + +impl<'a> PartialOrd for dyn ValueHelper + 'a { + fn partial_cmp(&self, other: &(dyn ValueHelper + 'a)) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl<'a> Eq for dyn ValueHelper + 'a { +} + +impl<'a> Ord for dyn ValueHelper + 'a { + fn cmp(&self, other: &(dyn ValueHelper + 'a)) -> std::cmp::Ordering { + match (self.as_value(), other.as_value()) { + (Ok(a), Ok(b)) => a.cmp(b), + (Err(a), Err(b)) => a.cmp(b), + (Ok(Value::S(a)), Err(b)) => (**a).cmp(b), + (Err(a), Ok(Value::S(b))) => a.cmp(b.borrow()), + (Ok(_), Err(_)) => std::cmp::Ordering::Less, + (Err(_), Ok(_)) => std::cmp::Ordering::Greater, + } + } +} + +impl From<&'static str> for Value { + fn from(x: &'static str) -> Value { + Value::S(x.into()) + } +} + + +impl<'a> Borrow<dyn ValueHelper + 'a> for Value { + fn borrow(&self) -> &(dyn ValueHelper + 'a) { + self + } +} + +impl PatternTypes for Value { + type Ref = Self; + type Own = Dummy; + + fn pairs<'b>( + item: RefOwn<'b, Self, Dummy> + ) -> Option<Box<dyn Iterator<Item=KVPair<'b, Self>> + 'b>> { + match item { + RefOwn::Ref(Value::M(map)) => { + Some(Box::new(map.iter().map(|(a, b)| (a.into(), b.into())))) + }, + _ => None + } + } + + fn get<'a, 'b>( + item: RefOwn<'b, Self, Dummy>, + key: RefOwn<'a, Self, Dummy> + ) -> Option<Option<KVPair<'b, Self>>> { + match item { + RefOwn::Ref(Value::M(map)) => { + Some(match key { + RefOwn::Ref(key) => map.get_key_value(key), + RefOwn::Own(key) => unreachable!(),//map.get_key_value(&Value::U(key)), + RefOwn::Str(key) => map.get_key_value(&key as &dyn ValueHelper), + }.map(|(k,v)| (k.into(), v.into()))) + }, + _ => None + } + } + + fn matches( + left: RefOwn<'_, Self, Dummy>, + right: RefOwn<'_, Self, Dummy> + ) -> bool { + left == right + } +} |