View Javadoc
1   /*
2    * Copyright 2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.driver.linux.proc;
6   
7   import static org.hamcrest.MatcherAssert.assertThat;
8   import static org.hamcrest.Matchers.greaterThan;
9   import static org.hamcrest.Matchers.greaterThanOrEqualTo;
10  import static org.junit.jupiter.api.Assertions.assertNotNull;
11  import static org.junit.jupiter.api.Assertions.assertTrue;
12  
13  import java.io.File;
14  import java.util.Map;
15  
16  import org.junit.jupiter.api.Test;
17  import org.junit.jupiter.api.condition.EnabledOnOs;
18  import org.junit.jupiter.api.condition.OS;
19  
20  import oshi.driver.linux.proc.ProcessStat.PidStat;
21  import oshi.driver.linux.proc.ProcessStat.PidStatM;
22  import oshi.software.os.OSProcess;
23  import oshi.software.os.OSProcess.State;
24  import oshi.util.ParseUtil;
25  import oshi.util.tuples.Triplet;
26  
27  @EnabledOnOs(OS.LINUX)
28  class ProcessStatTest {
29  
30      @Test
31      void testGetPidFiles() {
32          File[] files = ProcessStat.getPidFiles();
33          assertThat("Files should be non-empty array", files.length, greaterThan(0));
34          // No need to test every file, but no guarantee any one file exists due to race
35          // condition. Track that each test succeeds at least once.
36          boolean fileDescriptorFilesTested = false;
37          boolean pidStatMTested = false;
38          boolean pidStatsTested = false;
39          boolean threadIdsTested = false;
40          for (File f : files) {
41              int pid = ParseUtil.parseIntOrDefault(f.getName(), -1);
42              assertThat("Pid " + f.getName() + " must be numeric", pid, greaterThanOrEqualTo(0));
43              if (!fileDescriptorFilesTested) {
44                  fileDescriptorFilesTested = testGetFileDescriptorFiles(pid);
45              }
46              if (!pidStatMTested) {
47                  pidStatMTested = testGetPidStatM(pid);
48              }
49              if (!pidStatsTested) {
50                  pidStatsTested = testGetPidStats(pid);
51              }
52              if (!threadIdsTested) {
53                  threadIdsTested = testGetThreadIds(pid);
54              }
55              // If every test has passed at least once, we're done
56              if (fileDescriptorFilesTested && pidStatMTested && pidStatsTested && threadIdsTested) {
57                  break;
58              }
59          }
60          assertTrue(fileDescriptorFilesTested, "File Descriptor tests failed");
61          assertTrue(pidStatMTested, "PidStatM tests failed");
62          assertTrue(pidStatsTested, "PidStats tests failed");
63          assertTrue(threadIdsTested, "ThreadIds tests failed");
64      }
65  
66      private boolean testGetFileDescriptorFiles(int pid) {
67          // Pids should have STDIN, STDOUT, and STDERR fds
68          return ProcessStat.getFileDescriptorFiles(pid).length >= 3;
69      }
70  
71      private boolean testGetPidStatM(int pid) {
72          Map<PidStatM, Long> statM = ProcessStat.getPidStatM(pid);
73          assertNotNull(statM);
74          return !statM.isEmpty();
75      }
76  
77      private boolean testGetPidStats(int pid) {
78          Triplet<String, Character, Map<PidStat, Long>> stats = ProcessStat.getPidStats(pid);
79          assertNotNull(stats);
80          State procState = ProcessStat.getState(stats.getB());
81          return stats.getA().length() > 0 // at least one process should have nonempty name
82                  // At least one process should be running or sleeping
83                  && (procState.equals(OSProcess.State.RUNNING) || procState.equals(OSProcess.State.SLEEPING))
84                  // Have keys at least up to RSS
85                  && stats.getC().containsKey(PidStat.RSS);
86      }
87  
88      private boolean testGetThreadIds(int pid) {
89          // Every process should have at least one thread (itself)!
90          return !ProcessStat.getThreadIds(pid).isEmpty();
91      }
92  
93      @Test
94      void testQuerySocketToPidMap() {
95          assertThat("Socket to pid map shouldn't be empty.", ProcessStat.querySocketToPidMap().size(), greaterThan(0));
96      }
97  }