You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/07/13 00:03:31 UTC
[43/47] jclouds-labs git commit: JCLOUDS-613: Implement the
DigitalOcean v2 API
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/ImageToImageTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/ImageToImageTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/ImageToImageTest.java
new file mode 100644
index 0000000..6ab020c
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/ImageToImageTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.digitalocean2.compute.functions;
+
+import static org.jclouds.compute.domain.Image.Status.AVAILABLE;
+import static org.testng.Assert.assertEquals;
+
+import java.util.Date;
+
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.digitalocean2.domain.Image;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@Test(groups = "unit", testName = "ImageToImageTest")
+public class ImageToImageTest {
+
+ @Test
+ public void testConvertImage() {
+ Image image = Image.create(1, "14.04 x64", "distribution", "Ubuntu", "ubuntu-1404-x86", true,
+ ImmutableList.of("sfo1"), new Date());
+ org.jclouds.compute.domain.Image expected = new ImageBuilder()
+ .id("ubuntu-1404-x86")
+ .providerId("1")
+ .name("14.04 x64")
+ .description("Ubuntu 14.04 x64")
+ .status(AVAILABLE)
+ .operatingSystem(
+ OperatingSystem.builder().name("Ubuntu").description("Ubuntu 14.04 x64").family(OsFamily.UBUNTU)
+ .version("14.04").arch("x64").is64Bit(true).build())
+ .userMetadata(ImmutableMap.of("publicImage", "true")).build();
+
+ org.jclouds.compute.domain.Image result = new ImageToImage().apply(image);
+ assertEquals(result, expected);
+ assertEquals(result.getDescription(), expected.getDescription());
+ assertEquals(result.getOperatingSystem(), expected.getOperatingSystem());
+ assertEquals(result.getStatus(), expected.getStatus());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/RegionToLocationTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/RegionToLocationTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/RegionToLocationTest.java
new file mode 100644
index 0000000..879091b
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/RegionToLocationTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.digitalocean2.compute.functions;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.digitalocean2.DigitalOcean2ProviderMetadata;
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.location.suppliers.all.JustProvider;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+@Test(groups = "unit", testName = "RegionToLocationTest")
+public class RegionToLocationTest {
+
+ @Test
+ public void testConvertRegion() {
+ DigitalOcean2ProviderMetadata metadata = new DigitalOcean2ProviderMetadata();
+ JustProvider locationsSupplier = new JustProvider(metadata.getId(), Suppliers.<URI> ofInstance(URI
+ .create(metadata.getEndpoint())), ImmutableSet.<String> of());
+
+ Region region = Region.create("reg1", "Region1", ImmutableList.<String> of(), true, ImmutableList.<String> of());
+ Location expected = new LocationBuilder().id("reg1").description("reg1/Region 1")
+ .parent(getOnlyElement(locationsSupplier.get())).scope(LocationScope.REGION).build();
+
+ RegionToLocation function = new RegionToLocation(locationsSupplier);
+ assertEquals(function.apply(region), expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/SizeToHardwareTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/SizeToHardwareTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/SizeToHardwareTest.java
new file mode 100644
index 0000000..cba55bf
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/SizeToHardwareTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.digitalocean2.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume.Type;
+import org.jclouds.compute.domain.VolumeBuilder;
+import org.jclouds.digitalocean2.domain.Size;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Unit tests for the {@link SizeToHardware} class.
+ */
+@Test(groups = "unit", testName = "SizeToHardwareTest")
+public class SizeToHardwareTest {
+
+ @Test
+ public void testConvertSize() {
+ Size size = Size.create("2gb", true, 1.0f, 10f, 0.05f, 2048, 1, 20, ImmutableList.<String> of());
+ Hardware expected = new HardwareBuilder().id("2gb").providerId("2gb").name("2gb")
+ .processor(new Processor(1.0, 1.0)).ram(2048)
+ .volume(new VolumeBuilder().size(20f).type(Type.LOCAL).build())
+ .userMetadata(ImmutableMap.of("costPerHour", "0.05", "costPerMonth", "10")).build();
+
+ SizeToHardware function = new SizeToHardware();
+ assertEquals(function.apply(size), expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/TemplateOptionsToStatementWithoutPublicKeyTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/TemplateOptionsToStatementWithoutPublicKeyTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/TemplateOptionsToStatementWithoutPublicKeyTest.java
new file mode 100644
index 0000000..c3a6cd2
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/functions/TemplateOptionsToStatementWithoutPublicKeyTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.digitalocean2.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.scriptbuilder.domain.OsFamily;
+import org.jclouds.scriptbuilder.domain.Statement;
+import org.jclouds.scriptbuilder.domain.StatementList;
+import org.jclouds.scriptbuilder.statements.ssh.InstallRSAPrivateKey;
+import org.jclouds.ssh.SshKeys;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for the {@link TemplateOptionsToStatementWithoutPublicKey} class.
+ */
+@Test(groups = "unit", testName = "TemplateOptionsToStatementWithoutPublicKeyTest")
+public class TemplateOptionsToStatementWithoutPublicKeyTest {
+
+ @Test
+ public void testPublicKeyDoesNotGenerateAuthorizePublicKeyStatementIfOnlyPublicKeyOptionsConfigured() {
+ Map<String, String> keys = SshKeys.generate();
+ TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public"));
+
+ TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
+ assertNull(function.apply(options));
+ }
+
+ @Test
+ public void testPublicAndRunScriptKeyDoesNotGenerateAuthorizePublicKeyStatementIfRunScriptPresent() {
+ Map<String, String> keys = SshKeys.generate();
+ TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public")).runScript("uptime");
+
+ TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
+ Statement statement = function.apply(options);
+
+ assertEquals(statement.render(OsFamily.UNIX), "uptime\n");
+ }
+
+ @Test
+ public void testPublicAndPrivateKeyAndRunScriptDoesNotGenerateAuthorizePublicKeyStatementIfOtherOptionsPresent() {
+ Map<String, String> keys = SshKeys.generate();
+ TemplateOptions options = TemplateOptions.Builder.authorizePublicKey(keys.get("public"))
+ .installPrivateKey(keys.get("private")).runScript("uptime");
+
+ TemplateOptionsToStatementWithoutPublicKey function = new TemplateOptionsToStatementWithoutPublicKey();
+ Statement statement = function.apply(options);
+
+ assertTrue(statement instanceof StatementList);
+ StatementList statements = (StatementList) statement;
+
+ assertEquals(statements.size(), 2);
+ assertEquals(statements.get(0).render(OsFamily.UNIX), "uptime\n");
+ assertTrue(statements.get(1) instanceof InstallRSAPrivateKey);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/options/DigitalOcean2TemplateOptionsTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/options/DigitalOcean2TemplateOptionsTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/options/DigitalOcean2TemplateOptionsTest.java
new file mode 100644
index 0000000..982224c
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/compute/options/DigitalOcean2TemplateOptionsTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.digitalocean2.compute.options;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.compute.options.TemplateOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+@Test(groups = "unit", testName = "DigitalOcean2TemplateOptionsTest")
+public class DigitalOcean2TemplateOptionsTest {
+
+ @Test
+ public void testSShKeyIds() {
+ TemplateOptions options = new DigitalOcean2TemplateOptions().sshKeyIds(ImmutableSet.of(1, 2, 3));
+ assertEquals(options.as(DigitalOcean2TemplateOptions.class).getSshKeyIds(), ImmutableSet.of(1, 2, 3));
+ }
+
+ @Test
+ public void testPrivateNetworking() {
+ TemplateOptions options = new DigitalOcean2TemplateOptions().privateNetworking(true);
+ assertEquals(options.as(DigitalOcean2TemplateOptions.class).getPrivateNetworking(), true);
+ }
+
+ @Test
+ public void testBackupsEnabled() {
+ TemplateOptions options = new DigitalOcean2TemplateOptions().backupsEnabled(true);
+ assertEquals(options.as(DigitalOcean2TemplateOptions.class).getBackupsEnabled(), true);
+ }
+
+ @Test
+ public void testAutoCreateKeyPair() {
+ TemplateOptions options = new DigitalOcean2TemplateOptions().autoCreateKeyPair(false);
+ assertEquals(options.as(DigitalOcean2TemplateOptions.class).getAutoCreateKeyPair(), false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/domain/OperatingSystemTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/domain/OperatingSystemTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/domain/OperatingSystemTest.java
new file mode 100644
index 0000000..d6bd0fc
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/domain/OperatingSystemTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.digitalocean2.domain;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "OperatingSystemTest")
+public class OperatingSystemTest {
+
+ public void testParseStandard64bit() {
+ OperatingSystem os = OperatingSystem.create("12.10 x64", "Ubuntu");
+
+ assertEquals(os.distribution(), Distribution.UBUNTU);
+ assertEquals(os.version(), "12.10");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+
+ public void testLongVersionStandard64bit() {
+ OperatingSystem os = OperatingSystem.create("12.10.1 x64", "Ubuntu");
+
+ assertEquals(os.distribution(), Distribution.UBUNTU);
+ assertEquals(os.version(), "12.10.1");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+
+ public void testParseStandard64bitWithPrefix() {
+ OperatingSystem os = OperatingSystem.create("Arch Linux 12.10 x64 Desktop", "Arch Linux");
+
+ assertEquals(os.distribution(), Distribution.ARCHLINUX);
+ assertEquals(os.version(), "12.10");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+
+ public void testParseStandard() {
+ OperatingSystem os = OperatingSystem.create("12.10 x32", "Ubuntu");
+
+ assertEquals(os.distribution(), Distribution.UBUNTU);
+ assertEquals(os.version(), "12.10");
+ assertEquals(os.arch(), "x32");
+ assertFalse(os.is64bit());
+
+ os = OperatingSystem.create("6.5 x64", "CentOS");
+
+ assertEquals(os.distribution(), Distribution.CENTOS);
+ assertEquals(os.version(), "6.5");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+
+ os = OperatingSystem.create("6.5 x64", "Centos");
+
+ assertEquals(os.distribution(), Distribution.CENTOS);
+ assertEquals(os.version(), "6.5");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+
+ public void testParseNoArch() {
+ OperatingSystem os = OperatingSystem.create("12.10", "Ubuntu");
+
+ assertEquals(os.distribution(), Distribution.UBUNTU);
+ assertEquals(os.version(), "12.10");
+ assertEquals(os.arch(), "");
+ assertFalse(os.is64bit());
+ }
+
+ public void testParseNoVersion() {
+ OperatingSystem os = OperatingSystem.create("x64", "Ubuntu");
+
+ assertEquals(os.distribution(), Distribution.UBUNTU);
+ assertEquals(os.version(), "");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+
+ public void testParseUnknownDistribution() {
+ OperatingSystem os = OperatingSystem.create("12.04 x64", "Foo");
+
+ assertEquals(os.distribution(), Distribution.UNRECOGNIZED);
+ assertEquals(os.version(), "12.04");
+ assertEquals(os.arch(), "x64");
+ assertTrue(os.is64bit());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiLiveTest.java
new file mode 100644
index 0000000..44a9a17
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiLiveTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.digitalocean2.features;
+
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.Builder.page;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Action;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "ActionApiLiveTest")
+public class ActionApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListActions() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Action>() {
+ @Override
+ public boolean apply(Action input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.type());
+ }
+ }), "All actions must have the 'type' field populated");
+ assertTrue(found.get() > 0, "Expected some actions to be returned");
+ }
+
+ public void testListActionsOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1).perPage(5)).allMatch(new Predicate<Action>() {
+ @Override
+ public boolean apply(Action input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.type());
+ }
+ }), "All actions must have the 'type' field populated");
+ assertTrue(found.get() > 0, "Expected some actions to be returned");
+ }
+
+ public void testGetAction() {
+ Optional<Action> first = api().list().concat().first();
+ assertTrue(first.isPresent(), "At least one action was expected to exist");
+ assertNotNull(api().get(first.get().id()));
+ }
+
+ private ActionApi api() {
+ return api.actionApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiMockTest.java
new file mode 100644
index 0000000..aa890d5
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ActionApiMockTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.digitalocean2.domain.Action;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+
+@Test(groups = "unit", testName = "ActionApiMockTest", singleThreaded = true)
+public class ActionApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListActions() throws InterruptedException {
+ server.enqueue(jsonResponse("/actions-first.json"));
+ server.enqueue(jsonResponse("/actions-last.json"));
+
+ Iterable<Action> actions = api.actionApi().list().concat();
+
+ assertEquals(size(actions), 8); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/actions");
+ assertSent(server, "GET", "/actions?page=2&per_page=5");
+ }
+
+ public void testListActionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Action> actions = api.actionApi().list().concat();
+
+ assertTrue(isEmpty(actions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/actions");
+ }
+
+ public void testListActionsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/actions-first.json"));
+
+ Iterable<Action> actions = api.actionApi().list(page(1).perPage(5));
+
+ assertEquals(size(actions), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/actions?page=1&per_page=5");
+ }
+
+ public void testListActionsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Action> actions = api.actionApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(actions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/actions?page=1&per_page=5");
+ }
+
+ public void testGetAction() throws InterruptedException {
+ server.enqueue(jsonResponse("/action.json"));
+
+ Action action = api.actionApi().get(1);
+
+ assertEquals(action, actionFromResource("/action.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/actions/1");
+ }
+
+ public void testGetActionReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Action action = api.actionApi().get(1);
+
+ assertNull(action);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/actions/1");
+ }
+
+ private Action actionFromResource(String resource) {
+ return onlyObjectFromResource(resource, new TypeToken<Map<String, Action>>() {
+ private static final long serialVersionUID = 1L;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiLiveTest.java
new file mode 100644
index 0000000..f451d2e
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiLiveTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.logging.Logger.getAnonymousLogger;
+import static org.jclouds.digitalocean2.domain.Droplet.Status.ACTIVE;
+import static org.jclouds.digitalocean2.domain.Droplet.Status.OFF;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.digitalocean2.domain.Action;
+import org.jclouds.digitalocean2.domain.Backup;
+import org.jclouds.digitalocean2.domain.Droplet;
+import org.jclouds.digitalocean2.domain.DropletCreate;
+import org.jclouds.digitalocean2.domain.Image;
+import org.jclouds.digitalocean2.domain.Kernel;
+import org.jclouds.digitalocean2.domain.Key;
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.domain.Size;
+import org.jclouds.digitalocean2.domain.Snapshot;
+import org.jclouds.digitalocean2.domain.options.CreateDropletOptions;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+
+@Test(groups = "live", testName = "DropletApiLiveTest")
+public class DropletApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ private Region region;
+ private Size size;
+ private Image image;
+ private Key key;
+ private int dropletId = -1;
+
+ @BeforeClass
+ public void setupDroplet() {
+ region = firstAvailableRegion();
+ size = cheapestSizeInRegion(region);
+ image = ubuntuImageInRegion(region);
+
+ Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
+ key = api.keyApi().create(prefix + "-droplet-livetest", keyPair.get("public"));
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDown() {
+ if (key != null) {
+ api.keyApi().delete(key.id());
+ }
+ }
+
+ public void testCreate() {
+ DropletCreate dropletCreate = api().create(prefix + "-droplet-livetest", region.slug(), size.slug(), image.slug(),
+ CreateDropletOptions.builder().backupsEnabled(true).addSshKeyId(key.id()).build());
+ assertActionCompleted(getOnlyElement(dropletCreate.links().actions()).id());
+ dropletId = dropletCreate.droplet().id();
+ Droplet droplet = api().get(dropletId);
+ assertNotNull(droplet, "Droplet should not be null");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testCreate")
+ public void testListDroplets() {
+ assertTrue(api().list().concat().anyMatch(new Predicate<Droplet>() {
+ @Override
+ public boolean apply(Droplet input) {
+ return input.id() == dropletId;
+ }
+ }), "The created droplet must be in the list");
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testListKernels() {
+ Iterable<Kernel> kernels = api().listKernels(dropletId).concat();
+ assertEquals(kernels.iterator().next().name(), "DO-recovery-static-fsck");
+ }
+
+ @Test(dependsOnMethods = "testListKernels")
+ public void testPowerOff() {
+ Action action = api().powerOff(dropletId);
+ assertActionCompleted(action.id());
+ Droplet droplet = api().get(dropletId);
+ assertEquals(droplet.status(), OFF, "Droplet should be off");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testPowerOff")
+ public void testSnapshots() {
+ Action action = api().snapshot(dropletId, prefix + dropletId + "-snapshot");
+ assertActionCompleted(action.id());
+
+ List<Snapshot> snapshots = api().listSnapshots(dropletId).concat().toList();
+ assertEquals(snapshots.size(), 1, "Must contain 1 snapshot");
+
+ for (Snapshot snapshot : snapshots) {
+ try {
+ api.imageApi().delete(snapshot.id());
+ } catch (Exception ex) {
+ getAnonymousLogger().warning("Could not delete snapshot: " + snapshot.id());
+ }
+ }
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testSnapshots")
+ public void testBackups() {
+ Iterable<Backup> backups = api().listBackups(dropletId).concat();
+ // Backups are automatically taken by DO on a weekly basis, so we can't guarantee
+ // there will be any backup available. Just check that the call succeeds
+ assertNotNull(backups);
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testSnapshots")
+ public void testListActions() {
+ FluentIterable<Action> actions = api().listActions(dropletId).concat();
+ assertTrue(actions.anyMatch(new Predicate<Action>() {
+ @Override
+ public boolean apply(Action input) {
+ return "snapshot".equals(input.type());
+ }
+ }));
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testSnapshots")
+ public void testPowerOn() {
+ // Apparently droplets are automatically powered on after the snapshot process
+ Action action = api().powerOff(dropletId);
+ assertActionCompleted(action.id());
+
+ action = api().powerOn(dropletId);
+ assertActionCompleted(action.id());
+ Droplet droplet = api().get(dropletId);
+ assertEquals(droplet.status(), ACTIVE, "Droplet should be Active");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testPowerOn")
+ public void testReboot() {
+ Action action = api().reboot(dropletId);
+ assertActionCompleted(action.id());
+ Droplet droplet = api().get(dropletId);
+ assertEquals(droplet.status(), ACTIVE, "Droplet should be off");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testReboot")
+ public void testPowerCycle() {
+ Action action = api().powerCycle(dropletId);
+ assertActionCompleted(action.id());
+ Droplet droplet = api().get(dropletId);
+ assertEquals(droplet.status(), ACTIVE, "Droplet should be off");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testPowerCycle")
+ public void testShutdown() {
+ Action action = api().shutdown(dropletId);
+ assertActionCompleted(action.id());
+ // The shutdown action can fail if the shutdown command fails in the guest OS
+ // We can not guarantee that a graceful shutdown action will en up in the droplet
+ // being in OFF state
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testShutdown", alwaysRun = true)
+ public void testDelete() throws InterruptedException {
+ if (dropletId != -1) {
+ api().delete(dropletId);
+ assertNodeTerminated(dropletId);
+ assertNull(api().get(dropletId));
+ }
+ }
+
+ private DropletApi api() {
+ return api.dropletApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiMockTest.java
new file mode 100644
index 0000000..dcd6352
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/DropletApiMockTest.java
@@ -0,0 +1,401 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.digitalocean2.domain.Action;
+import org.jclouds.digitalocean2.domain.Backup;
+import org.jclouds.digitalocean2.domain.Droplet;
+import org.jclouds.digitalocean2.domain.DropletCreate;
+import org.jclouds.digitalocean2.domain.Kernel;
+import org.jclouds.digitalocean2.domain.Snapshot;
+import org.jclouds.digitalocean2.domain.options.CreateDropletOptions;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+
+@Test(groups = "unit", testName = "DropletApiMockTest", singleThreaded = true)
+public class DropletApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListDroplets() throws InterruptedException {
+ server.enqueue(jsonResponse("/droplets-first.json"));
+ server.enqueue(jsonResponse("/droplets-last.json"));
+
+ Iterable<Droplet> droplets = api.dropletApi().list().concat();
+
+ assertEquals(size(droplets), 2); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/droplets");
+ assertSent(server, "GET", "/droplets?page=2&per_page=1");
+ }
+
+ public void testListDropletsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Droplet> droplets = api.dropletApi().list().concat();
+
+ assertTrue(isEmpty(droplets));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets");
+ }
+
+ public void testListDropletsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/droplets-first.json"));
+
+ Iterable<Droplet> droplets = api.dropletApi().list(page(1).perPage(20));
+
+ assertEquals(size(droplets), 1);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/droplets?page=1&per_page=20");
+ }
+
+ public void testListDropletsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Droplet> droplets = api.dropletApi().list(page(1).perPage(20));
+
+ assertTrue(isEmpty(droplets));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets?page=1&per_page=20");
+ }
+
+ public void testGetDroplet() throws InterruptedException {
+ server.enqueue(jsonResponse("/droplet.json"));
+
+ Droplet droplet = api.dropletApi().get(1);
+
+ assertEquals(droplet, dropletFromResource("/droplet.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/1");
+ }
+
+ public void testGetDropletReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Droplet droplet = api.dropletApi().get(1);
+
+ assertNull(droplet);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/1");
+ }
+
+ public void testCreateDroplet() throws InterruptedException {
+ server.enqueue(jsonResponse("/droplet-create-res.json"));
+
+ DropletCreate droplet = api.dropletApi().create("digitalocean2-s-d5e", "sfo1", "512mb", "6374124", CreateDropletOptions.builder().addSshKeyId(421192).build());
+
+ assertEquals(droplet, objectFromResource("/droplet-create-res.json", DropletCreate.class));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets", stringFromResource("/droplet-create-req.json"));
+ }
+
+ public void testListKernels() throws InterruptedException {
+ server.enqueue(jsonResponse("/kernels-first.json"));
+ server.enqueue(jsonResponse("/kernels-last.json"));
+
+ Iterable<Kernel> kernels = api.dropletApi().listKernels(5425561).concat();
+
+ assertEquals(size(kernels), 10); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/droplets/5425561/kernels");
+ assertSent(server, "GET", "/droplets/5425561/kernels?page=2");
+ }
+
+ public void testListKernelsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Kernel> kernels = api.dropletApi().listKernels(5425561).concat();
+
+ assertTrue(isEmpty(kernels));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/kernels");
+ }
+
+ public void testListKernelsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/kernels-first.json"));
+
+ Iterable<Kernel> kernels = api.dropletApi().listKernels(5425561, page(1).perPage(20));
+
+ assertEquals(size(kernels), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/droplets/5425561/kernels?page=1&per_page=20");
+ }
+
+ public void testListKernelsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Kernel> kernels = api.dropletApi().listKernels(5425561, page(1).perPage(20));
+
+ assertTrue(isEmpty(kernels));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/kernels?page=1&per_page=20");
+ }
+
+ public void testListActions() throws InterruptedException {
+ server.enqueue(jsonResponse("/actions-first.json"));
+ server.enqueue(jsonResponse("/actions-last.json"));
+
+ Iterable<Action> actions = api.dropletApi().listActions(1).concat();
+
+ assertEquals(size(actions), 8); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/droplets/1/actions");
+ assertSent(server, "GET", "/droplets/1/actions?page=2&per_page=5");
+ }
+
+ public void testListActionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Action> actions = api.dropletApi().listActions(1).concat();
+
+ assertTrue(isEmpty(actions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/1/actions");
+ }
+
+ public void testListActionsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/actions-first.json"));
+
+ Iterable<Action> actions = api.dropletApi().listActions(1, page(1).perPage(5));
+
+ assertEquals(size(actions), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/droplets/1/actions?page=1&per_page=5");
+ }
+
+ public void testListActionsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Action> actions = api.dropletApi().listActions(1, page(1).perPage(5));
+
+ assertTrue(isEmpty(actions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/1/actions?page=1&per_page=5");
+ }
+
+ public void testListBackups() throws InterruptedException {
+ server.enqueue(jsonResponse("/backups-first.json"));
+ server.enqueue(jsonResponse("/backups-last.json"));
+
+ Iterable<Backup> backups = api.dropletApi().listBackups(5425561).concat();
+
+ assertEquals(size(backups), 2); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/droplets/5425561/backups");
+ assertSent(server, "GET", "/droplets/5425561/backups?page=2");
+ }
+
+ public void testListBackupsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Backup> backups = api.dropletApi().listBackups(5425561).concat();
+
+ assertTrue(isEmpty(backups));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/backups");
+ }
+
+ public void testListBackupsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/backups-first.json"));
+
+ Iterable<Backup> backups = api.dropletApi().listBackups(5425561, page(1).perPage(20));
+
+ assertEquals(size(backups), 1);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/droplets/5425561/backups?page=1&per_page=20");
+ }
+
+ public void testListBackupsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Backup> backups = api.dropletApi().listBackups(5425561, page(1).perPage(20));
+
+ assertTrue(isEmpty(backups));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/backups?page=1&per_page=20");
+ }
+
+ public void testListSnapshots() throws InterruptedException {
+ server.enqueue(jsonResponse("/snapshots-first.json"));
+ server.enqueue(jsonResponse("/snapshots-last.json"));
+
+ Iterable<Snapshot> snapshots = api.dropletApi().listSnapshots(5425561).concat();
+
+ assertEquals(size(snapshots), 2); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/droplets/5425561/snapshots");
+ assertSent(server, "GET", "/droplets/5425561/snapshots?page=2");
+ }
+
+ public void testListSnapshotsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Snapshot> snapshots = api.dropletApi().listSnapshots(5425561).concat();
+
+ assertTrue(isEmpty(snapshots));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/snapshots");
+ }
+
+ public void testListSnapshotsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/snapshots-first.json"));
+
+ Iterable<Snapshot> snapshots = api.dropletApi().listSnapshots(5425561, page(1).perPage(20));
+
+ assertEquals(size(snapshots), 1);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/droplets/5425561/snapshots?page=1&per_page=20");
+ }
+
+ public void testListSnapshotsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Snapshot> snapshots = api.dropletApi().listSnapshots(5425561, page(1).perPage(20));
+
+ assertTrue(isEmpty(snapshots));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/droplets/5425561/snapshots?page=1&per_page=20");
+ }
+
+ public void testDeleteDroplet() throws InterruptedException {
+ server.enqueue(response204());
+
+ api.dropletApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/droplets/1");
+ }
+
+ public void testDeleteDropletReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ api.dropletApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/droplets/1");
+ }
+
+ public void testPowerCycleDroplet() throws InterruptedException {
+ server.enqueue(jsonResponse("/power-cycle.json"));
+
+ Action action = api.dropletApi().powerCycle(1);
+
+ assertEquals(action, actionFromResource("/power-cycle.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"power_cycle\"}");
+ }
+
+ public void testPowerOn() throws InterruptedException {
+ server.enqueue(jsonResponse("/power-on.json"));
+
+ Action action = api.dropletApi().powerOn(1);
+
+ assertEquals(action, actionFromResource("/power-on.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"power_on\"}");
+ }
+
+ public void testPowerOff() throws InterruptedException {
+ server.enqueue(jsonResponse("/power-off.json"));
+
+ Action action = api.dropletApi().powerOff(1);
+
+ assertEquals(action, actionFromResource("/power-off.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"power_off\"}");
+ }
+
+ public void testReboot() throws InterruptedException {
+ server.enqueue(jsonResponse("/reboot.json"));
+
+ Action action = api.dropletApi().reboot(1);
+
+ assertEquals(action, actionFromResource("/reboot.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"reboot\"}");
+ }
+
+ public void testShutdown() throws InterruptedException {
+ server.enqueue(jsonResponse("/shutdown.json"));
+
+ Action action = api.dropletApi().shutdown(1);
+
+ assertEquals(action, actionFromResource("/shutdown.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"shutdown\"}");
+ }
+
+ public void testSnapshot() throws InterruptedException {
+ server.enqueue(jsonResponse("/snapshot.json"));
+
+ Action action = api.dropletApi().snapshot(1, "foo");
+
+ assertEquals(action, actionFromResource("/snapshot.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/droplets/1/actions", "{\"type\":\"snapshot\",\"name\":\"foo\"}");
+ }
+
+ private Droplet dropletFromResource(String resource) {
+ return onlyObjectFromResource(resource, new TypeToken<Map<String, Droplet>>() {
+ private static final long serialVersionUID = 1L;
+ });
+ }
+
+ private Action actionFromResource(String resource) {
+ return onlyObjectFromResource(resource, new TypeToken<Map<String, Action>>() {
+ private static final long serialVersionUID = 1L;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiLiveTest.java
new file mode 100644
index 0000000..8c4c96e
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiLiveTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.digitalocean2.features;
+
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.Builder.page;
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.Builder.type;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Image;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "ImageApiLiveTest")
+public class ImageApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListImages() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Image>() {
+ @Override
+ public boolean apply(Image input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.name());
+ }
+ }), "All images must have the 'name' field populated");
+ assertTrue(found.get() > 0, "Expected some images to be returned");
+ }
+
+ public void testListImagesOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1).perPage(5)).allMatch(new Predicate<Image>() {
+ @Override
+ public boolean apply(Image input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.name());
+ }
+ }), "All images must have the 'name' field populated");
+ assertTrue(found.get() > 0, "Expected some images to be returned");
+ }
+
+ public void testListImagesByType() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(type("distribution").perPage(5)).allMatch(new Predicate<Image>() {
+ @Override
+ public boolean apply(Image input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.distribution());
+ }
+ }), "All images must have the 'distribution' field populated");
+ assertTrue(found.get() > 0, "Expected some images to be returned");
+ }
+
+ public void testGetImage() {
+ Optional<Image> first = api().list().concat().first();
+ assertTrue(first.isPresent(), "At least one image was expected to exist");
+ assertNotNull(api().get(first.get().id()));
+ }
+
+ public void testGetImageBySlug() {
+ Optional<Image> first = api().list().concat().firstMatch(new Predicate<Image>() {
+ @Override
+ public boolean apply(Image input) {
+ return !isNullOrEmpty(input.slug());
+ }
+ });
+
+ assertTrue(first.isPresent(), "At least one image with the 'slug' field set was expected to exist");
+ assertNotNull(api().get(first.get().slug()));
+ }
+
+ // TODO: Delete live test once the create/transfer operations are implemented
+
+ private ImageApi api() {
+ return api.imageApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiMockTest.java
new file mode 100644
index 0000000..d172174
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/ImageApiMockTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.digitalocean2.domain.Image;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+
+@Test(groups = "unit", testName = "ImageApiMockTest", singleThreaded = true)
+public class ImageApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListImages() throws InterruptedException {
+ server.enqueue(jsonResponse("/images-first.json"));
+ server.enqueue(jsonResponse("/images-last.json"));
+
+ Iterable<Image> images = api.imageApi().list().concat();
+
+ assertEquals(size(images), 10); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/images");
+ assertSent(server, "GET", "/images?page=2&per_page=5&type=distribution");
+ }
+
+ public void testListImagesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Image> images = api.imageApi().list().concat();
+
+ assertTrue(isEmpty(images));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images");
+ }
+
+ public void testListImagesWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/images-first.json"));
+
+ Iterable<Image> images = api.imageApi().list(page(1).perPage(5).type("distribution"));
+
+ assertEquals(size(images), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/images?page=1&per_page=5&type=distribution");
+ }
+
+ public void testListImagesWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Image> images = api.imageApi().list(page(1).perPage(5).type("distribution"));
+
+ assertTrue(isEmpty(images));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images?page=1&per_page=5&type=distribution");
+ }
+
+ public void testGetImage() throws InterruptedException {
+ server.enqueue(jsonResponse("/image.json"));
+
+ Image image = api.imageApi().get(1);
+
+ assertEquals(image, imageFromResource("/image.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images/1");
+ }
+
+ public void testGetImageReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Image image = api.imageApi().get(1);
+
+ assertNull(image);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images/1");
+ }
+
+ public void testGetImageUsingSlug() throws InterruptedException {
+ server.enqueue(jsonResponse("/image.json"));
+
+ Image image = api.imageApi().get("foo");
+
+ assertEquals(image, imageFromResource("/image.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images/foo");
+ }
+
+ public void testGetImageUsingSlugReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Image image = api.imageApi().get("foo");
+
+ assertNull(image);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/images/foo");
+ }
+
+ public void testDeleteImage() throws InterruptedException {
+ server.enqueue(response204());
+
+ api.imageApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/images/1");
+ }
+
+ public void testDeleteImageReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ api.imageApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/images/1");
+ }
+
+ private Image imageFromResource(String resource) {
+ return onlyObjectFromResource(resource, new TypeToken<Map<String, Image>>() {
+ private static final long serialVersionUID = 1L;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiLiveTest.java
new file mode 100644
index 0000000..2911d79
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiLiveTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.digitalocean2.features;
+
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.jclouds.digitalocean2.domain.Key;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.common.collect.FluentIterable;
+import com.google.common.io.Resources;
+
+@Test(groups = "live", testName = "KeyApiLiveTest")
+public class KeyApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ private Key dsa;
+ private Key ecdsa;
+
+ public void testCreateKey() {
+ dsa = api().create("jclouds-test-dsa", loadKey("/ssh-dsa.pub"));
+ ecdsa = api().create("jclouds-test-ecdsa", loadKey("/ssh-ecdsa.pub"));
+
+ assertEquals(dsa.name(), "jclouds-test-dsa");
+ assertEquals(ecdsa.name(), "jclouds-test-ecdsa");
+ }
+
+ @Test(dependsOnMethods = "testCreateKey")
+ public void testListKeys() {
+ FluentIterable<Key> keys = api().list().concat();
+ assertTrue(keys.size() >= 2, "At least the two created keys must exist");
+ }
+
+ @Test(dependsOnMethods = "testCreateKey")
+ public void testListKeysOnePAge() {
+ FluentIterable<Key> keys = api().list(page(1));
+ assertTrue(keys.size() >= 2, "At least the two created keys must exist");
+ }
+
+ @Test(dependsOnMethods = "testCreateKey")
+ public void testGetKey() {
+ assertEquals(api().get(dsa.id()).fingerprint(), dsa.fingerprint());
+ assertEquals(api().get(ecdsa.fingerprint()).id(), ecdsa.id());
+ }
+
+ @Test(dependsOnMethods = "testCreateKey")
+ public void testUpdateKey() {
+ api().update(dsa.id(), "jclouds-test-dsa-updated");
+ assertEquals(api().get(dsa.id()).name(), "jclouds-test-dsa-updated");
+ api().update(dsa.fingerprint(), "jclouds-test-dsa-updated2");
+ assertEquals(api().get(dsa.id()).name(), "jclouds-test-dsa-updated2");
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void testDeleteKey() {
+ if (dsa != null) {
+ api().delete(dsa.id());
+ FluentIterable<Key> keys = api().list().concat();
+ assertFalse(keys.contains(dsa), "dsa key must not be present in list");
+ }
+ if (ecdsa != null) {
+ api().delete(ecdsa.fingerprint());
+ FluentIterable<Key> keys = api().list().concat();
+ assertFalse(keys.contains(ecdsa), "dsa key must not be present in list");
+ }
+ }
+
+ private String loadKey(String resourceName) {
+ try {
+ return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ private KeyApi api() {
+ return api.keyApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiMockTest.java
new file mode 100644
index 0000000..2f9d5d3
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/KeyApiMockTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.jclouds.digitalocean2.domain.Key;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+
+@Test(groups = "unit", testName = "KeyApiMockTest", singleThreaded = true)
+public class KeyApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListKeys() throws InterruptedException {
+ server.enqueue(jsonResponse("/keys-first.json"));
+ server.enqueue(jsonResponse("/keys-last.json"));
+
+ Iterable<Key> keys = api.keyApi().list().concat();
+
+ assertEquals(size(keys), 7); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/account/keys");
+ assertSent(server, "GET", "/account/keys?page=2&per_page=5");
+ }
+
+ public void testListKeysReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Key> keys = api.keyApi().list().concat();
+
+ assertTrue(isEmpty(keys));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys");
+ }
+
+ public void testListKeysWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/keys-first.json"));
+
+ Iterable<Key> keys = api.keyApi().list(page(1).perPage(5));
+
+ assertEquals(size(keys), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/account/keys?page=1&per_page=5");
+ }
+
+ public void testListKeysWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Key> keys = api.keyApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(keys));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys?page=1&per_page=5");
+ }
+
+ public void testCreateKey() throws InterruptedException {
+ server.enqueue(jsonResponse("/key.json").setStatus("HTTP/1.1 201 Created"));
+
+ String dsa = stringFromResource("/ssh-dsa.pub");
+
+ Key key = api.keyApi().create("foo", dsa);
+
+ assertEquals(key, keyFromResource("/key.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "/account/keys", String.format("{\"name\":\"foo\", \"public_key\":\"%s\"}", dsa));
+ }
+
+ public void testGetKey() throws InterruptedException {
+ server.enqueue(jsonResponse("/key.json"));
+
+ Key key = api.keyApi().get(1);
+
+ assertEquals(key, keyFromResource("/key.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys/1");
+ }
+
+ public void testGetKeyReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Key key = api.keyApi().get(1);
+
+ assertNull(key);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys/1");
+ }
+
+ public void testGetKeyUsingFingerprint() throws InterruptedException {
+ server.enqueue(jsonResponse("/key.json"));
+
+ Key key = api.keyApi().get("1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+
+ assertEquals(key, keyFromResource("/key.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys/1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+ }
+
+ public void testGetKeyUsingFingerprintReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Key key = api.keyApi().get("1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+
+ assertNull(key);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/account/keys/1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+ }
+
+ public void testUpdateKey() throws InterruptedException {
+ server.enqueue(jsonResponse("/key.json"));
+
+ Key key = api.keyApi().update(1, "foo");
+
+ assertEquals(key, keyFromResource("/key.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "PUT", "/account/keys/1", "{\"name\":\"foo\"}");
+ }
+
+ public void testUpdateKeyUsingFingerprint() throws InterruptedException {
+ server.enqueue(jsonResponse("/key.json"));
+
+ Key key = api.keyApi().update("1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90", "foo");
+
+ assertEquals(key, keyFromResource("/key.json"));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "PUT", "/account/keys/1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90", "{\"name\":\"foo\"}");
+ }
+
+ public void testDeleteKey() throws InterruptedException {
+ server.enqueue(response204());
+
+ api.keyApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/account/keys/1");
+ }
+
+ public void testDeleteKeyReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ api.keyApi().delete(1);
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/account/keys/1");
+ }
+
+ public void testDeleteKeyUsingFingerprint() throws InterruptedException {
+ server.enqueue(response204());
+
+ api.keyApi().delete("1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/account/keys/1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+ }
+
+ public void testDeleteKeyUsingfingerprintReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ api.keyApi().delete("1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "DELETE", "/account/keys/1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90");
+ }
+
+ private Key keyFromResource(String resource) {
+ return onlyObjectFromResource(resource, new TypeToken<Map<String, Key>>() {
+ private static final long serialVersionUID = 1L;
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
new file mode 100644
index 0000000..73c7451
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.digitalocean2.features;
+
+import static org.testng.Assert.assertTrue;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+import org.testng.util.Strings;
+
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "RegionApiLiveTest")
+public class RegionApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListRegions() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All regions must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some regions to be returned");
+ }
+
+ public void testListRegionsOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1)).allMatch(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All regions must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some regions to be returned");
+ }
+
+ private RegionApi api() {
+ return api.regionApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
new file mode 100644
index 0000000..8c8c326
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "RegionApiMockTest", singleThreaded = true)
+public class RegionApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListRegions() throws InterruptedException {
+ server.enqueue(jsonResponse("/regions-first.json"));
+ server.enqueue(jsonResponse("/regions-last.json"));
+
+ Iterable<Region> regions = api.regionApi().list().concat();
+
+ assertEquals(size(regions), 10); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/regions");
+ assertSent(server, "GET", "/regions?page=2&per_page=5");
+ }
+
+ public void testListRegionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Region> regions = api.regionApi().list().concat();
+
+ assertTrue(isEmpty(regions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/regions");
+ }
+
+ public void testListRegionsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/regions-first.json"));
+
+ Iterable<Region> regions = api.regionApi().list(page(1).perPage(5));
+
+ assertEquals(size(regions), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/regions?page=1&per_page=5");
+ }
+
+ public void testListRegionsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Region> regions = api.regionApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(regions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/regions?page=1&per_page=5");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
new file mode 100644
index 0000000..a9a8566
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.digitalocean2.features;
+
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Size;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+import org.testng.util.Strings;
+
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "SizeApiLiveTest")
+public class SizeApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListSizes() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Size>() {
+ @Override
+ public boolean apply(Size input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All sizes must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some sizes to be returned");
+ }
+
+ public void testListSizesOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1)).allMatch(new Predicate<Size>() {
+ @Override
+ public boolean apply(Size input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All sizes must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some sizes to be returned");
+ }
+
+ private SizeApi api() {
+ return api.sizeApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/a141b21b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
----------------------------------------------------------------------
diff --git a/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
new file mode 100644
index 0000000..7403518
--- /dev/null
+++ b/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.digitalocean2.domain.Size;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "SizeApiMockTest", singleThreaded = true)
+public class SizeApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListSizes() throws InterruptedException {
+ server.enqueue(jsonResponse("/sizes-first.json"));
+ server.enqueue(jsonResponse("/sizes-last.json"));
+
+ Iterable<Size> sizes = api.sizeApi().list().concat();
+
+ assertEquals(size(sizes), 9); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/sizes");
+ assertSent(server, "GET", "/sizes?page=2&per_page=5");
+ }
+
+ public void testListSizesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Size> sizes = api.sizeApi().list().concat();
+
+ assertTrue(isEmpty(sizes));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/sizes");
+ }
+
+ public void testListSizesWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/sizes-first.json"));
+
+ Iterable<Size> sizes = api.sizeApi().list(page(1).perPage(5));
+
+ assertEquals(size(sizes), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/sizes?page=1&per_page=5");
+ }
+
+ public void testListSizesWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Size> sizes = api.sizeApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(sizes));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/sizes?page=1&per_page=5");
+ }
+}