/*
* Copyright 2015 The Project Buendia Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at: http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distrib-
* uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for
* specific language governing permissions and limitations under the License.
*/
package org.projectbuendia.openmrs.api.db.hibernate;
import org.junit.Before;
import org.openmrs.BaseOpenmrsData;
import org.openmrs.test.BaseModuleContextSensitiveTest;
import org.openmrs.test.SkipBaseSetup;
import org.projectbuendia.openmrs.api.SyncToken;
import javax.annotation.Nullable;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.fail;
/**
* Base class for tests which test {@link HibernateProjectBuendiaDAO}.
*/
@SkipBaseSetup
public abstract class HibernateProjectBuendiaDAOTest extends BaseModuleContextSensitiveTest {
protected static final SyncToken CATCH_ALL_SYNCTOKEN = new SyncToken(new Date(0), null);
protected static final DateFormat DB_DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
protected static final String SAMPLE_PATIENT_DATA_SET =
"org/projectbuendia/openmrs/include/samplePatientsDataSet.xml";
private static final String BASE_DATASET =
"org/projectbuendia/openmrs/include/baseMetaDataSet.xml";
/**
* {@link BaseModuleContextSensitiveTest} does this initialization, but also pre-loads the
* database with a bunch of patient records. We don't want to load those patient records,
* because we'd then have to augment them with `buendia_patient_sync_map` records, which would
* couple our test integrity to the records in OpenMRS' test data. For this reason, we disable
* {@link BaseModuleContextSensitiveTest}'s setup by putting the {@link SkipBaseSetup}
* annotation on the class, but then we've got to explicitly init the database and authenticate
* ourselves.
*/
@Before
public void setUpData() throws Exception {
if (useInMemoryDatabase()) {
initializeInMemoryDatabase();
executeDataSet(BASE_DATASET);
authenticate();
}
}
/** Extracts a list of UUIDs from a list of OpenMRS data. */
protected String[] extractListOfUuids(List<? extends BaseOpenmrsData> data) {
String[] retVal = new String[data.size()];
for (int i = 0; i < data.size(); i++) {
retVal[i] = data.get(i).getUuid();
}
return retVal;
}
/**
* Creates a sync token, and converts any thrown exceptions to RuntimeExceptions so it can be
* used for static fields.
*
* @param dateString Specified in the same format as in the dataset XML files, for readability.
* e.g. "2015-07-18 12:00:00.0"
*/
protected static SyncToken createSyncToken(String dateString, @Nullable String uuid) {
try {
return new SyncToken(DB_DATE_FORMAT.parse(dateString), uuid);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* It's possible to generate inconsistent test data that will cause the other tests to fail,
* by using different UUIDs in the `person` table and the corresponding row in the
* `buendia_patient_sync_map`. This test explicitly checks for that, and fails if it finds any
* discrepancies. See `liquibase.xml` for why this inconsistency is possible in the data model.
*/
protected void testDataSetIsConsistent(String dataset, String baseTableName, String baseIdField,
String buendiaTableName, String buendiaIdField) throws Exception {
executeDataSet(dataset);
Statement statement = getConnection().createStatement();
String query = String.format(
"SELECT origin.%2$s, origin.uuid, buendia.uuid " +
"FROM %1$s origin " +
"LEFT JOIN %3$s buendia ON origin.%2$s = buendia.%4$s " +
"WHERE origin.uuid <> buendia.uuid",
baseTableName, baseIdField, buendiaTableName, buendiaIdField);
ResultSet results = statement.executeQuery(query);
int failures = 0;
while (results.next()) {
failures++;
System.out.printf("WARNING: Record with ID #%d has inconsistent entry in " +
"sync map.\nBase UUID: %s Sync Map UUID: %s\n",
results.getInt(1), results.getString(2), results.getString(3));
}
if (failures > 0) {
fail(String.format("%d record(s) had inconsistent test data.", failures));
}
}
}