/* * JBoss, Home of Professional Open Source * Copyright 2010 Red Hat Inc. and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.loaders.cloud; import org.infinispan.CacheDelegate; import org.infinispan.container.entries.InternalCacheEntry; import org.infinispan.test.fwk.TestInternalCacheEntryFactory; import org.infinispan.io.UnclosableObjectInputStream; import org.infinispan.io.UnclosableObjectOutputStream; import org.infinispan.loaders.BaseCacheStoreTest; import org.infinispan.loaders.CacheLoaderException; import org.infinispan.loaders.CacheStore; import org.infinispan.marshall.StreamingMarshaller; import org.infinispan.test.TestingUtil; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.ListContainerOptions; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; import java.util.Collections; import java.util.HashSet; import java.util.Set; import static org.testng.Assert.assertEquals; @Test(groups = "unit", sequential = true, testName = "loaders.cloud.CloudCacheStoreIntegrationTest") public class CloudCacheStoreIntegrationTest extends BaseCacheStoreTest { private String proxyHost; private String proxyPort = "-1"; private int maxConnections = 20; private boolean isSecure = false; private String csBucket; private String cs2Bucket; private String accessKey; private String secretKey; private String service; private static final String sysUsername = System.getProperty("infinispan.test.jclouds.username"); private static final String sysPassword = System.getProperty("infinispan.test.jclouds.password"); private static final String sysService = System.getProperty("infinispan.test.jclouds.service"); @BeforeTest @Parameters({"infinispan.test.jclouds.username", "infinispan.test.jclouds.password", "infinispan.test.jclouds.service"}) protected void setUpClient(@Optional String JcloudsUsername, @Optional String JcloudsPassword, @Optional String JcloudsService) throws Exception { accessKey = (JcloudsUsername == null) ? sysUsername : JcloudsUsername; secretKey = (JcloudsPassword == null) ? sysPassword : JcloudsPassword; service = (JcloudsService == null) ? sysService : JcloudsService; if (accessKey == null || accessKey.trim().length() == 0 || secretKey == null || secretKey.trim().length() == 0) { accessKey = "dummy"; secretKey = "dummy"; } csBucket = (System.getProperty("user.name") + "-" + this.getClass().getSimpleName()).toLowerCase(); System.out.printf("accessKey: %1$s, bucket: %2$s%n", accessKey, csBucket); cs2Bucket = csBucket + "2"; } protected CacheStore createCacheStore() throws Exception { return createAndStartCacheStore(csBucket); } protected CacheStore createAnotherCacheStore() throws Exception { return createAndStartCacheStore(cs2Bucket); } private CacheStore createAndStartCacheStore(String bucket) throws Exception { CloudCacheStore cs = new CloudCacheStore(); CloudCacheStoreConfig cfg = new CloudCacheStoreConfig(); cfg.setBucketPrefix(bucket); cfg.setCloudService(service); cfg.setCloudServiceLocation("Some-Gibberish"); cfg.setIdentity(accessKey); cfg.setPassword(secretKey); cfg.setProxyHost(proxyHost); cfg.setProxyPort(proxyPort); cfg.setSecure(isSecure); cfg.setMaxConnections(maxConnections); cfg.setCompress(true); cfg.setPurgeSynchronously(true); // for more accurate unit testing cs.init(cfg, new CacheDelegate("aName"), getMarshaller()); cs.start(); return cs; } /* Changes below are needed to support testing of multiple cache stores */ protected CacheStore cs2; @BeforeMethod @Override public void setUp() throws Exception { super.setUp(); cs.clear(); Set entries = cs.loadAll(); assert entries.isEmpty(); cs2 = createAnotherCacheStore(); cs2.clear(); entries = cs2.loadAll(); assert entries.isEmpty(); } @AfterMethod @Override public void tearDown() throws CacheLoaderException { if (cs != null) { cs.clear(); cs.stop(); } cs = null; if (cs2 != null) { cs2.clear(); cs2.stop(); } cs2 = null; } @SuppressWarnings("unchecked") @Override @Test(enabled = false, description = "Disabled until JClouds gains a proper streaming API") public void testStreamingAPI() throws IOException, ClassNotFoundException, CacheLoaderException { cs.store(TestInternalCacheEntryFactory.create("k1", "v1", -1, -1)); cs.store(TestInternalCacheEntryFactory.create("k2", "v2", -1, -1)); cs.store(TestInternalCacheEntryFactory.create("k3", "v3", -1, -1)); StreamingMarshaller marshaller = getMarshaller(); ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutput oo = marshaller.startObjectOutput(out, false); try { cs.toStream(new UnclosableObjectOutputStream(oo)); } finally { marshaller.finishObjectOutput(oo); out.close(); } ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ObjectInput oi = marshaller.startObjectInput(in, false); try { cs2.fromStream(new UnclosableObjectInputStream(oi)); } finally { marshaller.finishObjectInput(oi); in.close(); } Set<InternalCacheEntry> set = cs2.loadAll(); assertEquals(set.size(), 3); Set expected = new HashSet(); expected.add("k1"); expected.add("k2"); expected.add("k3"); for (InternalCacheEntry se : set) assert expected.remove(se.getKey()); assert expected.isEmpty(); } @Test(enabled = false, description = "Much too slow to run this on a live cloud setup") @Override public void testConcurrency() throws Exception { } public void testNegativeHashCodes() throws CacheLoaderException { ObjectWithNegativeHashcode objectWithNegativeHashcode = new ObjectWithNegativeHashcode(); cs.store(TestInternalCacheEntryFactory.create(objectWithNegativeHashcode, "hello", -1, -1)); InternalCacheEntry ice = cs.load(objectWithNegativeHashcode); assert ice.getKey().equals(objectWithNegativeHashcode); assert ice.getValue().equals("hello"); } private static class ObjectWithNegativeHashcode implements Serializable { String s = "hello"; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ObjectWithNegativeHashcode blah = (ObjectWithNegativeHashcode) o; return !(s != null ? !s.equals(blah.s) : blah.s != null); } @Override public int hashCode() { return -700; } } @Override @Test(enabled = false, description = "Disabled until we can build the blobstore stub to retain state somewhere.") public void testStopStartDoesNotNukeValues() throws InterruptedException, CacheLoaderException { } @SuppressWarnings("unchecked") @Override @Test(enabled = false, description = "Disabled until JClouds gains a proper streaming API") public void testStreamingAPIReusingStreams() throws IOException, ClassNotFoundException, CacheLoaderException { cs.store(TestInternalCacheEntryFactory.create("k1", "v1", -1, -1)); cs.store(TestInternalCacheEntryFactory.create("k2", "v2", -1, -1)); cs.store(TestInternalCacheEntryFactory.create("k3", "v3", -1, -1)); StreamingMarshaller marshaller = getMarshaller(); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] dummyStartBytes = {1, 2, 3, 4, 5, 6, 7, 8}; byte[] dummyEndBytes = {8, 7, 6, 5, 4, 3, 2, 1}; ObjectOutput oo = marshaller.startObjectOutput(out, false); try { oo.write(dummyStartBytes); cs.toStream(new UnclosableObjectOutputStream(oo)); oo.flush(); oo.write(dummyEndBytes); } finally { marshaller.finishObjectOutput(oo); out.close(); } // first pop the start bytes byte[] dummy = new byte[8]; ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ObjectInput oi = marshaller.startObjectInput(in, false); try { int bytesRead = oi.read(dummy, 0, 8); assert bytesRead == 8; for (int i = 1; i < 9; i++) assert dummy[i - 1] == i : "Start byte stream corrupted!"; cs2.fromStream(new UnclosableObjectInputStream(oi)); bytesRead = oi.read(dummy, 0, 8); assert bytesRead == 8; for (int i = 8; i > 0; i--) assert dummy[8 - i] == i : "Start byte stream corrupted!"; } finally { marshaller.finishObjectInput(oi); in.close(); } Set<InternalCacheEntry> set = cs2.loadAll(); assertEquals(set.size(), 3); Set expected = new HashSet(); expected.add("k1"); expected.add("k2"); expected.add("k3"); for (InternalCacheEntry se : set) assert expected.remove(se.getKey()); assert expected.isEmpty(); } public void testJCloudsMetadataTest() throws IOException { String blobName = "myBlob"; String containerName = (csBucket + "MetadataTest").toLowerCase(); BlobStore blobStore = ((CloudCacheStore) cs).blobStore; try { blobStore.deleteContainer(containerName); TestingUtil.sleepThread(2000); } catch (Exception e) { } blobStore.createContainerInLocation(null, containerName); TestingUtil.sleepThread(2000); Blob b = blobStore.newBlob(blobName); b.setPayload("Hello world"); b.getMetadata().setUserMetadata(Collections.singletonMap("hello", "world")); blobStore.putBlob(containerName, b); b = blobStore.getBlob(containerName, blobName); assert "world".equals(b.getMetadata().getUserMetadata().get("hello")); PageSet<? extends StorageMetadata> ps = blobStore.list(containerName, ListContainerOptions.Builder.withDetails()); for (StorageMetadata sm : ps) assert "world".equals(sm.getUserMetadata().get("hello")); } }