search: add EdgesTo handler and tests

This commit is contained in:
Brad Fitzpatrick 2012-11-05 15:09:34 +01:00
parent f696007a14
commit 832b774025
3 changed files with 111 additions and 0 deletions

View File

@ -137,6 +137,12 @@ func (id *IndexDeps) AddAttribute(permaNode *blobref.BlobRef, attr, value string
return id.uploadAndSignMap(m)
}
func (id *IndexDeps) DelAttribute(permaNode *blobref.BlobRef, attr string) *blobref.BlobRef {
m := schema.NewDelAttributeClaim(permaNode, attr)
m["claimDate"] = id.advanceTime()
return id.uploadAndSignMap(m)
}
func (id *IndexDeps) UploadFile(fileName string, contents string) (fileRef, wholeRef *blobref.BlobRef) {
cb := &test.Blob{Contents: contents}
id.BlobSource.AddBlob(cb)

View File

@ -123,6 +123,9 @@ func (sh *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
case "camli/search/signerpaths":
sh.serveSignerPaths(rw, req)
return
case "camli/search/edgesto":
sh.serveEdgesTo(rw, req)
return
}
}
@ -775,6 +778,81 @@ func (sh *Handler) serveSignerAttrValue(rw http.ResponseWriter, req *http.Reques
}
}
// Unlike the index interface's EdgesTo method, the "edgesto" Handler
// here additionally filters out since-deleted permanode edges.
func (sh *Handler) serveEdgesTo(rw http.ResponseWriter, req *http.Request) {
ret := jsonMap()
defer httputil.ReturnJSON(rw, ret)
defer setPanicError(ret)
toRef := blobref.MustParse(mustGet(req, "blobref"))
toRefStr := toRef.String()
blobInfo := jsonMap()
ret[toRefStr] = blobInfo
jsonEdges := jsonMapList()
edges, err := sh.index.EdgesTo(toRef, nil)
if err != nil {
panic(err)
}
type mapOrError struct {
m map[string]interface{} // nil if no map
err error
}
resc := make(chan mapOrError)
verify := func(edge *Edge) {
fromStr := edge.From.String()
db, err := sh.NewDescribeRequest().DescribeSync(edge.From)
if err != nil {
resc <- mapOrError{err: err}
return
}
found := false
if db.Permanode != nil {
for attr, vv := range db.Permanode.Attr {
if IsBlobReferenceAttribute(attr) {
for _, v := range vv {
if v == toRefStr {
found = true
}
}
}
}
}
var em map[string]interface{}
if found {
em = jsonMap()
em["from"] = fromStr
em["fromType"] = "permanode"
}
resc <- mapOrError{m: em}
}
verifying := 0
for _, edge := range edges {
if edge.FromType == "permanode" {
verifying++
go verify(edge)
continue
}
em := jsonMap()
em["from"] = edge.From.String()
em["fromType"] = edge.FromType
jsonEdges = append(jsonEdges, em)
}
for i := 0; i < verifying; i++ {
res := <-resc
if res.err != nil {
panic(res.err) // caught and put in JSON response
}
if res.m != nil {
jsonEdges = append(jsonEdges, res.m)
}
}
blobInfo["edgesTo"] = jsonEdges
}
func (sh *Handler) serveSignerPaths(rw http.ResponseWriter, req *http.Request) {
ret := jsonMap()
defer httputil.ReturnJSON(rw, ret)

View File

@ -165,6 +165,33 @@ var handlerTests = []handlerTest{
}
}`),
},
// edgeto handler: put a permanode (member) in two parent
// permanodes, then delete the second and verify that edges
// back from member only reveal the first parent.
{
setup: func(*test.FakeIndex) Index {
// Ignore the fakeindex and use the real (but in-memory) implementation,
// using IndexDeps to populate it.
idx := index.NewMemoryIndex()
id := indextest.NewIndexDeps(idx)
parent1 := id.NewPlannedPermanode("pn1") // sha1-7ca7743e38854598680d94ef85348f2c48a44513
parent2 := id.NewPlannedPermanode("pn2")
member := id.NewPlannedPermanode("member") // always sha1-9ca84f904a9bc59e6599a53f0a3927636a6dbcae
id.AddAttribute(parent1, "camliMember", member.String())
id.AddAttribute(parent2, "camliMember", member.String())
id.DelAttribute(parent2, "camliMember")
return indexAndOwner{idx, id.SignerBlobRef}
},
query: "edgesto?blobref=sha1-9ca84f904a9bc59e6599a53f0a3927636a6dbcae",
want: parseJSON(`{"sha1-9ca84f904a9bc59e6599a53f0a3927636a6dbcae": {
"edgesTo": [
{"from": "sha1-7ca7743e38854598680d94ef85348f2c48a44513",
"fromType": "permanode"}
]
}}`),
},
}
func TestHandler(t *testing.T) {