| /* |
| * Copyright 2012 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.shared.impl; |
| |
| 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.AutoBeanCodex; |
| import com.google.web.bindery.autobean.shared.AutoBeanUtils; |
| import com.google.web.bindery.event.shared.SimpleEventBus; |
| import com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport; |
| import com.google.web.bindery.requestfactory.shared.Receiver; |
| import com.google.web.bindery.requestfactory.shared.RequestTransport; |
| import com.google.web.bindery.requestfactory.shared.SimpleFooProxy; |
| import com.google.web.bindery.requestfactory.shared.SimpleFooRequest; |
| import com.google.web.bindery.requestfactory.shared.SimpleRequestFactory; |
| import com.google.web.bindery.requestfactory.shared.SimpleValueProxy; |
| import com.google.web.bindery.requestfactory.shared.messages.OperationMessage; |
| import com.google.web.bindery.requestfactory.shared.messages.RequestMessage; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| |
| /** |
| * Contains a few tests regarding request payload, to make sure we don't send |
| * too many things to the server. |
| * <p> |
| * Uses a special {@link RequestContext} that records the last request payload, |
| * then parses and introspects it to see what's really been sent over the wire |
| * in relation to what had been enqueued in the request context. |
| */ |
| public class RequestPayloadTest extends GWTTestCase { |
| |
| /** |
| * Records the request payload so it can be re-parsed and analyzed. |
| */ |
| protected static class RecordingRequestTransport implements RequestTransport { |
| public String lastRequestPayload; |
| private final RequestTransport realTransport; |
| |
| public RecordingRequestTransport(RequestTransport realTransport) { |
| this.realTransport = realTransport; |
| } |
| |
| @Override |
| public void send(String payload, TransportReceiver receiver) { |
| this.lastRequestPayload = payload; |
| realTransport.send(payload, receiver); |
| } |
| } |
| |
| protected SimpleRequestFactory factory; |
| protected RecordingRequestTransport transport; |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.web.bindery.requestfactory.gwt.RequestFactorySuite"; |
| } |
| |
| /** |
| * Tests that no more proxies and property values than necessary are being sent. |
| */ |
| public void testOperationPayload() throws Exception { |
| delayTestFinish(5000); |
| |
| SimpleFooRequest context = factory.simpleFooRequest(); |
| context.findSimpleFooById(1L).with("barField", "oneToManyField").fire( |
| new Receiver<SimpleFooProxy>() { |
| @Override |
| public void onSuccess(final SimpleFooProxy response) { |
| SimpleFooRequest context = factory.simpleFooRequest(); |
| final SimpleFooProxy foo = context.edit(response); |
| |
| // simply casting 'factory' to AbstractRequestFactory would fail |
| // when run as a JRE test. |
| final AbstractRequestFactory abstractRequestFactory = |
| AutoBeanUtils.getAutoBean(foo).<AbstractRequestContext.State> getTag( |
| Constants.REQUEST_CONTEXT_STATE).requestFactory; |
| final String fooTypeToken = abstractRequestFactory.getTypeToken(SimpleFooProxy.class); |
| final String valueTypeToken = |
| abstractRequestFactory.getTypeToken(SimpleValueProxy.class); |
| |
| // Create |
| final SimpleValueProxy created = context.create(SimpleValueProxy.class); |
| created.setNumber(42); |
| created.setString("Hello world!"); |
| created.setSimpleFoo(foo); |
| // Test cycles in value |
| created.setSimpleValue(Arrays.asList(created)); |
| |
| // Set |
| foo.setSimpleValue(created); |
| foo.setSimpleValues(Collections.singletonList(created)); |
| |
| context.persistAndReturnSelf().using(foo).with("barField", "oneToManyField", |
| "oneToManySetField", "simpleValue", "simpleValues").fire( |
| new Receiver<SimpleFooProxy>() { |
| @Override |
| public void onSuccess(SimpleFooProxy response) { |
| RequestMessage requestMessage = |
| AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, RequestMessage.class, |
| transport.lastRequestPayload).as(); |
| |
| int seenFoos = 0; |
| int seenValues = 0; |
| for (OperationMessage operationMessage : requestMessage.getOperations()) { |
| if (fooTypeToken.equals(operationMessage.getTypeToken())) { |
| seenFoos++; |
| @SuppressWarnings("unchecked") |
| SimpleProxyId<?> id = (SimpleProxyId<?>) foo.stableId(); |
| assertEquals(id.getServerId(), operationMessage.getServerId()); |
| assertEquals(2, operationMessage.getPropertyMap().size()); |
| assertTrue(operationMessage.getPropertyMap().containsKey("simpleValue")); |
| assertTrue(operationMessage.getPropertyMap().containsKey("simpleValues")); |
| } else if (valueTypeToken.equals(operationMessage.getTypeToken())) { |
| seenValues++; |
| AutoBean<SimpleValueProxy> bean = AutoBeanUtils.getAutoBean(created); |
| SimpleProxyId<?> id = BaseProxyCategory.stableId(bean); |
| assertEquals(id.getClientId(), operationMessage.getClientId()); |
| assertEquals(AutoBeanUtils.getAllProperties(bean).keySet(), |
| operationMessage.getPropertyMap().keySet()); |
| } |
| } |
| assertTrue(seenFoos > 0); |
| assertTrue(seenValues > 0); |
| |
| // Persist without any change |
| factory.simpleFooRequest().persistAndReturnSelf().using(response).fire( |
| new Receiver<SimpleFooProxy>() { |
| |
| @Override |
| public void onSuccess(SimpleFooProxy response) { |
| RequestMessage requestMessage = |
| AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, |
| RequestMessage.class, transport.lastRequestPayload).as(); |
| |
| int seenFoos = 0; |
| for (OperationMessage operationMessage : requestMessage.getOperations()) { |
| if (fooTypeToken.equals(operationMessage.getTypeToken())) { |
| seenFoos++; |
| assertNull(operationMessage.getPropertyMap()); |
| } |
| } |
| assertTrue(seenFoos > 0); |
| |
| finishTest(); |
| } |
| }); |
| } |
| }); |
| } |
| }); |
| } |
| |
| /** |
| * Create (without initializing) a new {@link SimpleRequestFactory}. |
| */ |
| protected SimpleRequestFactory createFactory() { |
| return GWT.create(SimpleRequestFactory.class); |
| } |
| |
| /** |
| * Create a new {@link RequestTransport}. |
| */ |
| protected RequestTransport createTransport() { |
| return new DefaultRequestTransport(); |
| } |
| |
| @Override |
| protected void gwtSetUp() throws Exception { |
| factory = createFactory(); |
| transport = new RecordingRequestTransport(createTransport()); |
| factory.initialize(new SimpleEventBus(), transport); |
| } |
| } |