Package org.apache.isis.runtimes.dflt.remoting.common.client

Source Code of org.apache.isis.runtimes.dflt.remoting.common.client.ProxyPersistorTest

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you 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.apache.isis.runtimes.dflt.remoting.common.client;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.List;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ObjectAdapterFactory;
import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.version.Version;
import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
import org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault;
import org.apache.isis.core.metamodel.spec.ObjectList;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLoader;
import org.apache.isis.core.testsupport.testdomain.Movie;
import org.apache.isis.core.testsupport.testdomain.Person;
import org.apache.isis.runtimes.dflt.bytecode.identity.objectfactory.ObjectFactoryBasic;
import org.apache.isis.runtimes.dflt.remoting.common.client.persistence.ClientSideTransactionManager;
import org.apache.isis.runtimes.dflt.remoting.common.client.persistence.PersistenceSessionProxy;
import org.apache.isis.runtimes.dflt.remoting.common.data.Data;
import org.apache.isis.runtimes.dflt.remoting.common.data.DummyEncodeableObjectData;
import org.apache.isis.runtimes.dflt.remoting.common.data.DummyIdentityData;
import org.apache.isis.runtimes.dflt.remoting.common.data.DummyNullValue;
import org.apache.isis.runtimes.dflt.remoting.common.data.DummyObjectData;
import org.apache.isis.runtimes.dflt.remoting.common.data.DummyReferenceData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.IdentityData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.NullData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.ObjectData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.ReferenceData;
import org.apache.isis.runtimes.dflt.remoting.common.data.query.PersistenceQueryData;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.ExecuteClientActionRequest;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.ExecuteClientActionResponse;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.FindInstancesRequest;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.HasInstancesRequest;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.KnownObjectsRequest;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.ResolveObjectRequest;
import org.apache.isis.runtimes.dflt.remoting.common.facade.ServerFacade;
import org.apache.isis.runtimes.dflt.remoting.common.protocol.ObjectEncoderDecoder;
import org.apache.isis.runtimes.dflt.runtime.persistence.adapterfactory.pojo.PojoAdapterFactory;
import org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager.AdapterManagerDefault;
import org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager.AdapterManagerExtended;
import org.apache.isis.runtimes.dflt.runtime.persistence.internal.RuntimeContextFromSession;
import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.ObjectFactory;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.OidGenerator;
import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSessionFactory;
import org.apache.isis.runtimes.dflt.runtime.testspec.MovieSpecification;
import org.apache.isis.runtimes.dflt.runtime.testsystem.ProxyJunit4TestCase;
import org.apache.isis.runtimes.dflt.runtime.testsystem.TestProxyAdapter;
import org.apache.isis.runtimes.dflt.runtime.testsystem.TestProxyOid;
import org.apache.isis.runtimes.dflt.runtime.testsystem.TestProxyOidGenerator;
import org.apache.isis.runtimes.dflt.runtime.testsystem.TestProxyVersion;

@RunWith(JMock.class)
public class ProxyPersistorTest extends ProxyJunit4TestCase {

    private final Mockery mockery = new JUnit4Mockery();

    private PersistenceSessionFactory mockPersistenceSessionFactory;
    private ServerFacade mockDistribution;
    private ObjectEncoderDecoder mockEncoder;

    private PersistenceSessionProxy persistenceSessionProxy;
    private ClientSideTransactionManager transactionManager;
    private AuthenticationSession session;

    private AdapterManagerExtended adapterManager;

    private ObjectAdapterFactory adapterFactory;
    private ObjectFactory objectFactory;
    private OidGenerator oidGenerator;

    @Before
    public void setUp() throws Exception {
        // createSystem();

        mockPersistenceSessionFactory = mockery.mock(PersistenceSessionFactory.class);
        mockDistribution = mockery.mock(ServerFacade.class);
        mockEncoder = mockery.mock(ObjectEncoderDecoder.class);

        adapterManager = new AdapterManagerDefault();
        adapterFactory = new PojoAdapterFactory();
        objectFactory = new ObjectFactoryBasic();
        oidGenerator = new TestProxyOidGenerator();

        final RuntimeContextFromSession runtimeContext = new RuntimeContextFromSession();
        final DomainObjectContainerDefault container = new DomainObjectContainerDefault();

        runtimeContext.injectInto(container);
        runtimeContext.setContainer(container);

        final ServicesInjectorDefault servicesInjector = new ServicesInjectorDefault();
        servicesInjector.setContainer(container);

        persistenceSessionProxy = new PersistenceSessionProxy(mockPersistenceSessionFactory, adapterFactory, objectFactory, servicesInjector, oidGenerator, adapterManager, mockDistribution, mockEncoder);

        persistenceSessionProxy.setSpecificationLoader(system.getReflector());
        transactionManager = new ClientSideTransactionManager(adapterManager, persistenceSessionProxy, mockDistribution, mockEncoder);
        transactionManager.injectInto(persistenceSessionProxy);

        session = IsisContext.getAuthenticationSession();

        system.setPersistenceSession(persistenceSessionProxy);

        ignoreCallsToInitializeMocks();
        persistenceSessionProxy.open();
    }

    @After
    public void tearDown() throws Exception {
    }

    private static SpecificationLoader getSpecificationLoader() {
        return IsisContext.getSpecificationLoader();
    }

    @Test
    public void testClientSideMakesNoRemoteCallsWhenNoWorkNeeded() throws Exception {
        mockery.checking(new Expectations() {
            {
                never(mockDistribution);
            }
        });

        transactionManager.startTransaction();
        transactionManager.endTransaction();
    }

    @Ignore("need to get working after refactoring")
    @Test
    public void testFindInstances() throws Exception {

        // The remote interface is asked for instances, which are returned as
        // data objects
        final DummyObjectData instanceData = new DummyObjectData(new TestProxyOid(12, true), Movie.class.getName(), true, new TestProxyVersion(3));

        // The data then needs to be decoded into the ObjectAdapter
        final TestProxyAdapter dummyObjectAdapter = new TestProxyAdapter();
        // new DummyOid(12, true), ResolveState.GHOST, "test");
        dummyObjectAdapter.setupObject(new Movie());
        dummyObjectAdapter.setupSpecification(new MovieSpecification());

        final PersistenceQueryData c = new TestCriteria();
        final ObjectSpecification noSpec = getSpecificationLoader().loadSpecification(Movie.class);
        final PersistenceQueryFindAllInstances criteria = new PersistenceQueryFindAllInstances(noSpec);

        final FindInstancesRequest request = new FindInstancesRequest(session, c);

        mockery.checking(new Expectations() {
            {
                one(mockEncoder).decode(instanceData);
                will(returnValue(dummyObjectAdapter));

                one(mockDistribution).findInstances(request);
                will(returnValue(new ObjectData[] { instanceData }));

                one(mockEncoder).encodePersistenceQuery(criteria);
                will(returnValue(c));
            }
        });

        final ObjectAdapter instances = persistenceSessionProxy.findInstances(criteria);

        // the proxy should return one instance, which will be the dummy object
        // created by the encoder's
        // restore call
        final ObjectList objects = (ObjectList) instances.getObject();
        assertEquals(1, objects.size());
        assertEquals(dummyObjectAdapter, objects.elements().nextElement());
    }

    @Test
    public void testResolveImmediatelyIgnoredWhenAlreadyResolving() throws Exception {

        final TestProxyAdapter object = new TestProxyAdapter();
        object.setupResolveState(ResolveState.RESOLVING);

        // implicit: expect no calls to encoder object
        mockery.checking(new Expectations() {
            {
                never(mockDistribution);
            }
        });

        persistenceSessionProxy.resolveImmediately(object);
    }

    @Ignore("need to get working after refactoring")
    @Test
    public void testResolveImmediately() throws Exception {

        final TestProxyAdapter object = new TestProxyAdapter();
        object.setupOid(new TestProxyOid(5));
        object.setupResolveState(ResolveState.GHOST);

        final IdentityData identityData = new DummyReferenceData();
        final ObjectData objectData = new DummyObjectData();
        final ResolveObjectRequest request = new ResolveObjectRequest(session, identityData);

        mockery.checking(new Expectations() {
            {
                // encoder used to create identity data for target object
                one(mockEncoder).encodeIdentityData(object);
                will(returnValue(identityData));

                // remote call asks for object's data
                one(mockDistribution).resolveImmediately(request);
                will(returnValue(objectData));

                // data decode expected
                one(mockEncoder).decode(objectData);
                will(returnValue(null));
            }
        });

        persistenceSessionProxy.resolveImmediately(object);

        /*
         *
         * assertEquals("ET", movie.getName()); assertEquals(new DummyOid(5),
         * object.getOid()); assertEquals(new DummyVersion(3),
         * object.getVersion());
         */
    }

    @Ignore("TODO")
    @Test
    public void testResolveField_TBI() {
    }

    @Ignore("need to get working after refactoring")
    @Test
    public void testHasInstances() throws Exception {

        final HasInstancesRequest request = new HasInstancesRequest(session, Movie.class.getName());
        mockery.checking(new Expectations() {
            {
                one(mockDistribution).hasInstances(request);
                will(returnValue(true));

                one(mockDistribution).hasInstances(request);
                will(returnValue(false));
            }
        });

        final ObjectSpecification type = getSpecificationLoader().loadSpecification(Movie.class);
        assertTrue(persistenceSessionProxy.hasInstances(type));
        assertFalse(persistenceSessionProxy.hasInstances(type));
    }

    public void testFindInstancesButNoneFound() throws Exception {

        // system.addSpecificationToLoader(new MovieSpecification());

        final PersistenceQueryData c = new TestCriteria();
        final ObjectSpecification noSpec = getSpecificationLoader().loadSpecification(Movie.class);
        final PersistenceQueryFindAllInstances criteria = new PersistenceQueryFindAllInstances(noSpec);
        final FindInstancesRequest request = new FindInstancesRequest(session, c);

        mockery.checking(new Expectations() {
            {
                one(mockDistribution).findInstances(request);
                will(returnValue(new ObjectData[0]));

                one(mockEncoder).encodePersistenceQuery(criteria);
                will(returnValue(c));
            }
        });

        persistenceSessionProxy.findInstances(criteria);
    }

    @Test(expected = IllegalStateException.class)
    public void testClientSideActionThrowsExceptionWhenTransactionNotStarted() throws Exception {

        transactionManager.endTransaction();
    }

    @Test
    public void testClientSideActionWhereObjectDeleted() throws Exception {

        final ObjectAdapter movieAdapter = system.createPersistentTestObject();

        // test starts here
        mockery.checking(new Expectations() {
            {
                final DummyIdentityData identityOfObjectToDelete = encoderShouldCreateIdentityDataForMovie(movieAdapter);
                distributionShouldExecuteClientActionForDeletedMovie(identityOfObjectToDelete);
            }

            private DummyIdentityData encoderShouldCreateIdentityDataForMovie(final ObjectAdapter movieAdapter) {
                final DummyIdentityData identityOfObjectToDelete = new DummyIdentityData();

                one(mockEncoder).encodeIdentityData(movieAdapter);
                will(returnValue(identityOfObjectToDelete));
                return identityOfObjectToDelete;
            }

            private void distributionShouldExecuteClientActionForDeletedMovie(final DummyIdentityData identityOfObjectToDelete) {
                final Version[] versionUpdates = new Version[] {};
                one(mockDistribution).executeClientAction(with(any(ExecuteClientActionRequest.class)));
                will(returnValue(new ExecuteClientActionResponse(new ObjectData[] {}, versionUpdates, new ObjectData[0])));
            }
        });

        // TODO: should look inside the request object and ensure:
        // with(equalTo(session)),
        // with(equalTo(new ReferenceData[] { identityOfObjectToDelete })),
        // with(equalTo(new int[] { ClientTransactionEvent.DELETE })),

        transactionManager.startTransaction();
        persistenceSessionProxy.destroyObject(movieAdapter);
        transactionManager.endTransaction();
        final List<ObjectAdapter> allDisposedObjects = IsisContext.getUpdateNotifier().getDisposedObjects();

        assertFalse(allDisposedObjects.isEmpty());
        assertEquals(movieAdapter, allDisposedObjects.get(0));
    }

    @Test
    public void testClientSideActionWhereObjectChanged() throws Exception {

        final TestProxyAdapter directorAdapter = new TestProxyAdapter();
        directorAdapter.setupResolveState(ResolveState.RESOLVED);

        final TestProxyAdapter movieAdapter = new TestProxyAdapter();
        movieAdapter.setupResolveState(ResolveState.RESOLVED);

        mockery.checking(new Expectations() {
            {
                final DummyObjectData movieData = encoderShouldCreateGraphForChangedMovie(movieAdapter);
                final DummyObjectData directorData = encoderShouldCreateGraphForChangedDirector(directorAdapter);
                distributionShouldExecuteClientActionForBothChangedObjects(movieData, directorData);
            }

            private DummyObjectData encoderShouldCreateGraphForChangedMovie(final TestProxyAdapter movieAdapter) {
                final DummyObjectData movieData = new DummyObjectData(new TestProxyOid(12, true), Movie.class.getName(), true, new TestProxyVersion(4));
                final DummyEncodeableObjectData expectedMovieName = new DummyEncodeableObjectData("War of the Worlds", String.class.getName());
                final DummyReferenceData expectedDirectorRef = new DummyReferenceData(new TestProxyOid(14, true), Person.class.getName(), new TestProxyVersion(8));
                movieData.setFieldContent(new Data[] { expectedDirectorRef, expectedMovieName });

                one(mockEncoder).encodeGraphForChangedObject(movieAdapter, new KnownObjectsRequest());
                will(returnValue(movieData));
                return movieData;
            }

            private DummyObjectData encoderShouldCreateGraphForChangedDirector(final TestProxyAdapter directorAdapter) {
                final DummyObjectData directorData = new DummyObjectData(new TestProxyOid(14, true), Person.class.getName(), true, new TestProxyVersion(8));
                final DummyEncodeableObjectData expectedDirectorName = new DummyEncodeableObjectData("Unknown", String.class.getName());
                directorData.setFieldContent(new Data[] { expectedDirectorName });

                one(mockEncoder).encodeGraphForChangedObject(directorAdapter, new KnownObjectsRequest());
                will(returnValue(directorData));
                return directorData;
            }

            private void distributionShouldExecuteClientActionForBothChangedObjects(final DummyObjectData movieData, final DummyObjectData directorData) {
                // final ObjectData[] changes = new ObjectData[] { movieData,
                // directorData };
                // final int[] types = new int[] {
                // ClientTransactionEvent.CHANGE, ClientTransactionEvent.CHANGE
                // };

                one(mockDistribution).executeClientAction(with(any(ExecuteClientActionRequest.class)));

                final Version[] versionUpdates = new Version[] { new TestProxyVersion(5), new TestProxyVersion(9) };
                will(returnValue(new ExecuteClientActionResponse(new ObjectData[] { movieData, directorData }, versionUpdates, new ObjectData[0])));
            }
        });
        // TODO: should look inside the request object and ensure:
        // with(equalTo(session)),
        // with(equalTo(changes)),
        // with(equalTo(types)),

        transactionManager.startTransaction();
        persistenceSessionProxy.objectChanged(movieAdapter);
        persistenceSessionProxy.objectChanged(directorAdapter);
        transactionManager.endTransaction();

        assertEquals(new TestProxyVersion(5), movieAdapter.getVersion());
        assertEquals(new TestProxyVersion(9), directorAdapter.getVersion());
    }

    @Test
    public void testClientSideActionWhereTransientObjectMadePersistent() throws Exception {

        final ObjectAdapter transientObject = system.createTransientTestObject();

        final TestProxyOid previousOid = (TestProxyOid) transientObject.getOid();
        final DummyObjectData movieData = new DummyObjectData(previousOid, Movie.class.getName(), true, null);
        final NullData directorData = new DummyNullValue(Person.class.getName());
        final DummyEncodeableObjectData nameData = new DummyEncodeableObjectData("Star Wars", String.class.getName());
        movieData.setFieldContent(new Data[] { directorData, nameData });

        mockery.checking(new Expectations() {
            {
                // this returns results data with new oid and version
                final TestProxyOid newOid = new TestProxyOid(123, true);
                newOid.setupPrevious(previousOid);
                final DummyReferenceData updateData = new DummyReferenceData(newOid, "type", new TestProxyVersion(456));

                // the server is called with data (movieData) for the object to
                // be persisted
                one(mockDistribution).executeClientAction(with(any(ExecuteClientActionRequest.class)));

                will(returnValue(new ExecuteClientActionResponse(new ReferenceData[] { updateData }, null, new ObjectData[0])));
            }

        });
        // TODO: should look inside the request object and ensure:
        // with(equalTo(session)),
        // with(equalTo(new ReferenceData[] { movieData })),
        // with(equalTo(new int[] { ClientTransactionEvent.ADD })),

        getAdapterManager().adapterFor(transientObject.getObject());

        // client needs to encode the object's transient aspects
        mockery.checking(new Expectations() {
            {
                one(mockEncoder).encodeMakePersistentGraph(with(equalTo(transientObject)), with(any(KnownObjectsRequest.class)));
                will(returnValue(movieData));
            }
        });

        transactionManager.startTransaction();
        persistenceSessionProxy.makePersistent(transientObject);
        transactionManager.endTransaction();
    }

    // /////////////////////////////
    // helpers
    // /////////////////////////////

    private void ignoreCallsToInitializeMocks() {
        mockery.checking(new Expectations() {
            {
                ignoring(mockDistribution).init();
            }
        });
    }

    private void ignoreCallsToDistribution() {
        mockery.checking(new Expectations() {
            {
                ignoring(mockDistribution);
            }
        });
    }

}

class TestCriteria implements PersistenceQueryData {
    private static final long serialVersionUID = 1L;

    @Override
    public Class getPersistenceQueryClass() {
        return null;
    }

    public boolean includeSubclasses() {
        return false;
    }

    @Override
    public String getType() {
        return null;
    }
}
TOP

Related Classes of org.apache.isis.runtimes.dflt.remoting.common.client.ProxyPersistorTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.