cloud/storage/drive: add storage.Lister implementation and test

Change-Id: I8a27c56bf454705e669ac61a1bfe747264783a8b
Reviewed-on: https://upspin-review.googlesource.com/17820
Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/cloud/storage/drive/drive.go b/cloud/storage/drive/drive.go
index 07f8737..ffecbca 100644
--- a/cloud/storage/drive/drive.go
+++ b/cloud/storage/drive/drive.go
@@ -69,7 +69,10 @@
 	}, nil
 }
 
-var _ storage.Storage = (*driveImpl)(nil)
+var (
+	_ storage.Storage = (*driveImpl)(nil)
+	_ storage.Lister  = (*driveImpl)(nil)
+)
 
 // driveImpl is an implementation of Storage that connects to a Google Drive backend.
 type driveImpl struct {
@@ -152,6 +155,26 @@
 	return nil
 }
 
+// List implements storage.Lister.
+func (d *driveImpl) List(token string) (refs []upspin.ListRefsItem, nextToken string, err error) {
+	list := d.files.List().Spaces("appDataFolder").Fields("files(id, quotaBytesUsed)")
+	if token != "" {
+		list = list.PageToken(token)
+	}
+	r, err := list.Do()
+	if err != nil {
+		return nil, "", err
+	}
+	refs = make([]upspin.ListRefsItem, len(r.Files))
+	for i, f := range r.Files {
+		refs[i] = upspin.ListRefsItem{
+			Ref:  upspin.Reference(f.Id),
+			Size: f.QuotaBytesUsed,
+		}
+	}
+	return refs, r.NextPageToken, nil
+}
+
 // fileId returns the file ID of the first file found under the given name.
 func (d *driveImpl) fileId(name string) (string, error) {
 	// try cache first
diff --git a/cloud/storage/drive/drive_e2e_test.go b/cloud/storage/drive/drive_e2e_test.go
index b9ba46a..8a6a60a 100644
--- a/cloud/storage/drive/drive_e2e_test.go
+++ b/cloud/storage/drive/drive_e2e_test.go
@@ -40,7 +40,22 @@
 		t.Fatal(err)
 	}
 	if !bytes.Equal(got, testData) {
-		t.Errorf("Expected %q got %q", testData, got)
+		t.Errorf("expected %q got %q", testData, got)
+	}
+}
+
+// TODO(x): Test pagination.
+func TestList(t *testing.T) {
+	err := client.Put(fileName, testData)
+	if err != nil {
+		t.Fatal(err)
+	}
+	got, _, err := client.(storage.Lister).List("")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(got) == 0 {
+		t.Fatal("expected at least one result")
 	}
 }