LCOV - code coverage report
Current view: top level - backend/engine/semantic/functions - numeric_edges_test.cc (source / functions) Coverage Total Hit
Test: _coverage_report.dat Lines: 100.0 % 70 70
Test Date: 2026-07-02 21:01:18 Functions: 100.0 % 13 13

            Line data    Source code
       1              : // Unit tests for the numeric-edges semantic-executor functions.
       2              : //
       3              : // These tests bypass the analyzer and call the per-function helpers
       4              : // directly with hand-built `Value` arguments. End-to-end coverage
       5              : // (analyzer -> dispatch -> result) lives in `dispatch_test.cc`.
       6              : 
       7              : #include "backend/engine/semantic/functions/numeric_edges.h"
       8              : 
       9              : #include <cmath>
      10              : #include <cstdint>
      11              : #include <limits>
      12              : #include <vector>
      13              : 
      14              : #include "absl/status/status.h"
      15              : #include "absl/status/statusor.h"
      16              : #include "backend/engine/semantic/error.h"
      17              : #include "backend/engine/semantic/value.h"
      18              : #include "googlesql/public/type.h"
      19              : #include "googlesql/public/value.h"
      20              : #include "gtest/gtest.h"
      21              : 
      22              : namespace bigquery_emulator {
      23              : namespace backend {
      24              : namespace engine {
      25              : namespace semantic {
      26              : namespace functions {
      27              : namespace {
      28              : 
      29            1 : TEST(BitCountTest, ZeroHasNoSetBits) {
      30            1 :   auto v = BitCount({Value::Int64(0)});
      31            2 :   ASSERT_TRUE(v.ok()) << v.status();
      32            1 :   EXPECT_EQ(v->int64_value(), 0);
      33            1 : }
      34              : 
      35            1 : TEST(BitCountTest, SmallPositive) {
      36            1 :   auto v = BitCount({Value::Int64(7)});  // 0b111
      37            2 :   ASSERT_TRUE(v.ok()) << v.status();
      38            1 :   EXPECT_EQ(v->int64_value(), 3);
      39            1 : }
      40              : 
      41            1 : TEST(BitCountTest, NegativeOneAllBitsSet) {
      42              :   // -1 in two's-complement has every bit set; BigQuery returns 64.
      43              :   // This is the key correctness case the row exists to pin: a
      44              :   // thin macro on DuckDB's unsigned `bit_count` cannot match this
      45              :   // without re-interpreting the bit pattern.
      46            1 :   auto v = BitCount({Value::Int64(-1)});
      47            2 :   ASSERT_TRUE(v.ok()) << v.status();
      48            1 :   EXPECT_EQ(v->int64_value(), 64);
      49            1 : }
      50              : 
      51            1 : TEST(BitCountTest, Int64MinSignBitOnly) {
      52            1 :   auto v = BitCount({Value::Int64(std::numeric_limits<int64_t>::min())});
      53            2 :   ASSERT_TRUE(v.ok()) << v.status();
      54            1 :   EXPECT_EQ(v->int64_value(), 1);
      55            1 : }
      56              : 
      57            1 : TEST(BitCountTest, NullPropagates) {
      58            1 :   auto v = BitCount({Value::NullInt64()});
      59            2 :   ASSERT_TRUE(v.ok()) << v.status();
      60            1 :   EXPECT_TRUE(v->is_null());
      61            1 : }
      62              : 
      63            1 : TEST(BitCountTest, NonInt64Rejected) {
      64            1 :   Value arg = Value::String("hi");
      65            1 :   auto v = BitCount({arg});
      66            1 :   ASSERT_FALSE(v.ok());
      67            1 :   EXPECT_EQ(GetSemanticErrorReason(v.status()),
      68            1 :             SemanticErrorReason::kInvalidArgument);
      69            1 : }
      70              : 
      71            1 : TEST(BitCountTest, ArityMismatchRejected) {
      72            1 :   auto v = BitCount({Value::Int64(1), Value::Int64(2)});
      73            1 :   ASSERT_FALSE(v.ok());
      74            1 :   EXPECT_EQ(v.status().code(), absl::StatusCode::kInvalidArgument);
      75            1 : }
      76              : 
      77            1 : TEST(IeeeDivideTest, FinitePath) {
      78            1 :   auto v = IeeeDivide({Value::Double(10.0), Value::Double(4.0)});
      79            2 :   ASSERT_TRUE(v.ok()) << v.status();
      80            1 :   EXPECT_DOUBLE_EQ(v->double_value(), 2.5);
      81            1 : }
      82              : 
      83            1 : TEST(IeeeDivideTest, DivisionByZeroProducesInf) {
      84              :   // IEEE_DIVIDE diverges from SAFE_DIVIDE and `/` here: SAFE_DIVIDE
      85              :   // returns NULL, `/` raises, IEEE_DIVIDE returns +/-Inf per IEEE 754.
      86            1 :   auto v = IeeeDivide({Value::Double(1.0), Value::Double(0.0)});
      87            2 :   ASSERT_TRUE(v.ok()) << v.status();
      88            1 :   EXPECT_TRUE(std::isinf(v->double_value()));
      89            1 :   EXPECT_GT(v->double_value(), 0.0);
      90            1 : }
      91              : 
      92            1 : TEST(IeeeDivideTest, NegativeOverZeroProducesNegativeInf) {
      93            1 :   auto v = IeeeDivide({Value::Double(-1.0), Value::Double(0.0)});
      94            2 :   ASSERT_TRUE(v.ok()) << v.status();
      95            1 :   EXPECT_TRUE(std::isinf(v->double_value()));
      96            1 :   EXPECT_LT(v->double_value(), 0.0);
      97            1 : }
      98              : 
      99            1 : TEST(IeeeDivideTest, ZeroOverZeroProducesNan) {
     100            1 :   auto v = IeeeDivide({Value::Double(0.0), Value::Double(0.0)});
     101            2 :   ASSERT_TRUE(v.ok()) << v.status();
     102            1 :   EXPECT_TRUE(std::isnan(v->double_value()));
     103            1 : }
     104              : 
     105            1 : TEST(IeeeDivideTest, NullPropagates) {
     106            1 :   auto v = IeeeDivide({Value::NullDouble(), Value::Double(1.0)});
     107            2 :   ASSERT_TRUE(v.ok()) << v.status();
     108            1 :   EXPECT_TRUE(v->is_null());
     109            1 : }
     110              : 
     111            1 : TEST(IeeeDivideTest, NonDoubleRejected) {
     112            1 :   auto v = IeeeDivide({Value::Int64(1), Value::Int64(2)});
     113            1 :   ASSERT_FALSE(v.ok());
     114            1 :   EXPECT_EQ(GetSemanticErrorReason(v.status()),
     115            1 :             SemanticErrorReason::kInvalidArgument);
     116            1 : }
     117              : 
     118              : }  // namespace
     119              : }  // namespace functions
     120              : }  // namespace semantic
     121              : }  // namespace engine
     122              : }  // namespace backend
     123              : }  // namespace bigquery_emulator
        

Generated by: LCOV version 2.0-1