Files
JIMRI/java/test/jmri/jmrit/permission/DefaultPermissionManagerTest.java
2026-06-17 14:00:51 +02:00

287 lines
11 KiB
Java

package jmri.jmrit.permission;
import jmri.util.JUnitUtil;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Locale;
/**
* Tests for DefaultPermissionManager session management.
*
* @author Ralf Lang
* @author JMRI Community (C) 2026
*/
public class DefaultPermissionManagerTest {
private DefaultPermissionManager manager;
/**
* Test successful remote login with valid credentials.
*/
@Test
public void testRemoteLoginSuccess() throws Exception {
// Add a test user
manager.addUser("testuser", "testpass");
// Attempt remote login
StringBuilder sessionId = new StringBuilder();
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
assertTrue(result, "Remote login should succeed with valid credentials");
assertNotNull(sessionId.toString(), "Session ID should not be null");
assertFalse(sessionId.toString().isBlank(), "Session ID should not be empty or whitespace-only");
assertEquals(10, sessionId.length(), "Session ID should be 10 characters long");
}
/**
* Test remote login with invalid password.
*/
@Test
public void testRemoteLoginInvalidPassword() throws Exception {
// Add a test user
manager.addUser("testuser", "testpass");
// Attempt remote login with wrong password
StringBuilder sessionId = new StringBuilder();
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "wrongpass");
assertFalse(result, "Remote login should fail with invalid password");
assertEquals(0, sessionId.length(), "Session ID should be empty on failed login");
}
/**
* Test remote login with non-existent user.
*/
@Test
public void testRemoteLoginNonExistentUser() {
// Attempt remote login with non-existent user
StringBuilder sessionId = new StringBuilder();
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "nonexistent", "anypass");
assertFalse(result, "Remote login should fail for non-existent user");
assertEquals(0, sessionId.length(), "Session ID should be empty on failed login");
}
/**
* Test that session ID is stored and can be verified.
*/
@Test
public void testRemoteSessionStorage() throws Exception {
// Add a test user and login
manager.addUser("testuser", "testpass");
StringBuilder sessionId = new StringBuilder();
manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
// Verify the session is stored
assertTrue(manager.isRemotelyLoggedIn(sessionId.toString()),
"Session should be marked as logged in");
}
/**
* Test that invalid session ID is not recognized.
*/
@Test
public void testInvalidSessionNotLoggedIn() {
assertFalse(manager.isRemotelyLoggedIn("invalid-session-id"),
"Invalid session should not be recognized as logged in");
assertFalse(manager.isRemotelyLoggedIn(null),
"Null session should not be recognized as logged in");
assertFalse(manager.isRemotelyLoggedIn(""),
"Empty session should not be recognized as logged in");
assertFalse(manager.isRemotelyLoggedIn(" "),
"Blank session should not be recognized as logged in");
}
/**
* Test remote logout removes the session.
*/
@Test
public void testRemoteLogout() throws Exception {
// Add a test user and login
manager.addUser("testuser", "testpass");
StringBuilder sessionId = new StringBuilder();
manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
// Verify session exists
assertTrue(manager.isRemotelyLoggedIn(sessionId.toString()),
"Session should exist before logout");
// Logout
manager.remoteLogout(sessionId.toString());
// Verify session is removed
assertFalse(manager.isRemotelyLoggedIn(sessionId.toString()),
"Session should be removed after logout");
}
/**
* Test remote logout with invalid session IDs (should not throw exception).
*/
@Test
public void testRemoteLogoutInvalidSessions() {
// These should not throw exceptions
assertDoesNotThrow(() -> manager.remoteLogout(null),
"Logout with null session should not throw");
assertDoesNotThrow(() -> manager.remoteLogout(""),
"Logout with empty session should not throw");
assertDoesNotThrow(() -> manager.remoteLogout(" "),
"Logout with blank session should not throw");
assertDoesNotThrow(() -> manager.remoteLogout("nonexistent-session"),
"Logout with non-existent session should not throw");
}
/**
* Test multiple simultaneous remote sessions for different users.
*/
@Test
public void testMultipleRemoteSessions() throws Exception {
// Add multiple users
manager.addUser("user1", "pass1");
manager.addUser("user2", "pass2");
// Login both users
StringBuilder sessionId1 = new StringBuilder();
StringBuilder sessionId2 = new StringBuilder();
manager.remoteLogin(sessionId1, Locale.getDefault(), "user1", "pass1");
manager.remoteLogin(sessionId2, Locale.getDefault(), "user2", "pass2");
// Verify both sessions exist
assertTrue(manager.isRemotelyLoggedIn(sessionId1.toString()),
"User1 session should exist");
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
"User2 session should exist");
// Sessions should be different
assertNotEquals(sessionId1.toString(), sessionId2.toString(),
"Different users should have different session IDs");
// Logout user1
manager.remoteLogout(sessionId1.toString());
// Verify user1 session removed but user2 session still exists
assertFalse(manager.isRemotelyLoggedIn(sessionId1.toString()),
"User1 session should be removed");
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
"User2 session should still exist");
}
/**
* Test that session IDs are generated uniquely.
* Note: This test verifies uniqueness for multiple logins,
* but does not test cryptographic randomness.
*/
@Test
public void testSessionIdUniqueness() throws Exception {
manager.addUser("testuser", "testpass");
// Generate multiple session IDs
StringBuilder sessionId1 = new StringBuilder();
StringBuilder sessionId2 = new StringBuilder();
StringBuilder sessionId3 = new StringBuilder();
manager.remoteLogin(sessionId1, Locale.getDefault(), "testuser", "testpass");
manager.remoteLogout(sessionId1.toString());
manager.remoteLogin(sessionId2, Locale.getDefault(), "testuser", "testpass");
manager.remoteLogout(sessionId2.toString());
manager.remoteLogin(sessionId3, Locale.getDefault(), "testuser", "testpass");
// Verify all session IDs are different
assertNotEquals(sessionId1.toString(), sessionId2.toString(),
"Consecutive session IDs should be different");
assertNotEquals(sessionId2.toString(), sessionId3.toString(),
"Consecutive session IDs should be different");
assertNotEquals(sessionId1.toString(), sessionId3.toString(),
"Consecutive session IDs should be different");
}
/**
* Test that pre-existing session ID in StringBuilder is used.
*/
@Test
public void testRemoteLoginWithPreExistingSessionId() throws Exception {
manager.addUser("testuser", "testpass");
// Provide a pre-existing session ID
StringBuilder sessionId = new StringBuilder("my-custom-session-id");
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
assertTrue(result, "Remote login should succeed");
assertEquals("my-custom-session-id", sessionId.toString(),
"Pre-existing session ID should be preserved");
assertTrue(manager.isRemotelyLoggedIn("my-custom-session-id"),
"Pre-existing session ID should be registered");
}
/**
* Test that guest user cannot login remotely.
* Guest user has null password which should cause login to fail safely.
*/
@Test
public void testGuestUserCannotLoginRemotely() {
StringBuilder sessionId = new StringBuilder();
// Guest user login should fail (guest has null password)
// This may throw NPE or return false depending on implementation
// We just verify that no session is created
try {
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "guest", "anypassword");
assertFalse(result, "Guest user should not be able to login remotely");
} catch (NullPointerException e) {
// Expected - guest user has null password which causes NPE in checkPassword
// This is acceptable behavior - guest cannot login remotely
}
// Verify no session was created for guest
assertFalse(manager.isRemotelyLoggedIn(sessionId.toString()),
"No session should be created for guest user");
}
/**
* Test same user can have multiple remote sessions simultaneously.
*/
@Test
public void testSameUserMultipleSessions() throws Exception {
manager.addUser("testuser", "testpass");
// Login same user twice with different sessions
StringBuilder sessionId1 = new StringBuilder();
StringBuilder sessionId2 = new StringBuilder();
manager.remoteLogin(sessionId1, Locale.getDefault(), "testuser", "testpass");
manager.remoteLogin(sessionId2, Locale.getDefault(), "testuser", "testpass");
// Both sessions should be valid
assertTrue(manager.isRemotelyLoggedIn(sessionId1.toString()),
"First session should be valid");
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
"Second session should be valid");
// Logout one session
manager.remoteLogout(sessionId1.toString());
// First session should be invalid, second should still be valid
assertFalse(manager.isRemotelyLoggedIn(sessionId1.toString()),
"First session should be invalidated");
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
"Second session should still be valid");
}
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
JUnitUtil.resetProfileManager();
manager = new DefaultPermissionManager().init();
}
@AfterEach
public void tearDown() {
JUnitUtil.tearDown();
}
}