g1-common 0.1.0-alpha.3

Common types and traits between the client and server portion of the G1 graph store.
use crate::query::{Clause, Predicate, Query, Value};
use pretty_assertions::assert_eq;
use proptest::{arbitrary::any, proptest};

proptest! {
    #[test]
    fn idempotent_parse_tostring_value(v in any::<Value>()) {
        let s = v.to_string();
        let v2 = s.parse().unwrap();
        assert_eq!(v, v2);
    }

    #[test]
    fn idempotent_parse_tostring_predicate(p in any::<Predicate>()) {
        let s = p.to_string();
        let p2 = s.parse().unwrap();
        assert_eq!(p, p2);
    }

    #[test]
    fn idempotent_parse_tostring_clause(c in any::<Clause>()) {
        let s = c.to_string();
        let c2 = s.parse().unwrap();
        assert_eq!(c, c2);
    }

    #[test]
    fn idempotent_parse_tostring_query(q in any::<Query>()) {
        let s = q.to_string();
        let q2 = s.parse().unwrap();
        assert_eq!(q, q2);
    }
}

#[test]
fn idempotent_parse_tostring_query_example() {
    let q = Query {
        clauses: vec![
            Clause {
                head: Predicate {
                    name: "edge".to_string(),
                    args: vec![Value::Str("A".to_string()), Value::Str("B".to_string())],
                },
                body: Vec::new(),
            },
            Clause {
                head: Predicate {
                    name: "edge".to_string(),
                    args: vec![Value::Str("A".to_string()), Value::Str("C".to_string())],
                },
                body: Vec::new(),
            },
            Clause {
                head: Predicate {
                    name: "edge".to_string(),
                    args: vec![Value::Str("B".to_string()), Value::Str("C".to_string())],
                },
                body: Vec::new(),
            },
            Clause {
                head: Predicate {
                    name: "path".to_string(),
                    args: vec![Value::Var("X".to_string()), Value::Var("X".to_string())],
                },
                body: Vec::new(),
            },
            Clause {
                head: Predicate {
                    name: "path".to_string(),
                    args: vec![Value::Var("X".to_string()), Value::Var("Z".to_string())],
                },
                body: vec![
                    (
                        false,
                        Predicate {
                            name: "path".to_string(),
                            args: vec![Value::Var("X".to_string()), Value::Var("Y".to_string())],
                        },
                    ),
                    (
                        false,
                        Predicate {
                            name: "edge".to_string(),
                            args: vec![Value::Var("Y".to_string()), Value::Var("Z".to_string())],
                        },
                    ),
                ],
            },
        ],
        goal: Predicate {
            name: "path".to_string(),
            args: vec![Value::Str("A".to_string()), Value::Var("X".to_string())],
        },
    };

    let s = q.to_string();
    let q2 = s.parse().unwrap();
    assert_eq!(q, q2);

    let s2 = r#"edge("A", "B").
edge("A", "C").
edge("B", "C").
path(X, X).
path(X, Z) :-
    path(X, Y),
    edge(Y, Z).
?- path("A", X)."#;
    assert_eq!(s, s2);
}