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

Information
Class: test_maintenance_standalone_c
Assembly: src.backend.tests.unit
File(s): ./src/backend/tests/unit/test_maintenance_standalone.c
Line coverage
96%
Covered lines: 220
Uncovered lines: 9
Coverable lines: 229
Total lines: 397
Line coverage: 96%
Branch coverage
68%
Covered branches: 41
Total branches: 60
Branch coverage: 68.3%
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: 96% (220/229) Branch coverage: 68.3% (41/60) Total lines: 397 2/18/2026 - 10:50:55 PM Line coverage: 96% (220/229) Branch coverage: 68.3% (41/60) Total lines: 397

File(s)

./src/backend/tests/unit/test_maintenance_standalone.c

#LineLine coverage
 1/*
 2 * STANDALONE MAINTENANCE SERVICE TEST FILE
 3 *
 4 * Compile ALONE:
 5 *   gcc -o test_maintenance.exe test_maintenance_standalone.c -std=c99
 6 */
 7
 8#include <stdio.h>
 9#include <stdlib.h>
 10#include <string.h>
 11#include <assert.h>
 12#include <stdbool.h>
 13
 14// ============================================================================
 15// TYPE DEFINITIONS
 16// ============================================================================
 17
 18typedef struct {
 19  void *pg_conn;
 20} DBConnection;
 21
 22typedef struct {
 23  int id;
 24  int machine_id;
 25  char technician_name[100];
 26  char log_date[32];
 27  char description[512];
 28  double cost;
 29} MaintenanceLog;
 30
 31typedef struct {
 32  int status;
 33  int ntuples;
 34  char data[100][10][512];
 35} PGresult;
 36
 37// ============================================================================
 38// MOCK STATE
 39// ============================================================================
 40
 41static DBConnection mock_connection = {.pg_conn = (void *)0x1234};
 42static bool mock_connection_available = true;
 43static bool mock_query_success = true;
 44static int mock_row_count = 0;
 45static PGresult mock_result;
 46
 47#define PGRES_COMMAND_OK 1
 48#define PGRES_TUPLES_OK 2
 49
 50// ============================================================================
 51// MOCK FUNCTIONS
 52// ============================================================================
 53
 854DBConnection *db_pool_acquire(void) {
 855  return mock_connection_available ? &mock_connection : NULL;
 56}
 57
 658void db_pool_release(DBConnection *conn) {
 59  (void)conn;
 660}
 61
 662PGresult *PQexec(void *conn, const char *query) {
 63  (void)conn;
 64
 665  if (!mock_query_success) {
 166    mock_result.status = -1;
 167    return &mock_result;
 68  }
 69
 570  if (strstr(query, "INSERT")) {
 171    mock_result.status = PGRES_COMMAND_OK;
 172    mock_result.ntuples = 0;
 473  } else if (strstr(query, "SELECT")) {
 274    mock_result.status = PGRES_TUPLES_OK;
 275    mock_result.ntuples = mock_row_count;
 76
 677    for (int i = 0; i < mock_row_count && i < 100; i++) {
 478      snprintf(mock_result.data[i][0], 512, "%d", i + 1);
 479      snprintf(mock_result.data[i][1], 512, "%d", 101 + i);
 480      snprintf(mock_result.data[i][2], 512, "John");
 481      snprintf(mock_result.data[i][3], 512, "2025-02-15");
 482      snprintf(mock_result.data[i][4], 512, "Routine maintenance");
 483      snprintf(mock_result.data[i][5], 512, "250.50");
 84    }
 285  } else if (strstr(query, "UPDATE") || strstr(query, "DELETE")) {
 286    mock_result.status = PGRES_COMMAND_OK;
 287    mock_result.ntuples = 0;
 88  }
 89
 590  return &mock_result;
 91}
 92
 693int PQresultStatus(PGresult *res) {
 694  return res->status;
 95}
 96
 297int PQntuples(PGresult *res) {
 298  return res->ntuples;
 99}
 100
 24101char *PQgetvalue(PGresult *res, int row, int col) {
 24102  return mock_result.data[row][col];
 103}
 104
 6105void PQclear(PGresult *res) {
 106  (void)res;
 6107}
 108
 1109char *PQerrorMessage(void *conn) {
 110  (void)conn;
 1111  return "Mock error";
 112}
 113
 114#define LOG_ERROR(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__)
 115#define LOG_INFO(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__)
 116
 117// ============================================================================
 118// MAINTENANCE SERVICE IMPLEMENTATION
 119// ============================================================================
 120
 3121bool add_maintenance_log(int machine_id, const char *technician, const char *description, double cost) {
 3122  DBConnection *conn_wrapper = db_pool_acquire();
 123
 3124  if (!conn_wrapper) {
 1125    LOG_ERROR("Could not acquire connection to add maintenance log.");
 1126    return false;
 127  }
 128
 129  char query[1024];
 2130  snprintf(query, sizeof(query),
 131           "INSERT INTO maintenance_logs (machine_id, performer, description, cost) "
 132           "VALUES (%d, '%s', '%s', %.2f);",
 133           machine_id, technician, description, cost);
 2134  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 135
 2136  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
 1137    LOG_ERROR("Failed to insert maintenance log: %s", PQerrorMessage(conn_wrapper->pg_conn));
 1138    PQclear(res);
 1139    db_pool_release(conn_wrapper);
 1140    return false;
 141  }
 142
 1143  PQclear(res);
 1144  db_pool_release(conn_wrapper);
 1145  LOG_INFO("Maintenance log added for Machine %d.", machine_id);
 1146  return true;
 147}
 148
 2149int get_maintenance_history(int machine_id, MaintenanceLog *out_logs, int max_logs) {
 2150  DBConnection *conn_wrapper = db_pool_acquire();
 151
 2152  if (!conn_wrapper) {
 1153    LOG_ERROR("Could not acquire connection to fetch maintenance history.");
 1154    return 0;
 155  }
 156
 157  char query[256];
 1158  snprintf(query, sizeof(query),
 159           "SELECT id, machine_id, performer, to_char(ts, 'YYYY-MM-DD'), description, cost "
 160           "FROM maintenance_logs WHERE machine_id = %d ORDER BY ts DESC;",
 161           machine_id);
 1162  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 163
 1164  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
 0165    LOG_ERROR("Failed to fetch maintenance history: %s", PQerrorMessage(conn_wrapper->pg_conn));
 0166    PQclear(res);
 0167    db_pool_release(conn_wrapper);
 0168    return 0;
 169  }
 170
 1171  int rows = PQntuples(res);
 1172  int count = (rows < max_logs) ? rows : max_logs;
 173
 2174  for (int i = 0; i < count; i++) {
 1175    out_logs[i].id = atoi(PQgetvalue(res, i, 0));
 1176    out_logs[i].machine_id = atoi(PQgetvalue(res, i, 1));
 1177    strncpy(out_logs[i].technician_name, PQgetvalue(res, i, 2), 99);
 1178    out_logs[i].technician_name[99] = '\0';
 1179    strncpy(out_logs[i].log_date, PQgetvalue(res, i, 3), 31);
 1180    out_logs[i].log_date[31] = '\0';
 1181    strncpy(out_logs[i].description, PQgetvalue(res, i, 4), 511);
 1182    out_logs[i].description[511] = '\0';
 1183    out_logs[i].cost = atof(PQgetvalue(res, i, 5));
 184  }
 185
 1186  PQclear(res);
 1187  db_pool_release(conn_wrapper);
 1188  LOG_INFO("Fetched %d maintenance logs for Machine %d.", count, machine_id);
 1189  return count;
 190}
 191
 1192int get_all_maintenance_logs(MaintenanceLog *out_logs, int max_logs) {
 1193  DBConnection *conn_wrapper = db_pool_acquire();
 194
 1195  if (!conn_wrapper) return 0;
 196
 1197  const char *query = "SELECT id, machine_id, performer, to_char(ts, 'YYYY-MM-DD'), description, cost "
 198                      "FROM maintenance_logs ORDER BY ts DESC;";
 1199  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 200
 1201  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
 0202    PQclear(res);
 0203    db_pool_release(conn_wrapper);
 0204    return 0;
 205  }
 206
 1207  int rows = PQntuples(res);
 1208  int count = (rows < max_logs) ? rows : max_logs;
 209
 4210  for (int i = 0; i < count; i++) {
 3211    out_logs[i].id = atoi(PQgetvalue(res, i, 0));
 3212    out_logs[i].machine_id = atoi(PQgetvalue(res, i, 1));
 3213    strncpy(out_logs[i].technician_name, PQgetvalue(res, i, 2), 99);
 3214    out_logs[i].technician_name[99] = '\0';
 3215    strncpy(out_logs[i].log_date, PQgetvalue(res, i, 3), 31);
 3216    out_logs[i].log_date[31] = '\0';
 3217    strncpy(out_logs[i].description, PQgetvalue(res, i, 4), 511);
 3218    out_logs[i].description[511] = '\0';
 3219    out_logs[i].cost = atof(PQgetvalue(res, i, 5));
 220  }
 221
 1222  PQclear(res);
 1223  db_pool_release(conn_wrapper);
 1224  return count;
 225}
 226
 1227bool update_maintenance_log(int log_id, const char *description, double cost) {
 1228  DBConnection *conn_wrapper = db_pool_acquire();
 229
 1230  if (!conn_wrapper) return false;
 231
 232  char query[1024];
 1233  snprintf(query, sizeof(query),
 234           "UPDATE maintenance_logs SET description = '%s', cost = %.2f WHERE id = %d;",
 235           description, cost, log_id);
 1236  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 1237  bool success = (PQresultStatus(res) == PGRES_COMMAND_OK);
 238
 1239  if (!success) {
 0240    LOG_ERROR("Failed to update log: %s", PQerrorMessage(conn_wrapper->pg_conn));
 241  } else {
 1242    LOG_INFO("Maintenance log %d updated successfully.", log_id);
 243  }
 244
 1245  PQclear(res);
 1246  db_pool_release(conn_wrapper);
 1247  return success;
 248}
 249
 1250bool delete_maintenance_log(int log_id) {
 1251  DBConnection *conn_wrapper = db_pool_acquire();
 252
 1253  if (!conn_wrapper) return false;
 254
 255  char query[128];
 1256  snprintf(query, sizeof(query), "DELETE FROM maintenance_logs WHERE id = %d;", log_id);
 1257  PGresult *res = PQexec(conn_wrapper->pg_conn, query);
 1258  bool success = (PQresultStatus(res) == PGRES_COMMAND_OK);
 259
 1260  if (!success) {
 0261    LOG_ERROR("Failed to delete log: %s", PQerrorMessage(conn_wrapper->pg_conn));
 262  } else {
 1263    LOG_INFO("Maintenance log %d deleted.", log_id);
 264  }
 265
 1266  PQclear(res);
 1267  db_pool_release(conn_wrapper);
 1268  return success;
 269}
 270
 271// ============================================================================
 272// TEST HELPER
 273// ============================================================================
 274
 8275void reset_mocks(void) {
 8276  mock_connection_available = true;
 8277  mock_query_success = true;
 8278  mock_row_count = 0;
 8279  memset(&mock_result, 0, sizeof(mock_result));
 8280}
 281
 282// ============================================================================
 283// TESTS
 284// ============================================================================
 285
 1286void test_add_maintenance_log_success(void) {
 1287  printf("\n[TEST] test_add_maintenance_log_success\n");
 1288  reset_mocks();
 1289  bool result = add_maintenance_log(101, "John Doe", "Oil change", 150.50);
 1290  assert(result == true);
 1291  printf("✓ PASSED\n");
 1292}
 293
 1294void test_add_maintenance_log_no_connection(void) {
 1295  printf("\n[TEST] test_add_maintenance_log_no_connection\n");
 1296  reset_mocks();
 1297  mock_connection_available = false;
 1298  bool result = add_maintenance_log(101, "John", "Test", 100.0);
 1299  assert(result == false);
 1300  printf("✓ PASSED\n");
 1301}
 302
 1303void test_add_maintenance_log_query_failure(void) {
 1304  printf("\n[TEST] test_add_maintenance_log_query_failure\n");
 1305  reset_mocks();
 1306  mock_query_success = false;
 1307  bool result = add_maintenance_log(101, "John", "Test", 100.0);
 1308  assert(result == false);
 1309  printf("✓ PASSED\n");
 1310}
 311
 1312void test_get_maintenance_history_success(void) {
 1313  printf("\n[TEST] test_get_maintenance_history_success\n");
 1314  reset_mocks();
 1315  mock_row_count = 1;
 316  MaintenanceLog logs[10];
 1317  int count = get_maintenance_history(101, logs, 10);
 1318  assert(count == 1);
 1319  assert(logs[0].id == 1);
 1320  assert(logs[0].machine_id == 101);
 1321  printf("✓ PASSED\n");
 1322}
 323
 1324void test_get_maintenance_history_no_connection(void) {
 1325  printf("\n[TEST] test_get_maintenance_history_no_connection\n");
 1326  reset_mocks();
 1327  mock_connection_available = false;
 328  MaintenanceLog logs[10];
 1329  int count = get_maintenance_history(101, logs, 10);
 1330  assert(count == 0);
 1331  printf("✓ PASSED\n");
 1332}
 333
 1334void test_get_all_maintenance_logs_success(void) {
 1335  printf("\n[TEST] test_get_all_maintenance_logs_success\n");
 1336  reset_mocks();
 1337  mock_row_count = 3;
 338  MaintenanceLog logs[10];
 1339  int count = get_all_maintenance_logs(logs, 10);
 1340  assert(count == 3);
 1341  printf("✓ PASSED\n");
 1342}
 343
 1344void test_update_maintenance_log_success(void) {
 1345  printf("\n[TEST] test_update_maintenance_log_success\n");
 1346  reset_mocks();
 1347  bool result = update_maintenance_log(1, "Updated", 200.0);
 1348  assert(result == true);
 1349  printf("✓ PASSED\n");
 1350}
 351
 1352void test_delete_maintenance_log_success(void) {
 1353  printf("\n[TEST] test_delete_maintenance_log_success\n");
 1354  reset_mocks();
 1355  bool result = delete_maintenance_log(1);
 1356  assert(result == true);
 1357  printf("✓ PASSED\n");
 1358}
 359
 360// ============================================================================
 361// MAIN
 362// ============================================================================
 363
 1364int main(void) {
 1365  printf("========================================\n");
 1366  printf("MAINTENANCE SERVICE TEST (STANDALONE)\n");
 1367  printf("========================================\n");
 1368  int total = 0, passed = 0;
 1369  test_add_maintenance_log_success();
 1370  total++;
 1371  passed++;
 1372  test_add_maintenance_log_no_connection();
 1373  total++;
 1374  passed++;
 1375  test_add_maintenance_log_query_failure();
 1376  total++;
 1377  passed++;
 1378  test_get_maintenance_history_success();
 1379  total++;
 1380  passed++;
 1381  test_get_maintenance_history_no_connection();
 1382  total++;
 1383  passed++;
 1384  test_get_all_maintenance_logs_success();
 1385  total++;
 1386  passed++;
 1387  test_update_maintenance_log_success();
 1388  total++;
 1389  passed++;
 1390  test_delete_maintenance_log_success();
 1391  total++;
 1392  passed++;
 1393  printf("\n========================================\n");
 1394  printf("TEST RESULTS: %d/%d PASSED\n", passed, total);
 1395  printf("========================================\n");
 1396  return (passed == total) ? 0 : 1;
 397}

Methods/Properties