Kinetica   C#   API  Version 7.2.3.1
RecordKeyDecimalTests.cs
Go to the documentation of this file.
1 using System;
2 using System.Reflection;
3 using Xunit;
4 
6 {
27  [Trait("Category", "WireFormat")]
28  [Trait("Category", "RecordKey")]
29  public class RecordKeyDecimalTests
30  {
31  // Get the RecordKey type via reflection since it's internal
32  private static readonly Type RecordKeyType = typeof(kinetica.Kinetica).Assembly
33  .GetType("kinetica.Utils.RecordKey");
34 
38  private object CreateRecordKey(int bufferSize)
39  {
40  return Activator.CreateInstance(RecordKeyType, bufferSize)!;
41  }
42 
46  private void InvokeAddDecimal(object key, string value, int precision, int scale)
47  {
48  var method = RecordKeyType.GetMethod("addDecimal", new[] { typeof(string), typeof(int), typeof(int) });
49  method!.Invoke(key, new object[] { value, precision, scale });
50  }
51 
55  private byte[] GetBuffer(object key)
56  {
57  var field = RecordKeyType.GetField("buffer", BindingFlags.NonPublic | BindingFlags.Instance);
58  return (byte[])field!.GetValue(key)!;
59  }
60 
64  private int GetCurrentSize(object key)
65  {
66  var field = RecordKeyType.GetField("current_size", BindingFlags.NonPublic | BindingFlags.Instance);
67  return (int)field!.GetValue(key)!;
68  }
69 
79  [Fact]
81  {
82  // Arrange: 8-byte decimal with precision 18, scale 4
83  var key = CreateRecordKey(8);
84 
85  // Act: Add decimal value "123.45"
86  InvokeAddDecimal(key, "123.45", 18, 4);
87 
88  // Assert: Buffer should be 8 bytes with scaled value
89  var buffer = GetBuffer(key);
90  Assert.Equal(8, GetCurrentSize(key));
91 
92  // 123.45 with scale 4 = 1234500 (as long in little-endian)
93  long expected = 1234500L;
94  long actual = BitConverter.ToInt64(buffer, 0);
95  Assert.Equal(expected, actual);
96  }
97 
107  [Fact]
109  {
110  // Arrange: 8-byte decimal with precision 18, scale 4
111  var key = CreateRecordKey(8);
112 
113  // Act: Add negative decimal value "-987.6543"
114  InvokeAddDecimal(key, "-987.6543", 18, 4);
115 
116  // Assert: Buffer should contain correct negative scaled value
117  var buffer = GetBuffer(key);
118  Assert.Equal(8, GetCurrentSize(key));
119 
120  // -987.6543 with scale 4 = -9876543 (as long)
121  long expected = -9876543L;
122  long actual = BitConverter.ToInt64(buffer, 0);
123  Assert.Equal(expected, actual);
124  }
125 
126  [Fact]
128  {
129  // Arrange
130  var key = CreateRecordKey(8);
131 
132  // Act: Add null value
133  InvokeAddDecimal(key, null!, 18, 4);
134 
135  // Assert: All bytes should be zero
136  var buffer = GetBuffer(key);
137  Assert.Equal(8, GetCurrentSize(key));
138  Assert.Equal(0L, BitConverter.ToInt64(buffer, 0));
139  }
140 
141  [Fact]
143  {
144  // Arrange: 12-byte decimal with precision 38, scale 10
145  var key = CreateRecordKey(12);
146 
147  // Act: Add decimal value "12345.678901"
148  InvokeAddDecimal(key, "12345.678901", 38, 10);
149 
150  // Assert: Buffer should be 12 bytes
151  var buffer = GetBuffer(key);
152  Assert.Equal(12, GetCurrentSize(key));
153 
154  // Value should be non-zero (actual encoding depends on BigInteger)
155  bool hasNonZero = false;
156  for (int i = 0; i < 12; i++)
157  {
158  if (buffer[i] != 0)
159  {
160  hasNonZero = true;
161  break;
162  }
163  }
164  Assert.True(hasNonZero, "12-byte decimal should have non-zero content");
165  }
166 
167  [Fact]
169  {
170  // Arrange
171  var key = CreateRecordKey(12);
172 
173  // Act: Add null/empty value
174  InvokeAddDecimal(key, "", 38, 10);
175 
176  // Assert: All 12 bytes should be zero
177  var buffer = GetBuffer(key);
178  Assert.Equal(12, GetCurrentSize(key));
179 
180  for (int i = 0; i < 12; i++)
181  {
182  Assert.Equal(0, buffer[i]);
183  }
184  }
185 
186  [Fact]
188  {
189  // Arrange: 12-byte decimal with precision 38
190  var key = CreateRecordKey(12);
191 
192  // Act: Add a large value that needs more than 8 bytes
193  InvokeAddDecimal(key, "9999999999999999999.9999999999", 38, 10);
194 
195  // Assert: Buffer should be 12 bytes
196  var buffer = GetBuffer(key);
197  Assert.Equal(12, GetCurrentSize(key));
198 
199  // The value should use multiple bytes due to its magnitude
200  bool hasHighBytes = buffer[8] != 0 || buffer[9] != 0 || buffer[10] != 0 || buffer[11] != 0;
201  // For large numbers, we expect some high bytes to be set
202  // This is a weak test, but verifies the 12-byte path is being used
203  }
204 
205  [Fact]
207  {
208  // Arrange: 12-byte decimal with precision > 18
209  var key = CreateRecordKey(12);
210 
211  // Act: Add negative value
212  InvokeAddDecimal(key, "-12345.678901", 38, 10);
213 
214  // Assert: Buffer should be 12 bytes
215  var buffer = GetBuffer(key);
216  Assert.Equal(12, GetCurrentSize(key));
217 
218  // For negative numbers, high bytes should be 0xFF (sign extension)
219  // Check that we have sign extension in the upper bytes
220  bool hasSignExtension = buffer[11] == 0xFF;
221  Assert.True(hasSignExtension, "Negative 12-byte decimal should have sign extension");
222  }
223 
233  [Fact]
235  {
236  // Arrange: Exactly at the boundary (precision = 18)
237  var key = CreateRecordKey(8);
238 
239  // Act
240  InvokeAddDecimal(key, "12345.6789", 18, 4);
241 
242  // Assert: Should successfully store in 8 bytes
243  Assert.Equal(8, GetCurrentSize(key));
244  }
245 
255  [Fact]
257  {
258  // Arrange: Just over the boundary (precision = 19)
259  var key = CreateRecordKey(12);
260 
261  // Act
262  InvokeAddDecimal(key, "12345.6789", 19, 4);
263 
264  // Assert: Should use 12 bytes
265  Assert.Equal(12, GetCurrentSize(key));
266  }
267  }
268 }
void AddDecimal_PrecisionBoundary_At18_Uses8Bytes()
WIRE FORMAT TEST: Verifies precision boundary - precision 18 uses 8-byte encoding.
void AddDecimal_PrecisionBoundary_At19_Uses12Bytes()
WIRE FORMAT TEST: Verifies precision boundary - precision 19 uses 12-byte encoding.
Wire-format pinning tests for RecordKey decimal encoding.
void AddDecimal_8Byte_WithNegativeValue_StoresCorrectly()
WIRE FORMAT TEST: Verifies 8-byte decimal encoding for negative values.
Immutable collection of metadata about a Kinetica type.
Definition: Type.cs:36
void AddDecimal_8Byte_WithSimpleValue_StoresCorrectly()
WIRE FORMAT TEST: Verifies 8-byte decimal encoding for positive values.
API to talk to Kinetica Database
Definition: Kinetica.cs:40