• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

llnl / dftracer-utils / 26195612357

20 May 2026 11:19PM UTC coverage: 49.859% (-2.3%) from 52.2%
26195612357

push

github

hariharan-devarajan
feat(aggregator): improve system metrics scanning and persistence error handling

16041 of 43831 branches covered (36.6%)

Branch coverage included in aggregate %.

6 of 17 new or added lines in 2 files covered. (35.29%)

1072 existing lines in 104 files now uncovered.

21423 of 31309 relevant lines covered (68.42%)

13054.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.55
/src/dftracer/utils/server/router.cpp
1
#include <dftracer/utils/server/http_request.h>
2
#include <dftracer/utils/server/http_response.h>
3
#include <dftracer/utils/server/router.h>
4

5
#include <algorithm>
6
#include <charconv>
7
#include <cstdlib>
8

9
namespace dftracer::utils::server {
10

11
// ============================================================================
12
// QueryParams
13
// ============================================================================
14

15
static std::string url_decode(std::string_view sv) {
100✔
16
    std::string result;
100✔
17
    result.reserve(sv.size());
100!
18
    for (std::size_t i = 0; i < sv.size(); ++i) {
703✔
19
        if (sv[i] == '%' && i + 2 < sv.size()) {
603!
20
            char hex[3] = {sv[i + 1], sv[i + 2], '\0'};
61✔
21
            char* end = nullptr;
61✔
22
            unsigned long val = std::strtoul(hex, &end, 16);
61✔
23
            if (end == hex + 2) {
61!
24
                result.push_back(static_cast<char>(val));
61!
25
                i += 2;
61✔
26
                continue;
61✔
27
            }
28
        } else if (sv[i] == '+') {
542✔
29
            result.push_back(' ');
1!
30
            continue;
1✔
31
        }
32
        result.push_back(sv[i]);
541!
33
    }
34
    return result;
100✔
UNCOV
35
}
×
36

37
QueryParams QueryParams::parse(std::string_view query) {
33✔
38
    QueryParams params;
33✔
39
    while (!query.empty()) {
85✔
40
        auto amp = query.find('&');
52✔
41
        auto pair = query.substr(0, amp);
52!
42
        query = (amp == std::string_view::npos) ? std::string_view{}
52✔
43
                                                : query.substr(amp + 1);
28!
44

45
        auto eq = pair.find('=');
52✔
46
        if (eq == std::string_view::npos) {
52✔
47
            params.params_.emplace_back(url_decode(pair), "");
4!
48
        } else {
49
            params.params_.emplace_back(url_decode(pair.substr(0, eq)),
48!
50
                                        url_decode(pair.substr(eq + 1)));
96!
51
        }
52
    }
53
    return params;
33✔
UNCOV
54
}
×
55

56
std::string_view QueryParams::get(std::string_view key,
131✔
57
                                  std::string_view default_value) const {
58
    for (const auto& [k, v] : params_) {
367✔
59
        if (k == key) return v;
282✔
60
    }
61
    return default_value;
85✔
62
}
63

64
bool QueryParams::has(std::string_view key) const {
30✔
65
    for (const auto& [k, v] : params_) {
53✔
66
        if (k == key) return true;
50✔
67
    }
68
    return false;
3✔
69
}
70

71
int QueryParams::get_int(std::string_view key, int default_value) const {
20✔
72
    auto sv = get(key);
20!
73
    if (sv.empty()) return default_value;
20✔
74
    int val = default_value;
11✔
75
    std::from_chars(sv.data(), sv.data() + sv.size(), val);
11!
76
    return val;
11✔
77
}
78

79
double QueryParams::get_double(std::string_view key,
39✔
80
                               double default_value) const {
81
    auto sv = get(key);
39!
82
    if (sv.empty()) return default_value;
39✔
83
    // std::from_chars for doubles not universally available in C++17
84
    // compilers. Use strtod as fallback.
85
    char* end = nullptr;
17✔
86
    std::string tmp(sv);
17!
87
    double val = std::strtod(tmp.c_str(), &end);
17✔
88
    if (end == tmp.c_str()) return default_value;
17✔
89
    return val;
16✔
90
}
17✔
91

92
// ============================================================================
93
// Router
94
// ============================================================================
95

96
void Router::get(const std::string& path, RouteHandler handler) {
14✔
97
    routes_.push_back(Route{"GET", path, std::move(handler)});
14!
98
}
14✔
99

100
void Router::post(const std::string& path, RouteHandler handler) {
×
101
    routes_.push_back(Route{"POST", path, std::move(handler)});
×
102
}
×
103

104
coro::CoroTask<HttpResponse> Router::handle(const HttpRequest& req) {
16!
105
    // Split path and query string.
106
    auto path = req.path;
107
    std::string_view query_str;
108
    auto qpos = path.find('?');
109
    if (qpos != std::string_view::npos) {
110
        query_str = path.substr(qpos + 1);
111
        path = path.substr(0, qpos);
112
    }
113

114
    auto params = QueryParams::parse(query_str);
115

116
    // Match routes (exact prefix match).
117
    for (const auto& route : routes_) {
118
        if (req.method == route.method && path == route.path) {
119
            co_return co_await route.handler(req, params);
120
        }
121
    }
122

123
    // Try prefix matches for parameterized routes
124
    // (e.g., "/api/v1/files/:file/info" matches "/api/v1/files/foo/info")
125
    // For now, use exact match only — parameterized routes can be added later.
126

127
    co_return HttpResponse::not_found();
128
}
32!
129

130
}  // namespace dftracer::utils::server
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc