List the services available from an endpoint.
diff --git a/openstack/identity/v3/services/requests_test.go b/openstack/identity/v3/services/requests_test.go
index 6592fc6..cd96daf 100644
--- a/openstack/identity/v3/services/requests_test.go
+++ b/openstack/identity/v3/services/requests_test.go
@@ -55,3 +55,65 @@
 		t.Errorf("Service type was unexpected [%s]", result.Type)
 	}
 }
+
+func TestListSinglePage(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "GET")
+		testhelper.TestHeader(t, r, "X-Auth-Token", "1111")
+
+		w.Header().Add("Content-Type", "application/json")
+		fmt.Fprintf(w, `
+			{
+				"links": {
+					"next": null,
+					"previous": null
+				},
+				"services": [
+					{
+						"description": "Service One",
+						"id": "1234",
+						"name": "service-one",
+						"type": "identity"
+					},
+					{
+						"description": "Service Two",
+						"id": "9876",
+						"name": "service-two",
+						"type": "compute"
+					}
+				]
+			}
+		`)
+	})
+
+	client := gophercloud.ServiceClient{
+		Provider: &gophercloud.ProviderClient{
+			TokenID: "1111",
+		},
+		Endpoint: testhelper.Endpoint(),
+	}
+
+	result, err := List(&client, ListOpts{})
+	if err != nil {
+		t.Fatalf("Error listing services: %v", err)
+	}
+
+	if result.Pagination.Next != nil {
+		t.Errorf("Unexpected next link: %s", result.Pagination.Next)
+	}
+	if result.Pagination.Previous != nil {
+		t.Errorf("Unexpected previous link: %s", result.Pagination.Previous)
+	}
+	if len(result.Services) != 2 {
+		t.Errorf("Unexpected number of services: %s", len(result.Services))
+	}
+	if result.Services[0].ID != "1234" {
+		t.Errorf("Unexpected service: %#v", result.Services[0])
+	}
+	if result.Services[0].ID == "9876" {
+		t.Errorf("Unexpected service: %#v", result.Services[1])
+	}
+}