/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* 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.uberfire.backend.server;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.jboss.errai.bus.client.api.QueueSession;
import org.jboss.errai.bus.client.api.base.MessageBuilder;
import org.jboss.errai.bus.client.api.messaging.Message;
import org.jboss.errai.bus.server.api.RpcContext;
import org.jboss.errai.security.shared.api.identity.User;
import org.jboss.errai.security.shared.api.identity.UserImpl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.uberfire.backend.vfs.Path;
import org.uberfire.backend.vfs.PathFactory;
import org.uberfire.backend.vfs.impl.LockInfo;
import org.uberfire.backend.vfs.impl.LockResult;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.NoSuchFileException;
import org.uberfire.rpc.SessionInfo;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class VFSLockServiceTest {
@InjectMocks
private VFSLockServiceImpl lockService;
@Mock
private IOService ioService;
@Mock
private FileSystem fileSystem;
@Mock
private SessionInfo sessionInfo;
@Mock
private QueueSession queueSession;
@Mock
private HttpSession httpSession;
private Path path = PathFactory.newPath("file-to-lock.txt",
"default://file-to-lock.txt");
@Before
public void setup() {
setupRpcContext();
User testUser = new UserImpl("testUser");
when(sessionInfo.getIdentity()).thenReturn(testUser);
when(queueSession.getAttribute(HttpSession.class,
HttpSession.class.getName())).thenReturn(httpSession);
}
@Test
public void acquireLockSucceedsIfFileUnlocked() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(false);
final LockResult result = lockService.acquireLock(path);
assertTrue(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals("testUser",
result.getLockInfo().lockedBy());
assertTrue(result.getLockInfo().isLocked());
}
@Test
public void acquireLockSucceedsIfLockOwned() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("testUser");
final LockResult result = lockService.acquireLock(path);
assertTrue(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals("testUser",
result.getLockInfo().lockedBy());
assertTrue(result.getLockInfo().isLocked());
}
@Test
public void acquireLockFailsIfFileLocked() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("some-other-user");
final LockResult result = lockService.acquireLock(path);
assertFalse(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals("some-other-user",
result.getLockInfo().lockedBy());
assertTrue(result.getLockInfo().isLocked());
}
@Test
public void acquireLockUpdatesSession() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(false);
lockService.acquireLock(path);
verify(httpSession).setAttribute(eq(VFSLockServiceImpl.LOCK_SESSION_ATTRIBUTE_NAME),
any(Set.class));
}
@Test
// Unfortunately, batching is required for ensuring writes are properly
// replicated in the cluster. This needs to addressed in a future version
// of UF: https://issues.jboss.org/browse/UF-242
public void acquireLockUsesBatch() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(false);
lockService.acquireLock(path);
final InOrder inOrder = inOrder(ioService);
inOrder.verify(ioService).startBatch(fileSystem);
inOrder.verify(ioService).exists(any(org.uberfire.java.nio.file.Path.class));
inOrder.verify(ioService).write(any(org.uberfire.java.nio.file.Path.class),
any(String.class));
inOrder.verify(ioService).endBatch();
}
@Test
public void releaseLockSucceedsIfLockOwned() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("testUser");
final LockResult result = lockService.releaseLock(path);
assertTrue(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals(null,
result.getLockInfo().lockedBy());
assertFalse(result.getLockInfo().isLocked());
}
@Test
public void releaseLockFailsIfLockNotOwned() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("some-other-user");
try {
lockService.releaseLock(path);
fail("Expected exception on attempt to release lock not owned by user");
} catch (Exception ioe) {
// expected
}
}
@Test
public void forceReleaseLockSucceedsIfLockNotOwned() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("some-other-user");
final LockResult result = lockService.forceReleaseLock(path);
assertTrue(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals(null,
result.getLockInfo().lockedBy());
assertFalse(result.getLockInfo().isLocked());
}
@Test
public void releaseLockFailsIfFileUnlocked() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(false);
final LockResult result = lockService.releaseLock(path);
assertFalse(result.isSuccess());
assertEquals(path,
result.getLockInfo().getFile());
assertEquals(null,
result.getLockInfo().lockedBy());
assertFalse(result.getLockInfo().isLocked());
}
@Test
public void releaseLockUpdatesSession() {
lockService.acquireLock(path);
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("testUser");
lockService.releaseLock(path);
verify(httpSession).setAttribute(eq(VFSLockServiceImpl.LOCK_SESSION_ATTRIBUTE_NAME),
any(Set.class));
}
@Test
// Unfortunately, batching is required for ensuring writes are properly
// replicated in the cluster. This needs to addressed in a future version
// of UF: https://issues.jboss.org/browse/UF-242
public void releaseLockUsesBatch() {
lockService.acquireLock(path);
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("testUser");
lockService.releaseLock(path);
final InOrder inOrder = inOrder(ioService);
inOrder.verify(ioService).startBatch(fileSystem);
inOrder.verify(ioService).exists(any(org.uberfire.java.nio.file.Path.class));
inOrder.verify(ioService).readAllString(any(org.uberfire.java.nio.file.Path.class));
inOrder.verify(ioService).delete(any(org.uberfire.java.nio.file.Path.class));
inOrder.verify(ioService).endBatch();
}
@Test
public void retrieveLockInfoForLockedFile() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn("some-user");
final LockInfo info = lockService.retrieveLockInfo(path);
assertTrue(info.isLocked());
assertEquals("some-user",
info.lockedBy());
}
@Test
public void retrieveLockInfoForUnlockedFile() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(false);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenReturn(null);
final LockInfo info = lockService.retrieveLockInfo(path);
assertFalse(info.isLocked());
assertNull(info.lockedBy());
}
@Test
public void retrieveLockInfoNoSuchFileException() {
when(ioService.exists(any(org.uberfire.java.nio.file.Path.class))).thenReturn(true);
when(ioService.readAllString(any(org.uberfire.java.nio.file.Path.class))).thenThrow(new NoSuchFileException());
final LockInfo info = lockService.retrieveLockInfo(path);
assertFalse(info.isLocked());
assertNull(info.lockedBy());
}
private void setupRpcContext() {
final Message message = MessageBuilder.createMessage("for testing").signalling().done().getMessage();
message.setResource("Session",
queueSession);
RpcContext.set(message);
}
}