Skip to content

Commit 1b70acd

Browse files
committed
FINERACT-2421: Add unit tests for SQLBuilder
1 parent e294ce8 commit 1b70acd

File tree

1 file changed

+245
-0
lines changed
  • fineract-core/src/test/java/org/apache/fineract/infrastructure/security/utils

1 file changed

+245
-0
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.security.utils;
20+
21+
import org.apache.fineract.infrastructure.security.utils.SQLBuilder.WhereLogicalOperator;
22+
import org.junit.jupiter.api.Assertions;
23+
import org.junit.jupiter.api.Test;
24+
25+
/**
26+
* Unit tests for {@link SQLBuilder}.
27+
* <p>
28+
* Tests the SQL WHERE clause builder utility that prevents SQL injection
29+
* by validating column names, operators, and using parameterized queries.
30+
* </p>
31+
*/
32+
class SQLBuilderTest {
33+
34+
@Test
35+
void testAddCriteriaWithValidEquals() {
36+
// given
37+
SQLBuilder builder = new SQLBuilder();
38+
// when
39+
builder.addCriteria("name =", "John");
40+
// then
41+
Assertions.assertEquals(" WHERE name = ?", builder.getSQLTemplate());
42+
Assertions.assertArrayEquals(new Object[] { "John" }, builder.getArguments());
43+
}
44+
45+
@Test
46+
void testAddCriteriaWithValidOperators() {
47+
// given
48+
SQLBuilder equalsBuilder = new SQLBuilder();
49+
SQLBuilder lessThanBuilder = new SQLBuilder();
50+
SQLBuilder greaterThanBuilder = new SQLBuilder();
51+
SQLBuilder lessEqualBuilder = new SQLBuilder();
52+
SQLBuilder greaterEqualBuilder = new SQLBuilder();
53+
SQLBuilder notEqualBuilder = new SQLBuilder();
54+
SQLBuilder likeBuilder = new SQLBuilder();
55+
// when
56+
equalsBuilder.addCriteria("age =", 25);
57+
lessThanBuilder.addCriteria("age <", 30);
58+
greaterThanBuilder.addCriteria("age >", 20);
59+
lessEqualBuilder.addCriteria("age <=", 30);
60+
greaterEqualBuilder.addCriteria("age >=", 20);
61+
notEqualBuilder.addCriteria("status <>", "inactive");
62+
likeBuilder.addCriteria("name LIKE", "%John%");
63+
// then
64+
Assertions.assertTrue(equalsBuilder.getSQLTemplate().contains("age = ?"));
65+
Assertions.assertTrue(lessThanBuilder.getSQLTemplate().contains("age < ?"));
66+
Assertions.assertTrue(greaterThanBuilder.getSQLTemplate().contains("age > ?"));
67+
Assertions.assertTrue(lessEqualBuilder.getSQLTemplate().contains("age <= ?"));
68+
Assertions.assertTrue(greaterEqualBuilder.getSQLTemplate().contains("age >= ?"));
69+
Assertions.assertTrue(notEqualBuilder.getSQLTemplate().contains("status <> ?"));
70+
Assertions.assertTrue(likeBuilder.getSQLTemplate().contains("name LIKE ?"));
71+
}
72+
73+
@Test
74+
void testAddCriteriaNullThrowsException() {
75+
// given
76+
SQLBuilder builder = new SQLBuilder();
77+
// when / then
78+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria(null, "value"));
79+
}
80+
81+
@Test
82+
void testAddCriteriaEmptyThrowsException() {
83+
// given
84+
SQLBuilder builder = new SQLBuilder();
85+
// when / then
86+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("", "value"));
87+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria(" ", "value"));
88+
}
89+
90+
@Test
91+
void testAddCriteriaWithQuestionMarkThrowsException() {
92+
// given
93+
SQLBuilder builder = new SQLBuilder();
94+
// when / then
95+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("name = ?", "value"));
96+
}
97+
98+
@Test
99+
void testAddCriteriaMissingOperatorThrowsException() {
100+
// given
101+
SQLBuilder builder = new SQLBuilder();
102+
// when / then
103+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("name", "value"));
104+
}
105+
106+
@Test
107+
void testAddCriteriaInvalidColumnNameThrowsException() {
108+
// given
109+
SQLBuilder builder = new SQLBuilder();
110+
// when / then
111+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("123name =", "value"));
112+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("na$me =", "value"));
113+
}
114+
115+
@Test
116+
void testAddCriteriaInvalidOperatorThrowsException() {
117+
// given
118+
SQLBuilder builder = new SQLBuilder();
119+
// when / then
120+
Assertions.assertThrows(IllegalArgumentException.class, () -> builder.addCriteria("name ++", "value"));
121+
}
122+
123+
@Test
124+
void testAddNonNullCriteriaSkipsNull() {
125+
// given
126+
SQLBuilder builder = new SQLBuilder();
127+
// when
128+
builder.addNonNullCriteria("name =", null);
129+
// then
130+
Assertions.assertEquals("", builder.getSQLTemplate());
131+
Assertions.assertArrayEquals(new Object[] {}, builder.getArguments());
132+
}
133+
134+
@Test
135+
void testAddNonNullCriteriaAddsWhenNotNull() {
136+
// given
137+
SQLBuilder builder = new SQLBuilder();
138+
// when
139+
builder.addNonNullCriteria("name =", "John");
140+
// then
141+
Assertions.assertEquals(" WHERE name = ?", builder.getSQLTemplate());
142+
Assertions.assertArrayEquals(new Object[] { "John" }, builder.getArguments());
143+
}
144+
145+
@Test
146+
void testGetSQLTemplateEmptyWhenNoCriteria() {
147+
// given
148+
SQLBuilder builder = new SQLBuilder();
149+
// when / then
150+
Assertions.assertEquals("", builder.getSQLTemplate());
151+
}
152+
153+
@Test
154+
void testGetArgumentsReturnsCorrectOrder() {
155+
// given
156+
SQLBuilder builder = new SQLBuilder();
157+
// when
158+
builder.addCriteria("name =", "John");
159+
builder.addCriteria("age =", 25);
160+
builder.addCriteria("status =", "active");
161+
// then
162+
Object[] args = builder.getArguments();
163+
Assertions.assertEquals(3, args.length);
164+
Assertions.assertEquals("John", args[0]);
165+
Assertions.assertEquals(25, args[1]);
166+
Assertions.assertEquals("active", args[2]);
167+
}
168+
169+
@Test
170+
void testWhereLogicalOperatorAnd() {
171+
// given
172+
SQLBuilder builder = new SQLBuilder();
173+
// when
174+
builder.addCriteria("name =", "John", WhereLogicalOperator.AND);
175+
builder.addCriteria("age =", 25, WhereLogicalOperator.AND);
176+
// then
177+
String sql = builder.getSQLTemplate();
178+
Assertions.assertTrue(sql.contains(" AND "));
179+
Assertions.assertTrue(sql.contains("name = ?"));
180+
Assertions.assertTrue(sql.contains("age = ?"));
181+
}
182+
183+
@Test
184+
void testWhereLogicalOperatorOr() {
185+
// given
186+
SQLBuilder builder = new SQLBuilder();
187+
// when
188+
builder.addCriteria("name =", "John", WhereLogicalOperator.AND);
189+
builder.addCriteria("name =", "Jane", WhereLogicalOperator.OR);
190+
// then
191+
String sql = builder.getSQLTemplate();
192+
Assertions.assertTrue(sql.contains(" OR "));
193+
}
194+
195+
@Test
196+
void testToStringFormat() {
197+
// given
198+
SQLBuilder builder = new SQLBuilder();
199+
builder.addCriteria("name =", "John");
200+
builder.addCriteria("age =", 25);
201+
// when
202+
String result = builder.toString();
203+
// then
204+
Assertions.assertTrue(result.startsWith("SQLBuilder{"));
205+
Assertions.assertTrue(result.endsWith("}"));
206+
Assertions.assertTrue(result.contains("name ="));
207+
Assertions.assertTrue(result.contains("'John'"));
208+
Assertions.assertTrue(result.contains("age ="));
209+
Assertions.assertTrue(result.contains("25"));
210+
}
211+
212+
@Test
213+
void testToStringWithNullArgument() {
214+
// given
215+
SQLBuilder builder = new SQLBuilder();
216+
builder.addCriteria("status is", null);
217+
// when
218+
String result = builder.toString();
219+
// then
220+
Assertions.assertTrue(result.contains("null"));
221+
}
222+
223+
@Test
224+
void testColumnNameWithTablePrefix() {
225+
// given
226+
SQLBuilder builder = new SQLBuilder();
227+
// when
228+
builder.addCriteria("t.name =", "John");
229+
// then
230+
Assertions.assertEquals(" WHERE t.name = ?", builder.getSQLTemplate());
231+
}
232+
233+
@Test
234+
void testColumnNameWithUnderscoreAndDash() {
235+
// given
236+
SQLBuilder builder = new SQLBuilder();
237+
// when
238+
builder.addCriteria("first_name =", "John");
239+
builder.addCriteria("last-name =", "Doe");
240+
// then
241+
String sql = builder.getSQLTemplate();
242+
Assertions.assertTrue(sql.contains("first_name = ?"));
243+
Assertions.assertTrue(sql.contains("last-name = ?"));
244+
}
245+
}

0 commit comments

Comments
 (0)