Skip to content

Commit 67692a1

Browse files
test: expand test coverage for error handling and edge cases
Add comprehensive unit tests for Configuration attributes (HypertableAttribute, Dimension, ReorderPolicyAttribute) with validation and edge case coverage. Enhance existing tests with error handling scenarios: - HypertableConvention: null entity types, whitespace time columns - ContinuousAggregateOperationGenerator: invalid parameters, edge cases - HypertableScaffoldingExtractor: connection state handling, malformed data Fix coverlet.runsettings by removing stray 'S' character that was causing XML parsing issues. Update README.md with explicit test coverage output directories for clarity.
1 parent 42463a8 commit 67692a1

8 files changed

Lines changed: 1734 additions & 5 deletions

File tree

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
using CmdScale.EntityFrameworkCore.TimescaleDB.Abstractions;
2+
3+
namespace CmdScale.EntityFrameworkCore.TimescaleDB.Tests.Configuration;
4+
5+
/// <summary>
6+
/// Tests that verify Dimension factory methods and validation.
7+
/// </summary>
8+
public class DimensionTests
9+
{
10+
#region CreateHash Validation Tests
11+
12+
[Fact]
13+
public void CreateHash_With_Null_ColumnName_ThrowsArgumentException()
14+
{
15+
// Arrange & Act & Assert
16+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash(null!, 4));
17+
Assert.Contains("Dimension column name must be provided", ex.Message);
18+
Assert.Equal("columnName", ex.ParamName);
19+
}
20+
21+
[Fact]
22+
public void CreateHash_With_Empty_ColumnName_ThrowsArgumentException()
23+
{
24+
// Arrange & Act & Assert
25+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash("", 4));
26+
Assert.Contains("Dimension column name must be provided", ex.Message);
27+
Assert.Equal("columnName", ex.ParamName);
28+
}
29+
30+
[Fact]
31+
public void CreateHash_With_Whitespace_ColumnName_ThrowsArgumentException()
32+
{
33+
// Arrange & Act & Assert
34+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash(" ", 4));
35+
Assert.Contains("Dimension column name must be provided", ex.Message);
36+
Assert.Equal("columnName", ex.ParamName);
37+
}
38+
39+
[Fact]
40+
public void CreateHash_With_Zero_Partitions_ThrowsArgumentException()
41+
{
42+
// Arrange & Act & Assert
43+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash("DeviceId", 0));
44+
Assert.Contains("Number of partitions must be greater than zero", ex.Message);
45+
Assert.Equal("numberOfPartitions", ex.ParamName);
46+
}
47+
48+
[Fact]
49+
public void CreateHash_With_Negative_Partitions_ThrowsArgumentException()
50+
{
51+
// Arrange & Act & Assert
52+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash("DeviceId", -5));
53+
Assert.Contains("Number of partitions must be greater than zero", ex.Message);
54+
Assert.Equal("numberOfPartitions", ex.ParamName);
55+
}
56+
57+
[Fact]
58+
public void CreateHash_With_NegativeOne_Partitions_ThrowsArgumentException()
59+
{
60+
// Arrange & Act & Assert
61+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash("DeviceId", -1));
62+
Assert.Contains("Number of partitions must be greater than zero", ex.Message);
63+
}
64+
65+
[Fact]
66+
public void CreateHash_With_Tabs_ColumnName_ThrowsArgumentException()
67+
{
68+
// Arrange & Act & Assert
69+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateHash("\t\t", 4));
70+
Assert.Contains("Dimension column name must be provided", ex.Message);
71+
}
72+
73+
#endregion
74+
75+
#region CreateHash Valid Tests
76+
77+
[Fact]
78+
public void CreateHash_With_Valid_Parameters_CreatesHashDimension()
79+
{
80+
// Arrange & Act
81+
Dimension dimension = Dimension.CreateHash("DeviceId", 4);
82+
83+
// Assert
84+
Assert.Equal("DeviceId", dimension.ColumnName);
85+
Assert.Equal(EDimensionType.Hash, dimension.Type);
86+
Assert.Equal(4, dimension.NumberOfPartitions);
87+
Assert.Null(dimension.Interval);
88+
}
89+
90+
[Fact]
91+
public void CreateHash_With_Single_Partition_CreatesCorrectly()
92+
{
93+
// Arrange & Act
94+
Dimension dimension = Dimension.CreateHash("Id", 1);
95+
96+
// Assert
97+
Assert.Equal(1, dimension.NumberOfPartitions);
98+
Assert.Equal(EDimensionType.Hash, dimension.Type);
99+
}
100+
101+
[Fact]
102+
public void CreateHash_With_Large_Partition_Count_CreatesCorrectly()
103+
{
104+
// Arrange & Act
105+
Dimension dimension = Dimension.CreateHash("TenantId", 256);
106+
107+
// Assert
108+
Assert.Equal(256, dimension.NumberOfPartitions);
109+
Assert.Equal(EDimensionType.Hash, dimension.Type);
110+
}
111+
112+
[Fact]
113+
public void CreateHash_With_Underscore_ColumnName_AcceptsIt()
114+
{
115+
// Arrange & Act
116+
Dimension dimension = Dimension.CreateHash("device_id", 8);
117+
118+
// Assert
119+
Assert.Equal("device_id", dimension.ColumnName);
120+
}
121+
122+
#endregion
123+
124+
#region CreateRange Validation Tests
125+
126+
[Fact]
127+
public void CreateRange_With_Null_ColumnName_ThrowsArgumentException()
128+
{
129+
// Arrange & Act & Assert
130+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange(null!, "1 day"));
131+
Assert.Contains("Dimension column name must be provided", ex.Message);
132+
Assert.Equal("columnName", ex.ParamName);
133+
}
134+
135+
[Fact]
136+
public void CreateRange_With_Empty_ColumnName_ThrowsArgumentException()
137+
{
138+
// Arrange & Act & Assert
139+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("", "1 day"));
140+
Assert.Contains("Dimension column name must be provided", ex.Message);
141+
Assert.Equal("columnName", ex.ParamName);
142+
}
143+
144+
[Fact]
145+
public void CreateRange_With_Whitespace_ColumnName_ThrowsArgumentException()
146+
{
147+
// Arrange & Act & Assert
148+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange(" ", "1 day"));
149+
Assert.Contains("Dimension column name must be provided", ex.Message);
150+
Assert.Equal("columnName", ex.ParamName);
151+
}
152+
153+
[Fact]
154+
public void CreateRange_With_Null_Interval_ThrowsArgumentException()
155+
{
156+
// Arrange & Act & Assert
157+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("SensorId", null!));
158+
Assert.Contains("Interval must be provided for a range dimension", ex.Message);
159+
Assert.Equal("interval", ex.ParamName);
160+
}
161+
162+
[Fact]
163+
public void CreateRange_With_Empty_Interval_ThrowsArgumentException()
164+
{
165+
// Arrange & Act & Assert
166+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("SensorId", ""));
167+
Assert.Contains("Interval must be provided for a range dimension", ex.Message);
168+
Assert.Equal("interval", ex.ParamName);
169+
}
170+
171+
[Fact]
172+
public void CreateRange_With_Whitespace_Interval_ThrowsArgumentException()
173+
{
174+
// Arrange & Act & Assert
175+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("SensorId", " "));
176+
Assert.Contains("Interval must be provided for a range dimension", ex.Message);
177+
Assert.Equal("interval", ex.ParamName);
178+
}
179+
180+
[Fact]
181+
public void CreateRange_With_Tabs_Interval_ThrowsArgumentException()
182+
{
183+
// Arrange & Act & Assert
184+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("SensorId", "\t\t"));
185+
Assert.Contains("Interval must be provided for a range dimension", ex.Message);
186+
}
187+
188+
[Fact]
189+
public void CreateRange_With_Newlines_Interval_ThrowsArgumentException()
190+
{
191+
// Arrange & Act & Assert
192+
ArgumentException ex = Assert.Throws<ArgumentException>(() => Dimension.CreateRange("SensorId", "\n\n"));
193+
Assert.Contains("Interval must be provided for a range dimension", ex.Message);
194+
}
195+
196+
#endregion
197+
198+
#region CreateRange Valid Tests
199+
200+
[Fact]
201+
public void CreateRange_With_Valid_Parameters_CreatesRangeDimension()
202+
{
203+
// Arrange & Act
204+
Dimension dimension = Dimension.CreateRange("SensorId", "1000");
205+
206+
// Assert
207+
Assert.Equal("SensorId", dimension.ColumnName);
208+
Assert.Equal(EDimensionType.Range, dimension.Type);
209+
Assert.Equal("1000", dimension.Interval);
210+
Assert.Null(dimension.NumberOfPartitions);
211+
}
212+
213+
[Fact]
214+
public void CreateRange_With_TimeInterval_CreatesCorrectly()
215+
{
216+
// Arrange & Act
217+
Dimension dimension = Dimension.CreateRange("Timestamp", "1 day");
218+
219+
// Assert
220+
Assert.Equal("1 day", dimension.Interval);
221+
Assert.Equal(EDimensionType.Range, dimension.Type);
222+
}
223+
224+
[Fact]
225+
public void CreateRange_With_HourInterval_CreatesCorrectly()
226+
{
227+
// Arrange & Act
228+
Dimension dimension = Dimension.CreateRange("EventTime", "6 hours");
229+
230+
// Assert
231+
Assert.Equal("6 hours", dimension.Interval);
232+
}
233+
234+
[Fact]
235+
public void CreateRange_With_NumericInterval_CreatesCorrectly()
236+
{
237+
// Arrange & Act
238+
Dimension dimension = Dimension.CreateRange("SequenceId", "10000");
239+
240+
// Assert
241+
Assert.Equal("10000", dimension.Interval);
242+
}
243+
244+
#endregion
245+
246+
#region Parameterless Constructor Tests
247+
248+
[Fact]
249+
public void ParameterlessConstructor_InitializesDefaultsCorrectly()
250+
{
251+
// Arrange & Act
252+
Dimension dimension = new();
253+
254+
// Assert
255+
Assert.Equal(string.Empty, dimension.ColumnName);
256+
Assert.Equal(EDimensionType.Range, dimension.Type);
257+
Assert.Null(dimension.NumberOfPartitions);
258+
Assert.Null(dimension.Interval);
259+
}
260+
261+
[Fact]
262+
public void ParameterlessConstructor_AllowsPropertyMutation()
263+
{
264+
// Arrange
265+
Dimension dimension = new()
266+
{
267+
// Act
268+
ColumnName = "TestColumn",
269+
Type = EDimensionType.Hash,
270+
NumberOfPartitions = 16,
271+
Interval = "1 week"
272+
};
273+
274+
// Assert
275+
Assert.Equal("TestColumn", dimension.ColumnName);
276+
Assert.Equal(EDimensionType.Hash, dimension.Type);
277+
Assert.Equal(16, dimension.NumberOfPartitions);
278+
Assert.Equal("1 week", dimension.Interval);
279+
}
280+
281+
#endregion
282+
}

0 commit comments

Comments
 (0)