Skip to content

Commit

Permalink
unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
lastpeony committed Oct 25, 2024
1 parent 80721e2 commit bae1bbc
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 24 deletions.
25 changes: 9 additions & 16 deletions src/main/java/io/antmedia/SystemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@ public static long osAvailableMemory() {
if(containerized) {
return osFreePhysicalMemory();
}
return Pointer.availablePhysicalBytes();

return availablePhysicalBytes();
}

/**
Expand Down Expand Up @@ -712,7 +712,6 @@ public static void getHeapDump(String filepath) {
}
}


private static HotSpotDiagnosticMXBean getHotspotMBean() {
try {
synchronized (SystemUtils.class) {
Expand All @@ -730,15 +729,21 @@ private static HotSpotDiagnosticMXBean getHotspotMBean() {
return hotspotMBean;
}

public static long availablePhysicalBytes(){
return Pointer.availablePhysicalBytes();
}

public static boolean isContainerized() {
try {
Path dockerEnvPath = Paths.get("/.dockerenv");

// 1. Check for .dockerenv file
if (new File("/.dockerenv").exists()) {
if (Files.exists(dockerEnvPath)) {
logger.debug("Container detected via .dockerenv file");
return true;
}


// 2. Check cgroup info
Path cgroupPath = Paths.get("/proc/self/cgroup");
if (Files.exists(cgroupPath)) {
Expand All @@ -754,18 +759,6 @@ public static boolean isContainerized() {
}
}

// 3. Check mount namespaces
Path mountInfo = Paths.get("/proc/self/mountinfo");
if (Files.exists(mountInfo)) {
List<String> mountContent = Files.readAllLines(mountInfo);
for (String line : mountContent) {
if (line.contains("/docker") || line.contains("/lxc")) {
logger.debug("Container detected via mountinfo: {}", line);
return true;
}
}
}

return false;

} catch (Exception e) {
Expand Down
109 changes: 101 additions & 8 deletions src/test/java/io/antmedia/test/statistic/StatsCollectorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
Expand All @@ -25,10 +26,12 @@
import org.apache.kafka.clients.producer.RecordMetadata;
import org.awaitility.Awaitility;
import org.bytedeco.ffmpeg.avutil.AVRational;
import org.bytedeco.javacpp.Pointer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.red5.server.Launcher;
import org.red5.server.api.IContext;
Expand Down Expand Up @@ -348,7 +351,7 @@ public void testHeartbeat() {
return true;
});

Mockito.verify(resMonitor, Mockito.times(1)).startAnalytic();
Mockito.verify(resMonitor, times(1)).startAnalytic();

resMonitor.cancelHeartBeat();

Expand All @@ -357,7 +360,7 @@ public void testHeartbeat() {
resMonitor.setHeartBeatEnabled(false);
resMonitor.start();
assertFalse(resMonitor.isHeartBeatEnabled());
Mockito.verify(resMonitor, Mockito.times(1)).startAnalytic();
Mockito.verify(resMonitor, times(1)).startAnalytic();

resMonitor.cancelHeartBeat();

Expand Down Expand Up @@ -481,7 +484,7 @@ public void testCollectAndSendWebRTCStats() {

resMonitor.collectAndSendWebRTCClientsStats();

verify(kafkaProducer, Mockito.times(1)).send(Mockito.any());
verify(kafkaProducer, times(1)).send(Mockito.any());

}

Expand Down Expand Up @@ -712,5 +715,95 @@ public void testGetAppAdaptor()


}


@Test
public void testOsAvailableMemory() {
long availableMemory = 1024;
long containerizedMemory = 2048;
try (MockedStatic<SystemUtils> mockedSystemUtils = Mockito.mockStatic(SystemUtils.class)) {
// Set up base mocking to allow real method call
mockedSystemUtils.when(SystemUtils::osAvailableMemory)
.thenCallRealMethod();

// Test non-containerized scenario
mockedSystemUtils.when(SystemUtils::isContainerized).thenReturn(false);
mockedSystemUtils.when(SystemUtils::availablePhysicalBytes).thenReturn(availableMemory);

long nonContainerizedResult = SystemUtils.osAvailableMemory();
assertEquals(availableMemory, nonContainerizedResult);

// Reset the state for containerized scenario
SystemUtils.containerized = null;

// Test containerized scenario
mockedSystemUtils.when(SystemUtils::isContainerized).thenReturn(true);
mockedSystemUtils.when(SystemUtils::osFreePhysicalMemory).thenReturn(containerizedMemory);

long containerizedResult = SystemUtils.osAvailableMemory();
assertEquals(containerizedMemory, containerizedResult);

// Verify all calls
mockedSystemUtils.verify(SystemUtils::isContainerized, times(2));
mockedSystemUtils.verify(SystemUtils::availablePhysicalBytes, times(1));
mockedSystemUtils.verify(SystemUtils::osFreePhysicalMemory, times(1));
}
}

@Test
public void testIsContainerized() {
Path mockDockerEnvPath = Path.of("/tmp/test/.dockerenv");
Path mockCgroupPath = Path.of("/tmp/test/cgroup");

try (MockedStatic<Files> mockedFiles = Mockito.mockStatic(Files.class);
MockedStatic<Paths> mockedPaths = Mockito.mockStatic(Paths.class)) {

// Setup path mocks
mockedPaths.when(() -> Paths.get("/.dockerenv")).thenReturn(mockDockerEnvPath);
mockedPaths.when(() -> Paths.get("/proc/self/cgroup")).thenReturn(mockCgroupPath);

// Test 1: Docker environment file exists
mockedFiles.when(() -> Files.exists(mockDockerEnvPath)).thenReturn(true);
assertTrue(SystemUtils.isContainerized());

// Test 2: Docker in cgroup
mockedFiles.when(() -> Files.exists(mockDockerEnvPath)).thenReturn(false);
mockedFiles.when(() -> Files.exists(mockCgroupPath)).thenReturn(true);
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenReturn(Collections.singletonList("12:memory:/docker/someId"));
assertTrue(SystemUtils.isContainerized());

// Test 3: LXC in cgroup
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenReturn(Collections.singletonList("12:memory:/lxc/someId"));
assertTrue(SystemUtils.isContainerized());

// Test 4: Kubernetes in cgroup
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenReturn(Collections.singletonList("12:memory:/kubepods/someId"));
assertTrue(SystemUtils.isContainerized());

// Test 5: Containerd in cgroup
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenReturn(Collections.singletonList("12:memory:/containerd/someId"));
assertTrue(SystemUtils.isContainerized());

// Test 6: No container
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenReturn(Collections.singletonList("12:memory:/user.slice"));
assertFalse(SystemUtils.isContainerized());

// Test 7: File access exception
mockedFiles.when(() -> Files.exists(mockDockerEnvPath))
.thenThrow(new SecurityException("Access denied"));
assertFalse(SystemUtils.isContainerized());

// Test 8: Read exception
mockedFiles.when(() -> Files.exists(mockDockerEnvPath)).thenReturn(false);
mockedFiles.when(() -> Files.exists(mockCgroupPath)).thenReturn(true);
mockedFiles.when(() -> Files.readAllLines(mockCgroupPath))
.thenThrow(new IOException("Read error"));
assertFalse(SystemUtils.isContainerized());
}
}

}

0 comments on commit bae1bbc

Please sign in to comment.