Skip to content

Commit 7da671f

Browse files
committed
Add test cases.
Relates to #60
1 parent 7ea192f commit 7da671f

33 files changed

Lines changed: 7412 additions & 3 deletions

File tree

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
package st.orm.core;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
8+
import java.sql.Connection;
9+
import java.sql.SQLException;
10+
import java.util.List;
11+
import javax.sql.DataSource;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.ExtendWith;
14+
import org.springframework.beans.factory.annotation.Autowired;
15+
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
16+
import org.springframework.test.context.ContextConfiguration;
17+
import org.springframework.test.context.junit.jupiter.SpringExtension;
18+
import st.orm.core.template.SqlDialect.ConstraintDiscoveryStrategy;
19+
import st.orm.core.template.SqlDialect.SequenceDiscoveryStrategy;
20+
import st.orm.core.template.impl.DatabaseSchema;
21+
import st.orm.core.template.impl.DatabaseSchema.DbColumn;
22+
import st.orm.core.template.impl.DatabaseSchema.DbForeignKey;
23+
import st.orm.core.template.impl.DatabaseSchema.DbPrimaryKey;
24+
import st.orm.core.template.impl.DatabaseSchema.DbUniqueKey;
25+
26+
/**
27+
* Integration tests for {@link DatabaseSchema} using the actual test schema loaded by Spring
28+
* (the same schema used by all integration tests). This tests schema introspection against
29+
* the real pet clinic schema with multiple tables, foreign keys, and views.
30+
*/
31+
@SuppressWarnings("ALL")
32+
@ExtendWith(SpringExtension.class)
33+
@ContextConfiguration(classes = IntegrationConfig.class)
34+
@DataJpaTest(showSql = false)
35+
public class DatabaseSchemaIntegrationTest {
36+
37+
@Autowired
38+
private DataSource dataSource;
39+
40+
// ---- Table existence ----
41+
42+
@Test
43+
public void testCoreTablesExist() throws SQLException {
44+
try (Connection connection = dataSource.getConnection()) {
45+
DatabaseSchema schema = DatabaseSchema.read(connection);
46+
assertTrue(schema.tableExists("city"));
47+
assertTrue(schema.tableExists("owner"));
48+
assertTrue(schema.tableExists("pet"));
49+
assertTrue(schema.tableExists("pet_type"));
50+
assertTrue(schema.tableExists("specialty"));
51+
assertTrue(schema.tableExists("vet"));
52+
assertTrue(schema.tableExists("vet_specialty"));
53+
assertTrue(schema.tableExists("visit"));
54+
assertTrue(schema.tableExists("pet_extension"));
55+
}
56+
}
57+
58+
@Test
59+
public void testCaseInsensitiveTableLookup() throws SQLException {
60+
try (Connection connection = dataSource.getConnection()) {
61+
DatabaseSchema schema = DatabaseSchema.read(connection);
62+
assertTrue(schema.tableExists("CITY"));
63+
assertTrue(schema.tableExists("City"));
64+
assertTrue(schema.tableExists("city"));
65+
}
66+
}
67+
68+
@Test
69+
public void testNonExistentTableNotFound() throws SQLException {
70+
try (Connection connection = dataSource.getConnection()) {
71+
DatabaseSchema schema = DatabaseSchema.read(connection);
72+
assertFalse(schema.tableExists("nonexistent_table"));
73+
}
74+
}
75+
76+
// ---- Views ----
77+
78+
@Test
79+
public void testViewsExist() throws SQLException {
80+
try (Connection connection = dataSource.getConnection()) {
81+
DatabaseSchema schema = DatabaseSchema.read(connection);
82+
assertTrue(schema.tableExists("owner_view"));
83+
assertTrue(schema.tableExists("visit_view"));
84+
}
85+
}
86+
87+
@Test
88+
public void testViewColumns() throws SQLException {
89+
try (Connection connection = dataSource.getConnection()) {
90+
DatabaseSchema schema = DatabaseSchema.read(connection);
91+
// visit_view: visit_date, description, pet_id, timestamp
92+
assertTrue(schema.getColumn("visit_view", "visit_date").isPresent());
93+
assertTrue(schema.getColumn("visit_view", "description").isPresent());
94+
assertTrue(schema.getColumn("visit_view", "pet_id").isPresent());
95+
}
96+
}
97+
98+
// ---- Column metadata ----
99+
100+
@Test
101+
public void testCityColumns() throws SQLException {
102+
try (Connection connection = dataSource.getConnection()) {
103+
DatabaseSchema schema = DatabaseSchema.read(connection);
104+
assertTrue(schema.getColumn("city", "id").isPresent());
105+
assertTrue(schema.getColumn("city", "name").isPresent());
106+
assertFalse(schema.getColumn("city", "nonexistent").isPresent());
107+
}
108+
}
109+
110+
@Test
111+
public void testCityIdAutoIncrement() throws SQLException {
112+
try (Connection connection = dataSource.getConnection()) {
113+
DatabaseSchema schema = DatabaseSchema.read(connection);
114+
DbColumn idColumn = schema.getColumn("city", "id").orElseThrow();
115+
assertTrue(idColumn.autoIncrement());
116+
}
117+
}
118+
119+
@Test
120+
public void testPetTypeIdNotAutoIncrement() throws SQLException {
121+
try (Connection connection = dataSource.getConnection()) {
122+
DatabaseSchema schema = DatabaseSchema.read(connection);
123+
DbColumn idColumn = schema.getColumn("pet_type", "id").orElseThrow();
124+
// pet_type(id) is not auto_increment
125+
assertFalse(idColumn.autoIncrement());
126+
}
127+
}
128+
129+
@Test
130+
public void testOwnerVersionColumnNullable() throws SQLException {
131+
try (Connection connection = dataSource.getConnection()) {
132+
DatabaseSchema schema = DatabaseSchema.read(connection);
133+
// version column has "default 0" but is nullable in schema definition
134+
DbColumn versionColumn = schema.getColumn("owner", "version").orElseThrow();
135+
assertTrue(versionColumn.nullable());
136+
}
137+
}
138+
139+
@Test
140+
public void testVetSpecialtySpecialtyIdNotNullable() throws SQLException {
141+
try (Connection connection = dataSource.getConnection()) {
142+
DatabaseSchema schema = DatabaseSchema.read(connection);
143+
DbColumn specialtyIdColumn = schema.getColumn("vet_specialty", "specialty_id").orElseThrow();
144+
assertFalse(specialtyIdColumn.nullable());
145+
}
146+
}
147+
148+
// ---- Primary keys ----
149+
150+
@Test
151+
public void testCityPrimaryKey() throws SQLException {
152+
try (Connection connection = dataSource.getConnection()) {
153+
DatabaseSchema schema = DatabaseSchema.read(connection);
154+
List<DbPrimaryKey> primaryKeys = schema.getPrimaryKeys("city");
155+
assertEquals(1, primaryKeys.size());
156+
}
157+
}
158+
159+
@Test
160+
public void testVetSpecialtyCompoundPrimaryKey() throws SQLException {
161+
try (Connection connection = dataSource.getConnection()) {
162+
DatabaseSchema schema = DatabaseSchema.read(connection);
163+
List<DbPrimaryKey> primaryKeys = schema.getPrimaryKeys("vet_specialty");
164+
assertEquals(2, primaryKeys.size());
165+
}
166+
}
167+
168+
@Test
169+
public void testPrimaryKeysForViewEmpty() throws SQLException {
170+
try (Connection connection = dataSource.getConnection()) {
171+
DatabaseSchema schema = DatabaseSchema.read(connection);
172+
List<DbPrimaryKey> primaryKeys = schema.getPrimaryKeys("owner_view");
173+
// Views don't have primary keys in metadata.
174+
assertNotNull(primaryKeys);
175+
assertTrue(primaryKeys.isEmpty());
176+
}
177+
}
178+
179+
// ---- Foreign keys ----
180+
181+
@Test
182+
public void testOwnerForeignKeyToCity() throws SQLException {
183+
try (Connection connection = dataSource.getConnection()) {
184+
DatabaseSchema schema = DatabaseSchema.read(connection);
185+
List<DbForeignKey> foreignKeys = schema.getForeignKeys("owner");
186+
assertFalse(foreignKeys.isEmpty());
187+
assertTrue(foreignKeys.stream().anyMatch(
188+
fk -> fk.fkColumnName().equalsIgnoreCase("city_id")
189+
&& fk.pkTableName().equalsIgnoreCase("city")));
190+
}
191+
}
192+
193+
@Test
194+
public void testPetForeignKeys() throws SQLException {
195+
try (Connection connection = dataSource.getConnection()) {
196+
DatabaseSchema schema = DatabaseSchema.read(connection);
197+
List<DbForeignKey> foreignKeys = schema.getForeignKeys("pet");
198+
// Pet has FK to owner and pet_type.
199+
assertTrue(foreignKeys.size() >= 2);
200+
assertTrue(foreignKeys.stream().anyMatch(
201+
fk -> fk.pkTableName().equalsIgnoreCase("owner")));
202+
assertTrue(foreignKeys.stream().anyMatch(
203+
fk -> fk.pkTableName().equalsIgnoreCase("pet_type")));
204+
}
205+
}
206+
207+
@Test
208+
public void testVetSpecialtyForeignKeys() throws SQLException {
209+
try (Connection connection = dataSource.getConnection()) {
210+
DatabaseSchema schema = DatabaseSchema.read(connection);
211+
List<DbForeignKey> foreignKeys = schema.getForeignKeys("vet_specialty");
212+
assertTrue(foreignKeys.size() >= 2);
213+
assertTrue(foreignKeys.stream().anyMatch(
214+
fk -> fk.pkTableName().equalsIgnoreCase("vet")));
215+
assertTrue(foreignKeys.stream().anyMatch(
216+
fk -> fk.pkTableName().equalsIgnoreCase("specialty")));
217+
}
218+
}
219+
220+
@Test
221+
public void testVisitCompoundForeignKey() throws SQLException {
222+
try (Connection connection = dataSource.getConnection()) {
223+
DatabaseSchema schema = DatabaseSchema.read(connection);
224+
List<DbForeignKey> foreignKeys = schema.getForeignKeys("visit");
225+
// Visit has FK to pet and compound FK to vet_specialty (vet_id, specialty_id).
226+
assertTrue(foreignKeys.size() >= 2);
227+
}
228+
}
229+
230+
@Test
231+
public void testForeignKeysForTableWithNone() throws SQLException {
232+
try (Connection connection = dataSource.getConnection()) {
233+
DatabaseSchema schema = DatabaseSchema.read(connection);
234+
// city has no foreign keys.
235+
List<DbForeignKey> foreignKeys = schema.getForeignKeys("city");
236+
assertTrue(foreignKeys.isEmpty());
237+
}
238+
}
239+
240+
// ---- Unique keys ----
241+
242+
@Test
243+
public void testUniqueKeysForNonExistentTable() throws SQLException {
244+
try (Connection connection = dataSource.getConnection()) {
245+
DatabaseSchema schema = DatabaseSchema.read(connection);
246+
List<DbUniqueKey> uniqueKeys = schema.getUniqueKeys("nonexistent");
247+
assertTrue(uniqueKeys.isEmpty());
248+
}
249+
}
250+
251+
// ---- JDBC_METADATA strategy ----
252+
253+
@Test
254+
public void testReadWithJdbcMetadataStrategy() throws SQLException {
255+
try (Connection connection = dataSource.getConnection()) {
256+
DatabaseSchema schema = DatabaseSchema.read(connection,
257+
connection.getCatalog(), connection.getSchema(),
258+
SequenceDiscoveryStrategy.INFORMATION_SCHEMA,
259+
ConstraintDiscoveryStrategy.JDBC_METADATA);
260+
assertTrue(schema.tableExists("city"));
261+
assertTrue(schema.tableExists("owner"));
262+
263+
// Verify primary keys are discovered.
264+
List<DbPrimaryKey> cityPrimaryKeys = schema.getPrimaryKeys("city");
265+
assertFalse(cityPrimaryKeys.isEmpty());
266+
267+
// Verify foreign keys are discovered.
268+
List<DbForeignKey> ownerForeignKeys = schema.getForeignKeys("owner");
269+
assertFalse(ownerForeignKeys.isEmpty());
270+
271+
// Verify unique keys for vet_specialty compound PK are discovered as unique index.
272+
List<DbUniqueKey> vetSpecialtyUniqueKeys = schema.getUniqueKeys("vet_specialty");
273+
// Compound PK is also reported as a unique index by JDBC_METADATA.
274+
assertNotNull(vetSpecialtyUniqueKeys);
275+
}
276+
}
277+
278+
// ---- Polymorphic tables ----
279+
280+
@Test
281+
public void testPolymorphicTablesExist() throws SQLException {
282+
try (Connection connection = dataSource.getConnection()) {
283+
DatabaseSchema schema = DatabaseSchema.read(connection);
284+
assertTrue(schema.tableExists("animal"));
285+
assertTrue(schema.tableExists("adoption"));
286+
assertTrue(schema.tableExists("post"));
287+
assertTrue(schema.tableExists("photo"));
288+
assertTrue(schema.tableExists("comment"));
289+
assertTrue(schema.tableExists("joined_animal"));
290+
assertTrue(schema.tableExists("joined_cat"));
291+
assertTrue(schema.tableExists("joined_dog"));
292+
}
293+
}
294+
295+
@Test
296+
public void testJoinedInheritanceForeignKeys() throws SQLException {
297+
try (Connection connection = dataSource.getConnection()) {
298+
DatabaseSchema schema = DatabaseSchema.read(connection);
299+
// joined_cat has FK to joined_animal
300+
List<DbForeignKey> catForeignKeys = schema.getForeignKeys("joined_cat");
301+
assertFalse(catForeignKeys.isEmpty());
302+
assertTrue(catForeignKeys.stream().anyMatch(
303+
fk -> fk.pkTableName().equalsIgnoreCase("joined_animal")));
304+
}
305+
}
306+
307+
// ---- DbColumn record properties ----
308+
309+
@Test
310+
public void testDbColumnRecordProperties() throws SQLException {
311+
try (Connection connection = dataSource.getConnection()) {
312+
DatabaseSchema schema = DatabaseSchema.read(connection);
313+
DbColumn nameColumn = schema.getColumn("city", "name").orElseThrow();
314+
assertNotNull(nameColumn.tableName());
315+
assertNotNull(nameColumn.columnName());
316+
assertNotNull(nameColumn.typeName());
317+
assertTrue(nameColumn.columnSize() > 0);
318+
}
319+
}
320+
321+
// ---- DbPrimaryKey record properties ----
322+
323+
@Test
324+
public void testDbPrimaryKeyRecordProperties() throws SQLException {
325+
try (Connection connection = dataSource.getConnection()) {
326+
DatabaseSchema schema = DatabaseSchema.read(connection);
327+
List<DbPrimaryKey> primaryKeys = schema.getPrimaryKeys("city");
328+
DbPrimaryKey primaryKey = primaryKeys.getFirst();
329+
assertNotNull(primaryKey.tableName());
330+
assertNotNull(primaryKey.columnName());
331+
assertTrue(primaryKey.keySeq() > 0);
332+
}
333+
}
334+
335+
// ---- Sequence discovery (H2 supports INFORMATION_SCHEMA.SEQUENCES) ----
336+
337+
@Test
338+
public void testSequenceNotExistsByDefault() throws SQLException {
339+
try (Connection connection = dataSource.getConnection()) {
340+
DatabaseSchema schema = DatabaseSchema.read(connection);
341+
// The test schema does not define any sequences.
342+
assertFalse(schema.sequenceExists("nonexistent_seq"));
343+
}
344+
}
345+
346+
// ---- Null schema/catalog handling ----
347+
348+
@Test
349+
public void testReadWithNullCatalogAndSchema() throws SQLException {
350+
try (Connection connection = dataSource.getConnection()) {
351+
DatabaseSchema schema = DatabaseSchema.read(connection, null, null,
352+
SequenceDiscoveryStrategy.INFORMATION_SCHEMA,
353+
ConstraintDiscoveryStrategy.INFORMATION_SCHEMA);
354+
// Should still discover tables even with null catalog/schema.
355+
assertTrue(schema.tableExists("city"));
356+
}
357+
}
358+
}

0 commit comments

Comments
 (0)