From a8778ff35bde88bb63d9fec769edf66e68d7969e Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sat, 30 Jul 2022 11:22:23 -0300 Subject: Initial work on 0.1.0 Missing the VM. --- tests/basic_match.rs | 284 ++++++++++++++++++++++++--------------------------- tests/common/mod.rs | 189 ---------------------------------- tests/parser_prop.rs | 28 +---- 3 files changed, 136 insertions(+), 365 deletions(-) delete mode 100644 tests/common/mod.rs (limited to 'tests') diff --git a/tests/basic_match.rs b/tests/basic_match.rs index 4697c63..1500356 100644 --- a/tests/basic_match.rs +++ b/tests/basic_match.rs @@ -1,157 +1,139 @@ -/* - * 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 . - */ +// Copyright (C) 2021-2022 Soni L. +// SPDX-License-Identifier: MIT OR Apache-2.0 -extern crate datafu; - -mod common; - -use common::Value; - -use datafu::RefOwn; +use serde_json::Deserializer as JsonDer; +use serde::Deserialize; #[test] fn test_basic() { - 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 preds = vec![("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); - let pat = datafu::Pattern::::compile::<&str, &str>("->X:?$dict->Y", Some(preds), None).unwrap(); - let mut matcher = pat.attempt_match(&tree); - let m = matcher.next().unwrap().unwrap(); - assert_eq!(m["X"].0, RefOwn::Ref(&Value::from("bar"))); - assert_eq!(m["Y"].0, RefOwn::Ref(&Value::from("baz"))); - assert_eq!(m["Y"].1, RefOwn::Ref(&Value::U(2))); - assert!(matcher.next().is_none()); -} - -#[test] -fn test_str() { - 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 preds = vec![("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); - let pat = datafu::Pattern::::compile::<&str, &str>("->X'bar'->Y", Some(preds), None).unwrap(); - let mut matcher = pat.attempt_match(&tree); - let m = matcher.next().unwrap().unwrap(); - assert_eq!(m["X"].0, RefOwn::Ref(&Value::from("bar"))); - assert_eq!(m["Y"].0, RefOwn::Ref(&Value::from("baz"))); - assert_eq!(m["Y"].1, RefOwn::Ref(&Value::U(2))); - assert!(matcher.next().is_none()); -} - -#[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 preds = vec![("d", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); - let pat = datafu::Pattern::::compile::<&str, &str>("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", Some(preds), None).unwrap(); - let mut matcher = pat.attempt_match(&tree); - let m = matcher.next().unwrap().unwrap(); - assert_eq!(m["P"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); - assert_eq!(m["U"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); - assert_eq!(m["B"].0, RefOwn::Ref(&Value::from("HEAD"))); - assert_eq!(m["B"].1, RefOwn::Ref(&Value::M(vec![(Value::from("active"), Value::B(true))].into_iter().collect()))); - assert!(matcher.next().is_none()); + let mut der = JsonDer::from_str(r#"{"foo": 1, "bar": {"baz": 2}}"#); + let preds = vec![("dict", datafu::pred(|v| { todo!() }))].into_iter().collect(); + let pat = datafu::Pattern::<()>::compile::<&str, &str>("->[x]:?$dict->y[yk]", Some(preds), None).unwrap(); + #[derive(Deserialize)] + struct Values { + x: String, + yk: String, + y: usize, + } + // should this error about needing multiple results/Vec requirement? + let matches: Values = pat.deserialize(&mut der).unwrap(); + assert_eq!(matches.x, "bar"); + assert_eq!(matches.yk, "baz"); + assert_eq!(matches.y, 2); + assert!(der.end().is_ok()); } -#[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 preds = vec![("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); - let pat = datafu::Pattern::::compile::<_, &str>(" - -> 'projects'? - -> commit /[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/? :?$dict - -> url :?$dict - -> branch :?$dict", - Some(preds), - None, - ).unwrap(); - let mut matcher = pat.attempt_match(&tree); - let m = matcher.next().unwrap().unwrap(); - assert_eq!(m["commit"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); - assert_eq!(m["url"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); - assert_eq!(m["branch"].0, RefOwn::Ref(&Value::from("HEAD"))); - assert_eq!(m["branch"].1, RefOwn::Ref(&Value::M(vec![(Value::from("active"), Value::B(true))].into_iter().collect()))); - assert!(matcher.next().is_none()); -} - -#[test] -fn test_harder() { - 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 preds = vec![ - ("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>), - ("str", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), - ("bool", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::B(_)))) as Box>), - // stubs, we don't particularly need to test these - ("commit", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), - ("uri", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), - ].into_iter().collect(); - let pat = datafu::Pattern::::compile::<_, &str>(" - ->'projects':$dict - ->commit[:?$str:?$commit]:?$dict - ->url[:?$str:?$uri]:?$dict - ->branch:?$dict - (->active'active'?:?$bool) - (->federate'federate'?:?$bool)?", - Some(preds), - None, - ).unwrap(); - let mut matcher = pat.attempt_match(&tree); - let m = matcher.next().unwrap().unwrap(); - assert_eq!(m["commit"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); - assert_eq!(m["url"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); - assert_eq!(m["branch"].0, RefOwn::Ref(&Value::from("HEAD"))); - assert_eq!(m["active"].1, RefOwn::Ref(&Value::B(true))); - assert_eq!(m.get("federate"), None); - assert!(matcher.next().is_none()); -} +//#[test] +//fn test_str() { +// //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 der = JsonDer::from_str(r#"{"foo": 1, "bar": {"baz": 2}}"#) +// let preds = vec![("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); +// let pat = datafu::Pattern::::compile::<&str, &str>("->X'bar'->Y", Some(preds), None).unwrap(); +// let mut matcher = pat.attempt_match(&tree); +// let m = matcher.next().unwrap().unwrap(); +// assert_eq!(m["X"].0, RefOwn::Ref(&Value::from("bar"))); +// assert_eq!(m["Y"].0, RefOwn::Ref(&Value::from("baz"))); +// assert_eq!(m["Y"].1, RefOwn::Ref(&Value::U(2))); +// assert!(matcher.next().is_none()); +//} +// +//#[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 preds = vec![("d", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); +// let pat = datafu::Pattern::::compile::<&str, &str>("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", Some(preds), None).unwrap(); +// let mut matcher = pat.attempt_match(&tree); +// let m = matcher.next().unwrap().unwrap(); +// assert_eq!(m["P"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); +// assert_eq!(m["U"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); +// assert_eq!(m["B"].0, RefOwn::Ref(&Value::from("HEAD"))); +// assert_eq!(m["B"].1, RefOwn::Ref(&Value::M(vec![(Value::from("active"), Value::B(true))].into_iter().collect()))); +// assert!(matcher.next().is_none()); +//} +// +//#[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 preds = vec![("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>)].into_iter().collect(); +// let pat = datafu::Pattern::::compile::<_, &str>(" +// -> 'projects'? +// -> commit /[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/? :?$dict +// -> url :?$dict +// -> branch :?$dict", +// Some(preds), +// None, +// ).unwrap(); +// let mut matcher = pat.attempt_match(&tree); +// let m = matcher.next().unwrap().unwrap(); +// assert_eq!(m["commit"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); +// assert_eq!(m["url"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); +// assert_eq!(m["branch"].0, RefOwn::Ref(&Value::from("HEAD"))); +// assert_eq!(m["branch"].1, RefOwn::Ref(&Value::M(vec![(Value::from("active"), Value::B(true))].into_iter().collect()))); +// assert!(matcher.next().is_none()); +//} +// +//#[test] +//fn test_harder() { +// 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 preds = vec![ +// ("dict", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::M(_)))) as Box>), +// ("str", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), +// ("bool", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::B(_)))) as Box>), +// // stubs, we don't particularly need to test these +// ("commit", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), +// ("uri", Box::new(|v: RefOwn<'_, _, _>| matches!(v, RefOwn::Ref(&Value::S(_)))) as Box>), +// ].into_iter().collect(); +// let pat = datafu::Pattern::::compile::<_, &str>(" +// ->'projects':$dict +// ->commit[:?$str:?$commit]:?$dict +// ->url[:?$str:?$uri]:?$dict +// ->branch:?$dict +// (->active'active'?:?$bool) +// (->federate'federate'?:?$bool)?", +// Some(preds), +// None, +// ).unwrap(); +// let mut matcher = pat.attempt_match(&tree); +// let m = matcher.next().unwrap().unwrap(); +// assert_eq!(m["commit"].0, RefOwn::Ref(&Value::from("385e734a52e13949a7a5c71827f6de920dbfea43"))); +// assert_eq!(m["url"].0, RefOwn::Ref(&Value::from("https://soniex2.autistic.space/git-repos/ganarchy.git"))); +// assert_eq!(m["branch"].0, RefOwn::Ref(&Value::from("HEAD"))); +// assert_eq!(m["active"].1, RefOwn::Ref(&Value::B(true))); +// assert_eq!(m.get("federate"), None); +// assert!(matcher.next().is_none()); +//} diff --git a/tests/common/mod.rs b/tests/common/mod.rs deleted file mode 100644 index d0b9e89..0000000 --- a/tests/common/mod.rs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * 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 . - */ - -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, Debug)] -pub enum Value { - U(usize), - B(bool), - M(BTreeMap), - S(Cow<'static, str>), -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -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 for Value { - fn eq(&self, other: &str) -> bool { - matches!(self, Value::S(l) if l == other) - } -} - -impl PartialEq for str { - fn eq(&self, other: &Value) -> bool { - matches!(other, Value::S(r) if self == r) - } -} - -impl PartialEq for Value { - fn eq(&self, other: &Dummy) -> bool { - let _ = other; - unreachable!() - } -} - -impl PartialEq for Dummy { - fn eq(&self, other: &Value) -> bool { - let _ = other; - unreachable!() - } -} - -impl PartialEq for Dummy { - fn eq(&self, other: &str) -> bool { - let _ = other; - unreachable!() - } -} - -impl PartialEq for str { - fn eq(&self, other: &Dummy) -> bool { - let _ = other; - 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 { - 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 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> + '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>> { - match item { - RefOwn::Ref(Value::M(map)) => { - Some(match key { - RefOwn::Ref(key) => map.get_key_value(key), - RefOwn::Own(_key) => unreachable!(), - 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 - } - - fn as_str<'b>( - item: RefOwn<'b, Self, Dummy> - ) -> Option<&'b str> { - match item { - RefOwn::Str(key) => Some(key), - RefOwn::Ref(Value::S(key)) => Some(key), - _ => None, - } - } -} diff --git a/tests/parser_prop.rs b/tests/parser_prop.rs index 57976cb..0b57171 100644 --- a/tests/parser_prop.rs +++ b/tests/parser_prop.rs @@ -1,33 +1,11 @@ -/* - * 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 . - */ - -extern crate proptest; -extern crate datafu; - -mod common; - -use common::Value; +// Copyright (C) 2021 Soni L. +// SPDX-License-Identifier: MIT OR Apache-2.0 use proptest::prelude::*; proptest! { #[test] fn doesnt_panic(s in "\\PC*") { - let _ = datafu::Pattern::::compile::<&str, &str>(&s, None, None); + let _ = datafu::Pattern::>::compile::<&str, &str>(&s, None, None); } } -- cgit 1.4.1