/* * Copyright (c) 2011-2013 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.emf.cdo.tests.bugzilla; import org.eclipse.emf.cdo.CDOInvalidationNotification; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.internal.net4j.protocol.CommitTransactionRequest; import org.eclipse.emf.cdo.net4j.CDONet4jSession; import org.eclipse.emf.cdo.net4j.CDONet4jSession.Options; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.tests.AbstractCDOTest; import org.eclipse.emf.cdo.tests.config.IModelConfig; import org.eclipse.emf.cdo.tests.model1.Customer; import org.eclipse.emf.cdo.tests.model1.SalesOrder; import org.eclipse.emf.cdo.tests.model1.legacy.Model1Factory; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CommitException; import org.eclipse.emf.cdo.view.CDOAdapterPolicy; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Bug 359992. * * @author Martin Fluegge */ public class Bugzilla_359992_Test extends AbstractCDOTest { private static final String RESOURCE_PATH = "/test1"; private CountDownLatch latch; @Override protected void doSetUp() throws Exception { super.doSetUp(); latch = new CountDownLatch(1); } @Requires(IModelConfig.CAPABILITY_LEGACY) public void testInvalidationNotification() throws Exception { CDOSession session = openSession(); CDONet4jSession.Options options = (Options)session.options(); options.setCommitTimeout(10 * CommitTransactionRequest.DEFAULT_MONITOR_TIMEOUT_SECONDS); CDOTransaction transaction1 = session.openTransaction(); transaction1.options().setInvalidationNotificationEnabled(true); CDOResource resource1 = transaction1.createResource(getResourcePath(RESOURCE_PATH)); // 1. Create a example model Customer customer1 = initializeModel(resource1); resource1.getContents().add(customer1); resource1.save(Collections.emptyMap()); transaction1.close(); session.close(); session = openSession(); transaction1 = session.openTransaction(); transaction1.options().setInvalidationNotificationEnabled(true); resource1 = transaction1.getResource(getResourcePath(RESOURCE_PATH)); customer1 = (Customer)resource1.getContents().get(1); TestAdapter adapter = new TestAdapter(); customer1.eAdapters().add(adapter); doClient2(); latch.await(10 * DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); assertEquals(true, adapter.notified()); assertEquals(adapter.getFailureMessage(), true, adapter.assertCorrectNotification()); } @Requires(IModelConfig.CAPABILITY_LEGACY) public void testDeltaNotification() throws Exception { CDOSession session = openSession(); CDONet4jSession.Options options = (Options)session.options(); options.setCommitTimeout(10 * CommitTransactionRequest.DEFAULT_MONITOR_TIMEOUT_SECONDS); CDOTransaction transaction1 = session.openTransaction(); transaction1.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL); CDOResource resource1 = transaction1.createResource(getResourcePath(RESOURCE_PATH)); // 1. Create a example model Customer customer1 = initializeModel(resource1); resource1.getContents().add(customer1); resource1.save(Collections.emptyMap()); transaction1.close(); session.close(); session = openSession(); transaction1 = session.openTransaction(); transaction1.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL); resource1 = transaction1.getResource(getResourcePath(RESOURCE_PATH)); customer1 = (Customer)resource1.getContents().get(1); TestAdapter adapter = new TestAdapter(); customer1.eAdapters().add(adapter); doClient2(); latch.await(10 * DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); assertEquals(true, adapter.notified()); assertEquals(adapter.getFailureMessage(), true, adapter.assertCorrectNotification()); } private Customer initializeModel(CDOResource resource1) { Customer customer1 = Model1Factory.eINSTANCE.createCustomer(); customer1.setName("Martin Fluegge"); customer1.setStreet("ABC Street 7"); customer1.setCity("Berlin"); SalesOrder salesOrder = Model1Factory.eINSTANCE.createSalesOrder(); customer1.getSalesOrders().add(salesOrder); resource1.getContents().add(salesOrder); return customer1; } private void doClient2() throws CommitException { CDOSession session = openSession(); CDONet4jSession.Options options = (Options)session.options(); options.setCommitTimeout(10 * CommitTransactionRequest.DEFAULT_MONITOR_TIMEOUT_SECONDS); CDOTransaction transaction2 = session.openTransaction(); Resource resource2 = transaction2.getResource(getResourcePath(RESOURCE_PATH)); Customer customer2 = (Customer)resource2.getContents().get(1); SalesOrder existingSalesOrder = customer2.getSalesOrders().get(0); EcoreUtil.delete(existingSalesOrder); SalesOrder newSalesOrder = Model1Factory.eINSTANCE.createSalesOrder(); customer2.getSalesOrders().add(newSalesOrder); resource2.getContents().add(newSalesOrder); transaction2.commit(); } /** * @author Martin Fluegge */ class TestAdapter extends AdapterImpl { private boolean assertCorrectNotification; private boolean notified; private String failureMessage; @Override public void notifyChanged(Notification notification) { // If a previous received notification was incorrect we doesn't checks anymore if (!notified || notified && assertCorrectNotification) { Object notifier = notification.getNotifier(); assertCorrectNotification = notifier instanceof Customer; if (!assertCorrectNotification) { failureMessage = "Notifier is not the expected type : " + notifier.getClass().getName(); } if (!(notification instanceof CDOInvalidationNotification) && assertCorrectNotification) { int eventType = notification.getEventType(); if (Notification.ADD == eventType) { Object newValue = notification.getNewValue(); assertCorrectNotification = newValue instanceof SalesOrder; if (!assertCorrectNotification) { failureMessage = "Notification.getNewValue() is not the expected type : " + newValue.getClass().getName(); } } else if (Notification.REMOVE == eventType) { Object oldValue = notification.getOldValue(); assertCorrectNotification = oldValue instanceof SalesOrder; if (!assertCorrectNotification) { failureMessage = "Notification.getOldValue() is not the expected type : " + oldValue.getClass().getName(); } } } notified = true; latch.countDown(); } } public boolean notified() { return notified; } public boolean assertCorrectNotification() { return assertCorrectNotification; } public String getFailureMessage() { return failureMessage; } } }