1 package uba.db;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import junit.framework.TestCase;
9
10 import org.apache.commons.collections.CollectionUtils;
11 import org.apache.commons.collections.TransformerUtils;
12
13 import uba.db.column.CharColumnSpecification;
14 import uba.db.column.Column;
15 import uba.db.column.ColumnConstraint;
16 import uba.db.column.ColumnSpecification;
17 import uba.db.column.IntegerColumnSpecification;
18 import uba.db.table.Row;
19 import uba.db.table.Table;
20 import uba.db.table.TableSchema;
21 import uba.db.table.TableSchemaBuilder;
22 import uba.db.table.io.TableReader;
23
24 /***
25 * Esta clase sirve como base para crear test de unidad de implementaciones de
26 * la base de datos (interfaz {@link Database}).
27 *
28 * @version $Revision: 1.4 $
29 */
30 public abstract class DatabaseImplTest extends TestCase {
31 /***
32 * Nombre utilizado para la tabla "Empleado"
33 */
34 protected static final String EMPLOYEE_TABLE_NAME = "empleado";
35
36 /***
37 * Esta variable se inicializa en el {@link #setUp()} con la implementación
38 * a testear.
39 */
40 protected Database database;
41
42 /***
43 * Esquema de tabla utilizado para las pruebas (se inicializa en
44 * {@link #setUp()}).
45 */
46 protected TableSchema employeeSchema;
47
48 /***
49 * @see junit.framework.TestCase#setUp()
50 */
51 protected void setUp() throws Exception {
52 super.setUp();
53 database = createDatabase();
54 employeeSchema = new TableSchemaBuilder(EMPLOYEE_TABLE_NAME)
55 .addColumn(new IntegerColumnSpecification("eid"))
56 .addColumn(new CharColumnSpecification("nombre", 20,
57 ColumnConstraint.NOT_NULL))
58 .addColumn(new IntegerColumnSpecification("salario",
59 ColumnConstraint.NOT_NULL))
60 .addColumn(new IntegerColumnSpecification("edad",
61 ColumnConstraint.NOT_NULL)).addPrimaryKeyConstraintTo("eid")
62 .build();
63 }
64
65 /***
66 * Las sub-clases deben implementar este método para retorna la instancia
67 * concreta de {@link Database} a testear.
68 *
69 * @throws DatabaseInitializationException
70 * si hubo un error al crear la instancia de la base de datos.
71 */
72 protected abstract Database createDatabase() throws DatabaseInitializationException;
73
74 /***
75 * Test: retornar las tablas del sistema.
76 */
77 public void testGetSystemTables() throws Exception {
78 assertEquals(3, database.systemTables().size());
79
80 Table table = database.tableNamed(SystemTableSchemas.TABLES_SCHEMA.tableName());
81 assertSameSchema(table, SystemTableSchemas.TABLES_SCHEMA);
82
83 table = database.tableNamed(SystemTableSchemas.COLUMNS_SCHEMA.tableName());
84 assertSameSchema(table, SystemTableSchemas.COLUMNS_SCHEMA);
85
86 table = database.tableNamed(SystemTableSchemas.DATATYPES_SCHEMA.tableName());
87 assertSameSchema(table, SystemTableSchemas.DATATYPES_SCHEMA);
88 }
89
90 /***
91 * Verifica que la tabla tenga el esquema dado.
92 *
93 * @param table tabla
94 * @param tableSchema esquema a verificar.
95 */
96 protected void assertSameSchema(Table table, TableSchema tableSchema) {
97 int ncolumns = table.columns().size();
98 List columnSpecifications = tableSchema.columnSpecifications();
99 assertEquals(columnSpecifications.size(), ncolumns);
100 for (int i = 0; i < ncolumns; i++) {
101 ColumnSpecification colSpec = (ColumnSpecification) columnSpecifications
102 .get(i);
103 Column col = (Column) table.columns().get(i);
104
105 assertEquals(colSpec.name(), col.name());
106 assertEquals(colSpec.constraint(), col.constraint());
107 assertEquals(colSpec.dataTypeDisplayString(), col.dataTypeDisplayString());
108 }
109 }
110
111 /***
112 * Test: crear una tabla.
113 */
114 public void testCreateTable() throws Exception {
115 database.createTable(employeeSchema);
116 assertEquals(1, database.userTables().size());
117
118 Table employeeTable = (Table) database.userTables().iterator().next();
119 assertSameSchema(employeeTable, employeeSchema);
120 }
121
122 /***
123 * Test: obtener todas las tablas (las de usuario y las del sistema).
124 */
125 public void testTables() throws Exception {
126 database.createTable(employeeSchema);
127
128 assertEquals(4, database.tables().size());
129
130 Collection tableNames = CollectionUtils
131 .collect(database.tables(), TransformerUtils.invokerTransformer("name"));
132
133 assertTrue(tableNames.contains(employeeSchema.tableName()));
134 assertTrue(tableNames.contains(SystemTableSchemas.TABLES_SCHEMA.tableName()));
135 assertTrue(tableNames.contains(SystemTableSchemas.COLUMNS_SCHEMA.tableName()));
136 assertTrue(tableNames.contains(SystemTableSchemas.DATATYPES_SCHEMA.tableName()));
137 }
138
139 /***
140 * Test: cuando se inserta una tabla se debe actualizar el contenido de las
141 * tablas del sistema.
142 */
143 public void testUpdateSystemTablesContents() throws Exception {
144 database.createTable(employeeSchema);
145 assertEquals(4, database.tables().size());
146
147
148 Table tables = database.tablesTable();
149 TableReader reader = tables.reader();
150 assertTrue("el catalogo debe tener una fila con la nueva tabla", reader
151 .hasMoreRows());
152 Row row = reader.fetchRow();
153 reader.close();
154
155 Integer rowId = (Integer) row.valueAt(0);
156 assertEquals("la nueva tabla debe figurar en el catalogo",
157 row.valueAt(1),
158 employeeSchema.tableName());
159
160
161 Table dataTypes = database.dataTypesTable();
162 reader = dataTypes.reader();
163 Map dataTypesMap = new HashMap();
164
165 while (reader.hasMoreRows()) {
166 row = reader.fetchRow();
167 dataTypesMap.put(row.valueAt(0), row.valueAt(1));
168 }
169 reader.close();
170
171 Table columns = database.columnsTable();
172 reader = columns.reader();
173 Map collectedColumns = new HashMap();
174 while (reader.hasMoreRows()) {
175 row = reader.fetchRow();
176 if (row.valueAt(0).equals(rowId)) {
177 collectedColumns.put(row.valueAt(2), dataTypesMap.get(row.valueAt(3)));
178 }
179 }
180 reader.close();
181
182 assertTrue(collectedColumns.containsKey("eid"));
183 assertEquals(IntegerColumnSpecification.DATATYPE_DISPLAY_STRING, collectedColumns
184 .get("eid"));
185 assertTrue(collectedColumns.containsKey("nombre"));
186 assertEquals(CharColumnSpecification.DATATYPE_DISPLAY_STRING, collectedColumns
187 .get("nombre"));
188 assertTrue(collectedColumns.containsKey("salario"));
189 assertEquals(IntegerColumnSpecification.DATATYPE_DISPLAY_STRING, collectedColumns
190 .get("salario"));
191 assertTrue(collectedColumns.containsKey("edad"));
192 assertEquals(IntegerColumnSpecification.DATATYPE_DISPLAY_STRING, collectedColumns
193 .get("edad"));
194 }
195
196 /***
197 * Test: Obtener una tabla por su nombre (el lookup debe ser case
198 * insesitve).
199 */
200 public void testTableNamed() throws Exception {
201 database.createTable(employeeSchema);
202 Table table = null;
203
204 try {
205 table = database.tableNamed("empleado");
206 } catch (UnknowTableName e) {
207 fail("No se pudo obtener la tabla empleado, aunque existe en la base");
208 }
209
210 assertNotNull(table);
211 assertSameSchema(table, employeeSchema);
212 }
213 }