func TestDataAccessObjeToCell(t *testing.T) { n, p, l := testNodePredicateLiteral(t) testTable := []struct { o *triple.Object c *table.Cell }{ { o: triple.NewNodeObject(n), c: &table.Cell{N: n}, }, { o: triple.NewPredicateObject(p), c: &table.Cell{P: p}, }, { o: triple.NewLiteralObject(l), c: &table.Cell{L: l}, }, } for _, entry := range testTable { c, err := objectToCell(entry.o) if err != nil { t.Errorf("objecToCell for object %q failed with error %v", entry.o, err) } if got, want := c, entry.c; !reflect.DeepEqual(got, want) { t.Errorf("objectToCell failed to properly convert the object into a cell; got %#v, want %#v", got, want) } } }
// Issue 40 (https://github.com/google/badwolf/issues/40) func TestDataAccessSimpleFetchIssue40(t *testing.T) { testBindings, ctx := []string{"?itme", "?t"}, context.Background() n, err := node.Parse("/room<Bedroom>") if err != nil { t.Fatalf("node.Parse failed to parse \"/room<Bedroom>\", %v", err) } cls := &semantic.GraphClause{ SBinding: "?item", PID: "in", PAnchorBinding: "?t", O: triple.NewNodeObject(n), } g, err := getTestStore(t, testTemporalTriples).Graph(ctx, "?test") if err != nil { t.Fatal(err) } tbl, err := simpleFetch(ctx, []storage.Graph{g}, cls, &storage.LookupOptions{}, 0) if err != nil { t.Errorf("simpleFetch failed with errorf %v", err) } if got, want := len(tbl.Bindings()), len(testBindings); got != want { t.Errorf("simpleFetch returned a table with wrong bindings set; got %v, want %v", got, want) } if got, want := tbl.NumRows(), 1; got != want { t.Errorf("simpleFetch returned the wrong number of rows; got %d, want %d\n%s", got, want, tbl) } for _, r := range tbl.Rows() { if got, want := len(r), len(testBindings); got != want { t.Errorf("simpleFetch returned row %v with the incorrect number of bindings; got %d, want %d", r, got, want) } } }
// newTriple creates new triple using the provided node IDs. func (r *randomGraph) newTriple(i, j int) (*triple.Triple, error) { s, err := r.newNode(i) if err != nil { return nil, err } o, err := r.newNode(j) if err != nil { return nil, err } return triple.New(s, r.predicate, triple.NewNodeObject(o)) }
// cellToObject returns an object for the given cell. func cellToObject(c *table.Cell) (*triple.Object, error) { if c == nil { return nil, errors.New("cannot create an object out of and empty cell") } if c.N != nil { return triple.NewNodeObject(c.N), nil } if c.P != nil { return triple.NewPredicateObject(c.P), nil } if c.L != nil { return triple.NewLiteralObject(c.L), nil } if c.S != "" { l, err := literal.DefaultBuilder().Parse(fmt.Sprintf(`"%s"^^type:string`, c.S)) if err != nil { return nil, err } return triple.NewLiteralObject(l), nil } return nil, fmt.Errorf("invalid cell %v", c) }
func TestWhereObjectClauseHook(t *testing.T) { st := &Statement{} f := whereObjectClause() st.ResetWorkingGraphClause() node, err := node.Parse("/_<foo>") if err != nil { t.Fatalf("node.Parse failed with error %v", err) } n := triple.NewNodeObject(node) pred, err := predicate.Parse(`"foo"@[2015-07-19T13:12:04.669618843-07:00]`) if err != nil { t.Fatalf("predicate.Parse failed with error %v", err) } p := triple.NewPredicateObject(pred) tlb, err := time.Parse(time.RFC3339Nano, `2015-07-19T13:12:04.669618843-07:00`) if err != nil { t.Fatalf("time.Parse failed to parse valid lower time bound with error %v", err) } tub, err := time.Parse(time.RFC3339Nano, `2016-07-19T13:12:04.669618843-07:00`) if err != nil { t.Fatalf("time.Parse failed to parse valid upper time bound with error %v", err) } l, err := triple.ParseObject(`"1"^^type:int64`, literal.DefaultBuilder()) if err != nil { t.Fatalf("literal.Parse should have never fail to pars %s with error %v", `"1"^^type:int64`, err) } runTabulatedClauseHookTest(t, "semantic.whereObjectClause", f, []testClauseTable{ { valid: true, id: "node_example", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemNode, Text: "/_<foo>", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemType, Text: "type", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ O: n, OAlias: "?bar", OTypeAlias: "?bar2", OIDAlias: "?bar3", }, }, { valid: true, id: "binding_example", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?foo", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemType, Text: "type", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ OBinding: "?foo", OAlias: "?bar", OTypeAlias: "?bar2", OIDAlias: "?bar3", }, }, { valid: true, id: "valid predicate", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemPredicate, Text: `"foo"@[2015-07-19T13:12:04.669618843-07:00]`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAt, Text: "at", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ O: p, OAlias: "?bar", OIDAlias: "?bar2", OAnchorAlias: "?bar3", OTemporal: true, }, }, { valid: true, id: "valid predicate with binding", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemPredicate, Text: `"foo"@[?foo]`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAt, Text: "at", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ OID: "foo", OAnchorBinding: "?foo", OAlias: "?bar", OIDAlias: "?bar2", OAnchorAlias: "?bar3", OTemporal: true, }, }, { valid: true, id: "valid bound with bindings", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemPredicateBound, Text: `"foo"@[?fooLower,?fooUpper]`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAt, Text: "at", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ OID: "foo", OLowerBoundAlias: "?fooLower", OUpperBoundAlias: "?fooUpper", OAlias: "?bar", OIDAlias: "?bar2", OAnchorAlias: "?bar3", OTemporal: true, }, }, { valid: true, id: "valid bound with dates", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemPredicateBound, Text: `"foo"@[2015-07-19T13:12:04.669618843-07:00,2016-07-19T13:12:04.669618843-07:00]`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAt, Text: "at", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ OID: "foo", OLowerBound: &tlb, OUpperBound: &tub, OAlias: "?bar", OIDAlias: "?bar2", OAnchorAlias: "?bar3", OTemporal: true, }, }, { valid: false, id: "invalid bound with dates", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemPredicateBound, Text: `"foo"@[2016-07-19T13:12:04.669618843-07:00,2015-07-19T13:12:04.669618843-07:00]`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedToken(&lexer.Token{ Type: lexer.ItemID, Text: "id", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar2", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAt, Text: "at", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar3", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{}, }, { valid: true, id: "literal with alias", ces: []ConsumedElement{ NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemLiteral, Text: `"1"^^type:int64`, }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemAs, Text: "as", }), NewConsumedSymbol("FOO"), NewConsumedToken(&lexer.Token{ Type: lexer.ItemBinding, Text: "?bar", }), NewConsumedSymbol("FOO"), }, want: &GraphClause{ O: l, OAlias: "?bar"}, }, }) }
// newTriple creates a new triple given the parent and the descendant as an object. func (t *treeGenerator) newTriple(parent, descendant *node.Node) (*triple.Triple, error) { return triple.New(parent, t.predicate, triple.NewNodeObject(descendant)) }