/*
* 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.junit.Test;
import org.openmrs.Patient;
import org.openmrs.api.context.Context;
import org.projectbuendia.openmrs.api.ProjectBuendiaService;
import org.projectbuendia.openmrs.api.SyncToken;
import org.projectbuendia.openmrs.api.db.SyncPage;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Test the patient-handling logic in {@link HibernateProjectBuendiaDAO}. Tests in this class test
* the DAO logic, even though they interact with the service.
*/
public class HibernateProjectBuendiaDAOPatientTest extends HibernateProjectBuendiaDAOTest {
private ProjectBuendiaService buendiaService;
// Dataset 1: no voided patients, no duplicate timestamps.
private static final String PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS =
"org/projectbuendia/openmrs/include/patientDataSetNoDuplicateTimestamps.xml";
private static final String[] EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS =
new String[] {
"aaaaa",
"eeeee",
"bbbbb",
"fffff",
"ddddd",
"ccccc",
"gggggg"
};
private static final SyncToken SYNC_TOKEN_FOR_RECORD_eeeee =
createSyncToken("2015-07-18 12:00:00.0", "eeeee");
// END Dataset 1.
// Dataset 2: voided patients, no duplicate timestamps
private static final String PATIENT_DATASET_INCLUDES_VOIDED =
"org/projectbuendia/openmrs/include/patientDataSetWithVoids.xml";
private static final String[] EXPECTED_UUID_ORDER_VOIDS_EXCLUDE_VOIDED =
new String[] {
"aaaaa",
"bbbbb",
"fffff",
"gggggg"
};
private static final String[] EXPECTED_UUID_ORDER_VOIDS_INCLUDE_VOIDED =
EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS;
// END Dataset 2.
// Dataset 3: voided patients, duplicate timestamps.
private static final String PATIENT_DATASET_DUPLICATE_TIMESTAMPS =
"org/projectbuendia/openmrs/include/patientDataSetWithDuplicateTimestamps.xml";
private static final String[] EXPECTED_UUID_ORDER_DUPLICATE_TIMESTAMPS =
new String[] {
"aaaaa",
"bbbbb",
"eeeee",
"fffff",
"ccccc",
"ddddd",
"gggggg"
};
private static final SyncToken SYNC_TOKEN_DATE_ONLY =
createSyncToken("2015-07-21 00:00:00.0", null);
// END Dataset 3.
@Before
public void setUpVariables() throws Exception {
buendiaService = Context.getService(ProjectBuendiaService.class);
}
@Test
public void testResultsInOrderWhenAllHaveDifferentUpdateTimes() throws Exception {
executeDataSet(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
SyncPage<Patient> results =
buendiaService.getPatientsModifiedAtOrAfter(null, false, 0);
String[] actual = extractListOfUuids(results.results);
assertArrayEquals(EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS, actual);
}
@Test
public void testPagesContainCorrectRecordsWhenAllHaveDifferentUpdateTimes() throws Exception {
executeDataSet(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
SyncPage<Patient> results =
buendiaService.getPatientsModifiedAtOrAfter(null, false, 3);
assertArrayEquals(
Arrays.copyOfRange(EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS, 0, 3),
extractListOfUuids(results.results));
SyncToken token = results.syncToken;
results = buendiaService.getPatientsModifiedAtOrAfter(token, false, 3);
assertArrayEquals(
Arrays.copyOfRange(EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS, 3, 6),
extractListOfUuids(results.results));
token = results.syncToken;
results = buendiaService.getPatientsModifiedAtOrAfter(token, false, 3);
assertArrayEquals(
// There should only be one in the last page.
Arrays.copyOfRange(EXPECTED_UUID_ORDER_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS, 6, 7),
extractListOfUuids(results.results));
}
@Test
public void testSyncTokenGeneratedFromLastResultInPage() throws Exception {
executeDataSet(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
SyncToken token = buendiaService.getPatientsModifiedAtOrAfter(null, false, 2).syncToken;
assertEquals(SYNC_TOKEN_FOR_RECORD_eeeee, token);
}
@Test
public void testFetchPastEndOfResultSet() throws Exception {
executeDataSet(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
// First, fetch all the data.
SyncToken token = buendiaService.getPatientsModifiedAtOrAfter(null, false, 0).syncToken;
// The sync token should be generated from the last result, so using it should return
// an empty result set.
SyncPage<Patient> result = buendiaService.getPatientsModifiedAtOrAfter(token, false, 0);
assertTrue("Expected empty results", result.results.isEmpty());
assertNull(result.syncToken);
}
@Test
public void testZeroMaxResultsReturnsLotsOfResults() throws Exception {
executeDataSet(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
SyncPage<Patient> results = buendiaService.getPatientsModifiedAtOrAfter(null, false, 0);
assertNotEquals(0, results.results.size());
results = buendiaService.getPatientsModifiedAtOrAfter(CATCH_ALL_SYNCTOKEN, false, 0);
assertNotEquals(0, results.results.size());
}
@Test
public void testVoidedPatientsIncludedWhenParameterTrue() throws Exception {
executeDataSet(PATIENT_DATASET_INCLUDES_VOIDED);
SyncPage<Patient> results = buendiaService.getPatientsModifiedAtOrAfter(null, true, 0);
assertArrayEquals(
EXPECTED_UUID_ORDER_VOIDS_INCLUDE_VOIDED,
extractListOfUuids(results.results));
}
@Test
public void testVoidedPatientsExcludedWhenParameterFalse() throws Exception {
executeDataSet(PATIENT_DATASET_INCLUDES_VOIDED);
SyncPage<Patient> results = buendiaService.getPatientsModifiedAtOrAfter(null, false, 0);
assertArrayEquals(
EXPECTED_UUID_ORDER_VOIDS_EXCLUDE_VOIDED,
extractListOfUuids(results.results));
}
@Test
public void testPagesContainCorrectRecordsWhenSomeHaveSameUpdateTime() throws Exception {
executeDataSet(PATIENT_DATASET_DUPLICATE_TIMESTAMPS);
SyncPage<Patient> results =
buendiaService.getPatientsModifiedAtOrAfter(null, true, 3);
assertArrayEquals(
Arrays.copyOfRange(EXPECTED_UUID_ORDER_DUPLICATE_TIMESTAMPS, 0, 3),
extractListOfUuids(results.results));
SyncToken token = results.syncToken;
results = buendiaService.getPatientsModifiedAtOrAfter(token, true, 3);
assertArrayEquals(
Arrays.copyOfRange(EXPECTED_UUID_ORDER_DUPLICATE_TIMESTAMPS, 3, 6),
extractListOfUuids(results.results));
token = results.syncToken;
results = buendiaService.getPatientsModifiedAtOrAfter(token, true, 3);
assertArrayEquals(
// There should only be one in the last page.
Arrays.copyOfRange(EXPECTED_UUID_ORDER_DUPLICATE_TIMESTAMPS, 6, 7),
extractListOfUuids(results.results));
}
@Test
public void testNullUuidInSyncTokenReturnsAllResultsNewerThanTimestamp() throws Exception {
executeDataSet(PATIENT_DATASET_DUPLICATE_TIMESTAMPS);
List<Patient> results =
buendiaService.getPatientsModifiedAtOrAfter(SYNC_TOKEN_DATE_ONLY, true, 0).results;
assertArrayEquals(
Arrays.copyOfRange(EXPECTED_UUID_ORDER_DUPLICATE_TIMESTAMPS, 4, 7),
extractListOfUuids(results));
}
@Test
public void testFetchWithNoResults() throws Exception {
// Don't add any data.
SyncPage<Patient> result = buendiaService.getPatientsModifiedAtOrAfter(null, false, 0);
assertTrue("Expected empty results", result.results.isEmpty());
assertNull(result.syncToken);
}
// DATASET CONSISTENCY TESTS. See note on {@link #testDataSetIsConsistent}.
@Test
public void testDataSetNoVoidedNoDuplicateTimestampsIsConsistent() throws Exception {
testDataSetIsConsistent(PATIENT_DATASET_NO_VOIDED_NO_DUPLICATE_TIMESTAMPS);
}
@Test
public void testDataSetWithVoidsIsConsistent() throws Exception {
testDataSetIsConsistent(PATIENT_DATASET_INCLUDES_VOIDED);
}
@Test
public void testDataSetWithDuplicateTimestampsisConsistent() throws Exception {
testDataSetIsConsistent(PATIENT_DATASET_DUPLICATE_TIMESTAMPS);
}
private void testDataSetIsConsistent(String dataset) throws Exception {
testDataSetIsConsistent(
dataset, "person", "person_id", "buendia_patient_sync_map", "patient_id");
}
}