< Summary - Backend C Tests - Coverage Report (WSL)

Information
Class: alert_service_c
Assembly: src.backend.database
File(s): ./src/backend/database/alert_service.c
Line coverage
89%
Covered lines: 73
Uncovered lines: 9
Coverable lines: 82
Total lines: 188
Line coverage: 89%
Branch coverage
85%
Covered branches: 29
Total branches: 34
Branch coverage: 85.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 2/18/2026 - 10:50:55 PM Line coverage: 89% (73/82) Branch coverage: 85.2% (29/34) Total lines: 188 2/18/2026 - 10:50:55 PM Line coverage: 89% (73/82) Branch coverage: 85.2% (29/34) Total lines: 188

File(s)

./src/backend/database/alert_service.c

#LineLine coverage
 1#include "alert_service.h"
 2#include "db_connection.h"
 3#include "logger.h"
 4#include <stdio.h>
 5#include <string.h>
 6#include <stdlib.h>
 7
 8/* ------------------------------------------------------------------
 9 * PRIVATE HELPERS
 10 * ------------------------------------------------------------------ */
 11
 1112const char *severity_to_str(AlertSeverity severity) {
 1113  switch (severity) {
 014    case SEVERITY_INFO:
 015      return "INFO";
 16
 717    case SEVERITY_WARNING:
 718      return "WARNING";
 19
 420    case SEVERITY_CRITICAL:
 421      return "CRITICAL";
 22
 023    default:
 024      return "UNKNOWN";
 25  }
 26}
 27
 28/* ------------------------------------------------------------------
 29 * PUBLIC API
 30 * ------------------------------------------------------------------ */
 31
 732bool create_alert(int sensor_id, AlertSeverity severity, const char *message) {
 733  DBConnection *conn_wrapper = db_pool_acquire();
 34
 735  if (!conn_wrapper) {
 136    LOG_ERROR("Could not acquire connection to create alert.");
 137    return false;
 38  }
 39
 40  char query[1024];
 641  snprintf(query, sizeof(query),
 42           "INSERT INTO alerts (sensor_id, severity, message) VALUES (%d, '%s', '%s');",
 43           sensor_id, severity_to_str(severity), message);
 644  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 45
 646  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
 147    LOG_ERROR("Failed to insert alert: %s", PQerrorMessage(conn_wrapper->pg_conn));
 148    PQclear(res);
 149    db_pool_release(conn_wrapper);
 150    return false;
 51  }
 52
 553  PQclear(res);
 554  db_pool_release(conn_wrapper);
 555  LOG_INFO("[ALERT CREATED] Sensor %d: %s (%s)", sensor_id, message, severity_to_str(severity));
 556  return true;
 57}
 58
 59/* ------------------------------------------------------------------ */
 60
 861void check_and_trigger_alerts(int sensor_id, const char *sensor_type, double value) {
 862  if (strcmp(sensor_type, "Temperature") == 0) {
 363    if (value > 90.0) {
 64      char msg[128];
 165      snprintf(msg, sizeof(msg), "Critical Temperature detected: %.2f C", value);
 166      create_alert(sensor_id, SEVERITY_CRITICAL, msg);
 267    } else if (value > 75.0) {
 68      char msg[128];
 169      snprintf(msg, sizeof(msg), "High Temperature warning: %.2f C", value);
 170      create_alert(sensor_id, SEVERITY_WARNING, msg);
 71    }
 572  } else if (strcmp(sensor_type, "Vibration") == 0) {
 273    if (value > 5.0) {
 74      char msg[128];
 175      snprintf(msg, sizeof(msg), "Excessive Vibration detected: %.2f Hz", value);
 176      create_alert(sensor_id, SEVERITY_CRITICAL, msg);
 77    }
 378  } else if (strcmp(sensor_type, "Pressure") == 0) {
 279    if (value > 12.0) {
 80      char msg[128];
 181      snprintf(msg, sizeof(msg), "High Pressure detected: %.2f Bar", value);
 182      create_alert(sensor_id, SEVERITY_WARNING, msg);
 83    }
 84  }
 885}
 86
 87/* ------------------------------------------------------------------ */
 88
 389int get_recent_alerts(AlertInfo *out_alerts, int max_alerts) {
 390  DBConnection *conn_wrapper = db_pool_acquire();
 91
 392  if (!conn_wrapper) return 0;
 93
 94  char query[256];
 295  snprintf(query, sizeof(query),
 96           "SELECT id, sensor_id, severity, message, to_char(alert_time, 'YYYY-MM-DD HH24:MI:SS') "
 97           "FROM alerts ORDER BY alert_time DESC LIMIT %d;",
 98           max_alerts);
 299  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 100
 2101  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
 0102    LOG_ERROR("Failed to fetch alerts: %s", PQerrorMessage(conn_wrapper->pg_conn));
 0103    PQclear(res);
 0104    db_pool_release(conn_wrapper);
 0105    return 0;
 106  }
 107
 2108  int rows = PQntuples(res);
 2109  int count = (rows < max_alerts) ? rows : max_alerts;
 110
 5111  for (int i = 0; i < count; i++) {
 3112    out_alerts[i].id = atoi(PQgetvalue(res, i, 0));
 3113    out_alerts[i].sensor_id = atoi(PQgetvalue(res, i, 1));
 3114    strncpy(out_alerts[i].severity, PQgetvalue(res, i, 2), 15);
 3115    out_alerts[i].severity[15] = '\0';
 3116    strncpy(out_alerts[i].message, PQgetvalue(res, i, 3), 255);
 3117    out_alerts[i].message[255] = '\0';
 3118    strncpy(out_alerts[i].created_at, PQgetvalue(res, i, 4), 31);
 3119    out_alerts[i].created_at[31] = '\0';
 120  }
 121
 2122  PQclear(res);
 2123  db_pool_release(conn_wrapper);
 2124  return count;
 125}
 126
 127/* ------------------------------------------------------------------
 128 * JSON SERIALIZATION (API ENDPOINTS)
 129 * ------------------------------------------------------------------ */
 130
 131#ifndef TEST_MODE
 132
 1133char *alert_service_serialize_alerts(void) {
 134  AlertInfo alerts[50];
 1135  int count = get_recent_alerts(alerts, 50);
 1136  char *json = (char *)malloc(4096);
 137
 1138  if (!json) return NULL;
 139
 1140  char *ptr = json;
 1141  ptr += sprintf(ptr, "{\"alerts\":[");
 142
 2143  for (int i = 0; i < count; i++) {
 1144    if (i > 0) {
 0145      ptr += sprintf(ptr, ",");
 146    }
 147
 1148    ptr += sprintf(ptr,
 149                   "{"
 150                   "\"id\":%d,"
 151                   "\"sensor_id\":%d,"
 152                   "\"severity\":\"%s\","
 153                   "\"message\":\"%s\","
 154                   "\"created_at\":\"%s\""
 155                   "}",
 156                   alerts[i].id,
 157                   alerts[i].sensor_id,
 1158                   alerts[i].severity,
 1159                   alerts[i].message,
 1160                   alerts[i].created_at
 161                  );
 162  }
 163
 1164  ptr += sprintf(ptr, "]}");
 1165  return json;
 166}
 167
 168#endif
 169
 170
 171
 172/* ------------------------------------------------------------------
 173 * TEST/MOCK VERSION (compile with -DTEST_MODE)
 174 * ------------------------------------------------------------------ */
 175
 176#ifdef TEST_MODE
 177
 178char *alert_service_serialize_alerts(void) {
 179  char *json = (char *)malloc(256);
 180
 181  if (json) {
 182    strcpy(json, "{\"alerts\":[]}");
 183  }
 184
 185  return json;
 186}
 187
 188#endif

Methods/Properties