diff --git a/src/main/java/org/opensearch/performanceanalyzer/commons/os/ThreadSched.java b/src/main/java/org/opensearch/performanceanalyzer/commons/os/ThreadSched.java index 5cc5926..7234784 100644 --- a/src/main/java/org/opensearch/performanceanalyzer/commons/os/ThreadSched.java +++ b/src/main/java/org/opensearch/performanceanalyzer/commons/os/ThreadSched.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; @@ -38,6 +39,27 @@ public static class SchedMetrics { this.contextSwitchRate = contextSwitchRate; } + @Override + public int hashCode() { + return Objects.hash(this.avgRuntime, this.avgWaittime, this.contextSwitchRate); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SchedMetrics other = (SchedMetrics) o; + + return Double.compare(avgRuntime, other.avgRuntime) == 0 + && Double.compare(avgWaittime, other.avgWaittime) == 0 + && Double.compare(contextSwitchRate, other.contextSwitchRate) == 0; + } + @Override public String toString() { return new StringBuilder() diff --git a/src/test/java/org/opensearch/performanceanalyzer/commons/os/ThreadSchedTests.java b/src/test/java/org/opensearch/performanceanalyzer/commons/os/ThreadSchedTests.java index 4b234fe..254f914 100644 --- a/src/test/java/org/opensearch/performanceanalyzer/commons/os/ThreadSchedTests.java +++ b/src/test/java/org/opensearch/performanceanalyzer/commons/os/ThreadSchedTests.java @@ -8,13 +8,14 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.verify; import java.util.List; import java.util.Map; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.opensearch.performanceanalyzer.commons.metrics_generator.linux.LinuxSchedMetricsGenerator; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -30,25 +31,61 @@ public class ThreadSchedTests { private Map> tidKVMap = Map.of( - "1", Map.of("runticks", "1", "waitticks", "2", "totctxsws", "3"), - "2", Map.of("runticks", "4", "waitticks", "5", "totctxsws", "6"), - "3", Map.of("runticks", "7", "waitticks", "8", "totctxsws", "9")); + "1", Map.of("runticks", 100000000L, "waitticks", 100000000L, "totctxsws", 100L), + "2", Map.of("runticks", 100000000L, "waitticks", 100000000L, "totctxsws", 10L), + "3", + Map.of( + "runticks", + 500000000L, + "waitticks", + 500000000L, + "totctxsws", + 120L)); + + private Map> nextTidKVMap = + Map.of( + "1", Map.of("runticks", 200000000L, "waitticks", 200000000L, "totctxsws", 200L), + "2", Map.of("runticks", 500000000L, "waitticks", 500000000L, "totctxsws", 20L), + "3", + Map.of( + "runticks", + 700000000L, + "waitticks", + 700000000L, + "totctxsws", + 220L)); + + @Test + public void testMetrics() throws Exception { + // this test checks that + // 1. ThreadSched calls the SchemaFileParser constructor with the correct path + // 2. ThreadSched calculates the correct metrics from procfile data - @Before - public void setUp() throws Exception { // mock OSGlobals PowerMockito.mockStatic(OSGlobals.class); PowerMockito.when(OSGlobals.getPid()).thenReturn("0"); PowerMockito.when(OSGlobals.getTids()).thenReturn(List.of("1", "2", "3")); - } - @Test - public void testMetrics() throws Exception { + // mock System.currentTimeMillis() + // used by ThreadSched to compute SchedMetric + PowerMockito.mockStatic(System.class); + // having the time difference = 1000ms + // means that contextSwitchRate = difference in totctxsws + PowerMockito.when(System.currentTimeMillis()).thenReturn(10L, 1010L); + + // mock the metrics generator used by ThreadSched + LinuxSchedMetricsGenerator linuxSchedMetricsGenerator = + Mockito.mock(LinuxSchedMetricsGenerator.class); + PowerMockito.whenNew(LinuxSchedMetricsGenerator.class) + .withNoArguments() + .thenReturn(linuxSchedMetricsGenerator); + // mock SchemaFileParser (used by ThreadSched to read procfiles) SchemaFileParser schemaFileParser = Mockito.mock(SchemaFileParser.class); PowerMockito.when(schemaFileParser.parse()) - .thenReturn(tidKVMap.get("1"), tidKVMap.get("2"), tidKVMap.get("3")); + .thenReturn(tidKVMap.get("1"), tidKVMap.get("2"), tidKVMap.get("3")) + .thenReturn(nextTidKVMap.get("1"), nextTidKVMap.get("2"), nextTidKVMap.get("3")); PowerMockito.whenNew(SchemaFileParser.class) .withAnyArguments() @@ -75,5 +112,15 @@ public void testMetrics() throws Exception { isA(SchemaFileParser.FieldTypes[].class)); assertEquals(tidKVMap, ThreadSched.INSTANCE.getTidKVMap()); + + ThreadSched.INSTANCE.addSample(); + + // verify that the metrics generator is given correct metrics + verify(linuxSchedMetricsGenerator) + .setSchedMetric("1", new ThreadSched.SchedMetrics(0.001, 0.001, 100.0)); + verify(linuxSchedMetricsGenerator) + .setSchedMetric("2", new ThreadSched.SchedMetrics(0.04, 0.04, 10.0)); + verify(linuxSchedMetricsGenerator) + .setSchedMetric("3", new ThreadSched.SchedMetrics(0.002, 0.002, 100.0)); } }