Skip to content

Commit 331083e

Browse files
committed
test: add BufferTests for decimal negation scenarios
1 parent bc20a0d commit 331083e

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
using NUnit.Framework;
2+
using QuestDB.Buffers;
3+
4+
namespace net_questdb_client_tests;
5+
6+
public class BufferTests
7+
{
8+
[Test]
9+
public void DecimalNegationSimple()
10+
{
11+
var buffer = new BufferV3(128, 128, 128);
12+
// Test simple negative decimal without carry propagation
13+
// -1.0m has unscaled value of -10 (with scale 1)
14+
buffer.Table("negation_test")
15+
.Symbol("tag", "simple")
16+
.Column("dec_neg_one", -1.0m)
17+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
18+
19+
// -10 in two's complement: 0xF6 (since 10 = 0x0A, ~0x0A + 1 = 0xF5 + 1 = 0xF6)
20+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_neg_one", 1, new byte[]
21+
{
22+
0xF6,
23+
});
24+
}
25+
26+
[Test]
27+
public void DecimalNegationCarryLowToMid()
28+
{
29+
var buffer = new BufferV3(128, 128, 128);
30+
31+
// Test carry propagation from low to mid part
32+
// Decimal with low=0x00000001, mid=0x00000000, high=0x00000000
33+
// After negation: low becomes 0xFFFFFFFF (overflow with carry), mid gets carry
34+
// This decimal is: -(2^96 / 10^28 + 1) which causes carry propagation
35+
// Use -4294967296 (which is -2^32) to force carry: low=0x00000000, mid=0x00000001
36+
// After negation: low = ~0 + 1 = 0, mid = ~1 + 1 = 0xFFFFFFFE + 1 = 0xFFFFFFFF
37+
var decimalValue = -4294967296m; // -2^32
38+
39+
buffer.Table("negation_test")
40+
.Symbol("tag", "carry_low_mid")
41+
.Column("dec_carry", decimalValue)
42+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
43+
44+
// -4294967296 has bits: low=0, mid=1, high=0
45+
// Two's complement: low = ~0 + 1 = 0 (with carry), mid = ~1 + carry = 0xFFFFFFFE + 1 = 0xFFFFFFFF
46+
// Result should be: 0xFF, 0x00, 0x00, 0x00, 0x00 (compressed)
47+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_carry", 0, new byte[]
48+
{
49+
0xFF,
50+
0x00, 0x00, 0x00, 0x00,
51+
});
52+
}
53+
54+
[Test]
55+
public void DecimalNegationCarryFullPropagation()
56+
{
57+
var buffer = new BufferV3(128, 128, 128);
58+
59+
// Test carry propagation through all parts (low -> mid -> high)
60+
// Create a decimal where low=0, mid=0, high=1
61+
// This is 2^64 = 18446744073709551616
62+
// After negation: low = ~0 + 1 = 0 (carry), mid = ~0 + 1 = 0 (carry), high = ~1 + 1 = 0xFFFFFFFE + 1 = 0xFFFFFFFF
63+
var decimalValue = -18446744073709551616m; // -2^64
64+
65+
buffer.Table("negation_test")
66+
.Symbol("tag", "carry_full")
67+
.Column("dec_full_carry", decimalValue)
68+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
69+
70+
// -18446744073709551616 has bits: low=0, mid=0, high=1
71+
// Two's complement propagates carry through all parts
72+
// Result: high=0xFFFFFFFF, mid=0, low=0
73+
// In big-endian with sign byte: 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
74+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_full_carry", 0, new byte[]
75+
{
76+
0xFF,
77+
0x00, 0x00, 0x00, 0x00,
78+
0x00, 0x00, 0x00, 0x00,
79+
});
80+
}
81+
82+
[Test]
83+
public void DecimalNegationZeroEdgeCase()
84+
{
85+
var buffer = new BufferV3(128, 128, 128);
86+
87+
// Test that -0.0m is treated as positive zero (line 92 in BufferV3.cs)
88+
// The code checks: var negative = (flags & SignMask) != 0 && value.Value != 0m;
89+
// This ensures that -0.0m doesn't get negated
90+
buffer.Table("negation_test")
91+
.Symbol("tag", "zero")
92+
.Column("dec_zero", 0.0m)
93+
.Column("dec_neg_zero", -0.0m)
94+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
95+
96+
// Both 0.0m and -0.0m should be encoded as positive zero: 0x00
97+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_zero", 1, new byte[]
98+
{
99+
0x00,
100+
});
101+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_neg_zero", 1, new byte[]
102+
{
103+
0x00,
104+
});
105+
}
106+
107+
[Test]
108+
public void DecimalNegationSmallestValue()
109+
{
110+
var buffer = new BufferV3(128, 128, 128);
111+
112+
// Test negation of the smallest representable positive value: 0.0000000000000000000000000001m
113+
// This has low=1, mid=0, high=0, scale=28
114+
// After negation: low = ~1 + 1 = 0xFFFFFFFE + 1 = 0xFFFFFFFF
115+
var decimalValue = -0.0000000000000000000000000001m;
116+
117+
buffer.Table("negation_test")
118+
.Symbol("tag", "smallest")
119+
.Column("dec_smallest", decimalValue)
120+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
121+
122+
// Result should be: 0xFF (single byte, compressed)
123+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_smallest", 28, new byte[]
124+
{
125+
0xFF,
126+
});
127+
}
128+
129+
[Test]
130+
public void DecimalNegationWithHighScale()
131+
{
132+
var buffer = new BufferV3(128, 128, 128);
133+
134+
// Test negation with high scale value
135+
// -0.00000001m has scale=8
136+
var decimalValue = -0.00000001m; // -10^-8
137+
138+
buffer.Table("negation_test")
139+
.Symbol("tag", "high_scale")
140+
.Column("dec_high_scale", decimalValue)
141+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
142+
143+
// -1 with scale 8 = 0xFF in two's complement
144+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_high_scale", 8, new byte[]
145+
{
146+
0xFF,
147+
});
148+
}
149+
150+
[Test]
151+
public void DecimalNegationBoundaryCarry()
152+
{
153+
var buffer = new BufferV3(128, 128, 128);
154+
155+
// Test a value where low=0xFFFFFFFF (all ones), which after negation becomes 1
156+
// This is the value 4294967295 (2^32 - 1)
157+
// After negation: low = ~0xFFFFFFFF + 1 = 0x00000000 + 1 = 0x00000001
158+
// So -4294967295 should give us: 0xFF, 0xFF, 0xFF, 0xFF, 0x01
159+
var decimalValue = -4294967295m;
160+
161+
buffer.Table("negation_test")
162+
.Symbol("tag", "boundary")
163+
.Column("dec_boundary", decimalValue)
164+
.At(new DateTime(1970, 01, 01, 0, 0, 1));
165+
166+
// Two's complement of 4294967295: negates to 0xFFFFFFFF00000001 (represented in big-endian)
167+
DecimalTestHelpers.AssertDecimalField(buffer.GetSendBuffer(), "dec_boundary", 0, new byte[]
168+
{
169+
0xFF,
170+
0xFF, 0xFF, 0xFF, 0x01,
171+
});
172+
}
173+
174+
}

0 commit comments

Comments
 (0)