|
58 | 58 | *Recommendation:* Either add a static_assert that count_ < 32 (not <= 32, since bit 32 of a uint32_t is UB), or add an explicit mask/clamp in method_bit. The existing static_assert at line 237 uses <= 32 which technically allows count_ == 32 (UB territory). Tightening it to < 32 would remove the ambiguity. |
59 | 59 | *Status:* fixed in this batch — static_assert tightened to `< 32`; method_bit comment updated to accurately describe the invariant. |
60 | 60 |
|
61 | | -11. [ ] **code-quality-reviewer** | `test/unit/http_method_test.cpp:154` | test-coverage |
| 61 | +11. [x] **code-quality-reviewer** | `test/unit/http_method_test.cpp:154` | test-coverage |
62 | 62 | The clean-code principle 'one assert per test' is violated throughout the test suite. Most LT_BEGIN_AUTO_TEST blocks contain multiple LT_CHECK calls testing distinct behaviors (e.g., test 5 checks get present, post present, and put absent in a single test). This makes it harder to identify exactly which assertion failed on a test failure. |
63 | 63 | *Recommendation:* Split multi-assertion tests into individual focused tests, each with a name that describes the single behavior under test. For example, split 'bitwise_or_two_enumerators_yields_set_with_both' into 'bitwise_or_includes_first_operand', 'bitwise_or_includes_second_operand', and 'bitwise_or_excludes_third_method'. This is a low-priority trade-off against test verbosity so keep it in mind for future expansion. |
64 | 64 | *Status:* deferred — the framework makes per-assertion test splitting very verbose; the reviewer's own note calls it "low-priority trade-off against test verbosity". Acceptable at current granularity. |
|
68 | 68 | *Recommendation:* Remove the empty set_up() and tear_down() bodies if the test framework allows omitting them. If the framework requires them, add a brief comment explaining they are intentionally empty (no per-test state). |
69 | 69 | *Status:* fixed in this batch — the littletest CRTP base requires these methods; added comment explaining they are required by the framework even when empty. |
70 | 70 |
|
71 | | -13. [ ] **code-quality-reviewer** | `test/unit/http_method_test.cpp:154` | test-coverage |
| 71 | +13. [x] **code-quality-reviewer** | `test/unit/http_method_test.cpp:154` | test-coverage |
72 | 72 | Several runtime tests contain multiple independent assertions (e.g. test 5 checks contains(get), contains(post), and !contains(put); test 10 chains three compound-assignment operations with five distinct checks). The clean-code Tests rule recommends one assert per test to keep failure messages pinpointed. |
73 | 73 | *Recommendation:* Split multi-assertion tests into focused single-behavior tests, e.g. separate 'bitwise_or_includes_left_operand', 'bitwise_or_includes_right_operand', and 'bitwise_or_excludes_absent_method'. This also improves the granularity of failure messages from LT_CHECK. |
74 | 74 | *Status:* deferred — same rationale as item 11; low-priority verbosity trade-off. Duplicate recommendation. |
|
83 | 83 | *Recommendation:* Remove the duplicate static_assert from the test file; the production header's assert fires in every TU that includes httpserver.hpp and is sufficient. Retain only the test-file-specific asserts (underlying type pin, bits field type, contiguity of count_) that add coverage beyond what the header already checks. |
84 | 84 | *Status:* partially addressed — the assertion is documented as intentional in the AC block with a comment; bound tightened to `< 32` to match header. |
85 | 85 |
|
86 | | -16. [ ] **code-simplifier** | `src/httpserver/http_method.hpp:116` | naming |
| 86 | +16. [x] **code-simplifier** | `src/httpserver/http_method.hpp:116` | naming |
87 | 87 | The switch arms in to_string construct std::string_view via its explicit single-argument constructor (e.g. std::string_view{"GET"}) rather than the more idiomatic string literal suffix ("GET"sv) available since C++17, which is the minimum required standard for this library. The explicit constructor form is correct and readable, but the sv suffix is the established C++17 idiom and would be slightly more concise and consistent with modern C++17 style. |
88 | 88 | *Recommendation:* Optionally replace `std::string_view{"GET"}` with `"GET"sv` (and similarly for each arm) after adding `using namespace std::string_view_literals;` or `using std::literals::string_view_literals::operator""sv;` at the top of the function or file. This is purely a style preference and should only be applied if it matches the style used elsewhere in the codebase. |
89 | 89 | *Status:* wontfix — cosmetic/style preference, no functional impact; purely stylistic; array literal form acceptable, low priority |
|
123 | 123 | *Recommendation:* Replace the switch with a static constexpr std::array<std::string_view, static_cast<std::size_t>(http_method::count_)> keyed by static_cast<std::uint8_t>(m), with a bounds check returning {} for out-of-range inputs. |
124 | 124 | *Status:* already addressed — to_string already uses a constexpr array implementation. |
125 | 125 |
|
126 | | -24. [ ] **performance-reviewer** | `src/httpserver/http_method.hpp:62` | missing-caching |
| 126 | +24. [x] **performance-reviewer** | `src/httpserver/http_method.hpp:62` | missing-caching |
127 | 127 | method_bit(m) involves a runtime shift whose shift amount is the uint8_t cast of m. For the 9 current methods the shift amount is 0–8, all within a single-byte range that most CPUs can compute in one instruction. However, if this function is called at a non-constexpr runtime site (e.g. looking up a parsed method from a network request) the shift is free but the cast chain (enum -> uint8_t -> uint32_t -> shift) adds two widening moves on some ABIs. Marking the caller sites that already have the integer value directly (e.g. after a parse step that produces uint8_t) to pass the method enum avoids double-conversion and is already satisfied by the current design — this is just a note that the design is correct. |
128 | 128 | *Recommendation:* No change needed; the current design is already optimal for the stated hot path. |
129 | 129 | *Status:* deferred — reviewer explicitly says no change needed; noted for completeness. |
130 | 130 |
|
131 | | -25. [ ] **performance-reviewer** | `src/httpserver/http_method.hpp:67` | algorithmic-complexity |
| 131 | +25. [x] **performance-reviewer** | `src/httpserver/http_method.hpp:67` | algorithmic-complexity |
132 | 132 | valid_method_mask() recomputes (1 << count_) - 1 on every call. Because count_ is a compile-time constant the compiler will constant-fold this, but the function is called in every complement and set_all operation. Marking the result consteval or caching it as a constexpr variable at namespace scope would make the intent explicit and remove any residual risk of non-constant evaluation in debug builds. |
133 | 133 | *Recommendation:* Add a constexpr constant: inline constexpr std::uint32_t k_valid_method_mask = detail::valid_method_mask(); and replace all call sites. |
134 | 134 | *Status:* deferred — the function is constexpr and constant-folded by the compiler; a micro-optimization that changes the public API surface. Defer to a later cleanup pass. |
135 | 135 |
|
136 | | -26. [ ] **security-reviewer** | `src/httpserver/http_method.hpp:116` | insecure-design |
| 136 | +26. [x] **security-reviewer** | `src/httpserver/http_method.hpp:116` | insecure-design |
137 | 137 | to_string() is the only direction provided (enum -> wire token). There is no from_string() or validate() primitive, so downstream parsing code will inevitably write ad-hoc string comparisons or unsafe static_casts from integer indices to produce an http_method value. |
138 | 138 | *Recommendation:* Consider adding a constexpr std::optional<http_method> from_string(std::string_view) noexcept in this header as a companion to to_string(). |
139 | 139 | *Status:* deferred — from_string() is out of scope for TASK-005 (not in the task spec). Tracked for a future task. |
|
143 | 143 | *Recommendation:* Add a guard inside method_bit() itself or change the static_assert to count_ < 32 (strictly less). |
144 | 144 | *Status:* fixed in this batch — static_assert tightened to `< 32` and method_bit comment updated. Same fix as items 9/10. |
145 | 145 |
|
146 | | -28. [ ] **security-reviewer** | `src/httpserver/http_method.hpp:79` | insecure-design |
| 146 | +28. [x] **security-reviewer** | `src/httpserver/http_method.hpp:79` | insecure-design |
147 | 147 | The method_set::bits field is public and mutable with no validation, allowing callers to directly inject arbitrary bitmask values. |
148 | 148 | *Recommendation:* Consider making bits private and providing a named constructor or factory (e.g. static constexpr method_set from_bits(uint32_t) noexcept that masks with valid_method_mask()). |
149 | 149 | *Status:* deferred — aggregate design is intentional (standard layout, trivially copyable); making bits private changes the public API. Design decision requiring a broader discussion. |
150 | 150 |
|
151 | | -29. [ ] **spec-alignment-checker** | `/Users/etr/progs/libhttpserver/.worktrees/TASK-005/src/httpserver/http_method.hpp:null` | specification-gap |
| 151 | +29. [x] **spec-alignment-checker** | `/Users/etr/progs/libhttpserver/.worktrees/TASK-005/src/httpserver/http_method.hpp:null` | specification-gap |
152 | 152 | PRD-HDL-REQ-006 requires 'webserver::route(http_method, path, handler)' as a registration entry point. TASK-005 only delivers the http_method enum and method_set bitmask primitive. |
153 | 153 | *Recommendation:* No action required for TASK-005. Downstream tasks (TASK-021 et al.) must implement webserver::route(). |
154 | 154 | *Status:* deferred — no action required per reviewer. |
155 | 155 |
|
156 | | -30. [ ] **test-quality-reviewer** | `test/unit/http_method_test.cpp:163` | redundant-test |
| 156 | +30. [x] **test-quality-reviewer** | `test/unit/http_method_test.cpp:163` | redundant-test |
157 | 157 | Runtime test `set_then_contains_runtime` (test 1) directly mirrors the AC #1 static_assert at line 35-37. |
158 | 158 | *Recommendation:* Remove the runtime test and rely on the static_assert, or broaden the runtime test to cover a scenario the static_assert cannot. |
159 | 159 | *Status:* deferred — the runtime test documents intent in the LT suite output and catches dynamic-only runtime failures. Minor redundancy acceptable. |
160 | 160 |
|
161 | | -31. [ ] **test-quality-reviewer** | `test/unit/http_method_test.cpp:254` | multiple-concerns |
| 161 | +31. [x] **test-quality-reviewer** | `test/unit/http_method_test.cpp:254` | multiple-concerns |
162 | 162 | Test `compound_assign_or_equals_with_enumerator` chains |=, &=, and ^= in sequence within one test body. If the &= step silently misbehaves, the ^= assertion may mask it, and the name only mentions `|=`. |
163 | 163 | *Recommendation:* Split into three tests: one for |=, one for &=, one for ^=. |
164 | 164 | *Status:* deferred — framework verbosity makes splitting burdensome; the combined test is a regression guard. A new test (14) explicitly tests method_set RHS overloads; this test covers the http_method RHS overloads. |
165 | 165 |
|
166 | | -32. [ ] **test-quality-reviewer** | `test/unit/http_method_test.cpp:272` | naming-convention |
| 166 | +32. [x] **test-quality-reviewer** | `test/unit/http_method_test.cpp:272` | naming-convention |
167 | 167 | Test `to_string_returns_uppercase_wire_tokens` contains 9 assertions for 9 different methods in a single test body. |
168 | 168 | *Recommendation:* This is acceptable as-is given the framework's lack of parametrize support. |
169 | 169 | *Status:* wontfix — cosmetic/style preference, no functional impact; reviewer says acceptable as-is; already addressed in TASK-027 |
|
0 commit comments