http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java new file mode 100644 index 0000000..9b1354e --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java @@ -0,0 +1,93 @@ +/* + * 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.chef.config; + +import static com.google.common.base.Objects.equal; +import static org.testng.Assert.assertEquals; + +import java.lang.reflect.Type; +import java.util.Map; + +import org.jclouds.chef.config.ChefParserModule.KeepLastRepeatedKeyMapTypeAdapterFactory; +import org.testng.annotations.Test; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Unit tests for the {@link ChefParserModule} class. + */ +@Test(groups = "unit", testName = "ChefParserModuleTest") +public class ChefParserModuleTest { + + private static class KeyValue { + private final String key; + private final String value; + + private KeyValue(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public int hashCode() { + return Objects.hashCode(key, value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + KeyValue that = KeyValue.class.cast(obj); + return equal(this.key, that.key) && equal(this.value, that.value); + } + } + + private Gson map = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory()) + .create(); + private Type mapType = new TypeToken<Map<String, String>>() { + private static final long serialVersionUID = 1L; + }.getType(); + private Type mapkeyValueType = new TypeToken<Map<String, KeyValue>>() { + private static final long serialVersionUID = 1L; + }.getType(); + + public void testKeepLastRepeatedKeyMapTypeAdapter() { + Map<String, String> noNulls = map.fromJson("{\"value\":\"a test string!\"}", mapType); + assertEquals(noNulls, ImmutableMap.of("value", "a test string!")); + Map<String, String> withNull = map.fromJson("{\"value\":null}", mapType); + assertEquals(withNull, ImmutableMap.of()); + Map<String, String> withEmpty = map.fromJson("{\"value\":\"\"}", mapType); + assertEquals(withEmpty, ImmutableMap.of("value", "")); + Map<String, KeyValue> keyValues = map.fromJson( + "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\"}}", + mapkeyValueType); + assertEquals(keyValues, + ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo"), "i-bar", new KeyValue("i-bar", "bar"))); + Map<String, KeyValue> duplicates = map + .fromJson( + "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\", \"value\":\"foo2\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\",\"value\":\"bar2\"}}", + mapkeyValueType); + assertEquals(duplicates, + ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo2"), "i-bar", new KeyValue("i-bar", "bar2"))); + } +}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java b/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java new file mode 100644 index 0000000..bfba190 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java @@ -0,0 +1,213 @@ +/* + * 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.chef.filters; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertEqualsNoOrder; +import static org.testng.Assert.assertTrue; + +import java.io.IOException; +import java.security.PrivateKey; + +import javax.inject.Provider; +import javax.ws.rs.HttpMethod; + +import org.jclouds.ContextBuilder; +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.crypto.Crypto; +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpUtils; +import org.jclouds.http.internal.SignatureWire; +import org.jclouds.logging.config.NullLoggingModule; +import org.jclouds.rest.internal.BaseRestApiTest.MockModule; +import org.jclouds.util.Strings2; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.Joiner; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.net.HttpHeaders; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; + +@Test(groups = { "unit" }) +public class SignedHeaderAuthTest { + + public static final String USER_ID = "spec-user"; + public static final String BODY = "Spec Body"; + // Base64.encode64(Digest::SHA1.digest("Spec Body")).chomp + public static final String HASHED_BODY = "DFteJZPVv6WKdQmMqZUQUumUyRs="; + public static final String TIMESTAMP_ISO8601 = "2009-01-01T12:00:00Z"; + + public static final String PATH = "/organizations/clownco"; + // Base64.encode64(Digest::SHA1.digest("/organizations/clownco")).chomp + + public static final String HASHED_CANONICAL_PATH = "YtBWDn1blGGuFIuKksdwXzHU9oE="; + public static final String REQUESTING_ACTOR_ID = "c0f8a68c52bffa1020222a56b23cccfa"; + + // Content hash is ???TODO + public static final String X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs="; + + public static final String[] X_OPS_AUTHORIZATION_LINES = new String[] { + "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4", + "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc", + "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O", + "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy", + "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" }; + + // We expect Mixlib::Authentication::SignedHeaderAuth//sign to return this + // if passed the BODY above. + public static final Multimap<String, String> EXPECTED_SIGN_RESULT = ImmutableMultimap.<String, String> builder() + .put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put("X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0") + .put("X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0]) + .put("X-Ops-Authorization-2", X_OPS_AUTHORIZATION_LINES[1]) + .put("X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2]) + .put("X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3]) + .put("X-Ops-Authorization-5", X_OPS_AUTHORIZATION_LINES[4]) + .put("X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); + + // Content hash for empty string + public static final String X_OPS_CONTENT_HASH_EMPTY = "2jmj7l5rSw0yVb/vlWAYkK/YBwk="; + public static final Multimap<String, String> EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap + .<String, String> builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put("X-Ops-Userid", USER_ID) + .put("X-Ops-Sign", "version=1.0") + .put("X-Ops-Authorization-1", "N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx") + .put("X-Ops-Authorization-2", "mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P") + .put("X-Ops-Authorization-3", "3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG") + .put("X-Ops-Authorization-4", "09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI") + .put("X-Ops-Authorization-5", "svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC") + .put("X-Ops-Authorization-6", "DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==") + .put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); + + public static String PUBLIC_KEY; + public static String PRIVATE_KEY; + + static { + try { + PUBLIC_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/pubkey.txt")); + + PRIVATE_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/privkey.txt")); + } catch (IOException e) { + Throwables.propagate(e); + } + } + + @Test + void canonicalizedPathRemovesMultipleSlashes() { + assertEquals(signing_obj.canonicalPath("///"), "/"); + } + + @Test + void canonicalizedPathRemovesTrailingSlash() { + assertEquals(signing_obj.canonicalPath("/path/"), "/path"); + } + + @Test + void shouldGenerateTheCorrectStringToSignAndSignature() { + + HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost/" + PATH) + .payload(BODY).build(); + + String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n").append("Hashed Path:") + .append(HASHED_CANONICAL_PATH).append("\n").append("X-Ops-Content-Hash:").append(HASHED_BODY).append("\n") + .append("X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append("X-Ops-UserId:").append(USER_ID) + .toString(); + + assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, TIMESTAMP_ISO8601), + expected_string_to_sign); + assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join(X_OPS_AUTHORIZATION_LINES)); + + request = signing_obj.filter(request); + Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); + headersWithoutContentLength.removeAll(HttpHeaders.CONTENT_LENGTH); + assertEqualsNoOrder(headersWithoutContentLength.values().toArray(), EXPECTED_SIGN_RESULT.values().toArray()); + } + + @Test + void shouldGenerateTheCorrectStringToSignAndSignatureWithNoBody() { + + HttpRequest request = HttpRequest.builder().method(HttpMethod.DELETE).endpoint("http://localhost/" + PATH) + .build(); + + request = signing_obj.filter(request); + Multimap<String, String> headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); + assertEqualsNoOrder(headersWithoutContentLength.entries().toArray(), EXPECTED_SIGN_RESULT_EMPTY.entries() + .toArray()); + } + + @Test + void shouldNotChokeWhenSigningARequestForAResourceWithALongName() { + StringBuilder path = new StringBuilder("nodes/"); + for (int i = 0; i < 100; i++) + path.append('A'); + HttpRequest request = HttpRequest.builder().method(HttpMethod.PUT) + .endpoint("http://localhost/" + path.toString()).payload(BODY).build(); + + signing_obj.filter(request); + } + + @Test + void shouldReplacePercentage3FWithQuestionMarkAtUrl() { + StringBuilder path = new StringBuilder("nodes/"); + path.append("test/cookbooks/myCookBook%3Fnum_versions=5"); + HttpRequest request = HttpRequest.builder().method(HttpMethod.GET) + .endpoint("http://localhost/" + path.toString()).payload(BODY).build(); + request = signing_obj.filter(request); + assertTrue(request.getRequestLine().contains("?num_versions=5")); + } + + private SignedHeaderAuth signing_obj; + + /** + * before class, as we need to ensure that the filter is threadsafe. + * + * @throws IOException + * + */ + @BeforeClass + protected void createFilter() throws IOException { + + Injector injector = ContextBuilder.newBuilder(new ChefApiMetadata()).credentials(USER_ID, PRIVATE_KEY) + .modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule())).buildInjector(); + + HttpUtils utils = injector.getInstance(HttpUtils.class); + Crypto crypto = injector.getInstance(Crypto.class); + + Supplier<PrivateKey> privateKey = injector.getInstance(Key.get(new TypeLiteral<Supplier<PrivateKey>>() { + })); + + signing_obj = new SignedHeaderAuth(new SignatureWire(), + Suppliers.ofInstance(new Credentials(USER_ID, PRIVATE_KEY)), privateKey, new Provider<String>() { + + @Override + public String get() { + return TIMESTAMP_ISO8601; + } + + }, utils, crypto); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java new file mode 100644 index 0000000..f326482 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java @@ -0,0 +1,74 @@ +/* + * 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.chef.functions; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApi; +import org.jclouds.chef.domain.Client; +import org.jclouds.chef.domain.DatabagItem; +import org.jclouds.rest.annotations.Api; +import org.testng.annotations.Test; + +@Test(groups = "unit", testName = "BootstrapConfigForGroupTest") +public class BootstrapConfigForGroupTest { + + @Test(expectedExceptions = IllegalStateException.class) + public void testWhenNoDatabagItem() throws IOException { + ChefApi chefApi = createMock(ChefApi.class); + Client client = createMock(Client.class); + + BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi); + + expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(null); + + replay(client); + replay(chefApi); + + fn.apply("foo"); + + verify(client); + verify(chefApi); + } + + @Test + public void testReturnsItem() throws IOException { + ChefApi chefApi = createMock(ChefApi.class); + Api api = createMock(Api.class); + + BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi); + DatabagItem config = new DatabagItem("foo", + "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}"); + + expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(config); + + replay(api); + replay(chefApi); + + assertEquals(fn.apply("foo"), config); + + verify(api); + verify(chefApi); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java new file mode 100644 index 0000000..4be873c --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java @@ -0,0 +1,106 @@ +/* + * 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.chef.functions; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.security.PrivateKey; + +import org.jclouds.chef.ChefApi; +import org.jclouds.chef.domain.Client; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +@Test(groups = "unit", testName = "ClientForGroupTest") +public class ClientForGroupTest { + + public void testWhenNoClientsInList() throws IOException { + ChefApi chefApi = createMock(ChefApi.class); + Client client = createMock(Client.class); + PrivateKey privateKey = createMock(PrivateKey.class); + + ClientForGroup fn = new ClientForGroup(chefApi); + + expect(chefApi.listClients()).andReturn(ImmutableSet.<String> of()); + expect(chefApi.createClient("foo-client-00")).andReturn(client); + expect(client.getPrivateKey()).andReturn(privateKey); + + replay(client); + replay(chefApi); + + Client compare = fn.apply("foo"); + assertEquals(compare.getClientname(), "foo-client-00"); + assertEquals(compare.getName(), "foo-client-00"); + assertEquals(compare.getPrivateKey(), privateKey); + + verify(client); + verify(chefApi); + } + + public void testWhenClientsInListAddsToEnd() throws IOException { + ChefApi chefApi = createMock(ChefApi.class); + Client client = createMock(Client.class); + PrivateKey privateKey = createMock(PrivateKey.class); + + ClientForGroup fn = new ClientForGroup(chefApi); + + expect(chefApi.listClients()).andReturn( + ImmutableSet.<String> of("foo-client-00", "foo-client-01", "foo-client-02")); + expect(chefApi.createClient("foo-client-03")).andReturn(client); + expect(client.getPrivateKey()).andReturn(privateKey); + + replay(client); + replay(chefApi); + + Client compare = fn.apply("foo"); + assertEquals(compare.getClientname(), "foo-client-03"); + assertEquals(compare.getName(), "foo-client-03"); + assertEquals(compare.getPrivateKey(), privateKey); + + verify(client); + verify(chefApi); + } + + public void testWhenClientsInListReplacesMissing() throws IOException { + ChefApi chefApi = createMock(ChefApi.class); + Client client = createMock(Client.class); + PrivateKey privateKey = createMock(PrivateKey.class); + + ClientForGroup fn = new ClientForGroup(chefApi); + + expect(chefApi.listClients()).andReturn(ImmutableSet.<String> of("foo-client-00", "foo-client-02")); + expect(chefApi.createClient("foo-client-01")).andReturn(client); + expect(client.getPrivateKey()).andReturn(privateKey); + + replay(client); + replay(chefApi); + + Client compare = fn.apply("foo"); + assertEquals(compare.getClientname(), "foo-client-01"); + assertEquals(compare.getName(), "foo-client-01"); + assertEquals(compare.getPrivateKey(), privateKey); + + verify(client); + verify(chefApi); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java new file mode 100644 index 0000000..8792025 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java @@ -0,0 +1,230 @@ +/* + * 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.chef.functions; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS; +import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM; +import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.security.PrivateKey; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefBootstrapModule; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.config.InstallChef; +import org.jclouds.chef.domain.DatabagItem; +import org.jclouds.crypto.PemsTest; +import org.jclouds.domain.JsonBall; +import org.jclouds.json.Json; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.jclouds.scriptbuilder.domain.OsFamily; +import org.jclouds.scriptbuilder.domain.ShellToken; +import org.jclouds.scriptbuilder.domain.Statement; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.Charsets; +import com.google.common.base.Functions; +import com.google.common.base.Optional; +import com.google.common.base.Suppliers; +import com.google.common.cache.CacheLoader; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Resources; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; + +@Test(groups = "unit", testName = "GroupToBootScriptTest") +public class GroupToBootScriptTest { + + private Json json; + private Statement installChefGems; + private Statement installChefOmnibus; + private Optional<String> validatorName; + + @BeforeClass + public void setup() { + Injector injectorGems = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true"); + bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true"); + bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("false"); + } + }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule()); + + Injector injectorOmnibus = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true"); + bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true"); + bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("true"); + } + }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule()); + + json = injectorGems.getInstance(Json.class); + installChefGems = injectorGems.getInstance(Key.get(Statement.class, InstallChef.class)); + installChefOmnibus = injectorOmnibus.getInstance(Key.get(Statement.class, InstallChef.class)); + validatorName = Optional.<String> of("chef-validator"); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testMustHaveValidatorName() { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems, + Optional.<String> absent(), validatorCredential); + fn.apply("foo"); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testMustHaveValidatorCredential() { + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems, + validatorName, Optional.<PrivateKey> absent()); + fn.apply("foo"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Key 'foo' not present in map") + public void testMustHaveRunScriptsName() { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of())), installChefGems, + validatorName, validatorCredential); + fn.apply("foo"); + } + + @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "null value in entry: foo=null") + public void testMustHaveRunScriptsValue() { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, DatabagItem> of("foo", (DatabagItem) null))), + installChefGems, validatorName, validatorCredential); + fn.apply("foo"); + } + + public void testOneRecipe() throws IOException { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall( + "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), + installChefGems, validatorName, validatorCredential); + + PrivateKey validatorKey = validatorCredential.get(); + expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); + replay(validatorKey); + + assertEquals( + fn.apply("foo").render(OsFamily.UNIX), + exitInsteadOfReturn( + OsFamily.UNIX, + Resources.toString(Resources.getResource("test_install_ruby." + ShellToken.SH.to(OsFamily.UNIX)), + Charsets.UTF_8) + + Resources.toString( + Resources.getResource("test_install_rubygems." + ShellToken.SH.to(OsFamily.UNIX)), + Charsets.UTF_8) + + "gem install chef --no-rdoc --no-ri\n" + + Resources.toString(Resources.getResource("bootstrap.sh"), Charsets.UTF_8))); + + verify(validatorKey); + } + + public void testOneRecipeAndEnvironment() throws IOException { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall( + "{\"tomcat6\":{\"ssl_port\":8433},\"environment\":\"env\"," + + "\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), installChefGems, + validatorName, validatorCredential); + + PrivateKey validatorKey = validatorCredential.get(); + expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); + replay(validatorKey); + + assertEquals( + fn.apply("foo").render(OsFamily.UNIX), + exitInsteadOfReturn( + OsFamily.UNIX, + Resources.toString(Resources.getResource("test_install_ruby." + ShellToken.SH.to(OsFamily.UNIX)), + Charsets.UTF_8) + + Resources.toString( + Resources.getResource("test_install_rubygems." + ShellToken.SH.to(OsFamily.UNIX)), + Charsets.UTF_8) + + "gem install chef --no-rdoc --no-ri\n" + + Resources.toString(Resources.getResource("bootstrap-env.sh"), Charsets.UTF_8))); + + verify(validatorKey); + } + + public void testOneRecipeOmnibus() throws IOException { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall( + "{\"tomcat6\":{\"ssl_port\":8433},\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), + installChefOmnibus, validatorName, validatorCredential); + + PrivateKey validatorKey = validatorCredential.get(); + expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); + replay(validatorKey); + + assertEquals( + fn.apply("foo").render(OsFamily.UNIX), + "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + + Resources.toString(Resources.getResource("bootstrap.sh"), Charsets.UTF_8)); + + verify(validatorKey); + } + + public void testOneRecipeAndEnvironmentOmnibus() throws IOException { + Optional<PrivateKey> validatorCredential = Optional.of(createMock(PrivateKey.class)); + GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), json, + CacheLoader.from(Functions.forMap(ImmutableMap.<String, JsonBall> of("foo", new JsonBall( + "{\"tomcat6\":{\"ssl_port\":8433},\"environment\":\"env\"," + + "\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}")))), installChefOmnibus, + validatorName, validatorCredential); + + PrivateKey validatorKey = validatorCredential.get(); + expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); + replay(validatorKey); + + assertEquals( + fn.apply("foo").render(OsFamily.UNIX), + "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + + Resources.toString(Resources.getResource("bootstrap-env.sh"), Charsets.UTF_8)); + + verify(validatorKey); + } + + private static String exitInsteadOfReturn(OsFamily family, String input) { + return input.replaceAll(ShellToken.RETURN.to(family), ShellToken.EXIT.to(family)); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java new file mode 100644 index 0000000..e8bebcb --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java @@ -0,0 +1,98 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.Client; +import org.jclouds.crypto.Crypto; +import org.jclouds.crypto.Pems; +import org.jclouds.encryption.internal.JCECrypto; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.io.Payloads; +import org.jclouds.io.payloads.RSADecryptingPayload; +import org.jclouds.io.payloads.RSAEncryptingPayload; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.base.Charsets; +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseClientFromJson} + */ +@Test(groups = { "unit" }) +public class ParseClientFromJsonTest { + + private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGB AMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n"; + private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-- ---END CERTIFICATE-----\n"; + private ParseJson<Client> handler; + private Crypto crypto; + private PrivateKey privateKey; + private X509Certificate certificate; + + @BeforeTest + protected void setUpInjector() throws IOException, CertificateException, InvalidKeySpecException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Client>>() { + })); + crypto = injector.getInstance(Crypto.class); + certificate = Pems.x509Certificate(ByteSource.wrap(CERTIFICATE.getBytes(Charsets.UTF_8)), null); + privateKey = crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(ByteSource.wrap(PRIVATE_KEY.getBytes(Charsets.UTF_8)))); + } + + public void test() throws IOException, CertificateException, NoSuchAlgorithmException { + + Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest") + .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).build(); + + byte[] encrypted = ByteStreams.toByteArray(new RSAEncryptingPayload(new JCECrypto(), Payloads.newPayload("fooya"), user + .getCertificate().getPublicKey())); + + assertEquals( + ByteStreams.toByteArray(new RSADecryptingPayload(new JCECrypto(), Payloads.newPayload(encrypted), user.getPrivateKey())), + "fooya".getBytes()); + + assertEquals( + handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseClientFromJsonTest.class.getResourceAsStream("/client.json")).build()), user); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.java new file mode 100644 index 0000000..300c8e0 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersionTest.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.chef.functions; + +import static org.testng.Assert.assertTrue; + +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseCookbookDefinitionCheckingChefVersion}. + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookDefinitionCheckingChefVersionTest { + + public void testParserFor09() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.9.8"); + } + }, new ChefParserModule(), new GsonModule()); + + ParseCookbookDefinitionCheckingChefVersion parser = injector + .getInstance(ParseCookbookDefinitionCheckingChefVersion.class); + assertTrue(parser.parser instanceof ParseKeySetFromJson); + } + + public void testParserFor010() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.10.8"); + } + }, new ChefParserModule(), new GsonModule()); + + ParseCookbookDefinitionCheckingChefVersion parser = injector + .getInstance(ParseCookbookDefinitionCheckingChefVersion.class); + assertTrue(parser.parser instanceof ParseCookbookDefinitionFromJson); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java new file mode 100644 index 0000000..736b283 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java @@ -0,0 +1,72 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseCookbookDefinitionFromJson}. + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookDefinitionFromJsonTest { + + private ParseCookbookDefinitionFromJson handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseCookbookDefinitionFromJson.class); + } + + public void testParse010Response() { + assertEquals(handler.apply(HttpResponse + .builder() + .statusCode(200) + .message("ok") + .payload( + "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + + "\"version\" => \"5.1.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + + "\"version\" => \"4.2.0\"}" + "]" + "}," + "\"nginx\" => {" + + "\"url\" => \"http://localhost:4000/cookbooks/nginx\"," + "\"versions\" => [" + + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\"," + "\"version\" => \"1.0.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\"," + "\"version\" => \"0.3.0\"}" + + "]" + "}" + "}").build()), ImmutableSet.of("apache2", "nginx")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java new file mode 100644 index 0000000..b5d8a8b --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10Test.java @@ -0,0 +1,74 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.CookbookDefinition; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookDefinitionFromJsonv10Test { + + private ParseCookbookDefinitionFromJsonv10 handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseCookbookDefinitionFromJsonv10.class); + } + + public void testCookbokDefinitionParsing() throws URISyntaxException { + CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); + CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); + CookbookDefinition definition = CookbookDefinition.builder() + .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); + + assertEquals(handler.apply(HttpResponse + .builder() + .statusCode(200) + .message("ok") + .payload( + "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + + "\"version\" => \"5.1.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), definition); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java new file mode 100644 index 0000000..04f8e35 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10Test.java @@ -0,0 +1,92 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.CookbookDefinition; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +@Test(groups = {"unit"}, singleThreaded = true) +public class ParseCookbookDefinitionListFromJsonv10Test { + + private ParseCookbookDefinitionListFromJsonv10 handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseCookbookDefinitionListFromJsonv10.class); + } + + public void testCookbokDefinitionListParsing() throws URISyntaxException { + CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); + CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); + CookbookDefinition apache2 = CookbookDefinition.builder() + .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); + + CookbookDefinition.Version v100 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/nginx/1.0.0")).version("1.0.0").build(); + CookbookDefinition.Version v030 = CookbookDefinition.Version.builder() + .url(new URI("http://localhost:4000/cookbooks/nginx/0.3.0")).version("0.3.0").build(); + CookbookDefinition nginx = CookbookDefinition.builder() + .name("nginx").url(new URI("http://localhost:4000/cookbooks/nginx")).version(v100).version(v030).build(); + + assertEquals(handler.apply(HttpResponse + .builder() + .statusCode(200) + .message("ok") + .payload( + "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + + "\"version\" => \"5.1.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + + "\"version\" => \"4.2.0\"}" + "]" + "}," + + "\"nginx\" => {" + + "\"url\" => \"http://localhost:4000/cookbooks/nginx\"," + + "\"versions\" => [" + + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\"," + + "\"version\" => \"1.0.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\"," + + "\"version\" => \"0.3.0\"}" + + "]}" + + "}").build()), + ImmutableSet.of(apache2, nginx)); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java new file mode 100644 index 0000000..7bc19bf --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java @@ -0,0 +1,129 @@ +/* + * 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.chef.functions; + +import static com.google.common.io.BaseEncoding.base16; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.CookbookVersion; +import org.jclouds.chef.domain.Metadata; +import org.jclouds.chef.domain.Resource; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.json.Json; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseCookbookVersionFromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookVersionFromJsonTest { + + private ParseJson<CookbookVersion> handler; + private Injector injector; + private Json json; + + @BeforeTest + protected void setUpInjector() throws IOException { + injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + json = injector.getInstance(Json.class); + handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<CookbookVersion>>() { + })); + } + + public void testBrew() throws IOException { + CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/brew-cookbook.json")).build()); + + assertEquals(cookbook, + handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); + } + + public void testTomcat() { + CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/tomcat-cookbook.json")).build()); + + assertEquals(cookbook, + handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); + } + + public void testMysql() throws IOException { + CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/mysql-cookbook.json")).build()); + + assertEquals(cookbook, + handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); + } + + public void testApache() { + CookbookVersion fromJson = handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/apache-chef-demo-cookbook.json")) + .build()); + + CookbookVersion expected = CookbookVersion + .builder("apache-chef-demo", "0.0.0") + .metadata(Metadata.builder() // + .license("Apache v2.0") // + .maintainer("Your Name") // + .maintainerEmail("[email protected]") // + .description("A fabulous new cookbook") // + .version("0.0.0").name("apache-chef-demo") // + .longDescription("") // + .build()) + .rootFile( + Resource + .builder() + .name("README") + .path("README") + .checksum(base16().lowerCase().decode("11637f98942eafbf49c71b7f2f048b78")) + .url(URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D")) // + .build()) + .rootFile( + Resource + .builder() + .name("Rakefile") + .path("Rakefile") + .checksum(base16().lowerCase().decode("ebcf925a1651b4e04b9cd8aac2bc54eb")) + .url(URI + .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D")) + .build()) // + .build(); + + assertEquals(fromJson, expected); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.java new file mode 100644 index 0000000..bad0edf --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersionTest.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.chef.functions; + +import static org.testng.Assert.assertTrue; + +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseCookbookVersionsCheckingChefVersion}. + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookVersionsCheckingChefVersionTest { + + public void testParserFor09() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.9.8"); + } + }, new ChefParserModule(), new GsonModule()); + + ParseCookbookVersionsCheckingChefVersion parser = injector + .getInstance(ParseCookbookVersionsCheckingChefVersion.class); + assertTrue(parser.parser instanceof ParseCookbookVersionsV09FromJson); + } + + public void testParserFor010() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance("0.10.8"); + } + }, new ChefParserModule(), new GsonModule()); + + ParseCookbookVersionsCheckingChefVersion parser = injector + .getInstance(ParseCookbookVersionsCheckingChefVersion.class); + assertTrue(parser.parser instanceof ParseCookbookVersionsV10FromJson); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java new file mode 100644 index 0000000..08cf1d2 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJsonTest.java @@ -0,0 +1,61 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseCookbookVersionsV09FromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookVersionsV09FromJsonTest { + + private ParseCookbookVersionsV09FromJson handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseCookbookVersionsV09FromJson.class); + } + + public void testRegex() { + assertEquals( + handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload("{\"apache2\": [\"0.1.8\", \"0.2\"]}").build()), ImmutableSet.of("0.1.8", "0.2")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java new file mode 100644 index 0000000..e8b396a --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJsonTest.java @@ -0,0 +1,68 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseCookbookVersionsV10FromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseCookbookVersionsV10FromJsonTest { + + private ParseCookbookVersionsV10FromJson handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseCookbookVersionsV10FromJson.class); + } + + public void testRegex() { + assertEquals(handler.apply(HttpResponse + .builder() + .statusCode(200) + .message("ok") + .payload( + "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + + "\"version\" => \"5.1.0\"}," + + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), ImmutableSet.of("5.1.0", "4.2.0")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java new file mode 100644 index 0000000..5dde523 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.DatabagItem; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.json.Json; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +@Test(groups = { "unit" }) +public class ParseDataBagItemFromJsonTest { + private ParseJson<DatabagItem> handler; + private Json mapper; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<DatabagItem>>() { + })); + mapper = injector.getInstance(Json.class); + } + + public void test1() { + String json = "{\"my_key\":\"my_data\",\"id\":\"item1\"}"; + DatabagItem item = new DatabagItem("item1", json); + assertEquals(handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json).build()), item); + assertEquals(mapper.toJson(item), json); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java new file mode 100644 index 0000000..940e858 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java @@ -0,0 +1,42 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.UnknownHostException; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +@Test(groups = { "unit" }) +public class ParseErrorFromJsonOrReturnBodyTest { + + @Test + public void testApplyInputStreamDetails() throws UnknownHostException { + InputStream is = Strings2 + .toInputStream("{\"error\":[\"invalid tarball: tarball root must contain java-bytearray\"]}"); + + ParseErrorFromJsonOrReturnBody parser = new ParseErrorFromJsonOrReturnBody(new ReturnStringIf2xx()); + String response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build()); + assertEquals(response, "invalid tarball: tarball root must contain java-bytearray"); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java new file mode 100644 index 0000000..8c646b2 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java @@ -0,0 +1,66 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ParseKeySetFromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseKeySetFromJsonTest { + + private ParseKeySetFromJson handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(ParseKeySetFromJson.class); + } + + public void testRegex() { + assertEquals( + handler.apply(HttpResponse + .builder() + .statusCode(200) + .message("ok") + .payload( + "{\n\"opscode-validator\": \"https://api.opscode.com/...\", \"pimp-validator\": \"https://api.opscode.com/...\"}") + .build()), ImmutableSet.of("opscode-validator", "pimp-validator")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java new file mode 100644 index 0000000..72b4956 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.Node; +import org.jclouds.domain.JsonBall; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseNodeFromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseNodeFromJsonTest { + + private ParseJson<Node> handler; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Node>>() { + })); + } + + public void test() { + Node node = Node.builder() // + .name("adrian-jcloudstest") // + .normalAttribute("tomcat6", new JsonBall("{\"ssl_port\":8433}")) // + .runListElement("recipe[java]") // + .environment("prod") // + .build(); + + assertEquals( + handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/node.json")).build()), node); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java new file mode 100644 index 0000000..dd31d38 --- /dev/null +++ b/apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java @@ -0,0 +1,71 @@ +/* + * 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.chef.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.chef.ChefApiMetadata; +import org.jclouds.chef.config.ChefParserModule; +import org.jclouds.chef.domain.Sandbox; +import org.jclouds.date.DateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.ApiVersion; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; + +/** + * Tests behavior of {@code ParseSandboxFromJson} + */ +@Test(groups = { "unit" }, singleThreaded = true) +public class ParseSandboxFromJsonTest { + + private ParseJson<Sandbox> handler; + private DateService dateService; + + @BeforeTest + protected void setUpInjector() throws IOException { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); + } + }, new ChefParserModule(), new GsonModule()); + + handler = injector.getInstance(Key.get(new TypeLiteral<ParseJson<Sandbox>>() { + })); + dateService = injector.getInstance(DateService.class); + } + + public void test() { + assertEquals( + handler.apply(HttpResponse.builder().statusCode(200).message("ok") + .payload(ParseSandboxFromJsonTest.class.getResourceAsStream("/sandbox.json")).build()), + Sandbox.builder().rev("1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2").isCompleted(false) + .createTime(dateService.iso8601SecondsDateParse("2010-07-07T03:36:00+00:00")) + .name("f9d6d9b72bae465890aae87969f98a9c").guid("f9d6d9b72bae465890aae87969f98a9c").build()); + } +}
