org.tsm.concharto.audit.IntegrationTestAuditEntry.java Source code

Java tutorial

Introduction

Here is the source code for org.tsm.concharto.audit.IntegrationTestAuditEntry.java

Source

/*******************************************************************************
 * Copyright 2009 Time Space Map, LLC
 * 
 * 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
 * distributed 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 the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package org.tsm.concharto.audit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.tsm.concharto.dao.AuditEntryDao;
import org.tsm.concharto.dao.AuditUserChange;
import org.tsm.concharto.dao.BaseEventIntegrationTest;
import org.tsm.concharto.dao.EventUtil;
import org.tsm.concharto.model.Event;
import org.tsm.concharto.model.Flag;
import org.tsm.concharto.model.audit.AuditEntry;
import org.tsm.concharto.model.audit.AuditFieldChange;
import org.tsm.concharto.model.geometry.TsGeometry;
import org.tsm.concharto.model.wiki.WikiText;
import org.tsm.concharto.service.RevertEventService;
import org.tsm.concharto.util.ContextUtil;
import org.tsm.concharto.web.util.CatalogUtil;

import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

public class IntegrationTestAuditEntry extends BaseEventIntegrationTest {

    private static final String USERNAME = "bob";
    private static final String USERNAME2 = "joe";
    private static final int MAX_RESULTS = 100;
    private static AuditEntryDao auditEntryDao;
    private static RevertEventService revertEventService;
    private static final String CATALOG = CatalogUtil.CATALOG_WWW;

    private Date begin;
    private Date end;

    @Before
    public void setUp() {
        Calendar cal = new GregorianCalendar(107 + 1900, 8, 22, 12, 22, 3);
        cal.set(Calendar.MILLISECOND, 750);
        begin = cal.getTime();
        cal.set(Calendar.SECOND, 35);
        end = cal.getTime();

    }

    @BeforeClass
    public static void setUpClass() {
        baseSetUpClass();
        ApplicationContext appCtx = ContextUtil.getCtx();
        auditEntryDao = (AuditEntryDao) appCtx.getBean("auditEntryDao");
        revertEventService = (RevertEventService) appCtx.getBean("revertEventService");
    }

    @Before
    public void setupUserContext() {
        setupUserContext(USERNAME);
        getEventTesterDao().deleteAll();
    }

    /**
     * 
     * @throws ParseException e
     * @throws InterruptedException e
     */
    @Test
    public void testSaveAndResave() throws ParseException, InterruptedException {
        Event event = getEventUtil().createEvent(begin, end);
        event.setDescription("This is some description.");
        Serializable id = getEventDao().save(event);
        getSessionFactory().getCurrentSession().evict(event); //guarantees the object gets written to the DB 

        Thread.sleep(1000);
        Event returned = getEventDao().findById((Long) id);
        returned.setDescription("sdfsdf");
        getEventDao().saveOrUpdate(returned);
        getSessionFactory().getCurrentSession().evict(returned);
        //save, but don't make any changes.  
        getEventDao().saveOrUpdate(returned);
        getSessionFactory().getCurrentSession().evict(returned);
        getEventDao().saveOrUpdate(returned);
        getSessionFactory().getCurrentSession().evict(returned);
        Event returned2 = getEventDao().findById((Long) id);

        assertEquals(EventUtil.filterMilliseconds(event.getCreated()), returned.getCreated());
        //make sure the last modified dates are different for the two instances we edited
        assertTrue(returned.getLastModified().compareTo(returned2.getLastModified()) != 0);

        //create another so that there are more than 2 total audit records
        getEventDao().save(getEventUtil().createEvent(begin, end));

        //now ensure correct number audit entries were created for this event
        List<AuditEntry> auditEntries = auditEntryDao.getAuditEntries(event, 0, MAX_RESULTS);
        assertEquals(4, auditEntries.size());
        //go down the list (entries are ordered by newest first)
        //verify username is in the field
        int version = auditEntries.size() - 1;
        for (AuditEntry auditEntry : auditEntries) {
            assertEquals((long) version--, auditEntry.getVersion());
            assertEquals(USERNAME, auditEntry.getUser());
        }

        //now test retrieval by fake object
        Event empty = new Event();
        empty.setId(event.getId());
        auditEntries = auditEntryDao.getAuditEntries(empty, 0, MAX_RESULTS);
        assertEquals(4, auditEntries.size());

        //now test getting the count
        Long count = auditEntryDao.getAuditEntriesCount(empty);
        assertEquals(4L, (long) count);

        //now test getting one of the entries
        //Session session = getEventTesterDao().getSessionFactory().openSession();
        //session.refresh(auditEntries.get(0));
        Collection<AuditFieldChange> changes = auditEntries.get(0).getAuditEntryFieldChange();
        for (AuditFieldChange auditFieldChange : changes) {
            AuditFieldChange newChange = auditEntryDao.getAuditFieldChange(auditFieldChange.getId());
            assertEquals(newChange.getNewValue(), auditFieldChange.getNewValue());
        }
        //session.close();

        //now test a bad ID
        empty.setId(4344L);
        auditEntries = auditEntryDao.getAuditEntries(empty, 0, MAX_RESULTS);
        assertEquals(0, auditEntries.size());

        //now test getting the count
        count = auditEntryDao.getAuditEntriesCount(empty);
        assertEquals(0L, (long) count);
    }

    @Test
    public void testRevert() throws ParseException {
        //create an event with five changes and revert each one
        Event rev0 = getEventUtil().createEvent(begin, end);
        rev0.setDescription("r0 description");
        rev0.setSummary("r0 summary");
        rev0.setSource(null);
        rev0.setUserTagsAsString("r0 tag a, tag b");
        Serializable id = getEventDao().save(rev0);
        freeFromSession(rev0);

        Event rev1 = getEventDao().findById((Long) id);
        rev1.setSummary("r1 summary");
        rev1.setSource("r1 source");
        getEventDao().saveOrUpdate(rev1);
        freeFromSession(rev1);

        Event rev2 = getEventDao().findById((Long) id);
        rev2.setDescription("r2 description");
        rev2.setSummary("r2 summary");
        rev2.setTsGeometry(new TsGeometry(new WKTReader().read("POINT (3300 3530)")));
        getEventDao().saveOrUpdate(rev2);
        freeFromSession(rev2);

        Event rev3 = getEventDao().findById((Long) id);
        rev3.setDescription("r3 description");
        rev3.setSummary("r3 summary");
        rev3.setTsGeometry(new TsGeometry(new WKTReader().read("POINT (530 530)")));
        getEventDao().saveOrUpdate(rev3);
        rev3.getFlags().size();
        freeFromSession(rev3);

        Event rev4 = getEventDao().findById((Long) id);
        rev4.setUserTagsAsString("r4tags, tag b");
        rev4.setDescription("r4 description");
        getEventDao().saveOrUpdate(rev4);
        freeFromSession(rev4);

        revertAndAssert(rev4, 4);
        getSessionFactory().getCurrentSession().flush();
        revertAndAssert(rev3, 3);
        revertAndAssert(rev2, 2);
        revertAndAssert(rev1, 1);
        revertAndAssert(rev0, 0);
    }

    /** 
     * Test getting auditable events by username
     * @throws ParseException
     */
    @Test
    public void byUsername() throws ParseException {
        makeEvents(3);
        setupUserContext(USERNAME2);
        makeEvents(5);
        assertEquals(3, auditEntryDao.getAuditEntries(CATALOG, USERNAME, Event.class, 0, 20).size());
        assertEquals(3L, (long) auditEntryDao.getAuditEntriesCount(CATALOG, USERNAME, Event.class));
        assertEquals(5, auditEntryDao.getAuditEntries(CATALOG, USERNAME2, Event.class, 0, 20).size());
        assertEquals(5L, (long) auditEntryDao.getAuditEntriesCount(CATALOG, USERNAME2, Event.class));
        //limit size of results
        List<AuditUserChange> entries = auditEntryDao.getAuditEntries(CATALOG, USERNAME2, Event.class, 0, 3);
        AuditUserChange first = entries.get(0);
        assertEquals(3, entries.size());
        //limit size of results, first record is different
        entries = auditEntryDao.getAuditEntries(CATALOG, USERNAME2, Event.class, 1, 3);
        AuditUserChange second = entries.get(0);
        assertEquals(3, entries.size());
        //check the order
        //TODO remove this for now.  Something wrong with this test such that it periodically fails.  Something
        //to do with DB id assignment?
        //       assertTrue("Entities out of order; " + first.getAuditEntry().getEntityId() + " should be less than " + second.getAuditEntry().getEntityId(),
        //             first.getAuditEntry().getEntityId() < second.getAuditEntry().getEntityId());
        //check the join.  The first event summary should be different than the second
        assertTrue(
                !((Event) first.getAuditable()).getSummary().equals(((Event) second.getAuditable()).getSummary()));
    }

    @Test
    public void wikiText() throws ParseException {
        Event event = getEventUtil().createEvent();
        WikiText wikiText = new WikiText();
        wikiText.setText("==header== some stuff here");
        event.setDiscussion(wikiText);
        getEventDao().saveOrUpdate(event);
        wikiText.setText("==header== some new stuff here");
        getEventDao().saveOrUpdate(event);

        List<AuditEntry> auditEntries = auditEntryDao.getAuditEntries(wikiText, 0, 20);
        assertEquals(2, auditEntries.size());
        Collection<AuditFieldChange> auditEntryFieldChanges = auditEntries.get(0).getAuditEntryFieldChange();
        assertEquals(1, auditEntryFieldChanges.size());

    }

    @Test
    public void testRevertWikiText() throws ParseException {
        //create an event with five changes and revert each one
        WikiText rev0 = new WikiText();
        rev0.setText("==header== some stuff here");
        Serializable id = getEventDao().saveAuditable(rev0);

        WikiText rev1 = (WikiText) getEventDao().findById(WikiText.class, (Long) id);
        rev1.setText("==header== some extra stuff here");
        getEventDao().saveOrUpdateAuditable(rev1);

        WikiText rev2 = (WikiText) getEventDao().findById(WikiText.class, (Long) id);
        rev2.setText("==header== some extra stuff here and here too!");
        getEventDao().saveOrUpdateAuditable(rev2);

        revertAndAssertWikiText(rev2, 2);
        revertAndAssertWikiText(rev1, 1);
        revertAndAssertWikiText(rev0, 0);
    }

    @Test
    public void testGetRecent() throws ParseException {
        makeEvents(3);
        assertEquals(3, auditEntryDao.getLatestAuditEntries(CATALOG, Event.class, 0, 10).size());
        Event event = getEventUtil().createEvent(begin, end);
        getEventDao().save(event);
        event.setDescription("some new text here");
        getEventDao().saveOrUpdate(event);
        assertEquals(5, auditEntryDao.getLatestAuditEntries(CATALOG, Event.class, 0, 10).size());
        assertEquals(5L, (long) auditEntryDao.getAuditEntriesCount(CATALOG, Event.class));

        //now add some wikitext
        WikiText text = new WikiText();
        text.setText("==header== some stuff here");
        getEventDao().saveAuditable(text);
        text.setText("==header== some extra stuff here");
        getEventDao().saveOrUpdateAuditable(text);
        assertEquals(2, auditEntryDao.getLatestAuditEntries(CATALOG, WikiText.class, 0, 10).size());
        assertEquals(2L, (long) auditEntryDao.getAuditEntriesCount(CATALOG, WikiText.class));

    }

    @Test
    public void testFlag() throws ParseException {
        //make an event
        Event event = getEventUtil().createEvent();
        getEventDao().save(event);
        //add a flag
        Flag flag = new Flag();
        flag.setComment("sdf");
        flag.setEvent(event);
        List<Flag> flags = new ArrayList<Flag>();
        flags.add(flag);
        event.setFlags(flags);
        event.setHasUnresolvedFlag(true);
        getEventDao().saveOrUpdate(event);

        //now ensure correct number audit entries were created for this event
        List<AuditEntry> auditEntries = auditEntryDao.getAuditEntries(event, 0, MAX_RESULTS);
        assertEquals(2, auditEntries.size());

    }

    @Test
    public void testCatalog() throws ParseException {
        //create three events, and another from another event.
        makeEvents(3);
        Event event = getEventUtil().createEvent();
        String newCatalog = "sdfsdf";
        event.setCatalog(newCatalog);
        getEventDao().save(event);

        //change them all
        List<Event> events = getEventDao().findRecent(4, 0);
        for (Event e : events) {
            e.setDescription("ee");
            getEventDao().saveOrUpdate(e);
        }

        //get all of the changes for the default catalog.  There should be 
        //two for each event (create and change)
        assertEquals(6, auditEntryDao.getLatestEventEntries(CatalogUtil.CATALOG_WWW, 0, 10).size());
        //get all of the changes for the new catalog  
        assertEquals(2, auditEntryDao.getLatestEventEntries(newCatalog, 0, 10).size());
    }

    private void makeEvents(int numEvents) throws ParseException {
        for (int i = 0; i < numEvents; i++) {
            getEventDao().save(getEventUtil().createEvent("summary " + i));
        }
    }

    private void revertAndAssertWikiText(WikiText expected, int rev) {
        //List<AuditEntry> auditEntries = auditEntryDao.getAuditEntries(expected, 0, MAX_RESULTS);
        WikiText reverted = (WikiText) revertEventService.revertToRevision(expected.getClass(), rev,
                expected.getId());
        assertEquals(expected.getText(), reverted.getText());
    }

    private void revertAndAssert(Event expected, int rev) {
        //List<AuditEntry> auditEntries = auditEntryDao.getAuditEntries(expected, 0, MAX_RESULTS);
        Event reverted = (Event) revertEventService.revertToRevision(Event.class, rev, expected.getId());
        getEventUtil().assertEquivalent(expected, reverted);
        reverted = getEventDao().findById(expected.getId());
        getEventUtil().assertEquivalent(expected, reverted);
    }

    /**
     * This is to handle a problem that only occurs during integration testing, where
     * we need to evict the object so that we can have multiple different copies of it that reflect
     * it's previous states!  When we do that, the collections won't get loaded in (lazy loading)
     * so we do it by hand by accessing one of the objects.
     * 
     * @param event
     */
    private void freeFromSession(Event event) {
        if (event.getFlags() != null) {
            event.getFlags().size();
        }
        event.getUserTags().size();
        getSessionFactory().getCurrentSession().evict(event);
    }

}