utils_proc_pids: moved to utils directory
authorAleksinski, MichalX <michalx.aleksinski@intel.com>
Wed, 20 Feb 2019 12:32:50 +0000 (12:32 +0000)
committerAleksinski, MichalX <michalx.aleksinski@intel.com>
Wed, 6 Mar 2019 07:04:16 +0000 (07:04 +0000)
Change-Id: Ia7c9bf5dca2b871b05c9ed3876059e6d34bd943e

Makefile.am
src/intel_rdt.c
src/utils/proc_pids/proc_pids.c [new file with mode: 0644]
src/utils/proc_pids/proc_pids.h [new file with mode: 0644]
src/utils/proc_pids/proc_pids_test.c [new file with mode: 0644]
src/utils_proc_pids.c [deleted file]
src/utils_proc_pids.h [deleted file]
src/utils_proc_pids_test.c [deleted file]

index b4195c1..7a64fbf 100644 (file)
@@ -378,7 +378,7 @@ test_utils_config_cores_SOURCES = \
 test_utils_config_cores_LDADD = libplugin_mock.la
 
 test_utils_proc_pids_SOURCES = \
-       src/utils_proc_pids_test.c \
+       src/utils/proc_pids/proc_pids_test.c \
        src/testing.h
 test_utils_proc_pids_LDADD = libplugin_mock.la
 
@@ -1071,8 +1071,8 @@ if BUILD_PLUGIN_INTEL_RDT
 pkglib_LTLIBRARIES += intel_rdt.la
 intel_rdt_la_SOURCES = \
        src/intel_rdt.c \
-       src/utils_proc_pids.c \
-       src/utils_proc_pids.h \
+       src/utils/proc_pids/proc_pids.c \
+       src/utils/proc_pids/proc_pids.h \
        src/utils/config_cores/config_cores.h \
        src/utils/config_cores/config_cores.c
 intel_rdt_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBPQOS_CPPFLAGS)
@@ -1082,7 +1082,7 @@ intel_rdt_la_LIBADD = $(BUILD_WITH_LIBPQOS_LIBS)
 test_plugin_intel_rdt_SOURCES = \
        src/intel_rdt_test.c \
        src/utils/config_cores/config_cores.c \
-       src/utils_proc_pids.c \
+       src/utils/proc_pids/proc_pids.c \
        src/daemon/configfile.c \
        src/daemon/types_list.c
 test_plugin_intel_rdt_CPPFLAGS = $(AM_CPPFLAGS)
index 7364820..003f71a 100644 (file)
@@ -31,7 +31,7 @@
 #include "collectd.h"
 #include "utils/common/common.h"
 #include "utils/config_cores/config_cores.h"
-#include "utils_proc_pids.h"
+#include "utils/proc_pids/proc_pids.h"
 #include <pqos.h>
 
 #define RDT_PLUGIN "intel_rdt"
@@ -526,7 +526,7 @@ static int rdt_config_ngroups(rdt_ctx_t *rdt, const oconfig_item_t *item) {
          name_idx++) {
       DEBUG(RDT_PLUGIN ":    checking process name [%zu]: %s", name_idx,
             rdt->ngroups[group_idx].names[name_idx]);
-      if (!is_proc_name_valid(rdt->ngroups[group_idx].names[name_idx])) {
+      if (!proc_pids_is_name_valid(rdt->ngroups[group_idx].names[name_idx])) {
         ERROR(RDT_PLUGIN ": Process name group '%s' contains invalid name '%s'",
               rdt->ngroups[group_idx].desc,
               rdt->ngroups[group_idx].names[name_idx]);
@@ -798,7 +798,7 @@ static int read_pids_data() {
 #endif /* COLLECT_DEBUG */
 
 groups_refresh:
-  ret = update_proc_pids(RDT_PROC_PATH, g_rdt->proc_pids, g_rdt->num_proc_pids);
+  ret = proc_pids_update(RDT_PROC_PATH, g_rdt->proc_pids, g_rdt->num_proc_pids);
   if (0 != ret) {
     ERROR(RDT_PLUGIN ": Initial update of proc pids failed");
     return ret;
@@ -839,8 +839,8 @@ static void rdt_init_pids_monitoring() {
      * PIDs statistics detection.
      */
     rdt_name_group_t *ng = &g_rdt->ngroups[group_idx];
-    int init_result = initialize_proc_pids((const char **)ng->names,
-                                           ng->num_names, &ng->proc_pids);
+    int init_result =
+        proc_pids_init((const char **)ng->names, ng->num_names, &ng->proc_pids);
     if (0 != init_result) {
       ERROR(RDT_PLUGIN
             ": Initialization of proc_pids for group %zu failed. Error: %d",
@@ -865,7 +865,7 @@ static void rdt_init_pids_monitoring() {
   }
 
   int update_result =
-      update_proc_pids(RDT_PROC_PATH, g_rdt->proc_pids, g_rdt->num_proc_pids);
+      proc_pids_update(RDT_PROC_PATH, g_rdt->proc_pids, g_rdt->num_proc_pids);
   if (0 != update_result)
     ERROR(RDT_PLUGIN ": Initial update of proc pids failed");
 
diff --git a/src/utils/proc_pids/proc_pids.c b/src/utils/proc_pids/proc_pids.c
new file mode 100644 (file)
index 0000000..336a996
--- /dev/null
@@ -0,0 +1,361 @@
+/**
+ * collectd - src/utils/proc_pids/proc_pids.c
+ *
+ * Copyright(c) 2018-2019 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Starzyk, Mateusz <mateuszx.starzyk@intel.com>
+ *   Wojciech Andralojc <wojciechx.andralojc@intel.com>
+ *   Michał Aleksiński <michalx.aleksinski@intel.com>
+ **/
+
+#include "collectd.h"
+#include "utils/common/common.h"
+#include "utils/proc_pids/proc_pids.h"
+
+#define UTIL_NAME "utils_proc_pids"
+
+void pids_list_free(pids_list_t *list) {
+  assert(list);
+
+  sfree(list->pids);
+  sfree(list);
+}
+
+int proc_pids_is_name_valid(const char *name) {
+
+  if (name != NULL) {
+    unsigned len = strlen(name);
+    if (len > 0 && len <= MAX_PROC_NAME_LEN)
+      return 1;
+    else {
+      DEBUG(UTIL_NAME
+            ": Process name \'%s\' is too long. Max supported len is %d chars.",
+            name, MAX_PROC_NAME_LEN);
+    }
+  }
+
+  return 0;
+}
+
+int pids_list_add_pid(pids_list_t *list, const pid_t pid) {
+  assert(list);
+
+  if (list->allocated == list->size) {
+    size_t new_allocated = list->allocated + 1 + list->allocated / 10;
+    pid_t *new_pids = realloc(list->pids, sizeof(pid_t) * new_allocated);
+
+    if (NULL == new_pids) {
+      ERROR(UTIL_NAME ": Alloc error\n");
+      return -1;
+    }
+
+    list->pids = new_pids;
+    list->allocated = new_allocated;
+  }
+
+  list->pids[list->size] = pid;
+  list->size++;
+
+  return 0;
+}
+
+int pids_list_add_list(pids_list_t *dst, pids_list_t *src) {
+  assert(dst);
+  assert(src);
+
+  if (dst->allocated < dst->size + src->size) {
+    pid_t *new_pids =
+        realloc(dst->pids, sizeof(pid_t) * (dst->size + src->size));
+
+    if (NULL == new_pids) {
+      ERROR(UTIL_NAME ": Alloc error\n");
+      return -1;
+    }
+
+    dst->allocated = dst->size + src->size;
+    dst->pids = new_pids;
+  }
+
+  memcpy(dst->pids + dst->size, src->pids, src->size * sizeof(*(src->pids)));
+  dst->size += src->size;
+
+  return 0;
+}
+
+int pids_list_clear(pids_list_t *list) {
+  assert(list);
+
+  if (list->pids != NULL)
+    sfree(list->pids);
+
+  list->size = 0;
+  list->allocated = 0;
+
+  return 0;
+}
+
+int pids_list_contains_pid(pids_list_t *list, const pid_t pid) {
+  assert(list);
+
+  for (int i = 0; i < list->size; i++)
+    if (list->pids[i] == pid)
+      return 1;
+
+  return 0;
+}
+
+/*
+ * NAME
+ *   read_proc_name
+ *
+ * DESCRIPTION
+ *   Reads process name from given pid directory.
+ *   Strips new-line character (\n).
+ *
+ * PARAMETERS
+ *   `procfs_path' Path to systems proc directory (e.g. /proc)
+ *   `pid_entry'   Dirent for PID directory
+ *   `name'        Output buffer for process name, recommended proc_comm.
+ *   `out_size'    Output buffer size, recommended sizeof(proc_comm)
+ *
+ * RETURN VALUE
+ *   On success, the number of read bytes (includes stripped \n).
+ *   -1 on file open error
+*/
+static int read_proc_name(const char *procfs_path,
+                          const struct dirent *pid_entry, char *name,
+                          const size_t out_size) {
+  assert(pid_entry);
+  assert(name);
+  assert(out_size);
+  memset(name, 0, out_size);
+
+  const char *comm_file_name = "comm";
+
+  char *path = ssnprintf_alloc("%s/%s/%s", procfs_path, pid_entry->d_name,
+                               comm_file_name);
+  if (path == NULL)
+    return -1;
+  FILE *f = fopen(path, "r");
+  if (f == NULL) {
+    ERROR(UTIL_NAME ": Failed to open comm file, error: %d\n", errno);
+    sfree(path);
+    return -1;
+  }
+  size_t read_length = fread(name, sizeof(char), out_size, f);
+  name[out_size - 1] = '\0';
+  fclose(f);
+  sfree(path);
+  /* strip new line ending */
+  char *newline = strchr(name, '\n');
+  if (newline) {
+    *newline = '\0';
+  }
+
+  return read_length;
+}
+
+/*
+ * NAME
+ *   get_pid_number
+ *
+ * DESCRIPTION
+ *   Gets pid number for given /proc/pid directory entry or
+ *   returns error if input directory does not hold PID information.
+ *
+ * PARAMETERS
+ *   `entry'    Dirent for PID directory
+ *   `pid'      PID number to be filled
+ *
+ * RETURN VALUE
+ *   0 on success. -1 on error.
+ */
+static int get_pid_number(struct dirent *entry, pid_t *pid) {
+  char *tmp_end; /* used for strtoul error check*/
+
+  if (pid == NULL || entry == NULL)
+    return -1;
+
+  if (entry->d_type != DT_DIR)
+    return -1;
+
+  /* trying to get pid number from directory name*/
+  *pid = strtoul(entry->d_name, &tmp_end, 10);
+  if (*tmp_end != '\0') {
+    return -1; /* conversion failed, not proc-pid */
+  }
+  /* all checks passed, marking as success */
+  return 0;
+}
+
+int proc_pids_init(const char **procs_names_array,
+                   const size_t procs_names_array_size,
+                   proc_pids_t **proc_pids[]) {
+
+  proc_pids_t **proc_pids_array;
+  assert(proc_pids);
+  assert(NULL == *proc_pids);
+
+  /* Copy procs names to output array. Initialize pids list with NULL value. */
+  proc_pids_array = calloc(procs_names_array_size, sizeof(*proc_pids_array));
+
+  if (NULL == proc_pids_array)
+    return -1;
+
+  for (size_t i = 0; i < procs_names_array_size; ++i) {
+    proc_pids_array[i] = calloc(1, sizeof(**proc_pids_array));
+    if (NULL == proc_pids_array[i])
+      goto proc_pids_init_error;
+
+    sstrncpy(proc_pids_array[i]->process_name, procs_names_array[i],
+             STATIC_ARRAY_SIZE(proc_pids_array[i]->process_name));
+    proc_pids_array[i]->prev = NULL;
+    proc_pids_array[i]->curr = NULL;
+  }
+
+  *proc_pids = proc_pids_array;
+
+  return 0;
+proc_pids_init_error:
+  if (NULL != proc_pids_array) {
+    for (size_t i = 0; i < procs_names_array_size; ++i) {
+      free(proc_pids_array[i]);
+    }
+    free(proc_pids_array);
+  }
+  return -1;
+}
+
+static void swap_proc_pids(proc_pids_t **proc_pids, size_t proc_pids_num) {
+  for (size_t i = 0; i < proc_pids_num; i++) {
+    pids_list_t *swap = proc_pids[i]->prev;
+    proc_pids[i]->prev = proc_pids[i]->curr;
+    proc_pids[i]->curr = swap;
+  }
+}
+
+int proc_pids_update(const char *procfs_path, proc_pids_t **proc_pids,
+                     size_t proc_pids_num) {
+  assert(procfs_path);
+  assert(proc_pids);
+
+  DIR *proc_dir = opendir(procfs_path);
+  if (proc_dir == NULL) {
+    ERROR(UTIL_NAME ": Could not open %s directory, error: %d", procfs_path,
+          errno);
+    return -1;
+  }
+
+  swap_proc_pids(proc_pids, proc_pids_num);
+
+  for (size_t i = 0; i < proc_pids_num; i++) {
+    if (NULL == proc_pids[i]->curr)
+      proc_pids[i]->curr = calloc(1, sizeof(*(proc_pids[i]->curr)));
+
+    if (NULL == proc_pids[i]->curr) {
+      ERROR(UTIL_NAME ": Alloc error\n");
+      goto update_error;
+    }
+
+    proc_pids[i]->curr->size = 0;
+  }
+
+  /* Go through procfs and find PIDS and their comms */
+  struct dirent *entry;
+  while ((entry = readdir(proc_dir)) != NULL) {
+    pid_t pid;
+    int pid_conversion = get_pid_number(entry, &pid);
+    if (pid_conversion < 0)
+      continue;
+
+    proc_comm_t comm;
+    int read_result =
+        read_proc_name(procfs_path, entry, comm, sizeof(proc_comm_t));
+    if (read_result <= 0)
+      continue;
+
+    /* Try to find comm in input procs array */
+    for (size_t i = 0; i < proc_pids_num; ++i) {
+      if (0 ==
+          strncmp(comm, proc_pids[i]->process_name, STATIC_ARRAY_SIZE(comm)))
+        pids_list_add_pid(proc_pids[i]->curr, pid);
+    }
+  }
+
+  int close_result = closedir(proc_dir);
+  if (0 != close_result) {
+    ERROR(UTIL_NAME ": failed to close /proc directory, error: %d", errno);
+    goto update_error;
+  }
+  return 0;
+
+update_error:
+  swap_proc_pids(proc_pids, proc_pids_num);
+  return -1;
+}
+
+int pids_list_diff(proc_pids_t *proc, pids_list_t *added,
+                   pids_list_t *removed) {
+  assert(proc);
+  assert(added);
+  assert(removed);
+
+  added->size = 0;
+  removed->size = 0;
+
+  if (NULL == proc->prev || 0 == proc->prev->size) {
+    /* append all PIDs from curr to added*/
+    return pids_list_add_list(added, proc->curr);
+  } else if (NULL == proc->curr || 0 == proc->curr->size) {
+    /* append all PIDs from prev to removed*/
+    return pids_list_add_list(removed, proc->prev);
+  }
+
+  for (int i = 0; i < proc->prev->size; i++)
+    if (0 == pids_list_contains_pid(proc->curr, proc->prev->pids[i])) {
+      int add_result = pids_list_add_pid(removed, proc->prev->pids[i]);
+      if (add_result < 0)
+        return add_result;
+    }
+
+  for (int i = 0; i < proc->curr->size; i++)
+    if (0 == pids_list_contains_pid(proc->prev, proc->curr->pids[i])) {
+      int add_result = pids_list_add_pid(added, proc->curr->pids[i]);
+      if (add_result < 0)
+        return add_result;
+    }
+
+  return 0;
+}
+
+int proc_pids_free(proc_pids_t *proc_pids[], size_t proc_pids_num) {
+  for (size_t i = 0; i < proc_pids_num; i++) {
+    if (NULL != proc_pids[i]->curr)
+      pids_list_free(proc_pids[i]->curr);
+    if (NULL != proc_pids[i]->prev)
+      pids_list_free(proc_pids[i]->prev);
+    sfree(proc_pids[i]);
+  }
+  sfree(proc_pids);
+
+  return 0;
+}
diff --git a/src/utils/proc_pids/proc_pids.h b/src/utils/proc_pids/proc_pids.h
new file mode 100644 (file)
index 0000000..8b19497
--- /dev/null
@@ -0,0 +1,226 @@
+/**
+ * collectd - src/utils/proc_pids/proc_pids.h
+ *
+ * Copyright(c) 2018-2019 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Starzyk, Mateusz <mateuszx.starzyk@intel.com>
+ *   Wojciech Andralojc <wojciechx.andralojc@intel.com>
+ *   Michał Aleksiński <michalx.aleksinski@intel.com>
+ **/
+
+#include <dirent.h>
+#include <sys/types.h>
+
+/*
+ * Process name inside comm file is limited to 16 chars.
+ * More info here: http://man7.org/linux/man-pages/man5/proc.5.html
+ */
+#define MAX_PROC_NAME_LEN 16
+
+/* Helper typedef for process name array
+ * Extra 1 char is added for string null termination.
+ */
+typedef char proc_comm_t[MAX_PROC_NAME_LEN + 1];
+
+/* List of pids. */
+typedef struct pids_list_s {
+  pid_t *pids;
+  size_t size;
+  size_t allocated;
+} pids_list_t;
+
+/* Holds process name and list of pids assigned to that name */
+typedef struct proc_pids_s {
+  proc_comm_t process_name;
+  pids_list_t *prev;
+  pids_list_t *curr;
+} proc_pids_t;
+
+/*
+ * NAME
+ *   pids_list_free
+ *
+ * DESCRIPTION
+ *   Free all elements of given pids list
+ *
+ * PARAMETERS
+ *   `list'     Head of target pids_list.
+ */
+void pids_list_free(pids_list_t *list);
+
+/*
+ * NAME
+ *   pids_list_add_pid
+ *
+ * DESCRIPTION
+ *   Adds pid at the end of the pids array.
+ *   Reallocates memory for new pid element, it is up to user to free it.
+ *
+ * PARAMETERS
+ *   `list'     Target pids_list.
+ *   `pid'      Pid to be added.
+ *
+ * RETURN VALUE
+ *   On success, returns 0.
+ *   -1 on memory allocation error.
+ */
+int pids_list_add_pid(pids_list_t *list, const pid_t pid);
+
+/*
+ * NAME
+ *   pids_list_clear
+ *
+ * DESCRIPTION
+ *   Remove all pids from the list
+ *
+ * PARAMETERS
+ *   `list'     Target pids_list.
+ *
+ * RETURN VALUE
+ *   On success, return 0
+ */
+int pids_list_clear(pids_list_t *list);
+
+/*
+ * NAME
+ *   pids_list_add_list
+ *
+ * DESCRIPTION
+ *   Adds pids list at the end of the pids list.
+ *   Allocates memory for new pid elements, it is up to user to free it.
+ *
+ * PARAMETERS
+ *   `dst'      Target PIDs list.
+ *   `src'      Source PIDs list.
+ *
+ * RETURN VALUE
+ *   On success, returns 0.
+ *   -1 on memory allocation error.
+ */
+int pids_list_add_list(pids_list_t *dst, pids_list_t *src);
+
+/*
+ * NAME
+ *   pids_list_contains_pid
+ *
+ * DESCRIPTION
+ *   Tests if pids list contains specific pid.
+ *
+ * PARAMETERS
+ *   `list'     pids_list to check.
+ *   `pid'      Pid to be searched for.
+ *
+ * RETURN VALUE
+ *   If PID found in list, returns 1,
+ *   Otherwise returns 0.
+ */
+int pids_list_contains_pid(pids_list_t *list, const pid_t pid);
+
+/*
+ * NAME
+ *   pids_list_diff
+ *
+ * DESCRIPTION
+ *   Searches for differences in two given lists
+ *
+ * PARAMETERS
+ *   `proc'            List of pids
+ *   `added'           New pids which appeared
+ *   `removed'         Result array storing pids which disappeared
+ * RETURN VALUE
+ *   0 on success. Negative number on error.
+ */
+int pids_list_diff(proc_pids_t *proc, pids_list_t *added, pids_list_t *removed);
+
+/*
+ * NAME
+ *   proc_pids_is_name_valid
+ *
+ * DESCRIPTION
+ *   Checks if given string is valid process name.
+ *
+ * PARAMETERS
+ *   `name'     null-terminated char array
+ *
+ * RETURN VALUE
+ *   If given name is a valid process name, returns 1,
+ *   Otherwise returns 0.
+ */
+int proc_pids_is_name_valid(const char *name);
+
+/*
+ * NAME
+ *   proc_pids_init
+ *
+ * DESCRIPTION
+ *   Helper function to properly initialize array of proc_pids.
+ *   Allocates memory for proc_pids structs.
+ *
+ * PARAMETERS
+ *   `procs_names_array'      Array of null-terminated strings with
+ *                            process' names to be copied to new array
+ *   `procs_names_array_size' procs_names_array element count
+ *   `proc_pids'              Address of pointer, under which new
+ *                            array of proc_pids will be allocated.
+ *                            Must be NULL.
+ * RETURN VALUE
+ *   0 on success. Negative number on error:
+ *   -1: allocation error
+ */
+int proc_pids_init(const char **procs_names_array,
+                   const size_t procs_names_array_size,
+                   proc_pids_t **proc_pids[]);
+
+/*
+ * NAME
+ *   proc_pids_update
+ *
+ * DESCRIPTION
+ *   Updates PIDs matching processes's names.
+ *   Searches all PID directories in /proc fs and updates current pids_list.
+ *
+ * PARAMETERS
+ *   `procfs_path'     Path to systems proc directory (e.g. /proc)
+ *   `proc_pids'       Array of proc_pids pointers to be updated.
+ *   `proc_pids_num'   proc_pids element count
+ *
+ * RETURN VALUE
+ *   0 on success. -1 on error.
+ */
+int proc_pids_update(const char *procfs_path, proc_pids_t *proc_pids[],
+                     size_t proc_pids_num);
+
+/*
+ * NAME
+ *   proc_pids_free
+ *
+ * DESCRIPTION
+ *   Releses memory allocatd for proc_pids
+ *
+ * PARAMETERS
+ *   `proc_pids'       Array of proc_pids
+ *   `proc_pids_num'   proc_pids element count
+ *
+ * RETURN VALUE
+ *   0 on success. -1 on error.
+ */
+int proc_pids_free(proc_pids_t *proc_pids[], size_t proc_pids_num);
diff --git a/src/utils/proc_pids/proc_pids_test.c b/src/utils/proc_pids/proc_pids_test.c
new file mode 100644 (file)
index 0000000..06b8d39
--- /dev/null
@@ -0,0 +1,505 @@
+#include "testing.h"
+#include "utils/proc_pids/proc_pids.c" /* sic */
+#include <sys/stat.h>
+
+/***************************************************************************
+ * helper functions
+ */
+
+typedef struct stub_proc_pid {
+  proc_comm_t comm;
+  pid_t pid;
+} stub_proc_pid_t;
+
+static const char *proc_fs = "/tmp/procfs_stub";
+
+/*
+ * NAME
+ *   stub_procfs_setup
+ *
+ * DESCRIPTION
+ *   Prepares testing environment by creating temporary
+ *   PID/comm file structure.
+ *
+ * PARAMETERS
+ *   `proc_pids_array'          Array of stub_proc_pid_t structs. Represents
+ *                              which PIDs should hold given process name.
+ *   `proc_pids_array_length'   Element count of input array.
+ *
+ * RETURN VALUE
+ *   0 on success.
+ *   -1 on base dir creation error.
+ *   -2 on comm file creation error.
+ *   -3 on comm file write error.
+ */
+int stub_procfs_setup(const stub_proc_pid_t *proc_pids_array,
+                      const size_t proc_pids_array_length) {
+  if (mkdir(proc_fs, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
+    return -1;
+  char path[256];
+
+  for (size_t i = 0; i < proc_pids_array_length; ++i) {
+    memset(path, 0, sizeof(path));
+    snprintf(path, STATIC_ARRAY_SIZE(path), "%s/%d", proc_fs,
+             proc_pids_array[i].pid);
+    mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+    strncat(path, "/comm", STATIC_ARRAY_SIZE(path) - strlen(path) - 1);
+
+    FILE *fp = fopen(path, "w");
+    if (!fp)
+      return -2;
+
+    size_t slen = strlen(proc_pids_array[i].comm);
+    size_t wlen = fwrite(proc_pids_array[i].comm, sizeof(char), slen, fp);
+    fclose(fp);
+
+    if (slen != wlen)
+      return -3;
+  }
+  return 0;
+}
+
+/*
+ * NAME
+ *   stub_procfs_teardown
+ *
+ * DESCRIPTION
+ *   Clears testing environment: removes stub proc files.
+ *   NOTE - This function could be implemented by usage of nftw, but this
+ *   would require #define _XOPEN_SOURCE 500, which
+ *   messes up intel_rdt includes.
+ *
+ * RETURN VALUE
+ *   system command result
+ */
+int stub_procfs_teardown() {
+  char cmd[256];
+  sstrncpy(cmd, "rm -rf ", STATIC_ARRAY_SIZE(cmd));
+  strncat(cmd, proc_fs, STATIC_ARRAY_SIZE(cmd) - strlen(cmd) - 1);
+  return system(cmd);
+}
+
+/* Max PID value. More info:
+ * http://web.archive.org/web/20111209081734/http://research.cs.wisc.edu/condor/condorg/linux_scalability.html
+ */
+#define MAX_PID 4194304
+#define MAX_PID_STR "4194304"
+
+/***************************************************************************
+ * tests
+ */
+DEF_TEST(proc_pids_init__on_nullptr) {
+  /* setup */
+  const char *procs_names_array[] = {"proc1", "proc2", "proc3"};
+  const size_t procs_names_array_size = STATIC_ARRAY_SIZE(procs_names_array);
+  proc_pids_t **proc_pids_array = NULL;
+
+  /* check */
+  int result = proc_pids_init(procs_names_array, procs_names_array_size,
+                              &proc_pids_array);
+  EXPECT_EQ_INT(0, result);
+  for (size_t i = 0; i < procs_names_array_size; ++i)
+    EXPECT_EQ_STR(procs_names_array[i], proc_pids_array[i]->process_name);
+
+  /* cleanup */
+  proc_pids_free(proc_pids_array, procs_names_array_size);
+  return 0;
+}
+
+DEF_TEST(pid_list_add_pid__empty_list) {
+  /* setup */
+  pids_list_t *proc_pids_instance = calloc(1, sizeof(*proc_pids_instance));
+  pid_t pid = 1234;
+
+  /* check */
+  pids_list_add_pid(proc_pids_instance, pid);
+  EXPECT_EQ_INT(pid, proc_pids_instance->pids[0]);
+
+  /* cleanup */
+  pids_list_free(proc_pids_instance);
+  return 0;
+}
+
+DEF_TEST(pid_list_add_pid__non_empty_list) {
+  /* setup */
+  pids_list_t *proc_pids_instance = calloc(1, sizeof(*proc_pids_instance));
+  pid_t pids[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+
+  /* check */
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids); ++i)
+    pids_list_add_pid(proc_pids_instance, pids[i]);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids); ++i) {
+    EXPECT_EQ_INT(pids[i], proc_pids_instance->pids[i]);
+  }
+
+  /* cleanup */
+  pids_list_free(proc_pids_instance);
+  return 0;
+}
+
+DEF_TEST(pids_list_add_pids_list__non_empty_lists) {
+  /* setup */
+  pid_t pids_array_1[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+  pid_t pids_array_2[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
+  pids_list_t *pids_list_1 = calloc(1, sizeof(*pids_list_1));
+  pids_list_t *pids_list_2 = calloc(1, sizeof(*pids_list_2));
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_1); ++i) {
+    pids_list_add_pid(pids_list_1, pids_array_1[i]);
+    pids_list_add_pid(pids_list_2, pids_array_2[i]);
+  }
+
+  /* check */
+  int result = pids_list_add_list(pids_list_1, pids_list_2);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_2) +
+                    STATIC_ARRAY_SIZE(pids_array_1),
+                pids_list_1->size);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_1); ++i) {
+    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array_1[i]));
+    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array_2[i]));
+  }
+
+  /* setup */
+  pids_list_free(pids_list_1);
+  pids_list_free(pids_list_2);
+  return 0;
+}
+
+DEF_TEST(pids_list_add_pids_list__add_to_empty) {
+  /* setup */
+  pid_t pids_array[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
+  pids_list_t *pids_list_1 = calloc(1, sizeof(*pids_list_1));
+  pids_list_t *pids_list_2 = calloc(1, sizeof(*pids_list_2));
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array); ++i)
+    pids_list_add_pid(pids_list_2, pids_array[i]);
+
+  /* check */
+  int result = pids_list_add_list(pids_list_1, pids_list_2);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array), pids_list_1->size);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array); ++i)
+    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array[i]));
+
+  /* setup */
+  pids_list_free(pids_list_1);
+  pids_list_free(pids_list_2);
+  return 0;
+}
+
+DEF_TEST(get_pid_number__valid_dir) {
+  /* setup */
+  struct dirent d;
+  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
+  d.d_type = DT_DIR;
+  pid_t pid = 0;
+
+  /* check */
+  int pid_conversion = get_pid_number(&d, &pid);
+
+  EXPECT_EQ_INT(0, pid_conversion);
+  EXPECT_EQ_INT(MAX_PID, pid);
+
+  /* cleanup */
+  return 0;
+}
+
+DEF_TEST(get_pid_number__invalid_dir_name) {
+  /* setup */
+  struct dirent d;
+  sstrncpy(d.d_name, "invalid", STATIC_ARRAY_SIZE(d.d_name));
+  d.d_type = DT_DIR;
+  pid_t pid = 0;
+
+  /* check */
+  int pid_conversion = get_pid_number(&d, &pid);
+
+  EXPECT_EQ_INT(-1, pid_conversion);
+  EXPECT_EQ_INT(0, pid);
+
+  /* cleanup */
+  return 0;
+}
+
+DEF_TEST(read_proc_name__valid_name) {
+  /* setup */
+  stub_proc_pid_t pp_stubs[] = {{"proc1", MAX_PID}};
+  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
+  struct dirent d;
+  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
+  d.d_type = DT_DIR;
+
+  /* check */
+  proc_comm_t comm;
+  int read_result = read_proc_name(proc_fs, &d, comm, STATIC_ARRAY_SIZE(comm));
+
+  EXPECT_EQ_INT(strlen(pp_stubs[0].comm), read_result);
+  EXPECT_EQ_STR(pp_stubs[0].comm, comm);
+
+  /* cleanup */
+  stub_procfs_teardown();
+  return 0;
+}
+
+DEF_TEST(read_proc_name__invalid_name) {
+  /* setup */
+  struct dirent d;
+  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
+  d.d_type = DT_DIR;
+
+  /* check */
+  proc_comm_t comm;
+  int read_result = read_proc_name(proc_fs, &d, comm, STATIC_ARRAY_SIZE(comm));
+
+  EXPECT_EQ_INT(-1, read_result);
+
+  /* cleanup */
+  return 0;
+}
+
+DEF_TEST(proc_pids_update__one_proc_many_pid) {
+  /* setup */
+  const char *proc_names[] = {"proc1"};
+  stub_proc_pid_t pp_stubs[] = {{"proc1", 1007},
+                                {"proc1", 1008},
+                                {"proc1", 1009},
+                                {"proc2", 1010},
+                                {"proc3", 1011}};
+  proc_pids_t **proc_pids = NULL;
+  int result;
+  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
+
+  result =
+      proc_pids_init(proc_names, STATIC_ARRAY_SIZE(proc_names), &proc_pids);
+  EXPECT_EQ_INT(0, result);
+
+  /* check */
+  result = proc_pids_update(proc_fs, proc_pids, STATIC_ARRAY_SIZE(proc_names));
+  EXPECT_EQ_INT(0, result);
+
+  /* proc name check */
+  EXPECT_EQ_STR(proc_names[0], proc_pids[0]->process_name);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pp_stubs); ++i) {
+    if (0 == strcmp(pp_stubs[i].comm, proc_names[0]))
+      /* check if proc struct has correct pids */
+      EXPECT_EQ_INT(pids_list_contains_pid(proc_pids[0]->curr, pp_stubs[i].pid),
+                    1);
+    else
+      /* check if proc struct has no incorrect pids */
+      EXPECT_EQ_INT(pids_list_contains_pid(proc_pids[0]->curr, pp_stubs[i].pid),
+                    0);
+  }
+
+  /* cleanup */
+  proc_pids_free(proc_pids, STATIC_ARRAY_SIZE(proc_names));
+  stub_procfs_teardown();
+  return 0;
+}
+
+DEF_TEST(proc_pids_update__many_proc_many_pid) {
+  /* setup */
+  const char *proc_names[] = {"proc1", "proc2", "proc3"};
+  stub_proc_pid_t pp_stubs[] = {
+      {"proc1", 1007}, {"proc1", 1008}, {"proc1", 1009}, {"proc2", 2007},
+      {"proc2", 2008}, {"proc2", 2009}, {"proc3", 3007}, {"proc3", 3008},
+      {"proc3", 3009}, {"proc4", 4007}, {"proc4", 4008}, {"proc4", 4009},
+      {"proc5", 5007}, {"proc5", 5008}, {"proc5", 5009}};
+  proc_pids_t **proc_pids = NULL;
+  int result;
+  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
+
+  result =
+      proc_pids_init(proc_names, STATIC_ARRAY_SIZE(proc_names), &proc_pids);
+  EXPECT_EQ_INT(0, result);
+
+  /* check */
+  result = proc_pids_update(proc_fs, proc_pids, STATIC_ARRAY_SIZE(proc_names));
+  EXPECT_EQ_INT(0, result);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(proc_names); ++i) {
+
+    /* proc name check */
+    EXPECT_EQ_STR(proc_names[i], proc_pids[i]->process_name);
+
+    for (size_t j = 0; j < STATIC_ARRAY_SIZE(pp_stubs); ++j) {
+      if (0 == strcmp(pp_stubs[j].comm, proc_names[i]))
+        /* check if proc struct has correct pids */
+        EXPECT_EQ_INT(
+            pids_list_contains_pid(proc_pids[i]->curr, pp_stubs[j].pid), 1);
+      else
+        /* check if proc struct has no incorrect pids */
+        EXPECT_EQ_INT(
+            pids_list_contains_pid(proc_pids[i]->curr, pp_stubs[j].pid), 0);
+    }
+  }
+
+  /* cleanup */
+  proc_pids_free(proc_pids, STATIC_ARRAY_SIZE(proc_names));
+  stub_procfs_teardown();
+  return 0;
+}
+
+DEF_TEST(pids_list_diff__all_changed) {
+  /* setup */
+  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+  pid_t pids_array_after[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
+  proc_pids_t proc_pids;
+  pids_list_t curr;
+  pids_list_t prev;
+
+  prev.pids = pids_array_before;
+  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
+  prev.allocated = prev.size;
+  curr.pids = pids_array_after;
+  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
+  curr.allocated = curr.size;
+  proc_pids.curr = &curr;
+  proc_pids.prev = &prev;
+
+  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
+  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
+
+  /* check */
+  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_before), lost_pids->size);
+  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_after), new_pids->size);
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_before); ++i) {
+    EXPECT_EQ_INT(1, pids_list_contains_pid(new_pids, pids_array_after[i]));
+    EXPECT_EQ_INT(1, pids_list_contains_pid(lost_pids, pids_array_before[i]));
+  }
+
+  /* cleanup */
+  pids_list_free(new_pids);
+  pids_list_free(lost_pids);
+
+  return 0;
+}
+
+DEF_TEST(pids_list_diff__nothing_changed) {
+  /* setup */
+  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+  proc_pids_t proc_pids;
+  pids_list_t curr;
+  pids_list_t prev;
+
+  prev.pids = pids_array_before;
+  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
+  prev.allocated = prev.size;
+  curr.pids = pids_array_before;
+  curr.size = STATIC_ARRAY_SIZE(pids_array_before);
+  curr.allocated = curr.size;
+  proc_pids.curr = &curr;
+  proc_pids.prev = &prev;
+
+  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
+  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
+
+  /* check */
+  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(0, lost_pids->size);
+  EXPECT_EQ_INT(0, new_pids->size);
+
+  /* cleanup */
+  pids_list_free(lost_pids);
+  pids_list_free(new_pids);
+
+  return 0;
+}
+
+DEF_TEST(pids_list_diff__one_added) {
+  /* setup */
+  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+  pid_t pids_array_after[] = {1000, 1001, 1002, 1003, 1004,
+                              1005, 1006, 1007, 1008};
+  proc_pids_t proc_pids;
+  pids_list_t curr;
+  pids_list_t prev;
+
+  prev.pids = pids_array_before;
+  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
+  prev.allocated = prev.size;
+  curr.pids = pids_array_after;
+  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
+  curr.allocated = curr.size;
+  proc_pids.curr = &curr;
+  proc_pids.prev = &prev;
+
+  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
+  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
+
+  /* check */
+  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(0, lost_pids->size);
+  EXPECT_EQ_INT(1, new_pids->size);
+  EXPECT_EQ_INT(1008, new_pids->pids[0]);
+
+  /* cleanup */
+  pids_list_free(lost_pids);
+  pids_list_free(new_pids);
+
+  return 0;
+}
+
+DEF_TEST(pids_list_diff__one_removed) {
+  /* setup */
+  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004,
+                               1005, 1006, 1007, 1008};
+  pid_t pids_array_after[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
+
+  proc_pids_t proc_pids;
+  pids_list_t curr;
+  pids_list_t prev;
+
+  prev.pids = pids_array_before;
+  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
+  prev.allocated = prev.size;
+  curr.pids = pids_array_after;
+  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
+  curr.allocated = curr.size;
+  proc_pids.curr = &curr;
+  proc_pids.prev = &prev;
+
+  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
+  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
+
+  /* check */
+  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
+  EXPECT_EQ_INT(0, result);
+  EXPECT_EQ_INT(0, new_pids->size);
+  EXPECT_EQ_INT(1, lost_pids->size);
+  EXPECT_EQ_INT(1008, lost_pids->pids[0]);
+
+  /* cleanup */
+  pids_list_free(lost_pids);
+  pids_list_free(new_pids);
+
+  return 0;
+}
+
+int main(void) {
+  stub_procfs_teardown();
+  RUN_TEST(proc_pids_init__on_nullptr);
+  RUN_TEST(pid_list_add_pid__empty_list);
+  RUN_TEST(pid_list_add_pid__non_empty_list);
+  RUN_TEST(pids_list_add_pids_list__non_empty_lists);
+  RUN_TEST(pids_list_add_pids_list__add_to_empty);
+  RUN_TEST(get_pid_number__valid_dir);
+  RUN_TEST(get_pid_number__invalid_dir_name);
+  RUN_TEST(read_proc_name__valid_name);
+  RUN_TEST(read_proc_name__invalid_name);
+  RUN_TEST(proc_pids_update__one_proc_many_pid);
+  RUN_TEST(proc_pids_update__many_proc_many_pid);
+  RUN_TEST(pids_list_diff__all_changed);
+  RUN_TEST(pids_list_diff__nothing_changed);
+  RUN_TEST(pids_list_diff__one_added);
+  RUN_TEST(pids_list_diff__one_removed);
+  stub_procfs_teardown();
+  END_TEST;
+}
diff --git a/src/utils_proc_pids.c b/src/utils_proc_pids.c
deleted file mode 100644 (file)
index 0fbea53..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/**
- * collectd - src/utils_config_pids.c
- *
- * Copyright(c) 2018-2019 Intel Corporation. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *   Starzyk, Mateusz <mateuszx.starzyk@intel.com>
- *   Wojciech Andralojc <wojciechx.andralojc@intel.com>
- *   Michał Aleksiński <michalx.aleksinski@intel.com>
- **/
-
-#include "collectd.h"
-#include "utils/common/common.h"
-#include "utils_proc_pids.h"
-
-#define UTIL_NAME "utils_proc_pids"
-
-void pids_list_free(pids_list_t *list) {
-  assert(list);
-
-  sfree(list->pids);
-  sfree(list);
-}
-
-int is_proc_name_valid(const char *name) {
-
-  if (name != NULL) {
-    unsigned len = strlen(name);
-    if (len > 0 && len <= MAX_PROC_NAME_LEN)
-      return 1;
-    else {
-      DEBUG(UTIL_NAME
-            ": Process name \'%s\' is too long. Max supported len is %d chars.",
-            name, MAX_PROC_NAME_LEN);
-    }
-  }
-
-  return 0;
-}
-
-int pids_list_add_pid(pids_list_t *list, const pid_t pid) {
-  assert(list);
-
-  if (list->allocated == list->size) {
-    size_t new_allocated = list->allocated + 1 + list->allocated / 10;
-    pid_t *new_pids = realloc(list->pids, sizeof(pid_t) * new_allocated);
-
-    if (NULL == new_pids) {
-      ERROR(UTIL_NAME ": Alloc error\n");
-      return -1;
-    }
-
-    list->pids = new_pids;
-    list->allocated = new_allocated;
-  }
-
-  list->pids[list->size] = pid;
-  list->size++;
-
-  return 0;
-}
-
-int pids_list_add_list(pids_list_t *dst, pids_list_t *src) {
-  assert(dst);
-  assert(src);
-
-  if (dst->allocated < dst->size + src->size) {
-    pid_t *new_pids =
-        realloc(dst->pids, sizeof(pid_t) * (dst->size + src->size));
-
-    if (NULL == new_pids) {
-      ERROR(UTIL_NAME ": Alloc error\n");
-      return -1;
-    }
-
-    dst->allocated = dst->size + src->size;
-    dst->pids = new_pids;
-  }
-
-  memcpy(dst->pids + dst->size, src->pids, src->size * sizeof(*(src->pids)));
-  dst->size += src->size;
-
-  return 0;
-}
-
-int pids_list_clear(pids_list_t *list) {
-  assert(list);
-
-  if (list->pids != NULL)
-    sfree(list->pids);
-
-  list->size = 0;
-  list->allocated = 0;
-
-  return 0;
-}
-
-int pids_list_contains_pid(pids_list_t *list, const pid_t pid) {
-  assert(list);
-
-  for (int i = 0; i < list->size; i++)
-    if (list->pids[i] == pid)
-      return 1;
-
-  return 0;
-}
-
-int read_proc_name(const char *procfs_path, const struct dirent *pid_entry,
-                   char *name, const size_t out_size) {
-  assert(pid_entry);
-  assert(name);
-  assert(out_size);
-  memset(name, 0, out_size);
-
-  const char *comm_file_name = "comm";
-
-  char *path = ssnprintf_alloc("%s/%s/%s", procfs_path, pid_entry->d_name,
-                               comm_file_name);
-  if (path == NULL)
-    return -1;
-  FILE *f = fopen(path, "r");
-  if (f == NULL) {
-    ERROR(UTIL_NAME ": Failed to open comm file, error: %d\n", errno);
-    sfree(path);
-    return -1;
-  }
-  size_t read_length = fread(name, sizeof(char), out_size, f);
-  name[out_size - 1] = '\0';
-  fclose(f);
-  sfree(path);
-  /* strip new line ending */
-  char *newline = strchr(name, '\n');
-  if (newline) {
-    *newline = '\0';
-  }
-
-  return read_length;
-}
-
-int get_pid_number(struct dirent *entry, pid_t *pid) {
-  char *tmp_end; /* used for strtoul error check*/
-
-  if (pid == NULL || entry == NULL)
-    return -1;
-
-  if (entry->d_type != DT_DIR)
-    return -1;
-
-  /* trying to get pid number from directory name*/
-  *pid = strtoul(entry->d_name, &tmp_end, 10);
-  if (*tmp_end != '\0') {
-    return -1; /* conversion failed, not proc-pid */
-  }
-  /* all checks passed, marking as success */
-  return 0;
-}
-
-int initialize_proc_pids(const char **procs_names_array,
-                         const size_t procs_names_array_size,
-                         proc_pids_t **proc_pids[]) {
-
-  proc_pids_t **proc_pids_array;
-  assert(proc_pids);
-  assert(NULL == *proc_pids);
-
-  /* Copy procs names to output array. Initialize pids list with NULL value. */
-  proc_pids_array = calloc(procs_names_array_size, sizeof(*proc_pids_array));
-
-  if (NULL == proc_pids_array)
-    return -1;
-
-  for (size_t i = 0; i < procs_names_array_size; ++i) {
-    proc_pids_array[i] = calloc(1, sizeof(**proc_pids_array));
-    if (NULL == proc_pids_array[i])
-      goto initialize_proc_pids_error;
-
-    sstrncpy(proc_pids_array[i]->process_name, procs_names_array[i],
-             STATIC_ARRAY_SIZE(proc_pids_array[i]->process_name));
-    proc_pids_array[i]->prev = NULL;
-    proc_pids_array[i]->curr = NULL;
-  }
-
-  *proc_pids = proc_pids_array;
-
-  return 0;
-initialize_proc_pids_error:
-  if (NULL != proc_pids_array) {
-    for (size_t i = 0; i < procs_names_array_size; ++i) {
-      free(proc_pids_array[i]);
-    }
-    free(proc_pids_array);
-  }
-  return -1;
-}
-
-static void swap_proc_pids(proc_pids_t **proc_pids, size_t proc_pids_num) {
-  for (size_t i = 0; i < proc_pids_num; i++) {
-    pids_list_t *swap = proc_pids[i]->prev;
-    proc_pids[i]->prev = proc_pids[i]->curr;
-    proc_pids[i]->curr = swap;
-  }
-}
-
-int update_proc_pids(const char *procfs_path, proc_pids_t **proc_pids,
-                     size_t proc_pids_num) {
-  assert(procfs_path);
-  assert(proc_pids);
-
-  DIR *proc_dir = opendir(procfs_path);
-  if (proc_dir == NULL) {
-    ERROR(UTIL_NAME ": Could not open %s directory, error: %d", procfs_path,
-          errno);
-    return -1;
-  }
-
-  swap_proc_pids(proc_pids, proc_pids_num);
-
-  for (size_t i = 0; i < proc_pids_num; i++) {
-    if (NULL == proc_pids[i]->curr)
-      proc_pids[i]->curr = calloc(1, sizeof(*(proc_pids[i]->curr)));
-
-    if (NULL == proc_pids[i]->curr) {
-      ERROR(UTIL_NAME ": Alloc error\n");
-      goto update_error;
-    }
-
-    proc_pids[i]->curr->size = 0;
-  }
-
-  /* Go through procfs and find PIDS and their comms */
-  struct dirent *entry;
-  while ((entry = readdir(proc_dir)) != NULL) {
-    pid_t pid;
-    int pid_conversion = get_pid_number(entry, &pid);
-    if (pid_conversion < 0)
-      continue;
-
-    proc_comm_t comm;
-    int read_result =
-        read_proc_name(procfs_path, entry, comm, sizeof(proc_comm_t));
-    if (read_result <= 0)
-      continue;
-
-    /* Try to find comm in input procs array */
-    for (size_t i = 0; i < proc_pids_num; ++i) {
-      if (0 ==
-          strncmp(comm, proc_pids[i]->process_name, STATIC_ARRAY_SIZE(comm)))
-        pids_list_add_pid(proc_pids[i]->curr, pid);
-    }
-  }
-
-  int close_result = closedir(proc_dir);
-  if (0 != close_result) {
-    ERROR(UTIL_NAME ": failed to close /proc directory, error: %d", errno);
-    goto update_error;
-  }
-  return 0;
-
-update_error:
-  swap_proc_pids(proc_pids, proc_pids_num);
-  return -1;
-}
-
-int pids_list_diff(proc_pids_t *proc, pids_list_t *added,
-                   pids_list_t *removed) {
-  assert(proc);
-  assert(added);
-  assert(removed);
-
-  added->size = 0;
-  removed->size = 0;
-
-  if (NULL == proc->prev || 0 == proc->prev->size) {
-    /* append all PIDs from curr to added*/
-    return pids_list_add_list(added, proc->curr);
-  } else if (NULL == proc->curr || 0 == proc->curr->size) {
-    /* append all PIDs from prev to removed*/
-    return pids_list_add_list(removed, proc->prev);
-  }
-
-  for (int i = 0; i < proc->prev->size; i++)
-    if (0 == pids_list_contains_pid(proc->curr, proc->prev->pids[i])) {
-      int add_result = pids_list_add_pid(removed, proc->prev->pids[i]);
-      if (add_result < 0)
-        return add_result;
-    }
-
-  for (int i = 0; i < proc->curr->size; i++)
-    if (0 == pids_list_contains_pid(proc->prev, proc->curr->pids[i])) {
-      int add_result = pids_list_add_pid(added, proc->curr->pids[i]);
-      if (add_result < 0)
-        return add_result;
-    }
-
-  return 0;
-}
-
-int proc_pids_free(proc_pids_t *proc_pids[], size_t proc_pids_num) {
-  for (size_t i = 0; i < proc_pids_num; i++) {
-    if (NULL != proc_pids[i]->curr)
-      pids_list_free(proc_pids[i]->curr);
-    if (NULL != proc_pids[i]->prev)
-      pids_list_free(proc_pids[i]->prev);
-    sfree(proc_pids[i]);
-  }
-  sfree(proc_pids);
-
-  return 0;
-}
diff --git a/src/utils_proc_pids.h b/src/utils_proc_pids.h
deleted file mode 100644 (file)
index a2a668d..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/**
- * collectd - src/utils_config_pids.h
- *
- * Copyright(c) 2018-2019 Intel Corporation. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *   Starzyk, Mateusz <mateuszx.starzyk@intel.com>
- *   Wojciech Andralojc <wojciechx.andralojc@intel.com>
- *   Michał Aleksiński <michalx.aleksinski@intel.com>
- **/
-
-#include <dirent.h>
-#include <sys/types.h>
-
-/*
- * Process name inside comm file is limited to 16 chars.
- * More info here: http://man7.org/linux/man-pages/man5/proc.5.html
- */
-#define MAX_PROC_NAME_LEN 16
-
-/* Helper typedef for process name array
- * Extra 1 char is added for string null termination.
- */
-typedef char proc_comm_t[MAX_PROC_NAME_LEN + 1];
-
-/* List of pids. */
-typedef struct pids_list_s {
-  pid_t *pids;
-  size_t size;
-  size_t allocated;
-} pids_list_t;
-
-/* Holds process name and list of pids assigned to that name */
-typedef struct proc_pids_s {
-  proc_comm_t process_name;
-  pids_list_t *prev;
-  pids_list_t *curr;
-} proc_pids_t;
-
-/*
- * NAME
- *   pids_list_free
- *
- * DESCRIPTION
- *   Free all elements of given pids list
- *
- * PARAMETERS
- *   `list'     Head of target pids_list.
- */
-void pids_list_free(pids_list_t *list);
-
-/*
- * NAME
- *   is_proc_name_valid
- *
- * DESCRIPTION
- *   Checks if given string as valid process name.
- *
- * PARAMETERS
- *   `name'     null-terminated char array
- *
- * RETURN VALUE
- *   If given name is a valid process name, returns 1,
- *   Otherwise returns 0.
- */
-int is_proc_name_valid(const char *name);
-
-/*
- * NAME
- *   pids_list_add_pid
- *
- * DESCRIPTION
- *   Adds pid at the end of the pids array.
- *   Reallocates memory for new pid element, it is up to user to free it.
- *
- * PARAMETERS
- *   `list'     Target pids_list.
- *   `pid'      Pid to be added.
- *
- * RETURN VALUE
- *   On success, returns 0.
- *   -1 on memory allocation error.
- */
-int pids_list_add_pid(pids_list_t *list, const pid_t pid);
-
-/*
- * NAME
- *   pids_list_clear
- *
- * DESCRIPTION
- *   Remove all pids from the list
- *
- * PARAMETERS
- *   `list'     Target pids_list.
- *
- * RETURN VALUE
- *   On success, return 0
- */
-int pids_list_clear(pids_list_t *list);
-
-/*
- * NAME
- *   pids_list_add_list
- *
- * DESCRIPTION
- *   Adds pids list at the end of the pids list.
- *   Allocates memory for new pid elements, it is up to user to free it.
- *
- * PARAMETERS
- *   `dst'      Target PIDs list.
- *   `src'      Source PIDs list.
- *
- * RETURN VALUE
- *   On success, returns 0.
- *   -1 on memory allocation error.
- */
-#
-int pids_list_add_list(pids_list_t *dst, pids_list_t *src);
-
-/*
- * NAME
- *   pids_list_contains_pid
- *
- * DESCRIPTION
- *   Tests if pids list contains specific pid.
- *
- * PARAMETERS
- *   `list'     pids_list to check.
- *   `pid'      Pid to be searched for.
- *
- * RETURN VALUE
- *   If PID found in list, returns 1,
- *   Otherwise returns 0.
- */
-int pids_list_contains_pid(pids_list_t *list, const pid_t pid);
-
-/*
- * NAME
- *   read_proc_name
- *
- * DESCRIPTION
- *   Reads process name from given pid directory.
- *   Strips new-line character (\n).
- *
- * PARAMETERS
- *   `procfs_path' Path to systems proc directory (e.g. /proc)
- *   `pid_entry'   Dirent for PID directory
- *   `name'        Output buffer for process name, recommended proc_comm.
- *   `out_size'    Output buffer size, recommended sizeof(proc_comm)
- *
- * RETURN VALUE
- *   On success, the number of read bytes (includes stripped \n).
- *   -1 on file open error
- */
-int read_proc_name(const char *procfs_path, const struct dirent *pid_entry,
-                   char *name, const size_t out_size);
-
-/*
- * NAME
- *   get_pid_number
- *
- * DESCRIPTION
- *   Gets pid number for given /proc/pid directory entry or
- *   returns error if input directory does not hold PID information.
- *
- * PARAMETERS
- *   `entry'    Dirent for PID directory
- *   `pid'      PID number to be filled
- *
- * RETURN VALUE
- *   0 on success. -1 on error.
- */
-int get_pid_number(struct dirent *entry, pid_t *pid);
-
-/*
- * NAME
- *   initialize_proc_pids
- *
- * DESCRIPTION
- *   Helper function to properly initialize array of proc_pids.
- *   Allocates memory for proc_pids structs.
- *
- * PARAMETERS
- *   `procs_names_array'      Array of null-terminated strings with
- *                            process' names to be copied to new array
- *   `procs_names_array_size' procs_names_array element count
- *   `proc_pids'              Address of pointer, under which new
- *                            array of proc_pids will be allocated.
- *                            Must be NULL.
- * RETURN VALUE
- *   0 on success. Negative number on error:
- *   -1: allocation error
- */
-int initialize_proc_pids(const char **procs_names_array,
-                         const size_t procs_names_array_size,
-                         proc_pids_t **proc_pids[]);
-
-/*
- * NAME
- *   update_proc_pids
- *
- * DESCRIPTION
- *   Updates PIDs matching processes's names.
- *   Searches all PID directories in /proc fs and updates current pids_list.
- *
- * PARAMETERS
- *   `procfs_path'     Path to systems proc directory (e.g. /proc)
- *   `proc_pids'       Array of proc_pids pointers to be updated.
- *   `proc_pids_num'   proc_pids element count
- *
- * RETURN VALUE
- *   0 on success. -1 on error.
- */
-int update_proc_pids(const char *procfs_path, proc_pids_t *proc_pids[],
-                     size_t proc_pids_num);
-
-/*
- * NAME
- *   pids_list_diff
- *
- * DESCRIPTION
- *   Searches for differences in two given lists
- *
- * PARAMETERS
- *   `proc'            List of pids
- *   `added'           New pids which appeared
- *   `removed'         Result array storing pids which disappeared
- * RETURN VALUE
- *   0 on success. Negative number on error.
- */
-int pids_list_diff(proc_pids_t *proc, pids_list_t *added, pids_list_t *removed);
-
-/*
- * NAME
- *   proc_pids_free
- *
- * DESCRIPTION
- *   Releses memory allocatd for proc_pids
- *
- * PARAMETERS
- *   `proc_pids'       Array of proc_pids
- *   `proc_pids_num'   proc_pids element count
- *
- * RETURN VALUE
- *   0 on success. -1 on error.
- */
-int proc_pids_free(proc_pids_t *proc_pids[], size_t proc_pids_num);
diff --git a/src/utils_proc_pids_test.c b/src/utils_proc_pids_test.c
deleted file mode 100644 (file)
index 21c8b34..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-#include "testing.h"
-#include "utils_proc_pids.c" /* sic */
-#include <sys/stat.h>
-
-/***************************************************************************
- * helper functions
- */
-
-typedef struct stub_proc_pid {
-  proc_comm_t comm;
-  pid_t pid;
-} stub_proc_pid_t;
-
-static const char *proc_fs = "/tmp/procfs_stub";
-
-/*
- * NAME
- *   stub_procfs_setup
- *
- * DESCRIPTION
- *   Prepares testing environment by creating temporary
- *   PID/comm file structure.
- *
- * PARAMETERS
- *   `proc_pids_array'          Array of stub_proc_pid_t structs. Represents
- *                              which PIDs should hold given process name.
- *   `proc_pids_array_length'   Element count of input array.
- *
- * RETURN VALUE
- *   0 on success.
- *   -1 on base dir creation error.
- *   -2 on comm file creation error.
- *   -3 on comm file write error.
- */
-int stub_procfs_setup(const stub_proc_pid_t *proc_pids_array,
-                      const size_t proc_pids_array_length) {
-  if (mkdir(proc_fs, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
-    return -1;
-  char path[256];
-
-  for (size_t i = 0; i < proc_pids_array_length; ++i) {
-    memset(path, 0, sizeof(path));
-    snprintf(path, STATIC_ARRAY_SIZE(path), "%s/%d", proc_fs,
-             proc_pids_array[i].pid);
-    mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-    strncat(path, "/comm", STATIC_ARRAY_SIZE(path) - strlen(path) - 1);
-
-    FILE *fp = fopen(path, "w");
-    if (!fp)
-      return -2;
-
-    size_t slen = strlen(proc_pids_array[i].comm);
-    size_t wlen = fwrite(proc_pids_array[i].comm, sizeof(char), slen, fp);
-    fclose(fp);
-
-    if (slen != wlen)
-      return -3;
-  }
-  return 0;
-}
-
-/*
- * NAME
- *   stub_procfs_teardown
- *
- * DESCRIPTION
- *   Clears testing environment: removes stub proc files.
- *   NOTE - This function could be implemented by usage of nftw, but this
- *   would require #define _XOPEN_SOURCE 500, which
- *   messes up intel_rdt includes.
- *
- * RETURN VALUE
- *   system command result
- */
-int stub_procfs_teardown() {
-  char cmd[256];
-  sstrncpy(cmd, "rm -rf ", STATIC_ARRAY_SIZE(cmd));
-  strncat(cmd, proc_fs, STATIC_ARRAY_SIZE(cmd) - strlen(cmd) - 1);
-  return system(cmd);
-}
-
-/* Max PID value. More info:
- * http://web.archive.org/web/20111209081734/http://research.cs.wisc.edu/condor/condorg/linux_scalability.html
- */
-#define MAX_PID 4194304
-#define MAX_PID_STR "4194304"
-
-/***************************************************************************
- * tests
- */
-DEF_TEST(initialize_proc_pids__on_nullptr) {
-  /* setup */
-  const char *procs_names_array[] = {"proc1", "proc2", "proc3"};
-  const size_t procs_names_array_size = STATIC_ARRAY_SIZE(procs_names_array);
-  proc_pids_t **proc_pids_array = NULL;
-
-  /* check */
-  int result = initialize_proc_pids(procs_names_array, procs_names_array_size,
-                                    &proc_pids_array);
-  EXPECT_EQ_INT(0, result);
-  for (size_t i = 0; i < procs_names_array_size; ++i)
-    EXPECT_EQ_STR(procs_names_array[i], proc_pids_array[i]->process_name);
-
-  /* cleanup */
-  proc_pids_free(proc_pids_array, procs_names_array_size);
-  return 0;
-}
-
-DEF_TEST(pid_list_add_pid__empty_list) {
-  /* setup */
-  pids_list_t *proc_pids_instance = calloc(1, sizeof(*proc_pids_instance));
-  pid_t pid = 1234;
-
-  /* check */
-  pids_list_add_pid(proc_pids_instance, pid);
-  EXPECT_EQ_INT(pid, proc_pids_instance->pids[0]);
-
-  /* cleanup */
-  pids_list_free(proc_pids_instance);
-  return 0;
-}
-
-DEF_TEST(pid_list_add_pid__non_empty_list) {
-  /* setup */
-  pids_list_t *proc_pids_instance = calloc(1, sizeof(*proc_pids_instance));
-  pid_t pids[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-
-  /* check */
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids); ++i)
-    pids_list_add_pid(proc_pids_instance, pids[i]);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids); ++i) {
-    EXPECT_EQ_INT(pids[i], proc_pids_instance->pids[i]);
-  }
-
-  /* cleanup */
-  pids_list_free(proc_pids_instance);
-  return 0;
-}
-
-DEF_TEST(pids_list_add_pids_list__non_empty_lists) {
-  /* setup */
-  pid_t pids_array_1[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-  pid_t pids_array_2[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
-  pids_list_t *pids_list_1 = calloc(1, sizeof(*pids_list_1));
-  pids_list_t *pids_list_2 = calloc(1, sizeof(*pids_list_2));
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_1); ++i) {
-    pids_list_add_pid(pids_list_1, pids_array_1[i]);
-    pids_list_add_pid(pids_list_2, pids_array_2[i]);
-  }
-
-  /* check */
-  int result = pids_list_add_list(pids_list_1, pids_list_2);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_2) +
-                    STATIC_ARRAY_SIZE(pids_array_1),
-                pids_list_1->size);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_1); ++i) {
-    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array_1[i]));
-    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array_2[i]));
-  }
-
-  /* setup */
-  pids_list_free(pids_list_1);
-  pids_list_free(pids_list_2);
-  return 0;
-}
-
-DEF_TEST(pids_list_add_pids_list__add_to_empty) {
-  /* setup */
-  pid_t pids_array[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
-  pids_list_t *pids_list_1 = calloc(1, sizeof(*pids_list_1));
-  pids_list_t *pids_list_2 = calloc(1, sizeof(*pids_list_2));
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array); ++i)
-    pids_list_add_pid(pids_list_2, pids_array[i]);
-
-  /* check */
-  int result = pids_list_add_list(pids_list_1, pids_list_2);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array), pids_list_1->size);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array); ++i)
-    EXPECT_EQ_INT(1, pids_list_contains_pid(pids_list_1, pids_array[i]));
-
-  /* setup */
-  pids_list_free(pids_list_1);
-  pids_list_free(pids_list_2);
-  return 0;
-}
-
-DEF_TEST(get_pid_number__valid_dir) {
-  /* setup */
-  struct dirent d;
-  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
-  d.d_type = DT_DIR;
-  pid_t pid = 0;
-
-  /* check */
-  int pid_conversion = get_pid_number(&d, &pid);
-
-  EXPECT_EQ_INT(0, pid_conversion);
-  EXPECT_EQ_INT(MAX_PID, pid);
-
-  /* cleanup */
-  return 0;
-}
-
-DEF_TEST(get_pid_number__invalid_dir_name) {
-  /* setup */
-  struct dirent d;
-  sstrncpy(d.d_name, "invalid", STATIC_ARRAY_SIZE(d.d_name));
-  d.d_type = DT_DIR;
-  pid_t pid = 0;
-
-  /* check */
-  int pid_conversion = get_pid_number(&d, &pid);
-
-  EXPECT_EQ_INT(-1, pid_conversion);
-  EXPECT_EQ_INT(0, pid);
-
-  /* cleanup */
-  return 0;
-}
-
-DEF_TEST(read_proc_name__valid_name) {
-  /* setup */
-  stub_proc_pid_t pp_stubs[] = {{"proc1", MAX_PID}};
-  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
-  struct dirent d;
-  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
-  d.d_type = DT_DIR;
-
-  /* check */
-  proc_comm_t comm;
-  int read_result = read_proc_name(proc_fs, &d, comm, STATIC_ARRAY_SIZE(comm));
-
-  EXPECT_EQ_INT(strlen(pp_stubs[0].comm), read_result);
-  EXPECT_EQ_STR(pp_stubs[0].comm, comm);
-
-  /* cleanup */
-  stub_procfs_teardown();
-  return 0;
-}
-
-DEF_TEST(read_proc_name__invalid_name) {
-  /* setup */
-  struct dirent d;
-  sstrncpy(d.d_name, MAX_PID_STR, STATIC_ARRAY_SIZE(d.d_name));
-  d.d_type = DT_DIR;
-
-  /* check */
-  proc_comm_t comm;
-  int read_result = read_proc_name(proc_fs, &d, comm, STATIC_ARRAY_SIZE(comm));
-
-  EXPECT_EQ_INT(-1, read_result);
-
-  /* cleanup */
-  return 0;
-}
-
-DEF_TEST(update_proc_pids__one_proc_many_pid) {
-  /* setup */
-  const char *proc_names[] = {"proc1"};
-  stub_proc_pid_t pp_stubs[] = {{"proc1", 1007},
-                                {"proc1", 1008},
-                                {"proc1", 1009},
-                                {"proc2", 1010},
-                                {"proc3", 1011}};
-  proc_pids_t **proc_pids = NULL;
-  int result;
-  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
-
-  result = initialize_proc_pids(proc_names, STATIC_ARRAY_SIZE(proc_names),
-                                &proc_pids);
-  EXPECT_EQ_INT(0, result);
-
-  /* check */
-  result = update_proc_pids(proc_fs, proc_pids, STATIC_ARRAY_SIZE(proc_names));
-  EXPECT_EQ_INT(0, result);
-
-  /* proc name check */
-  EXPECT_EQ_STR(proc_names[0], proc_pids[0]->process_name);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pp_stubs); ++i) {
-    if (0 == strcmp(pp_stubs[i].comm, proc_names[0]))
-      /* check if proc struct has correct pids */
-      EXPECT_EQ_INT(pids_list_contains_pid(proc_pids[0]->curr, pp_stubs[i].pid),
-                    1);
-    else
-      /* check if proc struct has no incorrect pids */
-      EXPECT_EQ_INT(pids_list_contains_pid(proc_pids[0]->curr, pp_stubs[i].pid),
-                    0);
-  }
-
-  /* cleanup */
-  proc_pids_free(proc_pids, STATIC_ARRAY_SIZE(proc_names));
-  stub_procfs_teardown();
-  return 0;
-}
-
-DEF_TEST(update_proc_pids__many_proc_many_pid) {
-  /* setup */
-  const char *proc_names[] = {"proc1", "proc2", "proc3"};
-  stub_proc_pid_t pp_stubs[] = {
-      {"proc1", 1007}, {"proc1", 1008}, {"proc1", 1009}, {"proc2", 2007},
-      {"proc2", 2008}, {"proc2", 2009}, {"proc3", 3007}, {"proc3", 3008},
-      {"proc3", 3009}, {"proc4", 4007}, {"proc4", 4008}, {"proc4", 4009},
-      {"proc5", 5007}, {"proc5", 5008}, {"proc5", 5009}};
-  proc_pids_t **proc_pids = NULL;
-  int result;
-  stub_procfs_setup(pp_stubs, STATIC_ARRAY_SIZE(pp_stubs));
-
-  result = initialize_proc_pids(proc_names, STATIC_ARRAY_SIZE(proc_names),
-                                &proc_pids);
-  EXPECT_EQ_INT(0, result);
-
-  /* check */
-  result = update_proc_pids(proc_fs, proc_pids, STATIC_ARRAY_SIZE(proc_names));
-  EXPECT_EQ_INT(0, result);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(proc_names); ++i) {
-
-    /* proc name check */
-    EXPECT_EQ_STR(proc_names[i], proc_pids[i]->process_name);
-
-    for (size_t j = 0; j < STATIC_ARRAY_SIZE(pp_stubs); ++j) {
-      if (0 == strcmp(pp_stubs[j].comm, proc_names[i]))
-        /* check if proc struct has correct pids */
-        EXPECT_EQ_INT(
-            pids_list_contains_pid(proc_pids[i]->curr, pp_stubs[j].pid), 1);
-      else
-        /* check if proc struct has no incorrect pids */
-        EXPECT_EQ_INT(
-            pids_list_contains_pid(proc_pids[i]->curr, pp_stubs[j].pid), 0);
-    }
-  }
-
-  /* cleanup */
-  proc_pids_free(proc_pids, STATIC_ARRAY_SIZE(proc_names));
-  stub_procfs_teardown();
-  return 0;
-}
-
-DEF_TEST(pids_list_diff__all_changed) {
-  /* setup */
-  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-  pid_t pids_array_after[] = {2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007};
-  proc_pids_t proc_pids;
-  pids_list_t curr;
-  pids_list_t prev;
-
-  prev.pids = pids_array_before;
-  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
-  prev.allocated = prev.size;
-  curr.pids = pids_array_after;
-  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
-  curr.allocated = curr.size;
-  proc_pids.curr = &curr;
-  proc_pids.prev = &prev;
-
-  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
-  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
-
-  /* check */
-  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_before), lost_pids->size);
-  EXPECT_EQ_INT(STATIC_ARRAY_SIZE(pids_array_after), new_pids->size);
-
-  for (size_t i = 0; i < STATIC_ARRAY_SIZE(pids_array_before); ++i) {
-    EXPECT_EQ_INT(1, pids_list_contains_pid(new_pids, pids_array_after[i]));
-    EXPECT_EQ_INT(1, pids_list_contains_pid(lost_pids, pids_array_before[i]));
-  }
-
-  /* cleanup */
-  pids_list_free(new_pids);
-  pids_list_free(lost_pids);
-
-  return 0;
-}
-
-DEF_TEST(pids_list_diff__nothing_changed) {
-  /* setup */
-  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-  proc_pids_t proc_pids;
-  pids_list_t curr;
-  pids_list_t prev;
-
-  prev.pids = pids_array_before;
-  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
-  prev.allocated = prev.size;
-  curr.pids = pids_array_before;
-  curr.size = STATIC_ARRAY_SIZE(pids_array_before);
-  curr.allocated = curr.size;
-  proc_pids.curr = &curr;
-  proc_pids.prev = &prev;
-
-  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
-  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
-
-  /* check */
-  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(0, lost_pids->size);
-  EXPECT_EQ_INT(0, new_pids->size);
-
-  /* cleanup */
-  pids_list_free(lost_pids);
-  pids_list_free(new_pids);
-
-  return 0;
-}
-
-DEF_TEST(pids_list_diff__one_added) {
-  /* setup */
-  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-  pid_t pids_array_after[] = {1000, 1001, 1002, 1003, 1004,
-                              1005, 1006, 1007, 1008};
-  proc_pids_t proc_pids;
-  pids_list_t curr;
-  pids_list_t prev;
-
-  prev.pids = pids_array_before;
-  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
-  prev.allocated = prev.size;
-  curr.pids = pids_array_after;
-  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
-  curr.allocated = curr.size;
-  proc_pids.curr = &curr;
-  proc_pids.prev = &prev;
-
-  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
-  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
-
-  /* check */
-  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(0, lost_pids->size);
-  EXPECT_EQ_INT(1, new_pids->size);
-  EXPECT_EQ_INT(1008, new_pids->pids[0]);
-
-  /* cleanup */
-  pids_list_free(lost_pids);
-  pids_list_free(new_pids);
-
-  return 0;
-}
-
-DEF_TEST(pids_list_diff__one_removed) {
-  /* setup */
-  pid_t pids_array_before[] = {1000, 1001, 1002, 1003, 1004,
-                               1005, 1006, 1007, 1008};
-  pid_t pids_array_after[] = {1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007};
-
-  proc_pids_t proc_pids;
-  pids_list_t curr;
-  pids_list_t prev;
-
-  prev.pids = pids_array_before;
-  prev.size = STATIC_ARRAY_SIZE(pids_array_before);
-  prev.allocated = prev.size;
-  curr.pids = pids_array_after;
-  curr.size = STATIC_ARRAY_SIZE(pids_array_after);
-  curr.allocated = curr.size;
-  proc_pids.curr = &curr;
-  proc_pids.prev = &prev;
-
-  pids_list_t *new_pids = calloc(1, sizeof(*new_pids));
-  pids_list_t *lost_pids = calloc(1, sizeof(*lost_pids));
-
-  /* check */
-  int result = pids_list_diff(&proc_pids, new_pids, lost_pids);
-  EXPECT_EQ_INT(0, result);
-  EXPECT_EQ_INT(0, new_pids->size);
-  EXPECT_EQ_INT(1, lost_pids->size);
-  EXPECT_EQ_INT(1008, lost_pids->pids[0]);
-
-  /* cleanup */
-  pids_list_free(lost_pids);
-  pids_list_free(new_pids);
-
-  return 0;
-}
-
-int main(void) {
-  stub_procfs_teardown();
-  RUN_TEST(initialize_proc_pids__on_nullptr);
-  RUN_TEST(pid_list_add_pid__empty_list);
-  RUN_TEST(pid_list_add_pid__non_empty_list);
-  RUN_TEST(pids_list_add_pids_list__non_empty_lists);
-  RUN_TEST(pids_list_add_pids_list__add_to_empty);
-  RUN_TEST(get_pid_number__valid_dir);
-  RUN_TEST(get_pid_number__invalid_dir_name);
-  RUN_TEST(read_proc_name__valid_name);
-  RUN_TEST(read_proc_name__invalid_name);
-  RUN_TEST(update_proc_pids__one_proc_many_pid);
-  RUN_TEST(update_proc_pids__many_proc_many_pid);
-  RUN_TEST(pids_list_diff__all_changed);
-  RUN_TEST(pids_list_diff__nothing_changed);
-  RUN_TEST(pids_list_diff__one_added);
-  RUN_TEST(pids_list_diff__one_removed);
-  stub_procfs_teardown();
-  END_TEST;
-}