// Copyright 2016 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// 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
}
