// Written by retoor@molodetz.nl // This code provides a console utility for performing code coverage analysis on a specified C source file using lcov and genhtml. It checks // for lcov installation, compiles the source file with coverage options, runs it, and generates an HTML report. // The code uses lcov and genhtml for coverage analysis and viewing, google-chrome for displaying the HTML report, and it requires gcc for // compilation. // MIT License #ifndef RCOV_H #define RCOV_H #include "rtypes.h" #include "rtemp.h" #include #include #include #include #include "rbench.h" bool check_lcov() { char buffer[1024 * 64]; FILE *fp = popen("lcov --help", "r"); if (fp == NULL) { return false; } if (fgets(buffer, sizeof(buffer), fp) == NULL) { return false; } pclose(fp); return strstr(buffer, "lcov: not found") ? false : true; } int rcov_main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: [source.c]\n"); return 1; } char argstr[4096] = {0}; for (int i = 2; i < argc; i++) { strcat(argstr, argv[i]); strcat(argstr, " "); } if (!check_lcov()) { printf("lcov is not installed. Please execute `sudo apt install lcov`.\n"); return 1; } char *source_file = argv[1]; char *commands[] = {"rm -f *.gcda 2>/dev/null", "rm -f *.gcno 2>/dev/null", "rm -f %s.coverage.info 2>/dev/null", "gcc -pg -fprofile-arcs -ftest-coverage -g -o %s_coverage.o %s", "./%s_coverage.o", "lcov --capture --directory . --output-file %s.coverage.info", "genhtml %s.coverage.info --output-directory /tmp/%s.coverage", "rm -f *.gcda 2>/dev/null", "rm -f *.gcno 2>/dev/null", "rm -f %s.coverage.info 2>/dev/null", "gprof %s_coverage.o gmon.out > output.rcov_analysis", "rm -f gmon.out", "cat output.rcov_analysis", "rm output.rcov_analysis", "rm -f %s_coverage.o", "google-chrome /tmp/%s.coverage/index.html"}; uint command_count = sizeof(commands) / sizeof(commands[0]); RBENCH(1, { for (uint i = 0; i < command_count; i++) { char *formatted_command = sbuf(""); sprintf(formatted_command, commands[i], source_file, source_file); if (formatted_command[0] == '.' && formatted_command[1] == '/') { strcat(formatted_command, " "); strcat(formatted_command, argstr); } if (system(formatted_command)) { printf("`%s` returned non-zero code.\n", formatted_command); } } }); return 0; } #endif