1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-16 18:01:37 +00:00

Update vendor dependencies

This commit is contained in:
Frédéric Guillot 2018-07-06 21:18:14 -07:00
parent 34a3fe426b
commit 459bb4531f
747 changed files with 89857 additions and 39711 deletions

View file

@ -79,7 +79,7 @@ result. Next will return Done when the iterator is exhausted.
Search takes a string query to determine which documents to return. The query
can be simple, such as a single word to match, or complex. The query
language is described at
https://cloud.google.com/appengine/docs/go/search/query_strings
https://cloud.google.com/appengine/docs/standard/go/search/query_strings
Search also takes an optional SearchOptions struct which gives much more
control over how results are calculated and returned.

View file

@ -29,6 +29,8 @@ import (
pb "google.golang.org/appengine/internal/search"
)
const maxDocumentsPerPutDelete = 200
var (
// ErrInvalidDocumentType is returned when methods like Put, Get or Next
// are passed a dst or src argument of invalid type.
@ -36,6 +38,10 @@ var (
// ErrNoSuchDocument is returned when no document was found for a given ID.
ErrNoSuchDocument = errors.New("search: no such document")
// ErrTooManyDocuments is returned when the user passes too many documents to
// PutMulti or DeleteMulti.
ErrTooManyDocuments = fmt.Errorf("search: too many documents given to put or delete (max is %d)", maxDocumentsPerPutDelete)
)
// Atom is a document field whose contents are indexed as a single indivisible
@ -120,39 +126,78 @@ func Open(name string) (*Index, error) {
// src must be a non-nil struct pointer or implement the FieldLoadSaver
// interface.
func (x *Index) Put(c context.Context, id string, src interface{}) (string, error) {
d, err := saveDoc(src)
ids, err := x.PutMulti(c, []string{id}, []interface{}{src})
if err != nil {
return "", err
}
if id != "" {
if !validIndexNameOrDocID(id) {
return "", fmt.Errorf("search: invalid ID %q", id)
}
d.Id = proto.String(id)
return ids[0], nil
}
// PutMulti is like Put, but is more efficient for adding multiple documents to
// the index at once.
//
// Up to 200 documents can be added at once. ErrTooManyDocuments is returned if
// you try to add more.
//
// ids can either be an empty slice (which means new IDs will be allocated for
// each of the documents added) or a slice the same size as srcs.
//
// The error may be an instance of appengine.MultiError, in which case it will
// be the same size as srcs and the individual errors inside will correspond
// with the items in srcs.
func (x *Index) PutMulti(c context.Context, ids []string, srcs []interface{}) ([]string, error) {
if len(ids) != 0 && len(srcs) != len(ids) {
return nil, fmt.Errorf("search: PutMulti expects ids and srcs slices of the same length")
}
if len(srcs) > maxDocumentsPerPutDelete {
return nil, ErrTooManyDocuments
}
docs := make([]*pb.Document, len(srcs))
for i, s := range srcs {
var err error
docs[i], err = saveDoc(s)
if err != nil {
return nil, err
}
if len(ids) != 0 && ids[i] != "" {
if !validIndexNameOrDocID(ids[i]) {
return nil, fmt.Errorf("search: invalid ID %q", ids[i])
}
docs[i].Id = proto.String(ids[i])
}
}
// spec is modified by Call when applying the current Namespace, so copy it to
// avoid retaining the namespace beyond the scope of the Call.
spec := x.spec
req := &pb.IndexDocumentRequest{
Params: &pb.IndexDocumentParams{
Document: []*pb.Document{d},
Document: docs,
IndexSpec: &spec,
},
}
res := &pb.IndexDocumentResponse{}
if err := internal.Call(c, "search", "IndexDocument", req, res); err != nil {
return "", err
return nil, err
}
if len(res.Status) > 0 {
if s := res.Status[0]; s.GetCode() != pb.SearchServiceError_OK {
return "", fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail())
multiErr, hasErr := make(appengine.MultiError, len(res.Status)), false
for i, s := range res.Status {
if s.GetCode() != pb.SearchServiceError_OK {
multiErr[i] = fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail())
hasErr = true
}
}
if len(res.Status) != 1 || len(res.DocId) != 1 {
return "", fmt.Errorf("search: internal error: wrong number of results (%d Statuses, %d DocIDs)",
len(res.Status), len(res.DocId))
if hasErr {
return res.DocId, multiErr
}
return res.DocId[0], nil
if len(res.Status) != len(docs) || len(res.DocId) != len(docs) {
return nil, fmt.Errorf("search: internal error: wrong number of results (%d Statuses, %d DocIDs, expected %d)",
len(res.Status), len(res.DocId), len(docs))
}
return res.DocId, nil
}
// Get loads the document with the given ID into dst.
@ -194,9 +239,22 @@ func (x *Index) Get(c context.Context, id string, dst interface{}) error {
// Delete deletes a document from the index.
func (x *Index) Delete(c context.Context, id string) error {
return x.DeleteMulti(c, []string{id})
}
// DeleteMulti deletes multiple documents from the index.
//
// The returned error may be an instance of appengine.MultiError, in which case
// it will be the same size as srcs and the individual errors inside will
// correspond with the items in srcs.
func (x *Index) DeleteMulti(c context.Context, ids []string) error {
if len(ids) > maxDocumentsPerPutDelete {
return ErrTooManyDocuments
}
req := &pb.DeleteDocumentRequest{
Params: &pb.DeleteDocumentParams{
DocId: []string{id},
DocId: ids,
IndexSpec: &x.spec,
},
}
@ -204,11 +262,19 @@ func (x *Index) Delete(c context.Context, id string) error {
if err := internal.Call(c, "search", "DeleteDocument", req, res); err != nil {
return err
}
if len(res.Status) != 1 {
return fmt.Errorf("search: internal error: wrong number of results (%d)", len(res.Status))
if len(res.Status) != len(ids) {
return fmt.Errorf("search: internal error: wrong number of results (%d, expected %d)",
len(res.Status), len(ids))
}
if s := res.Status[0]; s.GetCode() != pb.SearchServiceError_OK {
return fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail())
multiErr, hasErr := make(appengine.MultiError, len(ids)), false
for i, s := range res.Status {
if s.GetCode() != pb.SearchServiceError_OK {
multiErr[i] = fmt.Errorf("search: %s: %s", s.GetCode(), s.GetErrorDetail())
hasErr = true
}
}
if hasErr {
return multiErr
}
return nil
}
@ -438,7 +504,7 @@ type FieldExpression struct {
Name string
// Expr is evaluated to provide a custom content snippet for each document.
// See https://cloud.google.com/appengine/docs/go/search/options for
// See https://cloud.google.com/appengine/docs/standard/go/search/options for
// the supported expression syntax.
Expr string
}
@ -585,7 +651,7 @@ type SortOptions struct {
// SortExpression defines a single dimension for sorting a document.
type SortExpression struct {
// Expr is evaluated to provide a sorting value for each document.
// See https://cloud.google.com/appengine/docs/go/search/options for
// See https://cloud.google.com/appengine/docs/standard/go/search/options for
// the supported expression syntax.
Expr string
@ -863,8 +929,9 @@ func saveDoc(src interface{}) (*pb.Document, error) {
return nil, err
}
d := &pb.Document{
Field: fieldsProto,
OrderId: proto.Int32(int32(time.Since(orderIDEpoch).Seconds())),
Field: fieldsProto,
OrderId: proto.Int32(int32(time.Since(orderIDEpoch).Seconds())),
OrderIdSource: pb.Document_DEFAULTED.Enum(),
}
if meta != nil {
if meta.Rank != 0 {
@ -872,6 +939,7 @@ func saveDoc(src interface{}) (*pb.Document, error) {
return nil, fmt.Errorf("search: invalid rank %d, must be [0, 2^31)", meta.Rank)
}
*d.OrderId = int32(meta.Rank)
d.OrderIdSource = pb.Document_SUPPLIED.Enum()
}
if len(meta.Facets) > 0 {
facets, err := facetsToProto(meta.Facets)

View file

@ -169,6 +169,17 @@ func TestSaveDoc(t *testing.T) {
}
}
func TestSaveDocUsesDefaultedRankIfNotSpecified(t *testing.T) {
got, err := saveDoc(&searchDoc)
if err != nil {
t.Fatalf("saveDoc: %v", err)
}
orderIdSource := got.GetOrderIdSource()
if orderIdSource != pb.Document_DEFAULTED {
t.Errorf("OrderIdSource: got %v, wanted DEFAULTED", orderIdSource)
}
}
func TestLoadFieldList(t *testing.T) {
var got FieldList
want := searchFieldsWithLang
@ -183,7 +194,7 @@ func TestLoadFieldList(t *testing.T) {
func TestLangFields(t *testing.T) {
fl := &FieldList{
{Name: "Foo", Value: "I am English", Language: "en"},
{Name: "Bar", Value: "私は日本人だ", Language: "jp"},
{Name: "Bar", Value: "私は日本人だ", Language: "ja"},
}
var got FieldList
doc, err := saveDoc(fl)
@ -231,8 +242,9 @@ func TestLoadMeta(t *testing.T) {
Fields: searchFieldsWithLang,
}
doc := &pb.Document{
Field: protoFields,
OrderId: proto.Int32(42),
Field: protoFields,
OrderId: proto.Int32(42),
OrderIdSource: pb.Document_SUPPLIED.Enum(),
}
if err := loadDoc(&got, doc, nil); err != nil {
t.Fatalf("loadDoc: %v", err)
@ -251,8 +263,47 @@ func TestSaveMeta(t *testing.T) {
t.Fatalf("saveDoc: %v", err)
}
want := &pb.Document{
Field: protoFields,
OrderId: proto.Int32(42),
Field: protoFields,
OrderId: proto.Int32(42),
OrderIdSource: pb.Document_SUPPLIED.Enum(),
}
if !proto.Equal(got, want) {
t.Errorf("\ngot %v\nwant %v", got, want)
}
}
func TestSaveMetaWithDefaultedRank(t *testing.T) {
metaWithoutRank := &DocumentMetadata{
Rank: 0,
}
got, err := saveDoc(&FieldListWithMeta{
Meta: metaWithoutRank,
Fields: searchFields,
})
if err != nil {
t.Fatalf("saveDoc: %v", err)
}
want := &pb.Document{
Field: protoFields,
OrderId: got.OrderId,
OrderIdSource: pb.Document_DEFAULTED.Enum(),
}
if !proto.Equal(got, want) {
t.Errorf("\ngot %v\nwant %v", got, want)
}
}
func TestSaveWithoutMetaUsesDefaultedRank(t *testing.T) {
got, err := saveDoc(&FieldListWithMeta{
Fields: searchFields,
})
if err != nil {
t.Fatalf("saveDoc: %v", err)
}
want := &pb.Document{
Field: protoFields,
OrderId: got.OrderId,
OrderIdSource: pb.Document_DEFAULTED.Enum(),
}
if !proto.Equal(got, want) {
t.Errorf("\ngot %v\nwant %v", got, want)
@ -291,7 +342,8 @@ func TestLoadSaveWithStruct(t *testing.T) {
if err != nil {
t.Fatalf("saveDoc: %v", err)
}
gotPB.OrderId = nil // Don't test: it's time dependent.
gotPB.OrderId = nil // Don't test: it's time dependent.
gotPB.OrderIdSource = nil // Don't test because it's contingent on OrderId.
if !proto.Equal(gotPB, pb) {
t.Errorf("saving doc\ngot %v\nwant %v", gotPB, pb)
}
@ -486,7 +538,7 @@ func TestPut(t *testing.T) {
expectedIn := &pb.IndexDocumentRequest{
Params: &pb.IndexDocumentParams{
Document: []*pb.Document{
{Field: protoFields, OrderId: proto.Int32(42)},
{Field: protoFields, OrderId: proto.Int32(42), OrderIdSource: pb.Document_SUPPLIED.Enum()},
},
IndexSpec: &pb.IndexSpec{
Name: proto.String("Doc"),
@ -573,6 +625,101 @@ func TestPutBadStatus(t *testing.T) {
}
}
func TestPutMultiNilIDSlice(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "IndexDocument", func(in *pb.IndexDocumentRequest, out *pb.IndexDocumentResponse) error {
if len(in.Params.GetDocument()) < 1 {
return fmt.Errorf("got %v, want at least 1 document", in)
}
got, want := in.Params.Document[0].GetOrderId(), int32(time.Since(orderIDEpoch).Seconds())
if d := got - want; -5 > d || d > 5 {
return fmt.Errorf("got OrderId %d, want near %d", got, want)
}
*out = pb.IndexDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
},
DocId: []string{
"doc_id",
},
}
return nil
})
if _, err := index.PutMulti(c, nil, []interface{}{&searchFields}); err != nil {
t.Fatal(err)
}
}
func TestPutMultiError(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "IndexDocument", func(in *pb.IndexDocumentRequest, out *pb.IndexDocumentResponse) error {
*out = pb.IndexDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
{Code: pb.SearchServiceError_PERMISSION_DENIED.Enum(), ErrorDetail: proto.String("foo")},
},
DocId: []string{
"id1",
"",
},
}
return nil
})
switch _, err := index.PutMulti(c, nil, []interface{}{&searchFields, &searchFields}); {
case err == nil:
t.Fatalf("got nil, want error")
case err.(appengine.MultiError)[0] != nil:
t.Fatalf("got %v, want nil MultiError[0]", err.(appengine.MultiError)[0])
case err.(appengine.MultiError)[1] == nil:
t.Fatalf("got nil, want not-nill MultiError[1]")
}
}
func TestPutMultiWrongNumberOfIDs(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "IndexDocument", func(in *pb.IndexDocumentRequest, out *pb.IndexDocumentResponse) error {
return nil
})
if _, err := index.PutMulti(c, []string{"a"}, []interface{}{&searchFields, &searchFields}); err == nil {
t.Fatal("got success, want error")
}
}
func TestPutMultiTooManyDocs(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "IndexDocument", func(in *pb.IndexDocumentRequest, out *pb.IndexDocumentResponse) error {
return nil
})
srcs := make([]interface{}, 201)
for i, _ := range srcs {
srcs[i] = &searchFields
}
if _, err := index.PutMulti(c, nil, srcs); err != ErrTooManyDocuments {
t.Fatalf("got %v, want ErrTooManyDocuments", err)
}
}
func TestSortOptions(t *testing.T) {
index, err := Open("Doc")
if err != nil {
@ -998,3 +1145,126 @@ func TestNamespaceResetting(t *testing.T) {
t.Errorf(`Put with c2: ns = %q, want nil`, *ns)
}
}
func TestDelete(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "DeleteDocument", func(in *pb.DeleteDocumentRequest, out *pb.DeleteDocumentResponse) error {
expectedIn := &pb.DeleteDocumentRequest{
Params: &pb.DeleteDocumentParams{
DocId: []string{"id"},
IndexSpec: &pb.IndexSpec{Name: proto.String("Doc")},
},
}
if !proto.Equal(in, expectedIn) {
return fmt.Errorf("unsupported argument:\ngot %v\nwant %v", in, expectedIn)
}
*out = pb.DeleteDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
},
}
return nil
})
if err := index.Delete(c, "id"); err != nil {
t.Fatal(err)
}
}
func TestDeleteMulti(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "DeleteDocument", func(in *pb.DeleteDocumentRequest, out *pb.DeleteDocumentResponse) error {
expectedIn := &pb.DeleteDocumentRequest{
Params: &pb.DeleteDocumentParams{
DocId: []string{"id1", "id2"},
IndexSpec: &pb.IndexSpec{Name: proto.String("Doc")},
},
}
if !proto.Equal(in, expectedIn) {
return fmt.Errorf("unsupported argument:\ngot %v\nwant %v", in, expectedIn)
}
*out = pb.DeleteDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
{Code: pb.SearchServiceError_OK.Enum()},
},
}
return nil
})
if err := index.DeleteMulti(c, []string{"id1", "id2"}); err != nil {
t.Fatal(err)
}
}
func TestDeleteWrongNumberOfResults(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "DeleteDocument", func(in *pb.DeleteDocumentRequest, out *pb.DeleteDocumentResponse) error {
expectedIn := &pb.DeleteDocumentRequest{
Params: &pb.DeleteDocumentParams{
DocId: []string{"id1", "id2"},
IndexSpec: &pb.IndexSpec{Name: proto.String("Doc")},
},
}
if !proto.Equal(in, expectedIn) {
return fmt.Errorf("unsupported argument:\ngot %v\nwant %v", in, expectedIn)
}
*out = pb.DeleteDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
},
}
return nil
})
if err := index.DeleteMulti(c, []string{"id1", "id2"}); err == nil {
t.Fatalf("got nil, want error")
}
}
func TestDeleteMultiError(t *testing.T) {
index, err := Open("Doc")
if err != nil {
t.Fatalf("err from Open: %v", err)
}
c := aetesting.FakeSingleContext(t, "search", "DeleteDocument", func(in *pb.DeleteDocumentRequest, out *pb.DeleteDocumentResponse) error {
expectedIn := &pb.DeleteDocumentRequest{
Params: &pb.DeleteDocumentParams{
DocId: []string{"id1", "id2"},
IndexSpec: &pb.IndexSpec{Name: proto.String("Doc")},
},
}
if !proto.Equal(in, expectedIn) {
return fmt.Errorf("unsupported argument:\ngot %v\nwant %v", in, expectedIn)
}
*out = pb.DeleteDocumentResponse{
Status: []*pb.RequestStatus{
{Code: pb.SearchServiceError_OK.Enum()},
{Code: pb.SearchServiceError_PERMISSION_DENIED.Enum(), ErrorDetail: proto.String("foo")},
},
}
return nil
})
switch err := index.DeleteMulti(c, []string{"id1", "id2"}); {
case err == nil:
t.Fatalf("got nil, want error")
case err.(appengine.MultiError)[0] != nil:
t.Fatalf("got %v, want nil MultiError[0]", err.(appengine.MultiError)[0])
case err.(appengine.MultiError)[1] == nil:
t.Fatalf("got nil, want not-nill MultiError[1]")
}
}