You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/07/01 21:14:55 UTC

[08/24] JCLOUDS-151 - CloudStack refactored to remove async, *Client renamed to *Api.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java
deleted file mode 100644
index c2dfa5f..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-
-import static org.jclouds.cloudstack.options.ListISOsOptions.Builder.accountInDomain;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-
-import org.jclouds.cloudstack.CloudStackApiMetadata;
-import org.jclouds.cloudstack.CloudStackContext;
-import org.jclouds.cloudstack.domain.ISO;
-import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
-import org.jclouds.cloudstack.options.RegisterISOOptions;
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Test the CloudStack ISOClient
- *
- * @author Adrian Cole
- */
-@Test(groups = "unit", testName = "ISOClientExpectTest")
-public class ISOClientExpectTest extends BaseCloudStackExpectTest<ISOClient> {
-   
-   private static final ISO iso1 = ISO.builder()
-                                      .id("018e0928-8205-4d8e-9329-f731a9ccd488")
-                                      .name("xs-tools.iso")
-                                      .displayText("xen-pv-drv-iso")
-                                      .isPublic(true)
-                                      .created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-08-21T15:45:01+0530"))
-                                      .isReady(true)
-                                      .passwordEnabled(false)
-                                      .bootable(false)
-                                      .isFeatured(true)
-                                      .crossZones(false)
-                                      .account("system")
-                                      .domain("ROOT")
-                                      .domainid("9d189ea2-097e-4b2b-9bae-d885f5430d69")
-                                      .isExtractable(false).build();
-   
-   private static final ISO iso2 = ISO.builder()
-                                      .id("1e29244b-9cf0-4ff2-9978-677eb83f6bfb")
-                                      .name("vmware-tools.iso")
-                                      .displayText("VMware Tools Installer ISO")
-                                      .isPublic(true)
-                                      .created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-08-21T15:45:01+0530"))
-                                      .isReady(true)
-                                      .passwordEnabled(false)
-                                      .bootable(false)
-                                      .isFeatured(true)
-                                      .crossZones(false)
-                                      .account("system")
-                                      .domain("ROOT")
-                                      .domainid("9d189ea2-097e-4b2b-9bae-d885f5430d69")
-                                      .isExtractable(false).build();
-
-   HttpRequest listIsos = HttpRequest.builder().method("GET")
-                                     .endpoint("http://localhost:8080/client/api")
-                                     .addQueryParam("response", "json")
-                                     .addQueryParam("command", "listIsos")
-                                     .addQueryParam("listAll", "true")
-                                     .addQueryParam("apiKey", "identity")
-                                     .addQueryParam("signature", "qUUF6hCDc57Bc/nHriS9umbZBKA%3D")
-                                     .addHeader("Accept", "application/json")
-                                     .build();
-   
-   public void testListISOsWhenResponseIs2xx() {
-      ISOClient client = requestSendsResponse(listIsos,
-         HttpResponse.builder()
-                     .statusCode(200)
-                     .payload(payloadFromResource("/listisosresponse.json"))
-                     .build());
-
-      assertEquals(client.listISOs().toString(), ImmutableSet.of(iso1, iso2).toString());
-   }
-
-   public void testListISOsWhenResponseIs404() {
-      ISOClient client = requestSendsResponse(listIsos,
-         HttpResponse.builder()
-            .statusCode(404)
-            .build());
-
-      assertEquals(client.listISOs(), ImmutableSet.of());
-   }
-   
-   HttpRequest listIsosOptions = HttpRequest.builder().method("GET")
-                                            .endpoint("http://localhost:8080/client/api")
-                                            .addQueryParam("response", "json")
-                                            .addQueryParam("command", "listIsos")
-                                            .addQueryParam("listAll", "true")
-                                            .addQueryParam("account", "fred")
-                                            .addQueryParam("domainid", "5")
-                                            .addQueryParam("bootable", "true")
-                                            .addQueryParam("hypervisor", "xen")
-                                            .addQueryParam("id", "3")
-                                            .addQueryParam("isofilter", "featured")
-                                            .addQueryParam("ispublic", "true")
-                                            .addQueryParam("isready", "true")
-                                            .addQueryParam("keyword", "bob")
-                                            .addQueryParam("name", "bob%27s%20iso")
-                                            .addQueryParam("zoneid", "7")
-                                            .addQueryParam("apiKey", "identity")
-                                            .addQueryParam("signature", "4S5ustbaBErEnpymWLSj1rEJ/nk%3D")
-                                            .addHeader("Accept", "application/json")
-                                            .build();
-   
-   public void testListISOsOptionsWhenResponseIs2xx() {
-      ISOClient client = requestSendsResponse(listIsosOptions,
-         HttpResponse.builder()
-                     .statusCode(200)
-                     .payload(payloadFromResource("/listisosresponse.json"))
-                     .build());
-
-      assertEquals(client.listISOs(accountInDomain("fred", "5").bootable().hypervisor("xen").id("3").isoFilter(ISO.ISOFilter.featured).isPublic().isReady().keyword("bob").name("bob's iso").zoneId("7")).toString(), ImmutableSet.of(iso1, iso2).toString());
-   }
-
-   HttpRequest getIso = HttpRequest.builder().method("GET")
-                                     .endpoint("http://localhost:8080/client/api")
-                                     .addQueryParam("response", "json")
-                                     .addQueryParam("command", "listIsos")
-                                     .addQueryParam("listAll", "true")
-                                     .addQueryParam("id", "018e0928-8205-4d8e-9329-f731a9ccd488")
-                                     .addQueryParam("apiKey", "identity")
-                                     .addQueryParam("signature", "uZyPUJt6ThMDcQSDa%2BEv5LMs%2B2U%3D")
-                                     .addHeader("Accept", "application/json")
-                                     .build();
-   
-   public void testGetISOWhenResponseIs2xx() {
-      ISOClient client = requestSendsResponse(getIso,
-         HttpResponse.builder()
-                     .statusCode(200)
-                     .payload(payloadFromResource("/getisoresponse.json"))
-                     .build());
-
-      assertEquals(client.getISO("018e0928-8205-4d8e-9329-f731a9ccd488").toString(), iso1.toString());
-   }
-
-   public void testGetISOWhenResponseIs404() {
-      ISOClient client = requestSendsResponse(getIso,
-         HttpResponse.builder()
-            .statusCode(404)
-            .build());
-
-      assertNull(client.getISO("018e0928-8205-4d8e-9329-f731a9ccd488"));
-   }
-
-   HttpRequest registerIso = HttpRequest.builder().method("GET")
-                                        .endpoint("http://localhost:8080/client/api")
-                                        .addQueryParam("response", "json")
-                                        .addQueryParam("command", "registerIso")
-                                        .addQueryParam("name", "ubuntu10.10")
-                                        .addQueryParam("displaytext", "ubuntu 10.10 (32 bit)")
-                                        .addQueryParam("url", "http://ubuntu/ubuntu-10.10.iso")
-                                        .addQueryParam("zoneid", "1e0335d9-b6cc-4805-bddf-0828e66a0d01")
-                                        .addQueryParam("account", "root")
-                                        .addQueryParam("domainid", "99f4159b-c698-4bd9-b8c5-5ac462f101eb")
-                                        .addQueryParam("bootable", "true")
-                                        .addQueryParam("isextractable", "true")
-                                        .addQueryParam("isfeatured", "true")
-                                        .addQueryParam("ispublic", "true")
-                                        .addQueryParam("ostypeid", "1234-abcd")
-                                        .addQueryParam("apiKey", "identity")
-                                        .addQueryParam("signature", "YpFMYUUu0daLgwxNFubVfkV0Nw8%3D")
-                                        .addHeader("Accept", "application/json") 
-                                        .build();
-   
-   RegisterISOOptions registerISOOptions = RegisterISOOptions.Builder
-           .accountInDomain("root", "99f4159b-c698-4bd9-b8c5-5ac462f101eb")
-           .bootable(true).isExtractable(true).isFeatured(true).isPublic(true).osTypeId("1234-abcd");
-   
-   @Test
-   public void testRegisterISOsWhenResponseIs2xx() {
-      ISOClient client = requestSendsResponse(
-         registerIso,
-         HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/registerisoresponse.json"))
-            .build());
-      
-      assertEquals(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01", 
-              registerISOOptions),
-            ISO.builder().id("b52c509d-c6e2-452c-b6ec-aa00720ed6cd").name("ubuntu10.10").displayText("ubuntu 10.10 (32 bit)").isPublic(true)
-                .isReady(false).bootable(true).isFeatured(false).crossZones(false).osTypeId("0e0335d9-b6cc-4808-bddf-0828e66a0d03")
-                .created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-08-21T15:45:01+0530"))
-                .osTypeName("Ubuntu 10.10 (32-bit)").account("root").domain("ROOT").domainid("99f4159b-c698-4bd9-b8c5-5ac462f101eb").status("")
-                .account("admin").zoneId("6f9a2921-b22a-4149-8b71-6ffc275a2177").zoneName("Basic1")
-                .isExtractable(false).build());
-   }
-   
-   @Test(expectedExceptions=ResourceNotFoundException.class)
-   public void testRegisterISOWhenResponseIs404() {
-       ISOClient client = requestSendsResponse(registerIso,
-          HttpResponse.builder()
-             .statusCode(404)
-             .build());
-
-       assertNull(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01", 
-               registerISOOptions));
-    }
-   
-   @Override
-   protected ISOClient clientFrom(CloudStackContext context) {
-      return context.unwrap(CloudStackApiMetadata.CONTEXT_TOKEN).getApi().getISOClient();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientLiveTest.java
deleted file mode 100644
index 4cf028b..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientLiveTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-
-import static org.jclouds.cloudstack.options.ListZonesOptions.Builder.available;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Set;
-
-import org.jclouds.cloudstack.domain.ISO;
-import org.jclouds.cloudstack.domain.ISOPermissions;
-import org.jclouds.cloudstack.domain.OSType;
-import org.jclouds.cloudstack.domain.Zone;
-import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
-import org.jclouds.cloudstack.options.DeleteISOOptions;
-import org.jclouds.cloudstack.options.ListISOsOptions;
-import org.jclouds.cloudstack.options.RegisterISOOptions;
-import org.testng.SkipException;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-
-/**
- * Tests behavior of {@link ISOClient} and {@link ISOAsyncClient}
- * 
- * @author grkvlt@apache.org
- */
-@Test(groups = "live", singleThreaded = true, testName = "ISOClientLiveTest")
-public class ISOClientLiveTest extends BaseCloudStackClientLiveTest {
-    
-   private static final String isoName = "jcloudsTestISO";
-   private static final String url = System.getProperty("test.cloudstack.iso-url", "http://archive.ubuntu.com/ubuntu/dists/maverick/main/installer-i386/current/images/netboot/mini.iso");
-
-   public void testListPublicISOs() throws Exception {
-      Set<ISO> response = client.getISOClient().listISOs(ListISOsOptions.Builder.isPublic());
-      assertNotNull(response);
-      assertFalse(response.isEmpty());
-      long isoCount = response.size();
-      assertTrue(isoCount >= 0);
-
-      for (ISO iso : response) {
-         ISO query = client.getISOClient().getISO(iso.getId());
-         assertEquals(query.getId(), iso.getId());
-      }
-   }
-
-   public void testListISOPermissions() throws Exception {
-      Set<ISO> response = client.getISOClient().listISOs(ListISOsOptions.Builder.isPublic());
-      assertNotNull(response);
-      assertFalse(response.isEmpty());
-      long isoCount = response.size();
-      assertTrue(isoCount >= 0);
-
-      for (ISO iso : response) {
-         ISOPermissions perms = client.getISOClient().listISOPermissions(iso.getId());
-         assertNotNull(perms);
-      }
-   }
-   
-   public void testRegisterISO() throws Exception {
-      Optional<OSType> guestOSTypeOptional = Iterables.tryFind(client.getGuestOSClient().listOSTypes(), Predicates.notNull());
-      Optional<Zone> zoneOptional = Iterables.tryFind(client.getZoneClient().listZones(available(true)), Predicates.notNull());
-      if(guestOSTypeOptional.isPresent() && zoneOptional.isPresent()) {
-         String osTypeId = guestOSTypeOptional.get().getId();
-         String zoneId = zoneOptional.get().getId();
-         ISO iso = client.getISOClient().registerISO(isoName, "", url, zoneId, RegisterISOOptions.Builder.isPublic(true).osTypeId(osTypeId));
-             assertNotNull(iso);
-             assertNotNull(iso.getId());
-             assertEquals(iso.getName(), isoName);
-      } else {
-         String skipMessage = String.format("Cannot register the iso with url: %s", url);
-         if(zoneOptional.isPresent())
-             skipMessage += " without a valid zone";
-         else
-             skipMessage += " without a valid guest OS type";
-         throw new SkipException(skipMessage);
-      }
-   }
-
-   @AfterClass
-   @Override
-   protected void tearDownContext() {
-       Set<ISO> isos = client.getISOClient().listISOs(ListISOsOptions.Builder.name(isoName));
-       for (ISO iso : isos) {
-           client.getISOClient().deleteISO(iso.getId(), DeleteISOOptions.NONE);
-       }
-       super.tearDownContext();
-   }
-  
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiLiveTest.java
new file mode 100644
index 0000000..2c21020
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiLiveTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+
+import java.util.Set;
+
+import org.jclouds.cloudstack.domain.ResourceLimit;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code LimitApi}
+ *
+ * @author Vijay Kiran
+ */
+@Test(groups = "live", singleThreaded = true, testName = "LimitApiLiveTest")
+public class LimitApiLiveTest extends BaseCloudStackApiLiveTest {
+
+   public void testListResourceLimits() {
+      final Set<ResourceLimit> resourceLimits = client.getLimitApi().listResourceLimits();
+
+      for (ResourceLimit resourceLimit : resourceLimits) {
+         checkResourceLimit(resourceLimit);
+      }
+   }
+
+   private void checkResourceLimit(ResourceLimit resourceLimit) {
+      assert resourceLimit.getAccount() != null : resourceLimit;
+      assert resourceLimit.getDomain() != null : resourceLimit;
+      assert resourceLimit.getResourceType() != ResourceLimit.ResourceType.UNRECOGNIZED : resourceLimit;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiTest.java
new file mode 100644
index 0000000..c03cf42
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitApiTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.ListResourceLimitsOptions;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.Invokable;
+
+/**
+ * Tests behavior of {@code LimitApi}
+ *
+ * @author Vijay Kiran
+ */
+@Test(groups = "unit", testName = "LimitApiTest")
+public class LimitApiTest extends BaseCloudStackApiTest<LimitApi> {
+
+   public void testListResourceLimits() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LimitApi.class, "listResourceLimits", ListResourceLimitsOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listResourceLimits&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListResourceLimitsOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LimitApi.class, "listResourceLimits", ListResourceLimitsOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListResourceLimitsOptions.Builder.account("jclouds" , "23")));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listResourceLimits&listAll=true&account=jclouds&domainid=23 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitAsyncClientTest.java
deleted file mode 100644
index 919543f..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitAsyncClientTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
-import org.jclouds.cloudstack.options.ListResourceLimitsOptions;
-import org.jclouds.http.functions.ParseFirstJsonValueNamed;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.Invokable;
-
-/**
- * Tests behavior of {@code LimitAsyncClient}
- *
- * @author Vijay Kiran
- */
-@Test(groups = "unit", testName = "LimitAsyncClientTest")
-public class LimitAsyncClientTest extends BaseCloudStackAsyncClientTest<LimitAsyncClient> {
-
-   public void testListResourceLimits() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LimitAsyncClient.class, "listResourceLimits", ListResourceLimitsOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listResourceLimits&listAll=true HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testListResourceLimitsOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LimitAsyncClient.class, "listResourceLimits", ListResourceLimitsOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListResourceLimitsOptions.Builder.account("jclouds" , "23")));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listResourceLimits&listAll=true&account=jclouds&domainid=23 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitClientLiveTest.java
deleted file mode 100644
index bd39500..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LimitClientLiveTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-
-import java.util.Set;
-
-import org.jclouds.cloudstack.domain.ResourceLimit;
-import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code LimitClient}
- *
- * @author Vijay Kiran
- */
-@Test(groups = "live", singleThreaded = true, testName = "LimitClientLiveTest")
-public class LimitClientLiveTest extends BaseCloudStackClientLiveTest {
-
-   public void testListResourceLimits() {
-      final Set<ResourceLimit> resourceLimits = client.getLimitClient().listResourceLimits();
-
-      for (ResourceLimit resourceLimit : resourceLimits) {
-         checkResourceLimit(resourceLimit);
-      }
-   }
-
-   private void checkResourceLimit(ResourceLimit resourceLimit) {
-      assert resourceLimit.getAccount() != null : resourceLimit;
-      assert resourceLimit.getDomain() != null : resourceLimit;
-      assert resourceLimit.getResourceType() != ResourceLimit.ResourceType.UNRECOGNIZED : resourceLimit;
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java
new file mode 100644
index 0000000..79fdf99
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiLiveTest.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+
+import static com.google.common.collect.Iterables.find;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.cloudstack.predicates.NetworkPredicates.hasLoadBalancerService;
+import static org.jclouds.cloudstack.predicates.NetworkPredicates.isVirtualNetwork;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.jclouds.cloudstack.domain.AsyncJob;
+import org.jclouds.cloudstack.domain.JobResult;
+import org.jclouds.cloudstack.domain.LoadBalancerRule;
+import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
+import org.jclouds.cloudstack.domain.LoadBalancerRule.State;
+import org.jclouds.cloudstack.domain.Network;
+import org.jclouds.cloudstack.domain.PublicIPAddress;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.jclouds.cloudstack.predicates.LoadBalancerRuleActive;
+import org.jclouds.ssh.SshException;
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.net.HostAndPort;
+
+/**
+ * Tests behavior of {@code LoadBalancerApiLiveTest}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "LoadBalancerApiLiveTest")
+public class LoadBalancerApiLiveTest extends BaseCloudStackApiLiveTest {
+   private PublicIPAddress ip = null;
+   private VirtualMachine vm;
+   private LoadBalancerRule rule;
+   private Predicate<LoadBalancerRule> loadBalancerRuleActive;
+   private Network network;
+   private boolean networksDisabled;
+
+   @BeforeGroups(groups = "live")
+   public void setupContext() {
+      super.setupContext();
+      loadBalancerRuleActive = retry(new LoadBalancerRuleActive(client), 60, 1, 1, SECONDS);
+      prefix += "rule";
+      try {
+         network = find(client.getNetworkApi().listNetworks(),
+               Predicates.and(hasLoadBalancerService(), isVirtualNetwork(),
+                  new Predicate<Network>() {
+                     @Override
+                     public boolean apply(Network network) {
+                        return network.isDefault()
+                           && !network.isSecurityGroupEnabled()
+                           && !network.isSystem()
+                           && network.getAccount().equals(user.getName());
+                     }
+                  }));
+      } catch (NoSuchElementException e) {
+         networksDisabled = true;
+      }
+   }
+
+   public void testCreateVm() {
+      if (networksDisabled)
+         return;
+      String defaultTemplate = template != null ? template.getImageId() : null;
+      vm = VirtualMachineApiLiveTest.createVirtualMachineInNetwork(network,
+            defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()),
+            client, jobComplete, virtualMachineRunning);
+      if (vm.getPassword() != null && loginCredentials.getOptionalPassword() == null)
+         loginCredentials = loginCredentials.toBuilder().password(vm.getPassword()).build();
+   }
+
+   @Test(dependsOnMethods = "testCreateVm")
+   public void testCreateLoadBalancerRule() throws Exception {
+      if (networksDisabled)
+         return;
+      int attempts = 0;
+      while (rule == null && attempts < 10) {
+         ip = reuseOrAssociate.apply(network);
+         try {
+            String jobId = client.getLoadBalancerApi().createLoadBalancerRuleForPublicIP(ip.getId(),
+                  Algorithm.LEASTCONN, prefix, 22, 22);
+            assertTrue(jobComplete.apply(jobId));
+            AsyncJob<LoadBalancerRule> asyncJob = client.getAsyncJobApi().getAsyncJob(jobId);
+            LoadBalancerRule result = asyncJob.getResult();
+            rule = result;
+         } catch (IllegalStateException e) {
+            // very likely an ip conflict, so retry;
+            attempts++;
+         }
+      }
+      assertNotNull(rule, "Failed to get a load balancer rule after " + attempts + " attempts");
+      assert (rule.getPublicIPId() == ip.getId()) : rule;
+      assertEquals(rule.getPublicPort(), 22);
+      assertEquals(rule.getPrivatePort(), 22);
+      assertEquals(rule.getAlgorithm(), Algorithm.LEASTCONN);
+      assertEquals(rule.getName(), prefix);
+      assertEquals(rule.getState(), State.ADD);
+      assertEquals(client.getLoadBalancerApi().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
+      checkRule(rule);
+
+   }
+
+   @Test(dependsOnMethods = "testCreateLoadBalancerRule")
+   public void testAssignToLoadBalancerRule() throws Exception {
+      if (networksDisabled)
+         return;
+      String jobId = client.getLoadBalancerApi().assignVirtualMachinesToLoadBalancerRule(rule.getId(), vm.getId());
+      assertTrue(jobComplete.apply(jobId));
+      AsyncJob<JobResult> result = client.getAsyncJobApi().getAsyncJob(jobId);
+      assertTrue(result.hasSucceed());
+      Set<VirtualMachine> machines = client.getLoadBalancerApi().listVirtualMachinesAssignedToLoadBalancerRule(
+            rule.getId());
+      assertEquals(machines.size(), 1);
+      assertTrue(loadBalancerRuleActive.apply(rule), rule.toString());
+   }
+
+   @Test(dependsOnMethods = "testAssignToLoadBalancerRule")
+   public void testCanSshInThroughNewLoadBalancerRule() throws Exception {
+      loopAndCheckSSH();
+   }
+
+   // note that when in LB mode, there's a chance you'll have a connection
+   // failure
+   private void loopAndCheckSSH() throws IOException {
+      for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate.
+         try {
+            checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22));
+            return;
+         } catch (SshException e) {
+            e.printStackTrace();
+            try {
+               Thread.sleep(10 * 1000);
+            } catch (InterruptedException e1) {
+            }
+            continue;
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = "testAssignToLoadBalancerRule", expectedExceptions = SshException.class)
+   public void testRemoveFromLoadBalancerRule() throws Exception {
+      if (networksDisabled)
+         throw new SshException();
+      assertTrue(jobComplete.apply(client.getLoadBalancerApi().removeVirtualMachinesFromLoadBalancerRule(
+            rule.getId(), vm.getId())));
+      assertEquals(client.getLoadBalancerApi().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
+      assertEquals(rule.getState(), State.ADD);
+      checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22));
+   }
+
+   @AfterGroups(groups = "live")
+   @Override
+   protected void tearDownContext() {
+      if (rule != null) {
+         assertTrue(jobComplete.apply(client.getLoadBalancerApi().deleteLoadBalancerRule(rule.getId())));
+      }
+      if (vm != null) {
+         assertTrue(jobComplete.apply(client.getVirtualMachineApi().destroyVirtualMachine(vm.getId())));
+      }
+      if (ip != null) {
+         client.getAddressApi().disassociateIPAddress(ip.getId());
+      }
+      super.tearDownContext();
+   }
+
+   public void testListLoadBalancerRules() throws Exception {
+      Set<LoadBalancerRule> response = client.getLoadBalancerApi().listLoadBalancerRules();
+      assert null != response;
+      assertTrue(response.size() >= 0);
+      for (LoadBalancerRule rule : response) {
+         LoadBalancerRule newDetails = findRuleWithId(rule.getId());
+         assertEquals(rule.getId(), newDetails.getId());
+         checkRule(rule);
+      }
+   }
+
+   private LoadBalancerRule findRuleWithId(final String id) {
+      return find(client.getLoadBalancerApi().listLoadBalancerRules(), new Predicate<LoadBalancerRule>() {
+
+         @Override
+         public boolean apply(LoadBalancerRule arg0) {
+            return arg0.getId() == id;
+         }
+
+      });
+   }
+
+   protected void checkRule(LoadBalancerRule rule) {
+      assertEquals(rule.getId(), findRuleWithId(rule.getId()).getId());
+      assert rule.getId() != null : rule;
+      assert rule.getAccount() != null : rule;
+      assert rule.getAlgorithm() != null : rule;
+      assert rule.getPrivatePort() > 0 : rule;
+      assert rule.getPublicPort() > 0 : rule;
+      assert rule.getDomain() != null : rule;
+      assert rule.getDomainId() != null : rule;
+      assert rule.getState() != null : rule;
+      assert rule.getName() != null : rule;
+      assert rule.getPublicIP() != null : rule;
+      assert rule.getPublicIPId() != null : rule;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiTest.java
new file mode 100644
index 0000000..8b03b10
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerApiTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.CreateLoadBalancerRuleOptions;
+import org.jclouds.cloudstack.options.ListLoadBalancerRulesOptions;
+import org.jclouds.cloudstack.options.UpdateLoadBalancerRuleOptions;
+import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code LoadBalancerApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "LoadBalancerApiTest")
+public class LoadBalancerApiTest extends BaseCloudStackApiTest<LoadBalancerApi> {
+   public void testListLoadBalancerRules() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "listLoadBalancerRules",
+            ListLoadBalancerRulesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRules&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListLoadBalancerRulesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "listLoadBalancerRules",
+            ListLoadBalancerRulesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListLoadBalancerRulesOptions.Builder.publicIPId("3")));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRules&listAll=true&publicipid=3 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   HttpRequest createLoadBalancerRule = HttpRequest.builder().method("GET")
+                                                   .endpoint("http://localhost:8080/client/api")
+                                                   .addQueryParam("response", "json")
+                                                   .addQueryParam("command", "createLoadBalancerRule")
+                                                   .addQueryParam("publicipid", "6")
+                                                   .addQueryParam("algorithm", "leastconn")
+                                                   .addQueryParam("name", "tcp")
+                                                   .addQueryParam("privateport", "22")
+                                                   .addQueryParam("publicport", "22").build();
+
+   public void testCreateLoadBalancerRuleForPublicIP() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "createLoadBalancerRuleForPublicIP", String.class,
+            Algorithm.class, String.class, int.class, int.class, CreateLoadBalancerRuleOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(6, Algorithm.LEASTCONN, "tcp", 22, 22));
+
+      assertRequestLineEquals(httpRequest, createLoadBalancerRule.getRequestLine());
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testUpdateLoadBalancerRule() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "updateLoadBalancerRule", String.class, UpdateLoadBalancerRuleOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=updateLoadBalancerRule&id=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testDeleteLoadBalancerRule() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "deleteLoadBalancerRule", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=deleteLoadBalancerRule&id=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListVirtualMachinesAssignedToLoadBalancerRule() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(LoadBalancerApi.class, "listVirtualMachinesAssignedToLoadBalancerRule",
+            String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRuleInstances&listAll=true&id=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerAsyncClientTest.java
deleted file mode 100644
index eb41d89..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerAsyncClientTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
-import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
-import org.jclouds.cloudstack.options.CreateLoadBalancerRuleOptions;
-import org.jclouds.cloudstack.options.ListLoadBalancerRulesOptions;
-import org.jclouds.cloudstack.options.UpdateLoadBalancerRuleOptions;
-import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseFirstJsonValueNamed;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code LoadBalancerAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during
-// surefire
-@Test(groups = "unit", testName = "LoadBalancerAsyncClientTest")
-public class LoadBalancerAsyncClientTest extends BaseCloudStackAsyncClientTest<LoadBalancerAsyncClient> {
-   public void testListLoadBalancerRules() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "listLoadBalancerRules",
-            ListLoadBalancerRulesOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRules&listAll=true HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testListLoadBalancerRulesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "listLoadBalancerRules",
-            ListLoadBalancerRulesOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListLoadBalancerRulesOptions.Builder.publicIPId("3")));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRules&listAll=true&publicipid=3 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   HttpRequest createLoadBalancerRule = HttpRequest.builder().method("GET")
-                                                   .endpoint("http://localhost:8080/client/api")
-                                                   .addQueryParam("response", "json")
-                                                   .addQueryParam("command", "createLoadBalancerRule")
-                                                   .addQueryParam("publicipid", "6")
-                                                   .addQueryParam("algorithm", "leastconn")
-                                                   .addQueryParam("name", "tcp")
-                                                   .addQueryParam("privateport", "22")
-                                                   .addQueryParam("publicport", "22").build();
-
-   public void testCreateLoadBalancerRuleForPublicIP() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "createLoadBalancerRuleForPublicIP", String.class,
-            Algorithm.class, String.class, int.class, int.class, CreateLoadBalancerRuleOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(6, Algorithm.LEASTCONN, "tcp", 22, 22));
-
-      assertRequestLineEquals(httpRequest, createLoadBalancerRule.getRequestLine());
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testUpdateLoadBalancerRule() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "updateLoadBalancerRule", String.class, UpdateLoadBalancerRuleOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=updateLoadBalancerRule&id=5 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testDeleteLoadBalancerRule() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "deleteLoadBalancerRule", String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=deleteLoadBalancerRule&id=5 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testListVirtualMachinesAssignedToLoadBalancerRule() throws SecurityException, NoSuchMethodException,
-         IOException {
-      Invokable<?, ?> method = method(LoadBalancerAsyncClient.class, "listVirtualMachinesAssignedToLoadBalancerRule",
-            String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listLoadBalancerRuleInstances&listAll=true&id=5 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
deleted file mode 100644
index 2776ef0..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
-
-import static com.google.common.collect.Iterables.find;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.cloudstack.predicates.NetworkPredicates.hasLoadBalancerService;
-import static org.jclouds.cloudstack.predicates.NetworkPredicates.isVirtualNetwork;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.jclouds.cloudstack.domain.AsyncJob;
-import org.jclouds.cloudstack.domain.JobResult;
-import org.jclouds.cloudstack.domain.LoadBalancerRule;
-import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
-import org.jclouds.cloudstack.domain.LoadBalancerRule.State;
-import org.jclouds.cloudstack.domain.Network;
-import org.jclouds.cloudstack.domain.PublicIPAddress;
-import org.jclouds.cloudstack.domain.VirtualMachine;
-import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
-import org.jclouds.cloudstack.predicates.LoadBalancerRuleActive;
-import org.jclouds.ssh.SshException;
-import org.testng.annotations.AfterGroups;
-import org.testng.annotations.BeforeGroups;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.net.HostAndPort;
-
-/**
- * Tests behavior of {@code LoadBalancerClientLiveTest}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "LoadBalancerClientLiveTest")
-public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
-   private PublicIPAddress ip = null;
-   private VirtualMachine vm;
-   private LoadBalancerRule rule;
-   private Predicate<LoadBalancerRule> loadBalancerRuleActive;
-   private Network network;
-   private boolean networksDisabled;
-
-   @BeforeGroups(groups = "live")
-   public void setupContext() {
-      super.setupContext();
-      loadBalancerRuleActive = retry(new LoadBalancerRuleActive(client), 60, 1, 1, SECONDS);
-      prefix += "rule";
-      try {
-         network = find(client.getNetworkClient().listNetworks(),
-               Predicates.and(hasLoadBalancerService(), isVirtualNetwork(),
-                  new Predicate<Network>() {
-                     @Override
-                     public boolean apply(Network network) {
-                        return network.isDefault()
-                           && !network.isSecurityGroupEnabled()
-                           && !network.isSystem()
-                           && network.getAccount().equals(user.getName());
-                     }
-                  }));
-      } catch (NoSuchElementException e) {
-         networksDisabled = true;
-      }
-   }
-
-   public void testCreateVm() {
-      if (networksDisabled)
-         return;
-      String defaultTemplate = template != null ? template.getImageId() : null;
-      vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
-            defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()),
-            client, jobComplete, virtualMachineRunning);
-      if (vm.getPassword() != null && loginCredentials.getOptionalPassword() == null)
-         loginCredentials = loginCredentials.toBuilder().password(vm.getPassword()).build();
-   }
-
-   @Test(dependsOnMethods = "testCreateVm")
-   public void testCreateLoadBalancerRule() throws Exception {
-      if (networksDisabled)
-         return;
-      int attempts = 0;
-      while (rule == null && attempts < 10) {
-         ip = reuseOrAssociate.apply(network);
-         try {
-            String jobId = client.getLoadBalancerClient().createLoadBalancerRuleForPublicIP(ip.getId(),
-                  Algorithm.LEASTCONN, prefix, 22, 22);
-            assertTrue(jobComplete.apply(jobId));
-            AsyncJob<LoadBalancerRule> asyncJob = client.getAsyncJobClient().getAsyncJob(jobId);
-            LoadBalancerRule result = asyncJob.getResult();
-            rule = result;
-         } catch (IllegalStateException e) {
-            // very likely an ip conflict, so retry;
-            attempts++;
-         }
-      }
-      assertNotNull(rule, "Failed to get a load balancer rule after " + attempts + " attempts");
-      assert (rule.getPublicIPId() == ip.getId()) : rule;
-      assertEquals(rule.getPublicPort(), 22);
-      assertEquals(rule.getPrivatePort(), 22);
-      assertEquals(rule.getAlgorithm(), Algorithm.LEASTCONN);
-      assertEquals(rule.getName(), prefix);
-      assertEquals(rule.getState(), State.ADD);
-      assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
-      checkRule(rule);
-
-   }
-
-   @Test(dependsOnMethods = "testCreateLoadBalancerRule")
-   public void testAssignToLoadBalancerRule() throws Exception {
-      if (networksDisabled)
-         return;
-      String jobId = client.getLoadBalancerClient().assignVirtualMachinesToLoadBalancerRule(rule.getId(), vm.getId());
-      assertTrue(jobComplete.apply(jobId));
-      AsyncJob<JobResult> result = client.getAsyncJobClient().getAsyncJob(jobId);
-      assertTrue(result.hasSucceed());
-      Set<VirtualMachine> machines = client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(
-            rule.getId());
-      assertEquals(machines.size(), 1);
-      assertTrue(loadBalancerRuleActive.apply(rule), rule.toString());
-   }
-
-   @Test(dependsOnMethods = "testAssignToLoadBalancerRule")
-   public void testCanSshInThroughNewLoadBalancerRule() throws Exception {
-      loopAndCheckSSH();
-   }
-
-   // note that when in LB mode, there's a chance you'll have a connection
-   // failure
-   private void loopAndCheckSSH() throws IOException {
-      for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate.
-         try {
-            checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22));
-            return;
-         } catch (SshException e) {
-            e.printStackTrace();
-            try {
-               Thread.sleep(10 * 1000);
-            } catch (InterruptedException e1) {
-            }
-            continue;
-         }
-      }
-   }
-
-   @Test(dependsOnMethods = "testAssignToLoadBalancerRule", expectedExceptions = SshException.class)
-   public void testRemoveFromLoadBalancerRule() throws Exception {
-      if (networksDisabled)
-         throw new SshException();
-      assertTrue(jobComplete.apply(client.getLoadBalancerClient().removeVirtualMachinesFromLoadBalancerRule(
-            rule.getId(), vm.getId())));
-      assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
-      assertEquals(rule.getState(), State.ADD);
-      checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22));
-   }
-
-   @AfterGroups(groups = "live")
-   @Override
-   protected void tearDownContext() {
-      if (rule != null) {
-         assertTrue(jobComplete.apply(client.getLoadBalancerClient().deleteLoadBalancerRule(rule.getId())));
-      }
-      if (vm != null) {
-         assertTrue(jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId())));
-      }
-      if (ip != null) {
-         client.getAddressClient().disassociateIPAddress(ip.getId());
-      }
-      super.tearDownContext();
-   }
-
-   public void testListLoadBalancerRules() throws Exception {
-      Set<LoadBalancerRule> response = client.getLoadBalancerClient().listLoadBalancerRules();
-      assert null != response;
-      assertTrue(response.size() >= 0);
-      for (LoadBalancerRule rule : response) {
-         LoadBalancerRule newDetails = findRuleWithId(rule.getId());
-         assertEquals(rule.getId(), newDetails.getId());
-         checkRule(rule);
-      }
-   }
-
-   private LoadBalancerRule findRuleWithId(final String id) {
-      return find(client.getLoadBalancerClient().listLoadBalancerRules(), new Predicate<LoadBalancerRule>() {
-
-         @Override
-         public boolean apply(LoadBalancerRule arg0) {
-            return arg0.getId() == id;
-         }
-
-      });
-   }
-
-   protected void checkRule(LoadBalancerRule rule) {
-      assertEquals(rule.getId(), findRuleWithId(rule.getId()).getId());
-      assert rule.getId() != null : rule;
-      assert rule.getAccount() != null : rule;
-      assert rule.getAlgorithm() != null : rule;
-      assert rule.getPrivatePort() > 0 : rule;
-      assert rule.getPublicPort() > 0 : rule;
-      assert rule.getDomain() != null : rule;
-      assert rule.getDomainId() != null : rule;
-      assert rule.getState() != null : rule;
-      assert rule.getName() != null : rule;
-      assert rule.getPublicIP() != null : rule;
-      assert rule.getPublicIPId() != null : rule;
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiLiveTest.java
new file mode 100644
index 0000000..fd8d104
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiLiveTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.cloudstack.domain.IPForwardingRule;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.jclouds.cloudstack.options.ListIPForwardingRulesOptions;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code NATApiLiveTest}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NATApiLiveTest")
+public class NATApiLiveTest extends BaseCloudStackApiLiveTest {
+
+   @Test(enabled = false)
+   // takes too long
+   public void testListIPForwardingRules() throws Exception {
+      Set<IPForwardingRule> response = client.getNATApi().listIPForwardingRules();
+      assert null != response;
+      assertTrue(response.size() >= 0);
+      for (IPForwardingRule rule : response) {
+         IPForwardingRule newDetails = getOnlyElement(client.getNATApi().listIPForwardingRules(
+               ListIPForwardingRulesOptions.Builder.id(rule.getId())));
+         assertEquals(rule.getId(), newDetails.getId());
+         checkRule(rule);
+      }
+   }
+
+   protected void checkRule(IPForwardingRule rule) {
+      assertEquals(rule.getId(), client.getNATApi().getIPForwardingRule(rule.getId()).getId());
+      assert rule.getId() != null : rule;
+      assert rule.getIPAddress() != null : rule;
+      assert rule.getIPAddressId() != null : rule;
+      assert rule.getStartPort() > 0 : rule;
+      assert rule.getProtocol() != null : rule;
+      assert rule.getEndPort() > 0 : rule;
+      assert rule.getState() != null : rule;
+      assert rule.getVirtualMachineId() != null : rule;
+      assert rule.getVirtualMachineName() != null : rule;
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiTest.java
new file mode 100644
index 0000000..b049ec7
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/NATApiTest.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.cloudstack.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.CreateIPForwardingRuleOptions;
+import org.jclouds.cloudstack.options.ListIPForwardingRulesOptions;
+import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.http.functions.UnwrapOnlyJsonValue;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code NATApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "NATApiTest")
+public class NATApiTest extends BaseCloudStackApiTest<NATApi> {
+   public void testListIPForwardingRules() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "listIPForwardingRules", ListIPForwardingRulesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listIpForwardingRules&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListIPForwardingRulesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "listIPForwardingRules", ListIPForwardingRulesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(
+            ListIPForwardingRulesOptions.Builder.virtualMachineId("3")));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listIpForwardingRules&listAll=true&virtualmachineid=3 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testGetIPForwardingRule() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "getIPForwardingRule", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listIpForwardingRules&listAll=true&id=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   HttpRequest createIpForwardingRule = HttpRequest.builder().method("GET")
+                                                             .endpoint("http://localhost:8080/client/api")
+                                                             .addQueryParam("response", "json")
+                                                             .addQueryParam("command", "createIpForwardingRule")
+                                                             .addQueryParam("ipaddressid", "7")
+                                                             .addQueryParam("protocol", "tcp")
+                                                             .addQueryParam("startport", "22").build();
+
+   public void testCreateIPForwardingRuleForVirtualMachine() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(NATApi.class, "createIPForwardingRule", String.class, String.class, int.class,
+            CreateIPForwardingRuleOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(7, "tcp", 22));
+
+      assertRequestLineEquals(httpRequest, createIpForwardingRule.getRequestLine());
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   HttpRequest createIpForwardingRuleOptions = HttpRequest.builder().method("GET")
+                                                          .endpoint("http://localhost:8080/client/api")
+                                                          .addQueryParam("response", "json")
+                                                          .addQueryParam("command", "createIpForwardingRule")
+                                                          .addQueryParam("ipaddressid", "7")
+                                                          .addQueryParam("protocol", "tcp")
+                                                          .addQueryParam("startport", "22")
+                                                          .addQueryParam("endport", "22").build();
+
+   public void testCreateIPForwardingRuleForVirtualMachineOptions() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(NATApi.class, "createIPForwardingRule", String.class, String.class, int.class,
+            CreateIPForwardingRuleOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(7, "tcp", 22,
+            CreateIPForwardingRuleOptions.Builder.endPort(22)));
+
+      assertRequestLineEquals(httpRequest, createIpForwardingRuleOptions.getRequestLine());
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testEnableStaticNATForVirtualMachine() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "enableStaticNATForVirtualMachine", String.class, String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5, 6));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=enableStaticNat&virtualmachineid=5&ipaddressid=6 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testDisableStaticNATOnPublicIP() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "disableStaticNATOnPublicIP", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=disableStaticNat&ipaddressid=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testDeleteIPForwardingRule() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(NATApi.class, "deleteIPForwardingRule", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(5));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=deleteIpForwardingRule&id=5 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+}