package org.peerbox.app.manager.user;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import org.apache.commons.lang3.RandomUtils;
import org.hive2hive.core.H2HJUnitTest;
import org.hive2hive.core.api.interfaces.IH2HNode;
import org.hive2hive.core.exceptions.NoPeerConnectionException;
import org.hive2hive.core.exceptions.NoSessionException;
import org.hive2hive.core.security.UserCredentials;
import org.hive2hive.core.utils.FileTestUtil;
import org.hive2hive.core.utils.NetworkTestUtil;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.peerbox.BaseJUnitTest;
import org.peerbox.ResultStatus;
import org.peerbox.app.manager.node.INodeManager;
import org.peerbox.app.manager.user.IUserManager;
import org.peerbox.app.manager.user.LoginMessage;
import org.peerbox.app.manager.user.LogoutMessage;
import org.peerbox.app.manager.user.RegisterMessage;
import org.peerbox.app.manager.user.UserManager;
import org.peerbox.events.MessageBus;
public class UserManagerTest extends BaseJUnitTest {
private static final int NETWORK_SIZE = 15;
private static List<IH2HNode> network;
private UserCredentials userCredentials;
private Path root;
private ClientContext client;
@BeforeClass
public static void beforeClass() {
network = NetworkTestUtil.createH2HNetwork(NETWORK_SIZE);
}
@AfterClass
public static void afterClass() {
NetworkTestUtil.shutdownH2HNetwork(network);
}
@Before
public void beforeTest() {
root = FileTestUtil.getTempDirectory().toPath();
userCredentials = H2HJUnitTest.generateRandomCredentials();
// assemble random user manager to test
IH2HNode clientNode = network.get(RandomUtils.nextInt(0, network.size()));
client = createClientContext(clientNode);
}
@Test
public void testRegister() throws NoPeerConnectionException {
// check NOT registered
for(int i = 0; i < network.size(); ++i) {
ClientContext cc = createClientContext(network.get(i));
IUserManager usrMgr = cc.getUserManager();
assertFalse(usrMgr.isRegistered(userCredentials.getUserId()));
}
// register user
ResultStatus res = client.getUserManager().registerUser(
userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin());
assertTrue(res.isOk());
// got event?
ArgumentCaptor<RegisterMessage> event = ArgumentCaptor.forClass(RegisterMessage.class);
Mockito.verify(client.getMessageBus(), Mockito.times(1)).publish(event.capture());
assertNotNull(event.getValue());
assertEquals(userCredentials.getUserId(), event.getValue().getUsername());
// check again whether registered
for(int i = 0; i < network.size(); ++i) {
ClientContext cc = createClientContext(network.get(i));
IUserManager usrMgr = cc.getUserManager();
assertTrue(usrMgr.isRegistered(userCredentials.getUserId()));
}
}
@Test
public void testAlreadyRegistered() throws NoPeerConnectionException {
// register
ResultStatus res = client.getUserManager().registerUser(
userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin());
assertTrue(res.isOk());
// got event?
Mockito.verify(client.getMessageBus(), Mockito.times(1)).publish(Mockito.anyObject());
// try register -- should fail
for (int i = 0; i < network.size(); ++i) {
ClientContext cc = createClientContext(network.get(i));
IUserManager usrMgr = cc.getUserManager();
res = usrMgr.registerUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin());
assertTrue(res.isError());
// got NO event?
Mockito.verify(cc.getMessageBus(), Mockito.never()).publish(Mockito.anyObject());
}
}
@Test
public void testLogin() throws NoPeerConnectionException, IOException {
IUserManager userManager = client.getUserManager();
// not loggedIn
assertFalse(userManager.isLoggedIn());
// register
ResultStatus res = userManager.registerUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin());
assertTrue(res.isOk());
assertFalse(userManager.isLoggedIn());
// got event?
Mockito.verify(client.getMessageBus(), Mockito.times(1)).publish(Mockito.any());
// login and loggedIn
res = userManager.loginUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin(), root);
assertTrue(res.isOk());
assertTrue(userManager.isLoggedIn());
// got event?
ArgumentCaptor<LoginMessage> event = ArgumentCaptor.forClass(LoginMessage.class);
Mockito.verify(client.getMessageBus(), Mockito.times(2)).publish(event.capture());
assertNotNull(event.getValue());
assertEquals(userCredentials.getUserId(), event.getValue().getUsername());
}
@Test
public void testNotRegisteredLogin() throws NoPeerConnectionException, IOException {
IUserManager userManager = client.getUserManager();
// not registered
assertFalse(userManager.isRegistered(userCredentials.getUserId()));
// login and not loggedIn
ResultStatus res = userManager.loginUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin(), root);
assertTrue(res.isError());
assertFalse(userManager.isLoggedIn());
// got NO event?
Mockito.verify(client.getMessageBus(), Mockito.never()).publish(Mockito.anyObject());
}
@Test
public void testLoginWrongCredentials() throws NoPeerConnectionException, IOException {
IUserManager userManager = client.getUserManager();
// not loggedIn
assertFalse(userManager.isLoggedIn());
// register
ResultStatus res = userManager.registerUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin());
assertTrue(res.isOk());
assertFalse(userManager.isLoggedIn());
// got event?
Mockito.verify(client.getMessageBus(), Mockito.times(1)).publish(Mockito.any());
// wrong credentials -- login and loggedIn
UserCredentials wrongCred = H2HJUnitTest.generateRandomCredentials();
res = userManager.loginUser(wrongCred.getUserId(), wrongCred.getPassword(), wrongCred.getPin(), root);
assertFalse(res.isOk());
assertFalse(userManager.isLoggedIn());
// got NO additional event?
Mockito.verify(client.getMessageBus(), Mockito.times(1)).publish(Mockito.any());
// correct credentials -- login and loggedIn
res = userManager.loginUser(userCredentials.getUserId(), userCredentials.getPassword(), userCredentials.getPin(), root);
assertTrue(res.isOk());
assertTrue(userManager.isLoggedIn());
// got event?
ArgumentCaptor<LoginMessage> event = ArgumentCaptor.forClass(LoginMessage.class);
Mockito.verify(client.getMessageBus(), Mockito.times(2)).publish(event.capture());
assertNotNull(event.getValue());
assertEquals(userCredentials.getUserId(), event.getValue().getUsername());
}
@Test
public void testLogout() throws NoPeerConnectionException, IOException, NoSessionException {
// register and login
testLogin();
IUserManager userManager = client.getUserManager();
assertTrue(userManager.isLoggedIn());
ResultStatus res = userManager.logoutUser();
assertTrue(res.isOk());
assertFalse(userManager.isLoggedIn());
// got event? (Register, login, logout)
ArgumentCaptor<LogoutMessage> event = ArgumentCaptor.forClass(LogoutMessage.class);
Mockito.verify(client.getMessageBus(), Mockito.times(3)).publish(event.capture());
assertNotNull(event.getValue());
assertEquals(userCredentials.getUserId(), event.getValue().getUsername());
}
@Test(expected=NoSessionException.class)
public void testLogoutNotLoggedIn() throws NoPeerConnectionException, NoSessionException {
IUserManager userManager = client.getUserManager();
assertFalse(userManager.isLoggedIn());
ResultStatus res = userManager.logoutUser();
assertFalse(res.isOk());
fail("NoSessionException not thrown.");
}
private ClientContext createClientContext(IH2HNode node) {
return new ClientContext(node);
}
private class ClientContext {
private IH2HNode node;
private INodeManager nodeManager;
private IUserManager userManager;
private MessageBus messageBus;
public ClientContext(IH2HNode node) {
this.node = node;
nodeManager = Mockito.mock(INodeManager.class);
Mockito.stub(nodeManager.getNode()).toReturn(this.node);
messageBus = Mockito.mock(MessageBus.class);
userManager = new UserManager(nodeManager, messageBus);
}
public IUserManager getUserManager() {
return userManager;
}
public MessageBus getMessageBus() {
return messageBus;
}
}
}