166 lines
6.2 KiB
Java
166 lines
6.2 KiB
Java
|
|
package ai.nomyo;
|
||
|
|
|
||
|
|
import org.junit.jupiter.api.*;
|
||
|
|
|
||
|
|
import java.util.Map;
|
||
|
|
|
||
|
|
import static org.junit.jupiter.api.Assertions.*;
|
||
|
|
|
||
|
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||
|
|
class SecureMemoryTest {
|
||
|
|
|
||
|
|
@BeforeEach
|
||
|
|
void resetSecureMemoryState() {
|
||
|
|
SecureMemory.setSecureMemoryEnabled(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should return enabled=true by default")
|
||
|
|
void getMemoryProtectionInfo_default_shouldBeEnabled() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals(true, info.get("enabled"), "Memory protection should be enabled by default");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should report has_secure_zeroing=true")
|
||
|
|
void getMemoryProtectionInfo_shouldReportZeroing() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals(true, info.get("has_secure_zeroing"), "Should report secure zeroing available");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should report has_memory_locking=false")
|
||
|
|
void getMemoryProtectionInfo_shouldReportNoLocking() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals(false, info.get("has_memory_locking"), "Should report memory locking unavailable");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should report protection_level=zeroing_only")
|
||
|
|
void getMemoryProtectionInfo_protectionLevel_shouldBeZeroingOnly() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals("zeroing_only", info.get("protection_level"),
|
||
|
|
"Protection level should be zeroing_only (no memory locking)");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should return page_size from Constants")
|
||
|
|
void getMemoryProtectionInfo_pageSize_shouldMatchConstants() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals(Constants.PAGE_SIZE, info.get("page_size"),
|
||
|
|
"Page size should match Constants.PAGE_SIZE");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should report supports_full_protection=false without locking")
|
||
|
|
void getMemoryProtectionInfo_fullProtection_shouldBeFalse() {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
|
||
|
|
assertEquals(false, info.get("supports_full_protection"),
|
||
|
|
"Full protection should be false without memory locking");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("getMemoryProtectionInfo should report supports_full_protection=false when disabled")
|
||
|
|
void getMemoryProtectionInfo_disabled_shouldNotSupportFull() {
|
||
|
|
SecureMemory.setSecureMemoryEnabled(false);
|
||
|
|
try {
|
||
|
|
Map<String, Object> info = SecureMemory.getMemoryProtectionInfo();
|
||
|
|
assertEquals(false, info.get("supports_full_protection"),
|
||
|
|
"Full protection should be false when disabled");
|
||
|
|
assertEquals(false, info.get("enabled"), "Enabled should be false");
|
||
|
|
} finally {
|
||
|
|
SecureMemory.setSecureMemoryEnabled(true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("secureByteArray should create a SecureBuffer with data")
|
||
|
|
void secureByteArray_shouldCreateBuffer() {
|
||
|
|
byte[] data = new byte[]{1, 2, 3, 4, 5};
|
||
|
|
|
||
|
|
try (SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data)) {
|
||
|
|
assertNotNull(buffer.getData(), "Data segment should not be null");
|
||
|
|
assertEquals(5, buffer.getSize(), "Size should match input");
|
||
|
|
assertNotEquals(0, buffer.getAddress(), "Address should not be zero");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("secureByteArray should handle null data gracefully")
|
||
|
|
void secureByteArray_nullData_shouldHandleGracefully() {
|
||
|
|
try (SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(null)) {
|
||
|
|
assertNotNull(buffer, "Buffer should not be null even with null data");
|
||
|
|
assertEquals(0, buffer.getSize(), "Size should be 0 for null data");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("SecureBuffer zero should clear all bytes")
|
||
|
|
void secureBuffer_zero_shouldClearBytes() {
|
||
|
|
byte[] data = new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF};
|
||
|
|
SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data);
|
||
|
|
|
||
|
|
buffer.zero();
|
||
|
|
|
||
|
|
assertDoesNotThrow(() -> buffer.zero(), "Zeroing should not throw");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("SecureBuffer close should zero and unlock")
|
||
|
|
void secureBuffer_close_shouldZeroAndUnlock() {
|
||
|
|
byte[] data = new byte[]{1, 2, 3};
|
||
|
|
|
||
|
|
assertDoesNotThrow(() -> {
|
||
|
|
try (SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data)) {
|
||
|
|
assertNotNull(buffer.getData());
|
||
|
|
}
|
||
|
|
}, "Close via try-with-resources should not throw");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("SecureBuffer close should be idempotent")
|
||
|
|
void secureBuffer_close_idempotent() {
|
||
|
|
byte[] data = new byte[]{1, 2, 3};
|
||
|
|
SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data);
|
||
|
|
|
||
|
|
assertDoesNotThrow(() -> buffer.close(), "First close should not throw");
|
||
|
|
assertDoesNotThrow(() -> buffer.close(), "Second close should not throw");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("SecureBuffer lock should return false (not supported)")
|
||
|
|
void secureBuffer_lock_shouldReturnFalse() {
|
||
|
|
byte[] data = new byte[]{1, 2, 3};
|
||
|
|
SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data, true);
|
||
|
|
|
||
|
|
assertFalse(buffer.lock(), "Lock should return false (not supported)");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("SecureBuffer unlock should return false")
|
||
|
|
void secureBuffer_unlock_shouldReturnFalse() {
|
||
|
|
byte[] data = new byte[]{1, 2, 3};
|
||
|
|
SecureMemory.SecureBuffer buffer = SecureMemory.secureByteArray(data, true);
|
||
|
|
|
||
|
|
assertFalse(buffer.unlock(), "Unlock should return false");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("HAS_MEMORY_LOCKING should be false")
|
||
|
|
void hasMemoryLocking_shouldBeFalse() {
|
||
|
|
assertFalse(SecureMemory.isHAS_MEMORY_LOCKING(), "HAS_MEMORY_LOCKING should be false");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Test
|
||
|
|
@DisplayName("HAS_SECURE_ZEROING should be true")
|
||
|
|
void hasSecureZeroing_shouldBeTrue() {
|
||
|
|
assertTrue(SecureMemory.isHAS_SECURE_ZEROING(), "HAS_SECURE_ZEROING should be true");
|
||
|
|
}
|
||
|
|
}
|