forked from TrueCloudLab/rclone
Switch to using the dep tool and update all the dependencies
This commit is contained in:
parent
5135ff73cb
commit
98c2d2c41b
5321 changed files with 4483201 additions and 5922 deletions
187
vendor/google.golang.org/api/iterator/testing/testing.go
generated
vendored
Normal file
187
vendor/google.golang.org/api/iterator/testing/testing.go
generated
vendored
Normal file
|
@ -0,0 +1,187 @@
|
|||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package testing provides support functions for testing iterators conforming
|
||||
// to the standard pattern.
|
||||
// See package google.golang.org/api/iterator and
|
||||
// https://github.com/GoogleCloudPlatform/gcloud-golang/wiki/Iterator-Guidelines.
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"google.golang.org/api/iterator"
|
||||
)
|
||||
|
||||
// TestIterator tests the Next method of a standard iterator. It assumes that
|
||||
// the underlying sequence to be iterated over already exists.
|
||||
//
|
||||
// The want argument should be a slice that contains the elements of this
|
||||
// sequence. It may be an empty slice, but it must not be the nil interface
|
||||
// value. The elements must be comparable with reflect.DeepEqual.
|
||||
//
|
||||
// The create function should create and return a new iterator.
|
||||
// It will typically look like
|
||||
// func() interface{} { return client.Items(ctx) }
|
||||
//
|
||||
// The next function takes the return value of create and should return the
|
||||
// result of calling Next on the iterator. It can usually be defined as
|
||||
// func(it interface{}) (interface{}, error) { return it.(*ItemIterator).Next() }
|
||||
//
|
||||
// TestIterator checks that the iterator returns all the elements of want
|
||||
// in order, followed by (zero, done). It also confirms that subsequent calls
|
||||
// to next also return (zero, done).
|
||||
//
|
||||
// If the iterator implements the method
|
||||
// PageInfo() *iterator.PageInfo
|
||||
// then exact pagination with iterator.Pager is also tested. Pagination testing
|
||||
// will be more informative if the want slice contains at least three elements.
|
||||
//
|
||||
// On success, TestIterator returns ("", true). On failure, it returns a
|
||||
// suitable error message and false.
|
||||
func TestIterator(want interface{}, create func() interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
|
||||
vWant := reflect.ValueOf(want)
|
||||
if vWant.Kind() != reflect.Slice {
|
||||
return "'want' must be a slice", false
|
||||
}
|
||||
it := create()
|
||||
msg, ok := testNext(vWant, it, next)
|
||||
if !ok {
|
||||
return msg, ok
|
||||
}
|
||||
if _, ok := it.(iterator.Pageable); !ok || vWant.Len() == 0 {
|
||||
return "", true
|
||||
}
|
||||
return testPaging(vWant, create, next)
|
||||
}
|
||||
|
||||
// Check that the iterator returns vWant, the desired sequence.
|
||||
func testNext(vWant reflect.Value, it interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
|
||||
for i := 0; i < vWant.Len(); i++ {
|
||||
got, err := next(it)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("#%d: got %v, expected an item", i, err), false
|
||||
}
|
||||
w := vWant.Index(i).Interface()
|
||||
if !reflect.DeepEqual(got, w) {
|
||||
return fmt.Sprintf("#%d: got %+v, want %+v", i, got, w), false
|
||||
}
|
||||
}
|
||||
// We now should see (<zero value of item type>, done), no matter how many
|
||||
// additional calls we make.
|
||||
zero := reflect.Zero(vWant.Type().Elem()).Interface()
|
||||
for i := 0; i < 3; i++ {
|
||||
got, err := next(it)
|
||||
if err != iterator.Done {
|
||||
return fmt.Sprintf("at end: got error %v, want iterator.Done", err), false
|
||||
}
|
||||
// Since err == iterator.Done, got should be zero.
|
||||
if got != zero {
|
||||
return fmt.Sprintf("got %+v with done, want zero %T", got, zero), false
|
||||
}
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
// Test the iterator's behavior when used with iterator.Pager.
|
||||
func testPaging(vWant reflect.Value, create func() interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
|
||||
// Test page sizes that are smaller, equal to, and greater than the length
|
||||
// of the expected sequence.
|
||||
for _, pageSize := range []int{1, 2, vWant.Len(), vWant.Len() + 10} {
|
||||
wantPages := wantedPages(vWant, pageSize)
|
||||
// Test the Pager in two ways.
|
||||
// First, by creating a single Pager and calling NextPage in a loop,
|
||||
// ignoring the page token except for detecting the end of the
|
||||
// iteration.
|
||||
it := create().(iterator.Pageable)
|
||||
pager := iterator.NewPager(it, pageSize, "")
|
||||
msg, ok := testPager(fmt.Sprintf("ignore page token, pageSize %d", pageSize),
|
||||
vWant.Type(), wantPages,
|
||||
func(_ string, pagep interface{}) (string, error) {
|
||||
return pager.NextPage(pagep)
|
||||
})
|
||||
if !ok {
|
||||
return msg, false
|
||||
}
|
||||
// Second, by creating a new Pager for each page, passing in the page
|
||||
// token from the previous page, as would be done in a web handler.
|
||||
it = create().(iterator.Pageable)
|
||||
msg, ok = testPager(fmt.Sprintf("use page token, pageSize %d", pageSize),
|
||||
vWant.Type(), wantPages,
|
||||
func(pageToken string, pagep interface{}) (string, error) {
|
||||
return iterator.NewPager(it, pageSize, pageToken).NextPage(pagep)
|
||||
})
|
||||
if !ok {
|
||||
return msg, false
|
||||
}
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
// Create the pages we expect to see.
|
||||
func wantedPages(vWant reflect.Value, pageSize int) []interface{} {
|
||||
var pages []interface{}
|
||||
for i, j := 0, pageSize; i < vWant.Len(); i, j = j, j+pageSize {
|
||||
if j > vWant.Len() {
|
||||
j = vWant.Len()
|
||||
}
|
||||
pages = append(pages, vWant.Slice(i, j).Interface())
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
func testPager(prefix string, sliceType reflect.Type, wantPages []interface{},
|
||||
nextPage func(pageToken string, pagep interface{}) (string, error)) (string, bool) {
|
||||
tok := ""
|
||||
var err error
|
||||
for i := 0; i < len(wantPages)+1; i++ {
|
||||
vpagep := reflect.New(sliceType)
|
||||
tok, err = nextPage(tok, vpagep.Interface())
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%s, page #%d: got error %v", prefix, i, err), false
|
||||
}
|
||||
if i == len(wantPages) {
|
||||
// Allow one empty page at the end.
|
||||
if vpagep.Elem().Len() != 0 || tok != "" {
|
||||
return fmt.Sprintf("%s: did not get one empty page at end", prefix), false
|
||||
}
|
||||
break
|
||||
}
|
||||
if msg, ok := compareSlices(vpagep.Elem(), reflect.ValueOf(wantPages[i])); !ok {
|
||||
return fmt.Sprintf("%s, page #%d:\n%s", prefix, i, msg), false
|
||||
}
|
||||
if tok == "" {
|
||||
if i != len(wantPages)-1 {
|
||||
return fmt.Sprintf("%s, page #%d: got empty page token", prefix, i), false
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
// Compare two slices element-by-element. If they are equal, return ("", true).
|
||||
// Otherwise, return a description of the difference and false.
|
||||
func compareSlices(vgot, vwant reflect.Value) (string, bool) {
|
||||
if got, want := vgot.Len(), vwant.Len(); got != want {
|
||||
return fmt.Sprintf("got %d items, want %d", got, want), false
|
||||
}
|
||||
for i := 0; i < vgot.Len(); i++ {
|
||||
if got, want := vgot.Index(i).Interface(), vwant.Index(i).Interface(); !reflect.DeepEqual(got, want) {
|
||||
return fmt.Sprintf("got[%d] = %+v\nwant = %+v", i, got, want), false
|
||||
}
|
||||
}
|
||||
return "", true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue