std1.0.0-beta-7 SafeC docs

Source debug/coverage.sc

View in the repository

// SafeC Standard Library — Code Coverage Tracker Implementation
#pragma once
#include <std/debug/coverage.h>

namespace std {

// Definitions of the globals coverage.h declares extern.
struct Coverage coverage;


extern int printf(const char* fmt, ...);

// ── Global coverage instance ──────────────────────────────────────────────────


// ── coverage_init ─────────────────────────────────────────────────────────────

inline void coverage_init() {
    coverage.count = 0;
    int i = 0;
    while (i < COV_MAX_SITES) {
        unsafe {
            coverage.sites[i].file  = "";
            coverage.sites[i].line  = 0;
            coverage.sites[i].count = (unsigned long)0;
        }
        i = i + 1;
    }
}

// ── Coverage::register_site ───────────────────────────────────────────────────

inline int Coverage::register_site(const &char file, int line) {
    if (self.count >= COV_MAX_SITES) { return -1; }
    int idx = self.count;
    unsafe {
        self.sites[idx].file  = file;
        self.sites[idx].line  = line;
        self.sites[idx].count = (unsigned long)0;
    }
    self.count = self.count + 1;
    return idx;
}

// ── Coverage::hit ─────────────────────────────────────────────────────────────

inline void Coverage::hit(int idx) {
    if (idx < 0 || idx >= self.count) { return; }
    unsafe {
        self.sites[idx].count = self.sites[idx].count + (unsigned long)1;
    }
}

// ── Coverage::get ─────────────────────────────────────────────────────────────

inline unsigned long Coverage::get(int idx) const {
    if (idx < 0 || idx >= self.count) { return (unsigned long)0; }
    unsafe { return self.sites[idx].count; }
    return (unsigned long)0;
}

// ── Coverage::report ─────────────────────────────────────────────────────────

void Coverage::report() const {
#ifndef __SAFEC_FREESTANDING__
    int total = self.count;
    int covered = self.covered_count();
    int pct = self.coverage_pct();
    unsafe {
        printf("[coverage] %d/%d sites hit (%d%%)\n", covered, total, pct);
    }
    int i = 0;
    while (i < self.count) {
        unsafe {
            const char* fname = self.sites[i].file;
            int line = self.sites[i].line;
            unsigned long cnt = self.sites[i].count;
            if (cnt > (unsigned long)0) {
                printf("  [HIT]  %s:%d  count=%lu\n", fname, line, cnt);
            } else {
                printf("  [MISS] %s:%d\n", fname, line);
            }
        }
        i = i + 1;
    }
#endif
}

// ── Coverage::covered_count ───────────────────────────────────────────────────

inline int Coverage::covered_count() const {
    int n = 0;
    int i = 0;
    while (i < self.count) {
        unsafe {
            if (self.sites[i].count > (unsigned long)0) { n = n + 1; }
        }
        i = i + 1;
    }
    return n;
}

// ── Coverage::coverage_pct ────────────────────────────────────────────────────

inline int Coverage::coverage_pct() const {
    if (self.count == 0) { return 0; }
    int covered = self.covered_count();
    // Integer percentage: (covered * 100) / total.
    return (covered * 100) / self.count;
}

// ── Coverage::reset ───────────────────────────────────────────────────────────

inline void Coverage::reset() {
    int i = 0;
    while (i < self.count) {
        unsafe { self.sites[i].count = (unsigned long)0; }
        i = i + 1;
    }
}

} // namespace std