| 201 | } |
| 202 | |
| 203 | void BranchCoverageImpl::RecordImpl(int64_t expr_id, const CelValue& value) { |
| 204 | absl::MutexLock lock(coverage_nodes_mu_); |
| 205 | auto it = coverage_nodes_.find(expr_id); |
| 206 | if (it == coverage_nodes_.end()) { |
| 207 | unexpected_expr_ids_.insert(expr_id); |
| 208 | it = coverage_nodes_.insert({expr_id, CoverageNode{0, {}}}).first; |
| 209 | if (value.IsBool()) { |
| 210 | it->second.kind = BoolNode{0, 0, 0}; |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | CoverageNode& coverage_node = it->second; |
| 215 | coverage_node.evaluate_count++; |
| 216 | bool is_error = value.IsError() && |
| 217 | // Filter conversion errors for evaluator internal types. |
| 218 | // TODO(uncreated-issue/65): RecordImpl operates on legacy values so |
| 219 | // special case conversion errors. This error is really just a |
| 220 | // sentinel value and doesn't need to round-trip between |
| 221 | // legacy and legacy types. |
| 222 | value.ErrorOrDie() != &UnsupportedConversionError(); |
| 223 | |
| 224 | absl::visit(absl::Overload([&](ConstantNode& node) {}, |
| 225 | [&](OtherNode& cov) { |
| 226 | if (is_error) { |
| 227 | cov.result_error++; |
| 228 | } |
| 229 | }, |
| 230 | [&](BoolNode& cov) { |
| 231 | if (value.IsBool()) { |
| 232 | bool held_value = value.BoolOrDie(); |
| 233 | if (held_value) { |
| 234 | cov.result_true++; |
| 235 | } else { |
| 236 | cov.result_false++; |
| 237 | } |
| 238 | } else if (is_error) { |
| 239 | cov.result_error++; |
| 240 | } |
| 241 | }), |
| 242 | coverage_node.kind); |
| 243 | } |
| 244 | |
| 245 | } // namespace |
| 246 |
nothing calls this directly
no test coverage detected