You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: drivertest.go
    path of file: ./repos/go-cloud/docstore/drivertest
    
    the code of the file until where you have to start completion: // Copyright 2019 The Go Cloud Development Kit Authors
//
// 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
//
//     https://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 drivertest provides a conformance test for implementations of
// driver.
package drivertest // import "gocloud.dev/docstore/drivertest"

import (
	"context"
	"errors"
	"fmt"
	"io"
	"math"
	"reflect"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/google/go-cmp/cmp/cmpopts"
	"github.com/google/uuid"
	"gocloud.dev/docstore"
	"gocloud.dev/docstore/driver"
	"gocloud.dev/gcerrors"
	"google.golang.org/protobuf/proto"
	tspb "google.golang.org/protobuf/types/known/timestamppb"
)

// ByteArray is an array of 2 bytes.
type ByteArray [2]byte

// CollectionKind describes the kind of testing collection to create.
type CollectionKind int

const (
	// SingleKey is collection with a single primary key field of type string named
	// drivertest.KeyField.
	SingleKey CollectionKind = iota

	// TwoKey is a  collection that will consist entirely of HighScore structs (see below),
	// whose two primary key fields are "Game" and "Player", both strings. Use
	// drivertest.HighScoreKey as the key function.
	TwoKey

	// AltRev is a collection that behaves like a SingleKey collection, except
	// that the revision field should be drivertest.AlternateRevisionField.
	AltRev

	// NoRev is a collection whose documents will not have a revision field.
	NoRev
)

// Harness descibes the functionality test harnesses must provide to run
// conformance tests.
type Harness interface {
	// MakeCollection makes a driver.Collection for testing.
	MakeCollection(context.Context, CollectionKind) (driver.Collection, error)

	// BeforeDoTypes should return a list of values whose types are valid for the as
	// function given to BeforeDo. For example, if the driver converts Get actions
	// to *GetRequests and write actions to *WriteRequests, then BeforeDoTypes should
	// return []interface{}{&GetRequest{}, &WriteRequest{}}.
	// TODO(jba): consider splitting these by action kind.
	BeforeDoTypes() []interface{}

	// BeforeQueryTypes should return a list of values whose types are valid for the as
	// function given to BeforeQuery.
	BeforeQueryTypes() []interface{}

	// RevisionsEqual reports whether two revisions are equal.
	RevisionsEqual(rev1, rev2 interface{}) bool

	// Close closes resources used by the harness.
	Close()
}

// HarnessMaker describes functions that construct a harness for running tests.
// It is called exactly once per test; Harness.Close() will be called when the test is complete.
type HarnessMaker func(ctx context.Context, t *testing.T) (Harness, error)

// UnsupportedType is an enum for types not supported by native codecs. We chose
// to describe this negatively (types that aren't supported rather than types
// that are) to make the more inclusive cases easier to write. A driver can
// return nil for CodecTester.UnsupportedTypes, then add values from this enum
// one by one until all tests pass.
type UnsupportedType int

// These are known unsupported types by one or more driver. Each of them
// corresponses to an unsupported type specific test which if the driver
// actually supports.
const (
	// Native codec doesn't support any unsigned integer type
	Uint UnsupportedType = iota
	// Native codec doesn't support arrays
	Arrays
	// Native codec doesn't support full time precision
	NanosecondTimes
	// Native codec doesn't support [][]byte
	BinarySet
)

// CodecTester describes functions that encode and decode values using both the
// docstore codec for a driver, and that driver's own "native" codec.
type CodecTester interface {
	UnsupportedTypes() []UnsupportedType
	NativeEncode(interface{}) (interface{}, error)
	NativeDecode(value, dest interface{}) error
	DocstoreEncode(interface{}) (interface{}, error)
	DocstoreDecode(value, dest interface{}) error
}

// AsTest represents a test of As functionality.
type AsTest interface {
	// Name should return a descriptive name for the test.
	Name() string
	// CollectionCheck will be called to allow verification of Collection.As.
	CollectionCheck(coll *docstore.Collection) error
	// QueryCheck will be called after calling Query. It should call it.As and
	// verify the results.
	QueryCheck(it *docstore.DocumentIterator) error
	// ErrorCheck is called to allow verification of Collection.ErrorAs.
	ErrorCheck(c *docstore.Collection, err error) error
}

type verifyAsFailsOnNil struct{}

func (verifyAsFailsOnNil) Name() string {
	return "verify As returns false when passed nil"
}

func (verifyAsFailsOnNil) CollectionCheck(coll *docstore.Collection) error {
	if coll.As(nil) {
		return errors.New("want Collection.As to return false when passed nil")
	}
	return nil
}

func (verifyAsFailsOnNil) QueryCheck(it *docstore.DocumentIterator) error {
	if it.As(nil) {
		return errors.New("want DocumentIterator.As to return false when passed nil")
	}
	return nil
}

func (v verifyAsFailsOnNil) ErrorCheck(c *docstore.Collection, err error) (ret error) {
	defer func() {
		if recover() == nil {
			ret = errors.New("want ErrorAs to panic when passed nil")
		}
	}()
	c.ErrorAs(err, nil)
	return nil
}

// RunConformanceTests runs conformance tests for driver implementations of docstore.
func RunConformanceTests(t *testing
    
func testGetQuery(t *testing.T, _ Harness, coll *docstore.Collection) {
	ctx := context.Background()
	addHighScores(t, coll)

	// Query filters should have the same behavior when doing string and number
	// comparison.
	tests := []struct {
		name   string
		q      *docstore.Query
		fields []docstore.FieldPath       // fields to get
		want   func(*HighScore) bool      // filters highScores
		before func(x, y *HighScore) bool // if present, checks result order
	}{
		{
			name: "All",
			q:    coll.Query(),
			want: func(*HighScore) bool { return true },
		},
		{
			name: "Game",
			q:    coll.Query().Where("Game", "=", game2),
			want: func(h *HighScore) bool { return h.Game == game2 },
		},
		{
			name: "Score",
			q:    coll.Query().Where("Score", ">", 100),
			want: func(h *HighScore) bool { return h.Score > 100 },
		},
		{
			name: "Player",
			q:    coll.Query().Where("Player", "=", "billie"),
			want: func(h *HighScore) bool { return h.Player == "billie" },
		},
		{
			name: "GamePlayer",
			q:    coll.Query().Where("Player", "=", "andy").Where("Game", "=", game1),
			want: func(h *HighScore) bool { return h.Player == "andy" && h.Game == game1 },
		},
		{
			name: "PlayerScore",
			q:    coll.Query().Where("Player", "=", "pat").Where("Score", "<", 100),
			want: func(h *HighScore) bool { return h.Player == "pat" && h.Score < 100 },
		},
		{
			name: "GameScore",
			q:    coll.Query().Where("Game", "=", game1).Where("Score", ">=", 50),
			want: func(h *HighScore) bool { return h.Game == game1 && h.Score >= 50 },
		},
		{
			name: "PlayerTime",
			q:    coll.Query().Where("Player", "=", "mel").Where("Time", ">", date(4, 1)),
			want: func(h *HighScore) bool { return h.Player == "mel" && h.Time.After(date(4, 1)) },
		},
		{
			name: "ScoreTime",
			q:    coll.Query().Where("Score", ">=", 50).Where("Time", ">", date(4, 1)),
			want: func(h *HighScore) bool { return h.Score >= 50 && h.Time.After(date(4, 1)) },
		},
		{
			name: "PlayerIn",
			q:    coll.Query().Where("Player", "in", []string{"pat", "billie"}),
			want: func(h *HighScore) bool { return h.Player == "pat" || h.Player == "billie" },
		},
		{
			name: "PlayerNotIn",
			q:    coll.Query().Where("Player", "not-in", []string{"pat", "billie"}),
			want: func(h *HighScore) bool { return h.Player != "pat" && h.Player != "billie" },
		},
		{
			name:   "AllByPlayerAsc",
			q:      coll.Query().OrderBy("Player", docstore.Ascending),
			want:   func(h *HighScore) bool { return true },
			before: func(h1, h2 *HighScore) bool { return h1.Player < h2.Player },
		},
		{
			name:   "AllByPlayerDesc",
			q:      coll.Query().OrderBy("Player", docstore.Descending),
			want:   func(h *HighScore) bool { return true },
			before: func(h1, h2 *HighScore) bool { return h1.Player > h2.Player },
		},
		{
			name: "GameByPlayerAsc",
			// We need a filter on Player, and it can't be the empty string (DynamoDB limitation).
			// So pick any string that sorts less than all valid player names.
			q: coll.Query().Where("Game", "=", game1).Where("Player", ">", ".").
				OrderBy("Player", docstore.Ascending),
			want:   func(h *HighScore) bool { return h.Game == game1 },
			before: func(h1, h2 *HighScore) bool { return h1.Player < h2.Player },
		},
		{
			// Same as above, but descending.
			name: "GameByPlayerDesc",
			q: coll.Query().Where("Game", "=", game1).Where("Player", ">", ".").
				OrderBy("Player", docstore.Descending),
			want:   func(h *HighScore) bool { return h.Game == game1 },
			before: func(h1, h2 *HighScore) bool { return h1.Player > h2.Player },
		},
		// TODO(jba): add more OrderBy tests.
		{
			name:   "AllWithKeyFields",
			q:      coll.Query(),
			fields: []docstore.FieldPath{"Game", "Player", docstore.FieldPath(docstore.DefaultRevisionField)},
			want: func(h *HighScore) bool {
				h.Score = 0
				h.Time = time.Time{}
				return true
			},
		},
		{
			name:   "AllWithScore",
			q:      coll.Query(),
			fields: []docstore.FieldPath{"Game", "Player", "Score", docstore.FieldPath(docstore.DefaultRevisionField)},
			want: func(h *HighScore) bool {
				h.Time = time.Time{}
				return true
			},
		},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got, err := collectHighScores(ctx, tc.q.Get(ctx, tc.fields...))
			if err != nil {
				t.Fatal(err)
			}
			for _, g := range got {
				if g.DocstoreRevision == nil {
					t.Errorf("%v missing DocstoreRevision", g)
				} else {
					g.DocstoreRevision = nil
				}
			}
			want := filterHighScores(highScores, tc.want)
			_, err = tc.q.Plan()
			if err != nil {
				t.Fatal(err)
			}
			diff := cmp.Diff(got, want, cmpopts.SortSlices(highScoreLess))
			if diff != "" {
				t.Fatal(diff)
			}
			if tc.before != nil {
				// Verify that the results are sorted according to tc.less.
				for i := 1; i < len(got); i++ {
					if tc.before(got[i], got[i-1]) {
						t.Errorf("%s at %d sorts before previous %s", got[i], i, got[i-1])
					}
				}
			}
			// We can't assume anything about the query plan. Just verify that Plan returns
			// successfully.
			if _, err := tc.q.Plan(KeyField); err != nil {
				t.Fatal(err)
			}
		})
	}
	t.Run("Limit", func(t *testing.T) {
		// For limit, we can't be sure which documents will be returned, only their count.
		limitQ := coll.Query().Limit(2)
		got := mustCollectHighScores(ctx, t, limitQ.Get(ctx))
		if len(got) != 2 {
			t.Errorf("got %v, wanted two documents", got)
		}
	})
	t.Run("Offset", func(t *testing.T) {
		// For offset, we can't be sure which documents will be skipped, only their count.
		offsetQ := coll.Query().Offset(2)
		got := mustCollectHighScores(ctx, t, offsetQ.Get(ctx))
		if len(got) != len(highScores)-2 {
			t.Errorf("got %v, wanted %v documents", len(got), len(highScores)-2)
		}
	})
	t.Run("OffsetAndLimit", func(t *testing.T) {

		// Ensure there are at least 4 documents in the collection
		gotAll := mustCollectHighScores(ctx, t, coll.Query().Get(ctx))
		if len(gotAll) < 4 {
			t.Skip("Skipping test as there are less than 4 documents in the collection")
		}

		// Test both offset and limit together.
		offsetLimitQ := coll.Query().Offset(2).Limit(2)
		got := mustCollectHighScores(ctx, t, offsetLimitQ.Get(ctx))
		if len(got) != 2 {
			t.Errorf("got %v, wanted two documents", len(got))
		}
	})
}