/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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.hazelcast.internal.nearcache.impl.preloader; import com.hazelcast.core.HazelcastException; import com.hazelcast.logging.ILogger; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.HazelcastTestSupport; import com.hazelcast.test.annotation.ParallelTest; import com.hazelcast.test.annotation.QuickTest; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import static com.hazelcast.nio.IOUtil.closeResource; import static com.hazelcast.nio.IOUtil.deleteQuietly; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(HazelcastParallelClassRunner.class) @Category({QuickTest.class, ParallelTest.class}) public class NearCachePreloaderLockTest extends HazelcastTestSupport { @Rule public ExpectedException rule = ExpectedException.none(); private ILogger logger = mock(ILogger.class); private File preloaderLockFile = new File(randomName()); private File lockFile = new File(randomName()); private NearCachePreloaderLock preloaderLock; private FileChannel channel; @Before public void setUp() throws Exception { preloaderLock = new NearCachePreloaderLock(logger, preloaderLockFile.getAbsolutePath()); FileChannel realChannel = new RandomAccessFile(lockFile, "rw").getChannel(); channel = spy(realChannel); } @After public void tearDown() { closeResource(channel); deleteQuietly(lockFile); deleteQuietly(preloaderLockFile); } /** * The {@link FileChannel#tryLock()} returns: * <pre> * A lock object representing the newly-acquired lock, * or <tt>null</tt> if the lock could not be acquired * because another program holds an overlapping lock * </pre> */ @Test public void testAcquireLock_whenTryLockReturnsNull_thenThrowHazelcastException() throws Exception { when(channel.tryLock()).thenReturn(null); rule.expect(HazelcastException.class); rule.expectMessage("File is already being used by another Hazelcast instance."); preloaderLock.acquireLock(lockFile, channel); } /** * The {@link FileChannel#tryLock()} throws an {@link OverlappingFileLockException}: * <pre> * If a lock that overlaps the requested region is already held by * this Java virtual machine, or if another thread is already * blocked in this method and is attempting to lock an overlapping * region * </pre> */ @Test public void testAcquireLock_whenTryLockThrowsOverlappingFileLockException_thenThrowHazelcastException() throws Exception { when(channel.tryLock()).thenThrow(new OverlappingFileLockException()); rule.expect(HazelcastException.class); rule.expectMessage("File is already being used by this Hazelcast instance."); preloaderLock.acquireLock(lockFile, channel); } /** * The {@link FileChannel#tryLock()} throws an {@link IOException}: * <pre> * If some other I/O error occurs * </pre> */ @Test public void testAcquireLock_whenTryLockThrowsIOException_thenThrowHazelcastException() throws Exception { when(channel.tryLock()).thenThrow(new IOException("expected exception")); rule.expect(HazelcastException.class); rule.expectMessage("Unknown failure while acquiring lock on " + lockFile.getAbsolutePath()); preloaderLock.acquireLock(lockFile, channel); } @Test public void testRelease() throws Exception { FileLock lock = mock(FileLock.class); doThrow(new IOException("expected exception")).when(lock).release(); preloaderLock.releaseInternal(lock, channel); verify(logger).severe(anyString(), any(IOException.class)); } }