func TestNewGraph(t *testing.T) { var ex uint64 ex = 101 sg, err := NewGraph(ex, "") if err != nil { t.Error(err) } uo := flatbuffers.GetUOffsetT(sg.result) r := new(task.Result) r.Init(sg.result, uo) if r.UidmatrixLength() != 1 { t.Errorf("Expected length 1. Got: %v", r.UidmatrixLength()) } var ul task.UidList if ok := r.Uidmatrix(&ul, 0); !ok { t.Errorf("Unable to parse uidlist at index 0") } if ul.UidsLength() != 1 { t.Errorf("Expected length 1. Got: %v", ul.UidsLength()) } if ul.Uids(0) != ex { t.Errorf("Expected uid: %v. Got: %v", ex, ul.Uids(0)) } }
func sortedUniqueUids(r *task.Result) (sorted []uint64, rerr error) { // Let's serialize the matrix of uids in result to a // sorted unique list of uids. h := &x.Uint64Heap{} heap.Init(h) channels := make([]*ListChannel, r.UidmatrixLength()) for i := 0; i < r.UidmatrixLength(); i++ { tlist := new(task.UidList) if ok := r.Uidmatrix(tlist, i); !ok { return sorted, fmt.Errorf("While parsing Uidmatrix") } if tlist.UidsLength() > 0 { e := x.Elem{ Uid: tlist.Uids(0), Idx: i, } heap.Push(h, e) } channels[i] = &ListChannel{TList: tlist, Idx: 1} } // The resulting list of uids will be stored here. sorted = make([]uint64, 100) sorted = sorted[:0] var last uint64 last = 0 // Itearate over the heap. for h.Len() > 0 { me := (*h)[0] // Peek at the top element in heap. if me.Uid != last { sorted = append(sorted, me.Uid) // Add if unique. last = me.Uid } lc := channels[me.Idx] if lc.Idx >= lc.TList.UidsLength() { heap.Pop(h) } else { uid := lc.TList.Uids(lc.Idx) lc.Idx += 1 me.Uid = uid (*h)[0] = me heap.Fix(h, 0) // Faster than Pop() followed by Push(). } } return sorted, nil }
func check(r *task.Result, idx int, expected []uint64) error { var m task.UidList if ok := r.Uidmatrix(&m, idx); !ok { return fmt.Errorf("Unable to retrieve uidlist") } if m.UidsLength() != len(expected) { return fmt.Errorf("Expected length: %v. Got: %v", len(expected), m.UidsLength()) } for i, uid := range expected { if m.Uids(i) != uid { return fmt.Errorf("Uid mismatch at index: %v. Expected: %v. Got: %v", i, uid, m.Uids(i)) } } return nil }
func TestNewGraph(t *testing.T) { var ex uint64 ex = 101 dir, err := ioutil.TempDir("", "storetest_") if err != nil { t.Error(err) return } ps := new(store.Store) ps.Init(dir) sg, err := newGraph(ex, "", ps) if err != nil { t.Error(err) } worker.Init(ps) uo := flatbuffers.GetUOffsetT(sg.result) r := new(task.Result) r.Init(sg.result, uo) if r.UidmatrixLength() != 1 { t.Errorf("Expected length 1. Got: %v", r.UidmatrixLength()) } var ul task.UidList if ok := r.Uidmatrix(&ul, 0); !ok { t.Errorf("Unable to parse uidlist at index 0") } if ul.UidsLength() != 1 { t.Errorf("Expected length 1. Got: %v", ul.UidsLength()) } if ul.Uids(0) != ex { t.Errorf("Expected uid: %v. Got: %v", ex, ul.Uids(0)) } }
func postTraverse(g *SubGraph) (result map[uint64]interface{}, rerr error) { if len(g.query) == 0 { return result, nil } result = make(map[uint64]interface{}) // Get results from all children first. cResult := make(map[uint64]interface{}) for _, child := range g.Children { m, err := postTraverse(child) if err != nil { x.Err(glog, err).Error("Error while traversal") return result, err } // Merge results from all children, one by one. for k, v := range m { if val, present := cResult[k]; !present { cResult[k] = v } else { cResult[k] = mergeInterfaces(val, v) } } } // Now read the query and results at current node. uo := flatbuffers.GetUOffsetT(g.query) q := new(task.Query) q.Init(g.query, uo) ro := flatbuffers.GetUOffsetT(g.result) r := new(task.Result) r.Init(g.result, ro) if q.UidsLength() != r.UidmatrixLength() { glog.Fatal("Result uidmatrixlength: %v. Query uidslength: %v", r.UidmatrixLength(), q.UidsLength()) } if q.UidsLength() != r.ValuesLength() { glog.Fatalf("Result valuelength: %v. Query uidslength: %v", r.ValuesLength(), q.UidsLength()) } var ul task.UidList for i := 0; i < r.UidmatrixLength(); i++ { if ok := r.Uidmatrix(&ul, i); !ok { return result, fmt.Errorf("While parsing UidList") } l := make([]interface{}, ul.UidsLength()) for j := 0; j < ul.UidsLength(); j++ { uid := ul.Uids(j) m := make(map[string]interface{}) m["_uid_"] = fmt.Sprintf("%#x", uid) if ival, present := cResult[uid]; !present { l[j] = m } else { l[j] = mergeInterfaces(m, ival) } } if len(l) > 0 { m := make(map[string]interface{}) m[g.Attr] = l result[q.Uids(i)] = m } } var tv task.Value for i := 0; i < r.ValuesLength(); i++ { if ok := r.Values(&tv, i); !ok { return result, fmt.Errorf("While parsing value") } var ival interface{} if err := posting.ParseValue(&ival, tv.ValBytes()); err != nil { return result, err } if ival == nil { continue } if pval, present := result[q.Uids(i)]; present { glog.WithField("prev", pval). WithField("_uid_", q.Uids(i)). WithField("new", ival). Fatal("Previous value detected.") } m := make(map[string]interface{}) m["_uid_"] = fmt.Sprintf("%#x", q.Uids(i)) glog.WithFields(logrus.Fields{ "_uid_": q.Uids(i), "val": ival, }).Debug("Got value") m[g.Attr] = ival result[q.Uids(i)] = m } return result, nil }
func TestProcessGraph(t *testing.T) { dir, ps := populateGraph(t) defer os.RemoveAll(dir) // Alright. Now we have everything set up. Let's create the query. query := ` { me(_uid_: 0x01) { friend { name } name gender status } } ` gq, _, err := gql.Parse(query) if err != nil { t.Error(err) } sg, err := ToSubGraph(gq, ps) if err != nil { t.Error(err) } ch := make(chan error) go ProcessGraph(sg, ch, ps) err = <-ch if err != nil { t.Error(err) } if len(sg.Children) != 4 { t.Errorf("Expected len 4. Got: %v", len(sg.Children)) } child := sg.Children[0] if child.Attr != "friend" { t.Errorf("Expected attr friend. Got: %v", child.Attr) } if len(child.result) == 0 { t.Errorf("Expected some result.") return } uo := flatbuffers.GetUOffsetT(child.result) r := new(task.Result) r.Init(child.result, uo) if r.UidmatrixLength() != 1 { t.Errorf("Expected 1 matrix. Got: %v", r.UidmatrixLength()) } var ul task.UidList if ok := r.Uidmatrix(&ul, 0); !ok { t.Errorf("While parsing uidlist") } if ul.UidsLength() != 5 { t.Errorf("Expected 5 friends. Got: %v", ul.UidsLength()) } if ul.Uids(0) != 23 || ul.Uids(1) != 24 || ul.Uids(2) != 25 || ul.Uids(3) != 31 || ul.Uids(4) != 101 { t.Errorf("Friend ids don't match") } if len(child.Children) != 1 || child.Children[0].Attr != "name" { t.Errorf("Expected attr name") } child = child.Children[0] uo = flatbuffers.GetUOffsetT(child.result) r.Init(child.result, uo) if r.ValuesLength() != 5 { t.Errorf("Expected 5 names of 5 friends") } checkName(t, r, 0, "Rick Grimes") checkName(t, r, 1, "Glenn Rhee") checkName(t, r, 2, "Daryl Dixon") checkName(t, r, 3, "Andrea") { var tv task.Value if ok := r.Values(&tv, 4); !ok { t.Error("Unable to retrieve value") } if tv.ValLength() != 1 || tv.ValBytes()[0] != 0x00 { t.Error("Expected a null byte") } } checkSingleValue(t, sg.Children[1], "name", "Michonne") checkSingleValue(t, sg.Children[2], "gender", "female") checkSingleValue(t, sg.Children[3], "status", "alive") }