Skip to content

Commit fc1ceb2

Browse files
Flossyclaude
andcommitted
fix: Reject zero values in ResourceQuota.Builder (#168)
Changed validation to require positive values (> 0) instead of non-negative (>= 0) for resource limits, preventing impossible-to-satisfy quotas. Changes: - maxHeapBytes() now requires bytes > 0 - maxThreadCount() now requires count > 0 - maxCpuTimeNanos() now requires nanos > 0 - Updated all error messages from ">= 0" to "> 0" - Updated tests to verify zero values are rejected - Total 13 tests passing This ensures: - Resource quotas represent realistic, enforceable limits - Any application can potentially satisfy the quota - Clear error messages at build time for impossible quotas Fixes #168: ResourceQuota.Builder allows 0 for resource limits - creates impossible quotas Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 9b795da commit fc1ceb2

2 files changed

Lines changed: 38 additions & 24 deletions

File tree

jplatform-api/src/main/java/org/flossware/jplatform/api/ResourceQuota.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ public static class Builder {
120120
/**
121121
* Sets the maximum heap memory allowed.
122122
*
123-
* @param bytes the maximum heap size in bytes
123+
* @param bytes the maximum heap size in bytes (must be positive)
124124
* @return this builder
125-
* @throws IllegalArgumentException if bytes is negative
125+
* @throws IllegalArgumentException if bytes is zero or negative
126126
*/
127127
public Builder maxHeapBytes(long bytes) {
128-
if (bytes < 0) {
129-
throw new IllegalArgumentException("maxHeapBytes must be >= 0, got: " + bytes);
128+
if (bytes <= 0) {
129+
throw new IllegalArgumentException("maxHeapBytes must be > 0, got: " + bytes);
130130
}
131131
this.maxHeapBytes = Optional.of(bytes);
132132
return this;
@@ -135,13 +135,13 @@ public Builder maxHeapBytes(long bytes) {
135135
/**
136136
* Sets the maximum number of threads allowed.
137137
*
138-
* @param count the maximum thread count
138+
* @param count the maximum thread count (must be positive)
139139
* @return this builder
140-
* @throws IllegalArgumentException if count is negative
140+
* @throws IllegalArgumentException if count is zero or negative
141141
*/
142142
public Builder maxThreadCount(int count) {
143-
if (count < 0) {
144-
throw new IllegalArgumentException("maxThreadCount must be >= 0, got: " + count);
143+
if (count <= 0) {
144+
throw new IllegalArgumentException("maxThreadCount must be > 0, got: " + count);
145145
}
146146
this.maxThreadCount = Optional.of(count);
147147
return this;
@@ -150,13 +150,13 @@ public Builder maxThreadCount(int count) {
150150
/**
151151
* Sets the maximum CPU time allowed.
152152
*
153-
* @param nanos the maximum CPU time in nanoseconds
153+
* @param nanos the maximum CPU time in nanoseconds (must be positive)
154154
* @return this builder
155-
* @throws IllegalArgumentException if nanos is negative
155+
* @throws IllegalArgumentException if nanos is zero or negative
156156
*/
157157
public Builder maxCpuTimeNanos(long nanos) {
158-
if (nanos < 0) {
159-
throw new IllegalArgumentException("maxCpuTimeNanos must be >= 0, got: " + nanos);
158+
if (nanos <= 0) {
159+
throw new IllegalArgumentException("maxCpuTimeNanos must be > 0, got: " + nanos);
160160
}
161161
this.maxCpuTimeNanos = Optional.of(nanos);
162162
return this;

jplatform-api/src/test/java/org/flossware/jplatform/api/ResourceQuotaTest.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,30 @@ void testBuilderAcceptsValidValues() {
2929
}
3030

3131
@Test
32-
void testBuilderAcceptsZeroValues() {
33-
ResourceQuota quota = ResourceQuota.builder()
34-
.maxHeapBytes(0)
35-
.maxThreadCount(0)
36-
.maxCpuTimeNanos(0)
37-
.build();
32+
void testBuilderRejectsZeroHeapBytes() {
33+
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
34+
ResourceQuota.builder().maxHeapBytes(0);
35+
});
36+
37+
assertTrue(exception.getMessage().contains("maxHeapBytes must be > 0"));
38+
}
39+
40+
@Test
41+
void testBuilderRejectsZeroThreadCount() {
42+
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
43+
ResourceQuota.builder().maxThreadCount(0);
44+
});
45+
46+
assertTrue(exception.getMessage().contains("maxThreadCount must be > 0"));
47+
}
48+
49+
@Test
50+
void testBuilderRejectsZeroCpuTimeNanos() {
51+
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
52+
ResourceQuota.builder().maxCpuTimeNanos(0);
53+
});
3854

39-
assertEquals(0L, quota.getMaxHeapBytes().get());
40-
assertEquals(0, quota.getMaxThreadCount().get());
41-
assertEquals(0L, quota.getMaxCpuTimeNanos().get());
55+
assertTrue(exception.getMessage().contains("maxCpuTimeNanos must be > 0"));
4256
}
4357

4458
@Test
@@ -47,7 +61,7 @@ void testBuilderRejectsNegativeHeapBytes() {
4761
ResourceQuota.builder().maxHeapBytes(-512);
4862
});
4963

50-
assertEquals("maxHeapBytes must be >= 0, got: -512", exception.getMessage());
64+
assertEquals("maxHeapBytes must be > 0, got: -512", exception.getMessage());
5165
}
5266

5367
@Test
@@ -56,7 +70,7 @@ void testBuilderRejectsNegativeThreadCount() {
5670
ResourceQuota.builder().maxThreadCount(-10);
5771
});
5872

59-
assertEquals("maxThreadCount must be >= 0, got: -10", exception.getMessage());
73+
assertEquals("maxThreadCount must be > 0, got: -10", exception.getMessage());
6074
}
6175

6276
@Test
@@ -65,7 +79,7 @@ void testBuilderRejectsNegativeCpuTimeNanos() {
6579
ResourceQuota.builder().maxCpuTimeNanos(-1000);
6680
});
6781

68-
assertEquals("maxCpuTimeNanos must be >= 0, got: -1000", exception.getMessage());
82+
assertEquals("maxCpuTimeNanos must be > 0, got: -1000", exception.getMessage());
6983
}
7084

7185
@Test

0 commit comments

Comments
 (0)