/* * Copyright Terracotta, Inc. * * Licensed 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.ehcache.core.config; import org.ehcache.config.ResourcePool; import org.ehcache.config.ResourcePools; import org.ehcache.config.ResourceType; import org.ehcache.config.ResourceUnit; import org.ehcache.config.SizedResourcePool; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; import org.hamcrest.Matchers; import org.junit.Test; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import static org.ehcache.config.ResourceType.Core.HEAP; import static org.ehcache.config.ResourceType.Core.OFFHEAP; import static org.ehcache.config.units.EntryUnit.ENTRIES; import static org.ehcache.config.units.MemoryUnit.KB; import static org.ehcache.config.units.MemoryUnit.MB; import static org.ehcache.core.config.ResourcePoolsImpl.validateResourcePools; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** * * @author cdennis */ public class ResourcePoolsImplTest { private static class ArbitraryType implements ResourceType<SizedResourcePool> { private final int tierHeight; public ArbitraryType(int tierHeight) { this.tierHeight = tierHeight; } @Override public Class<SizedResourcePool> getResourcePoolClass() { return SizedResourcePool.class; } @Override public boolean isPersistable() { return false; } @Override public boolean requiresSerialization() { return false; } @Override public int getTierHeight() { return tierHeight; } @Override public String toString() { return "arbitrary"; } } @Test public void testMismatchedUnits() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, Integer.MAX_VALUE, ENTRIES, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); validateResourcePools(pools); } @Test public void testMatchingEqualUnitsWellTiered() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 9, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); validateResourcePools(pools); } @Test public void testMatchingUnequalUnitsWellTiered() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 9, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10240, KB, false)); validateResourcePools(pools); } @Test public void testArbitraryPoolWellTieredHeap() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 9, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(new ArbitraryType(HEAP.getTierHeight() - 1), 10, MB, false)); validateResourcePools(pools); } @Test public void testArbitraryPoolWellTieredOffHeap() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(new ArbitraryType(OFFHEAP.getTierHeight() + 1), 9, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); validateResourcePools(pools); } @Test public void testArbitraryPoolInversionHeap() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 10, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(new ArbitraryType(HEAP.getTierHeight() - 1), 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10 MB heap}' is not smaller than 'Pool {10 MB arbitrary}'")); } } @Test public void testArbitraryPoolInversionOffHeap() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(new ArbitraryType(OFFHEAP.getTierHeight() + 1), 10, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10 MB arbitrary}' is not smaller than 'Pool {10 MB offheap}'")); } } @Test public void testArbitraryPoolAmbiguity() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(new ArbitraryType(OFFHEAP.getTierHeight()), 10, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Ambiguity: 'Pool {10 MB arbitrary}' has the same tier height as 'Pool {10 MB offheap}'")); } } @Test public void testEntryResourceMatch() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 10, ENTRIES, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, ENTRIES, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10 entries heap}' is not smaller than 'Pool {10 entries offheap}'")); } } @Test public void testEntryResourceInversion() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 11, ENTRIES, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, ENTRIES, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {11 entries heap}' is not smaller than 'Pool {10 entries offheap}'")); } } @Test public void testMemoryResourceEqualUnitMatch() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 10, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10 MB heap}' is not smaller than 'Pool {10 MB offheap}'")); } } @Test public void testMemoryResourceEqualUnitInversion() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 11, MB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {11 MB heap}' is not smaller than 'Pool {10 MB offheap}'")); } } @Test public void testMemoryResourceUnequalUnitMatch() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 10240, KB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10240 kB heap}' is not smaller than 'Pool {10 MB offheap}'")); } } @Test public void testMemoryResourceUnequalUnitInversion() { Collection<SizedResourcePoolImpl<SizedResourcePool>> pools = asList( new SizedResourcePoolImpl<SizedResourcePool>(HEAP, 10241, KB, false), new SizedResourcePoolImpl<SizedResourcePool>(OFFHEAP, 10, MB, false)); try { validateResourcePools(pools); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Tiering Inversion: 'Pool {10241 kB heap}' is not smaller than 'Pool {10 MB offheap}'")); } } @Test public void testAddingNewTierWhileUpdating() { ResourcePools existing = new ResourcePoolsImpl(Collections.<ResourceType<?>, ResourcePool>singletonMap( ResourceType.Core.HEAP, new SizedResourcePoolImpl<SizedResourcePool>(ResourceType.Core.HEAP, 10L, EntryUnit.ENTRIES, false))); ResourcePools toBeUpdated = new ResourcePoolsImpl(Collections.<ResourceType<?>, ResourcePool>singletonMap( ResourceType.Core.DISK, new SizedResourcePoolImpl<SizedResourcePool>(ResourceType.Core.DISK, 10L, MemoryUnit.MB, false))); try { existing.validateAndMerge(toBeUpdated); fail(); } catch (IllegalArgumentException iae) { assertThat(iae.getMessage(), Matchers.is("Pools to be updated cannot contain previously undefined resources pools")); } } @Test public void testUpdatingOffHeap() { ResourcePools existing = ResourcePoolsHelper.createOffheapOnlyPools(10); ResourcePools toBeUpdated = ResourcePoolsHelper.createOffheapOnlyPools(50); try { existing.validateAndMerge(toBeUpdated); fail(); } catch (UnsupportedOperationException uoe) { assertThat(uoe.getMessage(), Matchers.is("Updating OFFHEAP resource is not supported")); } } @Test public void testUpdatingDisk() { ResourcePools existing = ResourcePoolsHelper.createDiskOnlyPools(10, MB); ResourcePools toBeUpdated = ResourcePoolsHelper.createDiskOnlyPools(50, MB); try { existing.validateAndMerge(toBeUpdated); fail(); } catch (UnsupportedOperationException uoe) { assertThat(uoe.getMessage(), Matchers.is("Updating DISK resource is not supported")); } } @Test public void testUpdateResourceUnitSuccess() { ResourcePools existing = ResourcePoolsHelper.createHeapDiskPools(200, MB, 4096); ResourcePools toBeUpdated = ResourcePoolsHelper.createHeapOnlyPools(2, MemoryUnit.GB); existing = existing.validateAndMerge(toBeUpdated); assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getSize(), Matchers.is(2L)); assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getUnit(), Matchers.<ResourceUnit>is(MemoryUnit.GB)); } @Test public void testUpdateResourceUnitFailure() { ResourcePools existing = ResourcePoolsHelper.createHeapDiskPools(20, MB, 200); ResourcePools toBeUpdated = ResourcePoolsHelper.createHeapOnlyPools(500, EntryUnit.ENTRIES); try { existing = existing.validateAndMerge(toBeUpdated); fail(); } catch (IllegalArgumentException uoe) { assertThat(uoe.getMessage(), Matchers.is("ResourcePool for heap with ResourceUnit 'entries' can not replace 'MB'")); } assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getSize(), Matchers.is(20L)); assertThat(existing.getPoolForResource(ResourceType.Core.HEAP).getUnit(), Matchers.<ResourceUnit>is(MemoryUnit.MB)); } private <T> Collection<T> asList(T value1, T value2) { @SuppressWarnings("unchecked") List<T> list = Arrays.asList(value1, value2); return list; } }