/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util.store; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mule.runtime.api.store.ObjectStoreManager.UNBOUNDED; import org.mule.runtime.core.api.config.MuleProperties; import org.mule.runtime.core.api.store.ListableObjectStore; import org.mule.runtime.api.store.ObjectStore; import org.mule.tck.junit4.AbstractMuleContextTestCase; import org.mule.tck.probe.JUnitProbe; import org.mule.tck.probe.PollingProber; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; import org.hamcrest.core.Is; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) /** * Tests MuleObjectStoreManager integration with the wrappers used to monitor each managed object store. */ public class MuleObjectStoreManagerIntegrationTestCase extends AbstractMuleContextTestCase { public static final String OBJECT_KEY = "key"; public static final String OBJECT_KEY_VALUE_1 = "value"; public static final String OBJECT_KEY_VALUE_2 = "anotherValue"; private final ObjectStoreFactory objectStoreFactory; private enum ObjectStoreType { DEFAULT, USER }; public MuleObjectStoreManagerIntegrationTestCase(ObjectStoreFactory objectStoreFactory) { this.objectStoreFactory = objectStoreFactory; } @Parameterized.Parameters public static Collection<Object[]> parameters() { return Arrays.asList(new Object[][] {{new ObjectStoreFactory(false, ObjectStoreType.DEFAULT)}, {new ObjectStoreFactory(true, ObjectStoreType.DEFAULT)}, {new ObjectStoreFactory(false, ObjectStoreType.USER)}, {new ObjectStoreFactory(true, ObjectStoreType.USER)}}); } @Before public void injectMuleContext() { objectStoreFactory .setMuleObjectStoreManager(muleContext.getRegistry().<MuleObjectStoreManager>get(MuleProperties.OBJECT_STORE_MANAGER)); } @Test public void partitionObjectStoreDoesNotCollide() throws Exception { ObjectStore os = objectStoreFactory.createObjectStore("myOs"); ObjectStore os2 = objectStoreFactory.createObjectStore("myOs2"); os.store(OBJECT_KEY, OBJECT_KEY_VALUE_1); os2.store(OBJECT_KEY, OBJECT_KEY_VALUE_2); assertThat(os.contains(OBJECT_KEY), is(true)); assertThat((String) os.retrieve(OBJECT_KEY), is(OBJECT_KEY_VALUE_1)); assertThat(os2.contains(OBJECT_KEY), is(true)); assertThat((String) os2.retrieve(OBJECT_KEY), is(OBJECT_KEY_VALUE_2)); assertThat((String) os.remove(OBJECT_KEY), is(OBJECT_KEY_VALUE_1)); assertThat((String) os2.remove(OBJECT_KEY), is(OBJECT_KEY_VALUE_2)); } @Test public void maxEntriesIsHonored() throws Exception { final int expirationInterval = 1000; final int maxEntries = 5; final ObjectStore os = objectStoreFactory.createObjectStore("myOs", 5, 0, expirationInterval); os.store(0, 0); ensureMilisecondChanged(); for (int i = 1; i < maxEntries + 1; i++) { os.store(i, i); } PollingProber prober = new PollingProber(expirationInterval * 5, expirationInterval); prober.check(new JUnitProbe() { @Override public boolean test() throws Exception { assertThat(os.contains(0), is(false)); for (int i = 1; i < maxEntries + 1; i++) { assertThat(os.contains(i), is(true)); } return true; } @Override public String describeFailure() { return "max entries were not honoured"; } }); } @Test public void expirationIntervalWithLowTTL() throws Exception { int maxEntries = 5; int entryTTL = 10; int expirationInterval = 100; final ListableObjectStore os = objectStoreFactory.createObjectStore("myOs", maxEntries, entryTTL, expirationInterval); for (int i = 0; i < maxEntries; i++) { os.store(i, i); } PollingProber prober = new PollingProber(1000, expirationInterval); prober.check(new JUnitProbe() { @Override public boolean test() throws Exception { return os.allKeys().isEmpty(); } @Override public String describeFailure() { return "not all entries were evicted"; } }); } @Test public void expirationIntervalWithHighTTLPersistentObjectStore() throws Exception { int maxEntries = 5; int entryTTL = 10000; ListableObjectStore os = objectStoreFactory.createObjectStore("myOs", maxEntries, entryTTL, 100); os.store(0, 0); ensureMilisecondChanged(); for (int i = 1; i < maxEntries; i++) { os.store(i, i); } os.store(OBJECT_KEY, OBJECT_KEY_VALUE_1); Thread.sleep(entryTTL / 5); assertThat(os.allKeys().size(), is(maxEntries)); for (int i = 1; i < maxEntries; i++) { assertThat(os.contains(i), is(true)); } assertThat(os.contains(OBJECT_KEY), is(true)); } private void ensureMilisecondChanged() throws InterruptedException { Thread.sleep(2); } @Test public void onlySizeBoundedObjectStore() throws Exception { final int maxEntries = 5; final int entryTTL = UNBOUNDED; final ListableObjectStore os = objectStoreFactory.createObjectStore("myOs", maxEntries, entryTTL, 1000); os.store(0, 0); ensureMilisecondChanged(); for (int i = 1; i < maxEntries + 1; i++) { os.store(i, i); } PollingProber prober = new PollingProber(5000, 1000); prober.check(new JUnitProbe() { @Override public boolean test() throws Exception { assertThat(os.allKeys().size(), is(maxEntries)); for (int i = 1; i < maxEntries + 1; i++) { assertThat(os.contains(i), is(true)); } return true; } @Override public String describeFailure() { return "objectStore was not trimmed"; } }); } @Test public void storeUsingBigKey() throws Exception { ListableObjectStore os = objectStoreFactory.createObjectStore("myOs"); StringBuilder bigKey = new StringBuilder(); for (int i = 0; i < 50; i++) { bigKey.append("abcdefghijklmnopqrstuvwxyz"); } os.store(bigKey.toString(), 1); assertThat((Integer) os.retrieve(bigKey.toString()), Is.is(1)); } private static class ObjectStoreFactory { private final boolean isPersistent; private final ObjectStoreType objectStoreType; private MuleObjectStoreManager muleObjectStoreManager; public ObjectStoreFactory(boolean isPersistent, ObjectStoreType objectStoreType) { this.isPersistent = isPersistent; this.objectStoreType = objectStoreType; } public void setMuleObjectStoreManager(MuleObjectStoreManager muleObjectStoreManager) { this.muleObjectStoreManager = muleObjectStoreManager; } public <T extends ObjectStore<? extends Serializable>> T createObjectStore(String name) { if (objectStoreType.equals(ObjectStoreType.USER)) { return muleObjectStoreManager.getUserObjectStore(name, isPersistent); } else { return muleObjectStoreManager.getObjectStore(name, isPersistent); } } public <T extends ObjectStore<? extends Serializable>> T createObjectStore(String name, int maxEntries, int entryTTL, int expirationInterval) { if (objectStoreType.equals(ObjectStoreType.USER)) { return muleObjectStoreManager.getUserObjectStore(name, isPersistent, maxEntries, entryTTL, expirationInterval); } else { return muleObjectStoreManager.getObjectStore(name, isPersistent, maxEntries, entryTTL, expirationInterval); } } } }