org.openmrs.module.sync.SyncInvalidRecordTest.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.sync.SyncInvalidRecordTest.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.sync;

import junit.framework.Assert;
import org.junit.Test;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifier;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.module.sync.api.SyncService;
import org.openmrs.module.sync.serialization.Record;
import org.openmrs.util.OpenmrsConstants;
import org.springframework.test.annotation.NotTransactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * This test is written in response to a production issue we have discovered, in which somehow an invalid sync record
 * is persisted and sent to the parent.  The problem manifests when the parent attempts to play back this record, finds
 * that the underlying object is invalid (eg. is missing a database required field), and fails to save, yet a sync record
 * for this item saves nonetheless (and saves in such a way that the original uuid is the same as the record uuid, so it
 * appears as a new record to subsequent children, thus causing an effect of bouncing back and forth forever and filling
 * up the sync record table with many invalid, duplicate sync records.
 */
public class SyncInvalidRecordTest extends SyncBaseTest {

    String syncRecordUuid = "e33761c7-25e0-40ca-b14a-58f99320c25e";

    @Override
    public String getInitialDataset() {
        try {
            return "org/openmrs/module/sync/include/" + new TestUtil().getTestDatasetFilename("syncCreateTest");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected List<SyncRecord> getSyncRecords() throws Exception {
        List<SyncRecord> ret = new ArrayList<SyncRecord>();

        User u = Context.getAuthenticatedUser();

        SyncRecord sr = new SyncRecord();
        sr.setUuid(syncRecordUuid);
        sr.setCreator(u.getId().toString());
        sr.setDatabaseVersion(OpenmrsConstants.OPENMRS_VERSION_SHORT);
        sr.setTimestamp(new Date());
        sr.setRetryCount(0);
        sr.setState(SyncRecordState.NEW);
        sr.setContainedClasses("org.openmrs.PatientIdentifier");
        sr.setOriginalUuid(syncRecordUuid);

        SyncItem item = new SyncItem();
        item.setContainedType(PatientIdentifier.class);
        item.setKey(new SyncItemKey<String>(UUID.randomUUID().toString(), String.class));
        item.setState(SyncItemState.NEW);

        StringBuilder content = new StringBuilder();
        content.append("<org.openmrs.PatientIdentifier>");
        content.append("<patient type=\"org.openmrs.Patient\">")
                .append(Context.getPatientService().getPatient(2).getUuid()).append("</patient>");
        content.append("<voided type=\"boolean\">false</voided>");
        content.append("<dateCreated type=\"timestamp\">2014-07-07T10:19:57.940-0400</dateCreated>");
        content.append("<uuid type=\"string\">54d3ca4a-d1ee-421c-a74e-5336c7519888</uuid>");
        content.append("<preferred type=\"boolean\">false</preferred>");
        content.append("<creator type=\"org.openmrs.User\">").append(u.getUuid()).append("</creator>");
        content.append("</org.openmrs.PatientIdentifier>");
        item.setContent(content.toString());
        sr.addItem(item);

        ret.add(sr);
        return ret;
    }

    @Override
    protected void repopulateDB(String xmlFileToExecute) throws Exception {
        super.repopulateDB(xmlFileToExecute);
        Context.addProxyPrivilege("SQL Level Access");
        Context.getAdministrationService()
                .executeSQL("alter table patient_identifier alter column identifier set not null", false);
    }

    @Test
    @NotTransactional
    public void shouldAddInvalidIdentifierTest() throws Exception {
        runSyncTest(new SyncTestHelper() {

            @Override
            public void runOnChild() {
            }

            @Override
            public void changedBeingApplied(List<SyncRecord> syncRecords, Record record) throws Exception {
                super.changedBeingApplied(syncRecords, record);

                // Assert that there are no sync records to start with
                assertNumSyncRecords(0);
            }

            @Override
            public void runOnParent() throws Exception {

                // Confirm that the identifier failed to save to the DB due to a validation error
                Patient p = Context.getPatientService().getPatient(2);
                Collection<PatientIdentifier> identifiers = p.getIdentifiers();
                Assert.assertEquals(2, identifiers.size());
                for (PatientIdentifier pi : p.getIdentifiers()) {
                    Assert.assertNotSame("54d3ca4a-d1ee-421c-a74e-5336c7519888", pi.getUuid());
                }

                // Since the identifier failed to save, confirm that no sync record was saved either
                assertNumSyncRecords(0);
            }
        });
    }

    protected void assertNumSyncRecords(int num) throws Exception {
        int numFound = Context.getService(SyncService.class).getSyncRecords().size();
        if (num != numFound) {
            System.out.println("Expected " + num + " sync records but found: " + numFound);
            org.openmrs.test.TestUtil.printOutTableContents(getConnection(), "sync_record");
        }
        Assert.assertEquals(num, numFound);
    }
}