/* * Copyright 2010 Google Inc. * * 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 com.google.web.bindery.requestfactory.gwt.client; import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.web.bindery.autobean.shared.AutoBean; import com.google.web.bindery.autobean.shared.AutoBeanUtils; import com.google.web.bindery.event.shared.EventBus; import com.google.web.bindery.event.shared.SimpleEventBus; import com.google.web.bindery.requestfactory.shared.BaseProxy; import com.google.web.bindery.requestfactory.shared.DefaultProxyStore; import com.google.web.bindery.requestfactory.shared.EntityProxy; import com.google.web.bindery.requestfactory.shared.EntityProxyChange; import com.google.web.bindery.requestfactory.shared.ProxySerializer; import com.google.web.bindery.requestfactory.shared.Receiver; import com.google.web.bindery.requestfactory.shared.RequestContext; import com.google.web.bindery.requestfactory.shared.SimpleFooRequest; import com.google.web.bindery.requestfactory.shared.SimpleRequestFactory; import com.google.web.bindery.requestfactory.shared.impl.BaseProxyCategory; import com.google.web.bindery.requestfactory.shared.impl.Constants; import com.google.web.bindery.requestfactory.shared.impl.SimpleProxyId; /** * A base class for anything that makes use of the SimpleRequestFactory. * Subclasses must always use {@link #finishTestAndReset()} in order to allow * calls to the reset methods to complete before the next test starts. * */ public abstract class RequestFactoryTestBase extends GWTTestCase { /** * Class for counting events. */ protected class SimpleFooEventHandler<P extends EntityProxy> implements EntityProxyChange.Handler<P> { int persistEventCount = 0; int deleteEventCount = 0; int totalEventCount = 0; int updateEventCount = 0; public void onProxyChange(EntityProxyChange<P> event) { totalEventCount++; switch (event.getWriteOperation()) { case PERSIST: persistEventCount++; break; case DELETE: deleteEventCount++; break; case UPDATE: updateEventCount++; break; default: break; } } } protected EventBus eventBus; protected SimpleRequestFactory req; @Override public void gwtSetUp() { req = createFactory(); eventBus = req.getEventBus(); } protected void checkEqualityAndHashcode(Object a, Object b) { assertNotNull(a); assertNotNull(b); assertEquals(a.hashCode(), b.hashCode()); assertEquals(a, b); assertEquals(b, a); } /** * Check that some proxy type can be created by the given context and that * some other proxy type can't. */ protected void checkReachableTypes(RequestContext ctx, Class<? extends BaseProxy> shouldWork, Class<? extends BaseProxy> shouldFail) { assertNotNull(ctx.create(shouldWork)); try { // Metadata computation has only RequestFactory resolution // http://code.google.com/p/google-web-toolkit/issues/detail?id=6658 if (GWT.isClient()) { ctx.create(shouldFail); fail(); } else { assertNotNull(ctx.create(shouldFail)); } } catch (IllegalArgumentException expected) { if (!GWT.isClient()) { fail("Expect the create call to always work in RFSource implementation"); } } } /** * Run the given proxy through a ProxySerializer and verify that the * before-and-after values match. */ protected <T extends BaseProxy> T checkSerialization(T proxy) { AutoBean<T> originalBean = AutoBeanUtils.getAutoBean(proxy); SimpleProxyId<T> id = BaseProxyCategory.stableId(originalBean); DefaultProxyStore store = new DefaultProxyStore(); ProxySerializer s = req.getSerializer(store); String key = s.serialize(proxy); assertNotNull(key); // Use a new instance store = new DefaultProxyStore(store.encode()); s = req.getSerializer(store); T restored = s.deserialize(id.getProxyClass(), key); AutoBean<? extends BaseProxy> restoredBean = AutoBeanUtils.getAutoBean(restored); assertNotSame(proxy, restored); /* * Performing a regular assertEquals() or even an AutoBeanUtils.diff() here * is wrong. If any of the objects in the graph are unpersisted, it's * expected that the stable ids would change. Instead, we do a value-based * check. */ assertTrue(AutoBeanUtils.deepEquals(originalBean, restoredBean)); if (proxy instanceof EntityProxy && !id.isEphemeral()) { assertEquals(((EntityProxy) proxy).stableId(), ((EntityProxy) restored).stableId()); } // In deference to testing stable ids, copy the original id into the clone restoredBean.setTag(Constants.STABLE_ID, originalBean.getTag(Constants.STABLE_ID)); return restored; } protected void checkStableIdEquals(EntityProxy expected, EntityProxy actual) { assertEquals(expected.stableId(), actual.stableId()); assertEquals(expected.stableId().hashCode(), actual.stableId().hashCode()); assertSame(expected.stableId(), actual.stableId()); // No assumptions about the proxy objects (being proxies and all) assertNotSame(expected, actual); assertFalse(expected.equals(actual)); } /** * Create and initialize a new {@link SimpleRequestFactory}. */ protected SimpleRequestFactory createFactory() { SimpleRequestFactory toReturn = GWT.create(SimpleRequestFactory.class); toReturn.initialize(new SimpleEventBus()); return toReturn; } protected void finishTestAndReset() { SimpleFooRequest ctx = req.simpleFooRequest(); ctx.reset(); ctx.append(req.simpleBarRequest()).reset(); ctx.fire(new Receiver<Void>() { @Override public void onSuccess(Void response) { finishTest(); } }); } }