/** * Copyright 2016 Hortonworks. * * 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 com.hortonworks.registries.common; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.IntStream; /** * */ public class SlotSynchronizerTest { @Test public void stressTestSlotLocks() throws Exception { SlotSynchronizer<Integer> slotSynchronizer = new SlotSynchronizer<>(); int key = new Random().nextInt(); int size = 64; long limit = 1000_000; AtomicLong aggregatedCount = new AtomicLong(); List<Thread> threads = new ArrayList<>(size); for (int i = 0; i < size; i++) { threads.add(new Thread(new Work(key, slotSynchronizer, limit, aggregatedCount))); } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } Assert.assertEquals(limit * size, aggregatedCount.get()); } @Test(expected = IllegalStateException.class) public void testIllegalUnlock() throws Exception { SlotSynchronizer<Integer> slotSynchronizer = new SlotSynchronizer<>(); int key = new Random().nextInt(); // complete lock/unlock for that slot. SlotSynchronizer<Integer>.Lock lock = slotSynchronizer.lockSlot(key); lock.unlock(); // call again unlock which should throw an Exception lock.unlock(); } @Test(expected = Exception.class) public void testNullKey() throws Exception { SlotSynchronizer<Integer> slotSynchronizer = new SlotSynchronizer<>(); slotSynchronizer.lockSlot(null); } @Test public void testCountSlots() throws Exception { SlotSynchronizer<Integer> slotSynchronizer = new SlotSynchronizer<>(); int count = new Random().nextInt(1000) + 1; Collection<SlotSynchronizer<Integer>.Lock> locks = new ArrayList<>(); IntStream keysStream = IntStream.range(0, count); keysStream.forEach(value -> locks.add(slotSynchronizer.lockSlot(value))); Assert.assertEquals(count, slotSynchronizer.occupiedSlots()); locks.forEach(lock -> lock.unlock()); Assert.assertEquals(0, slotSynchronizer.occupiedSlots()); } private static class Work implements Runnable { private final int k; private final SlotSynchronizer<Integer> slotSynchronizer; private final long limit; private final AtomicLong count; private Work(int k, SlotSynchronizer<Integer> slotSynchronizer, long limit, AtomicLong count) { this.k = k; this.slotSynchronizer = slotSynchronizer; this.limit = limit; this.count = count; } @Override public void run() { for (int i = 0; i < limit; i++) { slotSynchronizer.runInSlot(k, () -> { count.incrementAndGet(); }); } } } }