/*
 * 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.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyChange;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.OnlyUsedByRequestContextMethod;
import com.google.web.bindery.requestfactory.shared.OnlyUsedInListProxy;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.google.web.bindery.requestfactory.shared.SimpleBarProxy;
import com.google.web.bindery.requestfactory.shared.SimpleBarRequest;
import com.google.web.bindery.requestfactory.shared.SimpleEnum;
import com.google.web.bindery.requestfactory.shared.SimpleFooProxy;
import com.google.web.bindery.requestfactory.shared.SimpleFooRequest;
import com.google.web.bindery.requestfactory.shared.SimpleValueContext;
import com.google.web.bindery.requestfactory.shared.SimpleValueProxy;
import com.google.web.bindery.requestfactory.shared.Violation;
import com.google.web.bindery.requestfactory.shared.impl.SimpleEntityProxyId;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Tests for {@link com.google.web.bindery.requestfactory.shared.RequestFactory}.
 */
public class RequestFactoryTest extends RequestFactoryTestBase {
  /*
   * DO NOT USE finishTest(). Instead, call finishTestAndReset();
   * 
   * When possible, pass any returned proxies to checkSerialization() and use
   * the return value in the place of the returned object.
   */

  class FooReciever extends Receiver<SimpleFooProxy> {
    private SimpleFooProxy mutableFoo;
    private Request<SimpleFooProxy> persistRequest;
    private String expectedException;

    public FooReciever(SimpleFooProxy mutableFoo,
        Request<SimpleFooProxy> persistRequest, String exception) {
      this.mutableFoo = mutableFoo;
      this.persistRequest = persistRequest;
      this.expectedException = exception;
    }

    @Override
    public void onFailure(ServerFailure error) {
      assertEquals(expectedException, error.getExceptionType());
      if (expectedException != null) {
        assertFalse(error.getStackTraceString().length() == 0);
        assertEquals("THIS EXCEPTION IS EXPECTED BY A TEST", error.getMessage());
      } else {
        assertEquals(null, error.getStackTraceString());
        assertEquals("Server Error: THIS EXCEPTION IS EXPECTED BY A TEST",
            error.getMessage());
      }

      // Now show that we can fix the error and try again with the same
      // request

      mutableFoo.setPleaseCrash(24); // Only 42 and 43 crash
      persistRequest.fire(new Receiver<SimpleFooProxy>() {
        @Override
        public void onSuccess(SimpleFooProxy response) {
          response = checkSerialization(response);
          finishTestAndReset();
        }
      });
    }

    @Override
    public void onSuccess(SimpleFooProxy response) {
      fail("Failure expected but onSuccess() was called");
    }

    @Override
    public void onViolation(Set<Violation> errors) {
      fail("Failure expected but onViolation() was called");
    }
  }

  class NullReceiver extends Receiver<Object> {
    @Override
    public void onSuccess(Object response) {
      assertNull(response);
      finishTestAndReset();
    }
  }

  private class FailFixAndRefire<T> extends Receiver<T> {

    private final SimpleFooProxy proxy;
    private final Request<T> request;
    private boolean voidReturnExpected;

    FailFixAndRefire(SimpleFooProxy proxy, RequestContext context,
        Request<T> request) {
      this.proxy = context.edit(proxy);
      this.request = request;
    }

    @Override
    public void onSuccess(T response) {
      /*
       * Make sure your class path includes:
       * 
       * tools/lib/apache/log4j/log4j-1.2.16.jar
       * tools/lib/hibernate/validator/hibernate-validator-4.1.0.Final.jar
       * tools/lib/slf4j/slf4j-api/slf4j-api-1.6.1.jar
       * tools/lib/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar
       */
      fail("Violations expected (you might be missing some jars, "
          + "see the comment above this line)");
    }

    @Override
    public void onViolation(Set<Violation> errors) {

      // size violation expected

      assertEquals(1, errors.size());
      Violation error = errors.iterator().next();
      assertEquals("userName", error.getPath());
      assertEquals("size must be between 3 and 30", error.getMessage());
      assertEquals(proxy.stableId(), error.getProxyId());

      // Now re-used the request to fix the edit

      proxy.setUserName("long enough");
      request.fire(new Receiver<T>() {
        @Override
        public void onSuccess(T response) {
          if (voidReturnExpected) {
            assertNull(response);
          } else {
            assertEquals(proxy.stableId(),
                ((SimpleFooProxy) response).stableId());
          }
          finishTestAndReset();
        }
      });
    }

    void doTest() {
      proxy.setUserName("a"); // too short
      request.fire(this);
    }

    void doVoidTest() {
      voidReturnExpected = true;
      doTest();
    }
  }

  private static final int DELAY_TEST_FINISH = 10 * 1000;

  public <T extends EntityProxy> void assertContains(Collection<T> col, T value) {
    EntityProxyId<?> lookFor = value.stableId();
    for (T x : col) {
      EntityProxyId<?> found = x.stableId();
      if (found.equals(lookFor)) {
        return;
      }
    }
    assertTrue("Value " + value + " not found in collection " + col.toString(),
        false);
  }

  public <T extends EntityProxy> void assertNotContains(Collection<T> col,
      T value) {
    for (T x : col) {
      assertNotSame(x.stableId(), value.stableId());
    }
  }

  @Override
  public String getModuleName() {
    return "com.google.web.bindery.requestfactory.gwt.RequestFactorySuite";
  }

  /**
   * Test that the same object, referenced twice, points to the same instance.
   */
  public void testAntiAliasing() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().fetchDoubleReference().with("fooField",
        "selfOneToManyField").fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        assertNotNull(response.getFooField());
        assertSame(response.getFooField(),
            response.getSelfOneToManyField().get(0));
        finishTestAndReset();
      }
    });
  }

  /**
   * Test that we can commit child objects.
   */
  public void testCascadingCommit() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest context = req.simpleFooRequest();
    final SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    final SimpleBarProxy bar0 = context.create(SimpleBarProxy.class);
    final SimpleBarProxy bar1 = context.create(SimpleBarProxy.class);
    List<SimpleBarProxy> bars = new ArrayList<SimpleBarProxy>();
    bars.add(bar0);
    bars.add(bar1);

    final SimpleFooEventHandler<SimpleBarProxy> handler = new SimpleFooEventHandler<SimpleBarProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleBarProxy.class, handler);

    Request<SimpleFooProxy> request = context.persistCascadingAndReturnSelf().using(
        foo);
    SimpleFooProxy editFoo = context.edit(foo);
    editFoo.setOneToManyField(bars);
    request.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        assertFalse(((SimpleEntityProxyId<SimpleFooProxy>) response.stableId()).isEphemeral());
        assertEquals(2, handler.persistEventCount); // two bars persisted.
        assertEquals(2, handler.updateEventCount); // two bars persisted.
        assertEquals(4, handler.totalEventCount);
        finishTestAndReset();
      }
    });
  }

  public void testChangedCreate() {
    SimpleFooRequest context = simpleFooRequest();

    // Creates don't cause a change
    SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    assertFalse(context.isChanged());

    // Change
    foo.setCharField('c');
    assertTrue(context.isChanged());

    // Undo the change
    foo.setCharField(null);
    assertFalse(context.isChanged());
  }

  public void testChangedCreateValueProxy() {
    SimpleFooRequest context = simpleFooRequest();

    // Creates don't cause a change
    SimpleValueProxy foo = context.create(SimpleValueProxy.class);
    assertFalse(context.isChanged());

    // Change
    foo.setString("foo");
    assertTrue(context.isChanged());

    // Undo the change
    foo.setString(null);
    assertFalse(context.isChanged());
  }

  public void testChangedEdit() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(1L).fire(
        new Receiver<SimpleFooProxy>() {

          @Override
          public void onSuccess(SimpleFooProxy foo) {
            foo = checkSerialization(foo);
            SimpleFooRequest context = simpleFooRequest();

            // edit() doesn't cause a change
            foo = context.edit(foo);
            assertFalse(context.isChanged());

            final String newName = "something else;";
            String oldName = foo.getUserName();
            assertFalse("Don't accidentally set the same name",
                newName.equals(oldName));

            // gets don't cause a change
            assertFalse(context.isChanged());

            // Change
            foo.setUserName(newName);
            assertTrue(context.isChanged());

            // Undo the change
            foo.setUserName(oldName);
            assertFalse(context.isChanged());

            finishTestAndReset();
          }
        });
  }

  public void testChangedNothing() {
    SimpleFooRequest context = simpleFooRequest();
    assertFalse(context.isChanged());
  }

  public void testClassToken() {
    String token = req.getHistoryToken(SimpleFooProxy.class);
    assertEquals(SimpleFooProxy.class, req.getProxyClass(token));

    SimpleFooProxy foo = simpleFooRequest().create(SimpleFooProxy.class);
    assertEquals(SimpleFooProxy.class, foo.stableId().getProxyClass());
  }

  public void testCollectionSubProperties() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().getSimpleFooWithSubPropertyCollection().with(
        "selfOneToManyField", "selfOneToManyField.fooField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertEquals(
                "I'm here",
                response.getSelfOneToManyField().get(0).getFooField().getUserName());
            finishTestAndReset();
          }
        });
  }

  public void testDomainUpcast() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnSimpleFooSubclass().fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertEquals(42, response.getIntId().intValue());
            finishTestAndReset();
          }
        });
  }

  public void testDummyCreate() {
    delayTestFinish(DELAY_TEST_FINISH);

    final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, handler);

    SimpleFooRequest context = simpleFooRequest();
    final SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    final EntityProxyId<SimpleFooProxy> futureId = foo.stableId();
    assertTrue(((SimpleEntityProxyId<?>) futureId).isEphemeral());
    Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(foo);
    fooReq.fire(new Receiver<SimpleFooProxy>() {

      @Override
      public void onSuccess(SimpleFooProxy returned) {
        returned = checkSerialization(returned);
        EntityProxyId<SimpleFooProxy> returnedId = returned.stableId();
        assertEquals(futureId, returnedId);
        assertFalse((((SimpleEntityProxyId<?>) returnedId).isEphemeral()));
        assertEquals(1, handler.persistEventCount);
        assertEquals(1, handler.updateEventCount);
        assertEquals(2, handler.totalEventCount);

        checkStableIdEquals(foo, returned);
        finishTestAndReset();
      }
    });
  }

  public void testDummyCreateBar() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleBarRequest context = simpleBarRequest();
    final SimpleBarProxy foo = context.create(SimpleBarProxy.class);
    assertTrue(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());
    Request<SimpleBarProxy> fooReq = context.persistAndReturnSelf().using(foo);
    fooReq.fire(new Receiver<SimpleBarProxy>() {

      @Override
      public void onSuccess(SimpleBarProxy returned) {
        returned = checkSerialization(returned);
        assertFalse(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());

        checkStableIdEquals(foo, returned);
        finishTestAndReset();
      }
    });
  }

  public void testDummyCreateList() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleBarRequest context = simpleBarRequest();
    final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
    assertTrue(((SimpleEntityProxyId<?>) bar.stableId()).isEphemeral());
    Request<SimpleBarProxy> fooReq = context.returnFirst(Collections.singletonList(bar));
    fooReq.fire(new Receiver<SimpleBarProxy>() {

      @Override
      public void onSuccess(SimpleBarProxy returned) {
        returned = checkSerialization(returned);
        assertFalse(((SimpleEntityProxyId<?>) bar.stableId()).isEphemeral());
        assertFalse(((SimpleEntityProxyId<?>) returned.stableId()).isEphemeral());

        checkStableIdEquals(bar, returned);
        finishTestAndReset();
      }
    });
  }

  /**
   * Tests behaviors relating to editing an object with one context and then
   * using with another.
   */
  public void testEditAcrossContexts() {
    SimpleFooRequest contextA = simpleFooRequest();
    final SimpleFooRequest contextB = simpleFooRequest();

    SimpleFooProxy fromA = contextA.create(SimpleFooProxy.class);

    try {
      contextB.edit(fromA);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    try {
      contextB.persistAndReturnSelf().using(fromA).fire(
          new Receiver<SimpleFooProxy>() {
            @Override
            public void onSuccess(SimpleFooProxy response) {
              fail();
            }
          });
      fail();
    } catch (IllegalArgumentException expected) {
    }

    delayTestFinish(DELAY_TEST_FINISH);
    contextA.findSimpleFooById(999L).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        // The response shouldn't be associated with a RequestContext
        contextB.edit(response);
        finishTestAndReset();
      }
    });
  }

  /**
   * Tests that enum values used only as method parameters in a RequestContext
   * are in the EnumMap. This test only applies to GWT-based clients.
   */
  public void testEnumOnlyUsedByRequestContext() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest ctx = simpleFooRequest();
    ctx.receiveEnum(OnlyUsedByRequestContextMethod.FOO).fire(
        new Receiver<Void>() {
          @Override
          public void onSuccess(Void response) {
            finishTest();
          }
        });
  }

  /**
   * Check default value, a newly-set value, and a null value.
   */
  public void testEnumProperty() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            assertEquals(SimpleEnum.FOO, response.getEnumField());
            SimpleFooRequest ctx = simpleFooRequest();
            response = ctx.edit(response);
            response.setEnumField(SimpleEnum.BAR);
            ctx.persistAndReturnSelf().using(response).fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy response) {
                    assertEquals(SimpleEnum.BAR, response.getEnumField());
                    SimpleFooRequest ctx = simpleFooRequest();
                    response = ctx.edit(response);
                    response.setEnumField(null);
                    ctx.persistAndReturnSelf().using(response).fire(
                        new Receiver<SimpleFooProxy>() {
                          @Override
                          public void onSuccess(SimpleFooProxy response) {
                            assertNull(response.getEnumField());
                            finishTestAndReset();
                          }
                        });
                  }
                });
          }
        });
  }

  public void testFetchEntity() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertEquals(42, (int) response.getIntId());
            assertEquals("GWT", response.getUserName());
            assertEquals(8L, (long) response.getLongField());
            assertEquals(com.google.web.bindery.requestfactory.shared.SimpleEnum.FOO,
                response.getEnumField());
            assertEquals(null, response.getBarField());
            finishTestAndReset();
          }
        });
  }

  public void testFetchEntityWithRelation() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).with("barField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertEquals(42, (int) response.getIntId());
            assertEquals("GWT", response.getUserName());
            assertEquals(8L, (long) response.getLongField());
            assertEquals(com.google.web.bindery.requestfactory.shared.SimpleEnum.FOO,
                response.getEnumField());
            assertNotNull(response.getBarField());
            finishTestAndReset();
          }
        });
  }

  public void testFetchList() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findAll().fire(new Receiver<List<SimpleFooProxy>>() {
      @Override
      public void onSuccess(List<SimpleFooProxy> responseList) {
        SimpleFooProxy response = checkSerialization(responseList.get(0));
        assertEquals(42, (int) response.getIntId());
        assertEquals("GWT", response.getUserName());
        assertEquals(8L, (long) response.getLongField());
        assertEquals(com.google.web.bindery.requestfactory.shared.SimpleEnum.FOO,
            response.getEnumField());
        finishTestAndReset();
      }
    });
  }

  public void testFetchSet() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleBarRequest().findAsSet().fire(new Receiver<Set<SimpleBarProxy>>() {
      @Override
      public void onSuccess(Set<SimpleBarProxy> response) {
        assertEquals(2, response.size());
        finishTestAndReset();
      }
    });
  }

  public void testFindFindEdit() {
    delayTestFinish(DELAY_TEST_FINISH);

    final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, handler);

    req.simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {

          @Override
          public void onSuccess(SimpleFooProxy newFoo) {
            newFoo = checkSerialization(newFoo);
            assertEquals(1, handler.updateEventCount);
            assertEquals(1, handler.totalEventCount);

            req.simpleFooRequest().findSimpleFooById(999L).fire(
                new Receiver<SimpleFooProxy>() {

                  @Override
                  public void onSuccess(SimpleFooProxy newFoo) {
                    newFoo = checkSerialization(newFoo);
                    // no events are fired second time.
                    assertEquals(1, handler.updateEventCount);
                    assertEquals(1, handler.totalEventCount);
                    SimpleFooRequest context = req.simpleFooRequest();
                    final Request<Void> mutateRequest = context.persist().using(
                        newFoo);
                    newFoo = context.edit(newFoo);
                    newFoo.setUserName("Ray");
                    mutateRequest.fire(new Receiver<Void>() {
                      @Override
                      public void onSuccess(Void response) {
                        // events fired on updates.
                        assertEquals(2, handler.updateEventCount);
                        assertEquals(2, handler.totalEventCount);

                        finishTestAndReset();
                      }
                    });
                  }
                });
          }
        });
  }

  public void testForwardReferenceDecode() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().getTripletReference().with(
        "selfOneToManyField.selfOneToManyField.fooField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertNotNull(response.getSelfOneToManyField().get(0));
            assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField());
            assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField().get(
                0));
            assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField().get(
                0).getFooField());
            finishTestAndReset();
          }
        });
  }

  public void testGetEventBus() {
    assertEquals(eventBus, req.getEventBus());
  }

  public void testGetListLongId() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Long ids
    simpleFooRequest().findAll().with("barField.userName").fire(
        new Receiver<List<SimpleFooProxy>>() {
          @Override
          public void onSuccess(List<SimpleFooProxy> response) {
            assertEquals(2, response.size());
            for (SimpleFooProxy foo : response) {
              foo = checkSerialization(foo);
              assertNotNull(foo.stableId());
              assertEquals("FOO", foo.getBarField().getUserName());
            }
            finishTestAndReset();
          }
        });
  }

  public void testGetListStringId() {
    delayTestFinish(DELAY_TEST_FINISH);

    // String ids
    simpleBarRequest().findAll().fire(new Receiver<List<SimpleBarProxy>>() {
      @Override
      public void onSuccess(List<SimpleBarProxy> response) {
        assertEquals(2, response.size());
        for (SimpleBarProxy bar : response) {
          bar = checkSerialization(bar);
          assertNotNull(bar.stableId());
          finishTestAndReset();
        }
        finishTestAndReset();
      }
    });
  }

  public void testHistoryToken() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleBarRequest context = simpleBarRequest();
    final SimpleBarProxy foo = context.create(SimpleBarProxy.class);
    final EntityProxyId<SimpleBarProxy> futureId = foo.stableId();
    final String futureToken = req.getHistoryToken(futureId);

    // Check that a newly-created object's token can be found
    assertEquals(futureId, req.getProxyId(futureToken));
    assertEquals(futureId.getProxyClass(), req.getProxyClass(futureToken));

    Request<SimpleBarProxy> fooReq = context.persistAndReturnSelf().using(foo);
    fooReq.fire(new Receiver<SimpleBarProxy>() {
      @Override
      public void onSuccess(SimpleBarProxy returned) {
        returned = checkSerialization(returned);
        EntityProxyId<SimpleBarProxy> persistedId = returned.stableId();
        String persistedToken = req.getHistoryToken(returned.stableId());

        // Expect variations after persist
        assertFalse(futureToken.equals(persistedToken));

        // Make sure the token is stable after persist using the future id
        assertEquals(persistedToken, req.getHistoryToken(futureId));

        // Check that the persisted object can be found with future token
        assertEquals(futureId, req.getProxyId(futureToken));
        assertEquals(futureId, req.getProxyId(persistedToken));
        assertEquals(futureId.getProxyClass(),
            req.getProxyClass(persistedToken));

        assertEquals(persistedId, req.getProxyId(futureToken));
        assertEquals(persistedId, req.getProxyId(persistedToken));
        assertEquals(persistedId.getProxyClass(),
            req.getProxyClass(futureToken));

        finishTestAndReset();
      }
    });
  }

  public void testInstanceServiceRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    req.instanceServiceRequest().add(5).fire(new Receiver<Integer>() {
      @Override
      public void onSuccess(Integer response) {
        assertEquals(10, (int) response);
        finishTestAndReset();
      }
    });
  }

  public void testInstanceServiceRequestByName() {
    delayTestFinish(DELAY_TEST_FINISH);
    req.instanceServiceRequestByName().add(5).fire(new Receiver<Integer>() {
      @Override
      public void onSuccess(Integer response) {
        assertEquals(10, (int) response);
        finishTestAndReset();
      }
    });
  }

  /**
   * Make sure our stock RF logging service keeps receiving.
   */
  public void testLoggingService() {
    delayTestFinish(DELAY_TEST_FINISH);
    String logRecordJson = new StringBuilder("{") //
    .append("\"level\": \"ALL\", ") //
    .append("\"loggerName\": \"logger\", ") //
    .append("\"msg\": \"Hi mom\", ") //
    .append("\"timestamp\": \"1234567890\",") //
    .append("\"thrown\": {}") //
    .append("}") //
    .toString();

    req.loggingRequest().logMessage(logRecordJson).fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void response) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Test that removing a parent entity and implicitly removing the child sends
   * an event to the client that the child was removed.
   */
  public void testMethodWithSideEffectDeleteChild() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Handle changes to SimpleFooProxy.
    final SimpleFooEventHandler<SimpleFooProxy> fooHandler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, fooHandler);

    // Handle changes to SimpleBarProxy.
    final SimpleFooEventHandler<SimpleBarProxy> barHandler = new SimpleFooEventHandler<SimpleBarProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleBarProxy.class, barHandler);

    // Persist bar.
    SimpleBarRequest context = req.simpleBarRequest();
    final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
    context.persistAndReturnSelf().using(bar).fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy persistentBar) {
            persistentBar = checkSerialization(persistentBar);
            // Persist foo with bar as a child.
            SimpleFooRequest context = req.simpleFooRequest();
            SimpleFooProxy foo = context.create(SimpleFooProxy.class);
            final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
                foo).with("barField");
            foo = context.edit(foo);
            foo.setUserName("John");
            foo.setBarField(bar);
            persistRequest.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy persistentFoo) {
                persistentFoo = checkSerialization(persistentFoo);

                // Delete bar.
                SimpleFooRequest context = req.simpleFooRequest();
                final Request<Void> deleteRequest = context.deleteBar().using(
                    persistentFoo);
                deleteRequest.fire(new Receiver<Void>() {
                  @Override
                  public void onSuccess(Void response) {
                    assertEquals(1, fooHandler.persistEventCount);
                    assertEquals(2, fooHandler.updateEventCount);
                    assertEquals(3, fooHandler.totalEventCount);

                    assertEquals(1, barHandler.persistEventCount);
                    assertEquals(1, barHandler.updateEventCount);
                    assertEquals(1, barHandler.deleteEventCount);
                    assertEquals(3, barHandler.totalEventCount);
                    finishTestAndReset();
                  }
                });
              }
            });
          }
        });
  }

  /*
   * tests that (a) any method can have a side effect that is handled correctly.
   * (b) instance methods are handled correctly and (c) a request cannot be
   * reused after a successful response is received. (Yet?)
   */
  public void testMethodWithSideEffects() {
    delayTestFinish(DELAY_TEST_FINISH);

    final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, handler);

    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {

          @Override
          public void onSuccess(SimpleFooProxy newFoo) {
            newFoo = checkSerialization(newFoo);
            assertEquals(1, handler.updateEventCount);
            assertEquals(1, handler.totalEventCount);
            SimpleFooRequest context = simpleFooRequest();
            final Request<Long> mutateRequest = context.countSimpleFooWithUserNameSideEffect().using(
                newFoo);
            newFoo = context.edit(newFoo);
            newFoo.setUserName("Ray");
            mutateRequest.fire(new Receiver<Long>() {
              @Override
              public void onSuccess(Long response) {
                assertCannotFire(mutateRequest);
                assertEquals(new Long(2L), response);
                assertEquals(2, handler.updateEventCount);
                assertEquals(2, handler.totalEventCount);

                // confirm that the instance method did have the desired
                // sideEffect.
                simpleFooRequest().findSimpleFooById(999L).fire(
                    new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy finalFoo) {
                        finalFoo = checkSerialization(finalFoo);
                        assertEquals("Ray", finalFoo.getUserName());
                        assertEquals(2, handler.updateEventCount);
                        assertEquals(2, handler.totalEventCount);
                        finishTestAndReset();
                      }
                    });
              }

            });

            try {
              newFoo.setUserName("Barney");
              fail();
            } catch (IllegalStateException e) {
              /* pass, cannot change a request that is in flight */
            }
          }
        });
  }

  public void testMultipleEdits() {
    RequestContext c1 = req.simpleFooRequest();
    SimpleFooProxy proxy = c1.create(SimpleFooProxy.class);
    // Re-editing is idempotent
    assertSame(proxy, c1.edit(c1.edit(proxy)));

    // Should not allow "crossing the steams"
    RequestContext c2 = req.simpleFooRequest();
    try {
      c2.edit(proxy);
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  /**
   * Tests a no-op request.
   */
  public void testNoOpRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void response) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Ensures that a service method can respond with a null value.
   */
  public void testNullEntityProxyResult() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnNullSimpleFoo().fire(new NullReceiver());
  }

  /**
   * Test that a null value can be sent in a request.
   */
  public void testNullListRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<Void> fooReq = req.simpleFooRequest().receiveNullList(null);
    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void v) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Ensures that a service method can respond with a null value.
   */
  public void testNullListResult() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnNullList().fire(new NullReceiver());
  }

  /**
   * Test that a null value can be sent in a request.
   */
  public void testNullSimpleFooRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<Void> fooReq = req.simpleFooRequest().receiveNullSimpleFoo(
        null);
    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void v) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Test that a null value can be sent to an instance method.
   */
  public void testNullStringInstanceRequest() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Get a valid proxy entity.
    req.simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            Request<Void> fooReq = req.simpleFooRequest().receiveNull(null).using(
                response);
            fooReq.fire(new Receiver<Void>() {
              @Override
              public void onSuccess(Void v) {
                finishTestAndReset();
              }
            });
          }
        });
  }

  /**
   * Test that a null value can be sent in a request.
   */
  public void testNullStringRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<Void> fooReq = req.simpleFooRequest().receiveNullString(null);
    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void v) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Ensures that a service method can respond with a null value.
   */
  public void testNullStringResult() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnNullString().fire(new NullReceiver());
  }

  /**
   * Test that a null value can be sent within a list of entities.
   */
  public void testNullValueInEntityListRequest() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Get a valid proxy entity.
    req.simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            List<SimpleFooProxy> list = new ArrayList<SimpleFooProxy>();
            list.add(response); // non-null
            list.add(null); // null
            final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInEntityList(
                list);
            fooReq.fire(new Receiver<Void>() {
              @Override
              public void onSuccess(Void v) {
                finishTestAndReset();
              }
            });
          }
        });
  }

  /**
   * Test that a null value can be sent within a list of objects.
   */
  public void testNullValueInIntegerListRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    List<Integer> list = Arrays.asList(new Integer[] {1, 2, null});
    final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInIntegerList(
        list);
    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void v) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Test that a null value can be sent within a list of strings.
   */
  public void testNullValueInStringListRequest() {
    delayTestFinish(DELAY_TEST_FINISH);
    List<String> list = Arrays.asList(new String[] {"nonnull", "null", null});
    final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInStringList(
        list);
    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void v) {
        finishTestAndReset();
      }
    });
  }

  /**
   * Tests a message consisting only of operations, with no invocations.
   */
  public void testOperationOnlyMessage() {
    delayTestFinish(DELAY_TEST_FINISH);
    RequestContext ctx = simpleFooRequest();
    SimpleFooProxy proxy = ctx.create(SimpleFooProxy.class);
    proxy.setUserName("GWT");
    ctx.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void response) {
        finishTestAndReset();
      }
    });
  }

  public void testPersistAllValueTypes() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest r = simpleFooRequest();
    SimpleFooProxy f = r.create(SimpleFooProxy.class);

    f.setUserName("user name");
    f.setByteField((byte) 100);
    f.setShortField((short) 12345);
    f.setFloatField(1234.56f);
    f.setDoubleField(1.2345);
    f.setLongField(1234L);
    f.setBoolField(false);
    f.setOtherBoolField(true);
    f.setCreated(new Date(397387389L));

    r.persistAndReturnSelf().using(f).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy f) {
        f = checkSerialization(f);
        assertEquals("user name", f.getUserName());
        assertEquals(Byte.valueOf((byte) 100), f.getByteField());
        assertEquals(Short.valueOf((short) 12345), f.getShortField());
        assertEquals(0, (int) Math.rint(123456f - 100 * f.getFloatField()));
        assertEquals(Double.valueOf(1.2345), f.getDoubleField());
        assertEquals(Long.valueOf(1234L), f.getLongField());
        assertFalse(f.getBoolField());
        assertTrue(f.getOtherBoolField());
        assertEquals(new Date(397387389L), f.getCreated());

        finishTestAndReset();
      }
    });
  }

  /**
   * Test that the server code will not allow a persisted entity to be returned
   * if it has a null version property.
   */
  public void testPersistedEntityWithNullVersion() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().getSimpleFooWithNullVersion().fire(
        new Receiver<SimpleFooProxy>() {

          @Override
          public void onFailure(ServerFailure error) {
            finishTestAndReset();
          }

          @Override
          public void onSuccess(SimpleFooProxy response) {
            fail();
          }
        });
  }

  public void testPersistExistingEntityExistingRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Retrieve a Bar
    simpleBarRequest().findSimpleBarById("999L").fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy barProxy = checkSerialization(response);
            // Retrieve a Foo
            simpleFooRequest().findSimpleFooById(999L).fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy fooProxy) {
                    fooProxy = checkSerialization(fooProxy);
                    SimpleFooRequest context = simpleFooRequest();
                    fooProxy = context.edit(fooProxy);
                    // Make the Foo point to the Bar
                    fooProxy.setBarField(barProxy);
                    fooProxy.setUserName("Hello");
                    fooProxy.setByteField((byte) 55);
                    context.persistAndReturnSelf().using(fooProxy).with(
                        "barField").fire(new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy received) {
                        received = checkSerialization(received);
                        // Check that Foo points to Bar
                        assertNotNull(received.getBarField());
                        assertEquals(barProxy.stableId(),
                            received.getBarField().stableId());
                        assertEquals("Hello", received.getUserName());
                        assertTrue(55 == received.getByteField());

                        // Unset the association
                        SimpleFooRequest context = simpleFooRequest();
                        received = context.edit(received);
                        received.setBarField(null);
                        received.setUserName(null);
                        received.setByteField(null);
                        context.persistAndReturnSelf().using(received).fire(
                            new Receiver<SimpleFooProxy>() {
                              @Override
                              public void onSuccess(SimpleFooProxy response) {
                                response = checkSerialization(response);
                                assertNull(response.getBarField());
                                assertNull(response.getUserName());
                                assertNull(response.getByteField());
                                finishTestAndReset();
                              }
                            });
                      }
                    });
                  }
                });
          }
        });
  }

  /*
   * Find Entity Create Entity2 Relate Entity2 to Entity Persist Entity
   */
  public void testPersistExistingEntityNewRelation() {
    delayTestFinish(DELAY_TEST_FINISH);
    // Make a new bar
    SimpleBarRequest context = simpleBarRequest();
    SimpleBarProxy makeABar = context.create(SimpleBarProxy.class);
    Request<SimpleBarProxy> persistRequest = context.persistAndReturnSelf().using(
        makeABar);
    makeABar = context.edit(makeABar);
    makeABar.setUserName("Amit");

    persistRequest.fire(new Receiver<SimpleBarProxy>() {
      @Override
      public void onSuccess(SimpleBarProxy response) {
        final SimpleBarProxy persistedBar = checkSerialization(response);

        // It was made, now find a foo to assign it to
        simpleFooRequest().findSimpleFooById(999L).fire(
            new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);

                // Found the foo, edit it
                SimpleFooRequest context = simpleFooRequest();
                Request<Void> fooReq = context.persist().using(response);
                response = context.edit(response);
                response.setBarField(persistedBar);
                fooReq.fire(new Receiver<Void>() {
                  @Override
                  public void onSuccess(Void response) {

                    // Foo was persisted, fetch it again check the goods
                    simpleFooRequest().findSimpleFooById(999L).with(
                        "barField.userName").fire(
                        new Receiver<SimpleFooProxy>() {

                          // Here it is
                          @Override
                          public void onSuccess(SimpleFooProxy finalFooProxy) {
                            finalFooProxy = checkSerialization(finalFooProxy);
                            assertEquals("Amit",
                                finalFooProxy.getBarField().getUserName());
                            finishTestAndReset();
                          }
                        });
                  }
                });
              }
            });
      }
    });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */

  /**
   * Ensure that a relationship can be set up between two newly-created objects.
   */
  public void testPersistFutureToFuture() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final SimpleBarProxy newBar = context.create(SimpleBarProxy.class);

    Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(
        newFoo).with("barField");
    newFoo = context.edit(newFoo);
    newFoo.setBarField(newBar);

    fooReq.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        assertNotNull(response.getBarField());
        assertEquals(newBar.stableId(), response.getBarField().stableId());
        finishTestAndReset();
      }
    });
  }

  /*
   * Find Entity2 Create Entity, Persist Entity Relate Entity2 to Entity Persist
   * Entity
   */
  public void testPersistNewEntityExistingRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.edit(context.create(SimpleFooProxy.class));
    final Request<Void> fooReq = context.persist().using(newFoo);

    newFoo.setUserName("Ray");

    final SimpleFooProxy finalFoo = newFoo;
    simpleBarRequest().findSimpleBarById("999L").fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            response = checkSerialization(response);
            finalFoo.setBarField(response);
            fooReq.fire(new Receiver<Void>() {
              @Override
              public void onSuccess(Void response) {
                simpleFooRequest().findSimpleFooById(999L).fire(
                    new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy finalFooProxy) {
                        finalFooProxy = checkSerialization(finalFooProxy);
                        // newFoo hasn't been persisted, so userName is the old
                        // value.
                        assertEquals("GWT", finalFooProxy.getUserName());
                        finishTestAndReset();
                      }
                    });
              }
            });
          }
        });
  }

  /*
   * Create Entity, Persist Entity Create Entity2, Perist Entity2 relate Entity2
   * to Entity Persist
   */
  public void testPersistNewEntityNewRelation() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);

    final Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(
        newFoo);
    newFoo = context.edit(newFoo);
    newFoo.setUserName("Ray");

    SimpleBarRequest context2 = simpleBarRequest();
    SimpleBarProxy newBar = context2.create(SimpleBarProxy.class);
    final Request<SimpleBarProxy> barReq = context2.persistAndReturnSelf().using(
        newBar);
    newBar = context2.edit(newBar);
    newBar.setUserName("Amit");

    fooReq.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(final SimpleFooProxy response) {
        final SimpleFooProxy persistedFoo = checkSerialization(response);
        barReq.fire(new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy persistedBar = checkSerialization(response);

            assertEquals("Ray", persistedFoo.getUserName());
            SimpleFooRequest context = simpleFooRequest();
            final Request<Void> fooReq2 = context.persist().using(persistedFoo);
            SimpleFooProxy editablePersistedFoo = context.edit(persistedFoo);
            editablePersistedFoo.setBarField(persistedBar);
            fooReq2.fire(new Receiver<Void>() {
              @Override
              public void onSuccess(Void response) {
                req.simpleFooRequest().findSimpleFooById(persistedFoo.getId()).with(
                    "barField.userName").fire(new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy finalFooProxy) {
                    finalFooProxy = checkSerialization(finalFooProxy);
                    assertEquals("Amit",
                        finalFooProxy.getBarField().getUserName());
                    finishTestAndReset();
                  }
                });
              }
            });
          }
        });
      }
    });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistOneToManyExistingEntityExistingRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    simpleBarRequest().findSimpleBarById("999L").fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy barProxy = checkSerialization(response);
            simpleFooRequest().findSimpleFooById(999L).with("oneToManyField").fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy fooProxy) {
                    fooProxy = checkSerialization(fooProxy);

                    SimpleFooRequest context = simpleFooRequest();
                    Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                        fooProxy).with("oneToManyField");
                    fooProxy = context.edit(fooProxy);

                    List<SimpleBarProxy> barProxyList = fooProxy.getOneToManyField();
                    final int listCount = barProxyList.size();
                    barProxyList.add(barProxy);
                    updReq.fire(new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(response.getOneToManyField().size(),
                            listCount + 1);
                        assertContains(response.getOneToManyField(), barProxy);
                        finishTestAndReset();
                      }
                    });
                  }
                });
          }
        });
  }

  public void testPersistRecursiveRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy rayFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> persistRay = context.persistAndReturnSelf().using(
        rayFoo);
    rayFoo = context.edit(rayFoo);
    rayFoo.setUserName("Ray");
    rayFoo.setFooField(rayFoo);
    persistRay.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        finishTestAndReset();
      }
    });
  }

  public void testPersistRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy rayFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> persistRay = context.persistAndReturnSelf().using(
        rayFoo);
    rayFoo = context.edit(rayFoo);
    rayFoo.setUserName("Ray");

    persistRay.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        final SimpleFooProxy persistedRay = checkSerialization(response);
        SimpleBarRequest context = simpleBarRequest();
        SimpleBarProxy amitBar = context.create(SimpleBarProxy.class);
        final Request<SimpleBarProxy> persistAmit = context.persistAndReturnSelf().using(
            amitBar);
        amitBar = context.edit(amitBar);
        amitBar.setUserName("Amit");

        persistAmit.fire(new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            response = checkSerialization(response);

            SimpleFooRequest context = simpleFooRequest();
            final Request<SimpleFooProxy> persistRelationship = context.persistAndReturnSelf().using(
                persistedRay).with("barField");
            SimpleFooProxy newRec = context.edit(persistedRay);
            newRec.setBarField(response);

            persistRelationship.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                assertEquals("Amit", response.getBarField().getUserName());
                finishTestAndReset();
              }
            });
          }
        });
      }
    });
  }

  public void testPersistSelfOneToManyExistingEntityExistingRelation() {
    delayTestFinish(DELAY_TEST_FINISH);

    simpleFooRequest().findSimpleFooById(999L).with("selfOneToManyField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy).with("selfOneToManyField");
            fooProxy = context.edit(fooProxy);
            List<SimpleFooProxy> fooProxyList = fooProxy.getSelfOneToManyField();
            final int listCount = fooProxyList.size();
            fooProxyList.add(fooProxy);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                assertEquals(response.getSelfOneToManyField().size(),
                    listCount + 1);
                assertContains(response.getSelfOneToManyField(), response);
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */

  public void testPersistValueList() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);
            fooProxy.getNumberListField().add(100);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                assertTrue(response.getNumberListField().contains(100));
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueListNull() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);

            fooProxy.setNumberListField(null);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                List<Integer> list = response.getNumberListField();
                assertNull(list);
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueListRemove() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);
            final int oldValue = fooProxy.getNumberListField().remove(0);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                assertFalse(response.getNumberListField().contains(oldValue));
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueListReplace() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);
            final ArrayList<Integer> al = new ArrayList<Integer>();
            al.add(5);
            al.add(8);
            al.add(13);
            fooProxy.setNumberListField(al);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                List<Integer> list = response.getNumberListField();
                assertEquals(5, (int) list.get(0));
                assertEquals(8, (int) list.get(1));
                assertEquals(13, (int) list.get(2));
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueListReverse() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);
            final ArrayList<Integer> al = new ArrayList<Integer>();
            List<Integer> listField = fooProxy.getNumberListField();
            al.addAll(listField);
            Collections.reverse(listField);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                Collections.reverse(al);
                assertTrue(response.getNumberListField().equals(al));
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueListSetIndex() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy fooProxy) {
            fooProxy = checkSerialization(fooProxy);
            SimpleFooRequest context = simpleFooRequest();
            Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                fooProxy);
            fooProxy = context.edit(fooProxy);
            fooProxy.getNumberListField().set(0, 10);
            updReq.fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                assertTrue(response.getNumberListField().get(0) == 10);
                finishTestAndReset();
              }
            });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueSetAddNew() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleBarRequest context = simpleBarRequest();
    SimpleBarProxy newBar = context.create(SimpleBarProxy.class);

    context.persistAndReturnSelf().using(newBar).fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy barProxy = checkSerialization(response);
            simpleFooRequest().findSimpleFooById(999L).with("oneToManySetField").fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy fooProxy) {
                    fooProxy = checkSerialization(fooProxy);
                    SimpleFooRequest context = simpleFooRequest();
                    Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                        fooProxy).with("oneToManySetField");
                    fooProxy = context.edit(fooProxy);

                    Set<SimpleBarProxy> setField = fooProxy.getOneToManySetField();
                    final int listCount = setField.size();
                    setField.add(barProxy);
                    updReq.fire(new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(listCount + 1,
                            response.getOneToManySetField().size());
                        assertContains(response.getOneToManySetField(),
                            barProxy);
                        finishTestAndReset();
                      }
                    });
                  }
                });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueSetAlreadyExists() {
    delayTestFinish(DELAY_TEST_FINISH);

    simpleBarRequest().findSimpleBarById("1L").fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy barProxy = checkSerialization(response);

            simpleFooRequest().findSimpleFooById(999L).with("oneToManySetField").fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy fooProxy) {
                    fooProxy = checkSerialization(fooProxy);
                    SimpleFooRequest context = simpleFooRequest();
                    Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                        fooProxy).with("oneToManySetField");
                    fooProxy = context.edit(fooProxy);

                    Set<SimpleBarProxy> setField = fooProxy.getOneToManySetField();
                    final int listCount = setField.size();
                    assertContains(setField, barProxy);
                    setField.add(barProxy);
                    updReq.fire(new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(response.getOneToManySetField().size(),
                            listCount);
                        assertContains(response.getOneToManySetField(),
                            barProxy);
                        finishTestAndReset();
                      }
                    });
                  }
                });
          }
        });
  }

  /*
   * TODO: all these tests should check the final values. It will be easy when
   * we have better persistence than the singleton pattern.
   */
  public void testPersistValueSetRemove() {
    delayTestFinish(DELAY_TEST_FINISH);

    simpleBarRequest().findSimpleBarById("1L").fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            final SimpleBarProxy barProxy = checkSerialization(response);
            simpleFooRequest().findSimpleFooById(999L).with("oneToManySetField").fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy fooProxy) {
                    fooProxy = checkSerialization(fooProxy);
                    SimpleFooRequest context = simpleFooRequest();
                    Request<SimpleFooProxy> updReq = context.persistAndReturnSelf().using(
                        fooProxy).with("oneToManySetField");
                    fooProxy = context.edit(fooProxy);

                    Set<SimpleBarProxy> setField = fooProxy.getOneToManySetField();
                    final int listCount = setField.size();
                    assertContains(setField, barProxy);
                    setField.remove(context.edit(barProxy));
                    assertNotContains(setField, barProxy);
                    updReq.fire(new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(listCount - 1,
                            response.getOneToManySetField().size());
                        assertNotContains(response.getOneToManySetField(),
                            barProxy);
                        finishTestAndReset();
                      }
                    });
                  }
                });
          }
        });
  }

  public void testPrimitiveList() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<List<Integer>> fooReq = simpleFooRequest().getNumberList();
    fooReq.fire(new Receiver<List<Integer>>() {
      @Override
      public void onSuccess(List<Integer> response) {
        assertEquals(3, response.size());
        assertEquals(1, (int) response.get(0));
        assertEquals(2, (int) response.get(1));
        assertEquals(3, (int) response.get(2));
        finishTestAndReset();
      }
    });
  }

  public void testPrimitiveListAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<SimpleFooProxy> fooReq = simpleFooRequest().findSimpleFooById(
        999L);
    fooReq.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        final Request<Integer> sumReq = simpleFooRequest().sum(
            Arrays.asList(1, 2, 3)).using(response);
        sumReq.fire(new Receiver<Integer>() {
          @Override
          public void onSuccess(Integer response) {
            assertEquals(6, response.intValue());
            finishTestAndReset();
          }
        });
      }
    });
  }

  public void testPrimitiveListBigDecimalAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Keep these values in sync with SimpleFoo.processBigIntegerList
    final List<BigDecimal> testList = new ArrayList<BigDecimal>();
    testList.add(BigDecimal.TEN);
    testList.add(new BigDecimal("12345.6789") {
      // This is an anonymous subtype
    });
    simpleFooRequest().processBigDecimalList(testList).fire(
        new Receiver<List<BigDecimal>>() {
          @Override
          public void onSuccess(List<BigDecimal> response) {
            // Check upcasted values only
            assertEquals(testList, response);
            finishTestAndReset();
          }
        });
  }

  public void testPrimitiveListBigIntegerAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Keep these values in sync with SimpleFoo.processBigIntegerList
    final List<BigInteger> testList = new ArrayList<BigInteger>();
    testList.add(BigInteger.TEN);
    testList.add(new BigInteger("12345") {
      // This is an anonymous subtype
    });
    simpleFooRequest().processBigIntegerList(testList).fire(
        new Receiver<List<BigInteger>>() {
          @Override
          public void onSuccess(List<BigInteger> response) {
            // Check upcasted values only
            assertEquals(testList, response);
            finishTestAndReset();
          }
        });
  }

  public void testPrimitiveListBooleanAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);

    Request<Boolean> procReq = simpleFooRequest().processBooleanList(
        Arrays.asList(true, false));

    procReq.fire(new Receiver<Boolean>() {
      @Override
      public void onSuccess(Boolean response) {
        assertEquals(true, (boolean) response);
        finishTestAndReset();
      }
    });
  }

  @SuppressWarnings("deprecation")
  public void testPrimitiveListDateAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);

    // Keep these values in sync with SimpleFoo.processDateList
    Date date = new Date(90, 0, 1);
    java.sql.Date sqlDate = new java.sql.Date(90, 0, 2);
    Time sqlTime = new Time(1, 2, 3);
    Timestamp sqlTimestamp = new Timestamp(12345L);
    final List<Date> testList = Arrays.asList(date, sqlDate, sqlTime,
        sqlTimestamp);
    simpleFooRequest().processDateList(testList).fire(
        new Receiver<List<Date>>() {
          @Override
          public void onSuccess(List<Date> response) {
            // Check upcasted values only
            assertEquals(testList.size(), response.size());
            Iterator<Date> expected = testList.iterator();
            Iterator<Date> actual = response.iterator();
            while (expected.hasNext()) {
              assertEquals(expected.next().getTime(), actual.next().getTime());
            }
            finishTestAndReset();
          }
        });
  }

  public void testPrimitiveListEnumAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);

    Request<SimpleEnum> procReq = simpleFooRequest().processEnumList(
        Arrays.asList(SimpleEnum.BAR));

    procReq.fire(new Receiver<SimpleEnum>() {
      @Override
      public void onSuccess(SimpleEnum response) {
        assertEquals(SimpleEnum.BAR, response);
        finishTestAndReset();
      }
    });
  }

  public void testPrimitiveParameter() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().add(3, 5).fire(new Receiver<Integer>() {
      @Override
      public void onSuccess(Integer response) {
        assertTrue(8 == response);
        finishTestAndReset();
      }
    });
  }

  public void testPrimitiveSet() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<Set<Integer>> fooReq = simpleFooRequest().getNumberSet();
    fooReq.fire(new Receiver<Set<Integer>>() {
      @Override
      public void onSuccess(Set<Integer> response) {
        assertEquals(3, response.size());
        assertTrue(response.contains(1));
        assertTrue(response.contains(2));
        assertTrue(response.contains(3));
        finishTestAndReset();
      }
    });
  }

  public void testPrimitiveString() {
    delayTestFinish(DELAY_TEST_FINISH);
    final String testString = "test\"string\'with\nstring\u2060characters\t";
    final Request<String> fooReq = simpleFooRequest().processString(testString);
    fooReq.fire(new Receiver<String>() {
      @Override
      public void onSuccess(String response) {
        assertEquals(testString, response);
        finishTestAndReset();
      }
    });
  }

  public void testProxyList() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<SimpleFooProxy> fooReq = simpleFooRequest().findSimpleFooById(
        999L).with("oneToManyField");
    fooReq.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        assertEquals(2, response.getOneToManyField().size());

        // Check lists of proxies returned from a mutable object are mutable
        response = simpleFooRequest().edit(response);
        response.getOneToManyField().get(0).setUserName("canMutate");
        finishTestAndReset();
      }
    });
  }

  public void testProxyListAsParameter() {
    delayTestFinish(DELAY_TEST_FINISH);
    final Request<SimpleFooProxy> fooReq = simpleFooRequest().findSimpleFooById(
        999L).with("selfOneToManyField");
    fooReq.fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        final SimpleFooProxy fooProxy = checkSerialization(response);
        final Request<String> procReq = simpleFooRequest().processList(
            fooProxy.getSelfOneToManyField()).using(fooProxy);
        procReq.fire(new Receiver<String>() {
          @Override
          public void onSuccess(String response) {
            assertEquals(fooProxy.getUserName(), response);
            finishTestAndReset();
          }
        });
      }
    });
  }

  public void testProxysAsInstanceMethodParams() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().findSimpleFooById(999L).fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            SimpleFooRequest context = simpleFooRequest();
            SimpleBarProxy bar = context.create(SimpleBarProxy.class);
            Request<String> helloReq = context.hello(bar).using(response);
            bar = context.edit(bar);
            bar.setUserName("BAR");
            helloReq.fire(new Receiver<String>() {
              @Override
              public void onSuccess(String response) {
                assertEquals("Greetings BAR from GWT", response);
                finishTestAndReset();
              }
            });
          }
        });
  }

  public void testServerFailureCheckedException() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
        newFoo);
    final SimpleFooProxy mutableFoo = context.edit(newFoo);
    // 43 is the crash causing magic number for a checked exception
    mutableFoo.setPleaseCrash(43);
    persistRequest.fire(new FooReciever(mutableFoo, persistRequest, null));
  }

  public void testServerFailureRuntimeException() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
        newFoo);
    final SimpleFooProxy mutableFoo = context.edit(newFoo);
    // 42 is the crash causing magic number for a runtime exception
    mutableFoo.setPleaseCrash(42);
    persistRequest.fire(new FooReciever(mutableFoo, persistRequest, null));
  }

  /**
   * Tests the behaviors of setters and their effects on getters.
   */
  public void testSetters() {
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    SimpleBarProxy bar = context.create(SimpleBarProxy.class);

    // Assert that uninitalize references are null
    assertNull(foo.getBarField());

    // Assert that objects are mutable after creation
    foo.setBarField(bar);

    assertSame(foo, context.edit(foo));
    foo.setBarField(bar);

    // Assert that the set value is retained
    SimpleBarProxy returnedBarField = foo.getBarField();
    assertNotNull(returnedBarField);
    assertEquals(bar.stableId(), returnedBarField.stableId());
    assertEquals(returnedBarField, foo.getBarField());
    assertSame(returnedBarField, foo.getBarField());

    // Getters called on mutable objects are also mutable
    returnedBarField.setUserName("userName");
    assertEquals("userName", returnedBarField.getUserName());
  }

  /**
   * There's plenty of special-case code for Collection properties, so they need
   * to be tested as well.
   */
  public void testSettersWithCollections() {
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    SimpleBarProxy bar = context.create(SimpleBarProxy.class);
    List<SimpleBarProxy> originalList = Collections.singletonList(bar);

    // Assert that uninitalize references are null
    assertNull(foo.getOneToManyField());

    // Assert that objects are mutable after creation
    foo.setOneToManyField(null);

    assertSame(foo, context.edit(foo));
    foo.setOneToManyField(originalList);
    // There's a "dummy" create case here; AbstractRequest, DVS is untestable

    // Quick sanity check on the behavior
    List<SimpleBarProxy> list = foo.getOneToManyField();
    assertNotSame(originalList, list);
    assertEquals(originalList, list);
    assertEquals(1, list.size());
    assertEquals(bar.stableId(), list.get(0).stableId());
    assertEquals(list, foo.getOneToManyField());

    // Assert that entities returned from editable list are mutable
    list.get(0).setUserName("userName");
  }

  public void testSettersWithMutableObject() {
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    foo = context.edit(foo);

    SimpleBarProxy immutableBar = context.create(SimpleBarProxy.class);
    SimpleBarProxy mutableBar = context.edit(immutableBar);
    mutableBar.setUserName("userName");
    foo.setBarField(mutableBar);

    // Creating a new editable object in the same request should read through
    context.edit(immutableBar).setUserName("Reset");
    assertEquals("Reset", foo.getBarField().getUserName());
  }

  public void testStableId() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    final SimpleFooProxy foo = context.create(SimpleFooProxy.class);
    final Object futureId = foo.getId();
    assertTrue(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());
    Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(foo);

    final SimpleFooProxy newFoo = context.edit(foo);
    assertEquals(futureId, foo.getId());
    assertTrue(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());
    assertEquals(futureId, newFoo.getId());
    assertTrue(((SimpleEntityProxyId<?>) newFoo.stableId()).isEphemeral());

    newFoo.setUserName("GWT basic user");
    fooReq.fire(new Receiver<SimpleFooProxy>() {

      @Override
      public void onSuccess(SimpleFooProxy response) {
        final SimpleFooProxy returned = checkSerialization(response);
        assertEquals(futureId, foo.getId());
        assertFalse(((SimpleEntityProxyId<?>) foo.stableId()).isEphemeral());
        assertEquals(futureId, newFoo.getId());
        assertFalse(((SimpleEntityProxyId<?>) newFoo.stableId()).isEphemeral());

        assertFalse(((SimpleEntityProxyId<?>) returned.stableId()).isEphemeral());

        checkStableIdEquals(foo, returned);
        checkStableIdEquals(newFoo, returned);
        SimpleFooRequest context = simpleFooRequest();
        Request<SimpleFooProxy> editRequest = context.persistAndReturnSelf().using(
            returned);
        final SimpleFooProxy editableFoo = context.edit(returned);
        editableFoo.setUserName("GWT power user");
        editRequest.fire(new Receiver<SimpleFooProxy>() {

          @Override
          public void onSuccess(SimpleFooProxy response) {
            response = checkSerialization(response);
            assertEquals(response.getId(), returned.getId());
            assertEquals("GWT power user", response.getUserName());
            checkStableIdEquals(editableFoo, response);
            finishTestAndReset();
          }
        });
      }
    });
  }

  /**
   * Test that a proxy only referenced via a parameterization is available.
   */
  public void testOnlyUsedInList() {
    OnlyUsedInListProxy proxy = simpleFooRequest().create(
        OnlyUsedInListProxy.class);
    assertNotNull(proxy);
  }

  /**
   * Check if a graph of unpersisted objects can be echoed.
   */
  public void testUnpersistedEchoComplexGraph() {
    delayTestFinish(DELAY_TEST_FINISH);
    final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, handler);
    SimpleFooRequest context = req.simpleFooRequest();
    final SimpleBarProxy simpleBar = context.create(SimpleBarProxy.class);
    simpleBar.setUnpersisted(true);
    final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
    simpleFoo.setUnpersisted(true);
    simpleFoo.setBarField(simpleBar);
    context.echoComplex(simpleFoo, simpleBar).with("barField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            // The reconstituted object may not have the same stable id
            checkStableIdEquals(simpleBar, response.getBarField());
            response = checkSerialization(response);
            assertEquals(0, handler.totalEventCount);
            checkStableIdEquals(simpleFoo, response);
            SimpleBarProxy responseBar = response.getBarField();
            assertNotNull(responseBar);
            finishTestAndReset();
          }
        });
  }

  /**
   * Check if an unpersisted object can be echoed.
   */
  public void testUnpersistedEchoObject() {
    delayTestFinish(DELAY_TEST_FINISH);
    final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
    EntityProxyChange.registerForProxyType(req.getEventBus(),
        SimpleFooProxy.class, handler);
    SimpleFooRequest context = req.simpleFooRequest();
    final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
    simpleFoo.setUnpersisted(true);
    context.echo(simpleFoo).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        assertEquals(0, handler.totalEventCount);
        checkStableIdEquals(simpleFoo, response);
        finishTestAndReset();
      }
    });
  }

  /**
   * Return an unpersisted object from a service method and echo it.
   */
  public void testUnpersistedObjectFetch() {
    delayTestFinish(DELAY_TEST_FINISH);
    req.simpleFooRequest().getUnpersistedInstance().fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(SimpleFooProxy response) {
            final SimpleFooProxy created = checkSerialization(response);
            assertNotNull(created);
            assertTrue(created.getUnpersisted());
            req.simpleFooRequest().echo(created).fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy response) {
                    response = checkSerialization(response);
                    assertNotNull(response);
                    assertEquals(created.stableId(), response.stableId());
                    assertTrue(response.getUnpersisted());
                    finishTestAndReset();
                  }
                });
          }
        });
  }

  /**
   * This is analagous to FindServiceTest.testFetchDeletedEntity() only we're
   * trying to invoke a method on the deleted entity using a stale EntityProxy
   * reference on the client.
   */
  public void testUseOfDeletedEntity() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleBarRequest context = simpleBarRequest();
    SimpleBarProxy willDelete = context.create(SimpleBarProxy.class);
    willDelete.setUserName("A");

    // Persist the newly-created object
    context.persistAndReturnSelf().using(willDelete).fire(
        new Receiver<SimpleBarProxy>() {
          @Override
          public void onSuccess(SimpleBarProxy response) {
            response = checkSerialization(response);
            assertEquals("A", response.getUserName());
            // Mark the object as deleted
            SimpleBarRequest context = simpleBarRequest();
            response = context.edit(response);
            response.setFindFails(true);
            response.setUserName("B");
            context.persistAndReturnSelf().using(response).fire(
                new Receiver<SimpleBarProxy>() {

                  @Override
                  public void onSuccess(SimpleBarProxy response) {
                    response = checkSerialization(response);
                    // The last-known state should be returned
                    assertNotNull(response);
                    assertEquals("B", response.getUserName());

                    SimpleBarRequest context = simpleBarRequest();
                    // Ensure attempts to mutate deleted objects don't blow up
                    response = context.edit(response);
                    response.setUserName("C");

                    // Attempting to use the now-deleted object should fail
                    context.persistAndReturnSelf().using(response).fire(
                        new Receiver<SimpleBarProxy>() {
                          @Override
                          public void onFailure(ServerFailure error) {
                            assertTrue(error.getMessage().contains(
                                "The requested entity is not available on"
                                    + " the server"));
                            finishTestAndReset();
                          }

                          @Override
                          public void onSuccess(SimpleBarProxy response) {
                            response = checkSerialization(response);
                            fail();
                          }
                        });
                  }
                });
          }
        });
  }

  public void testValueMethodInvocation() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleValueContext ctx = req.simpleValueContext();
    SimpleValueProxy p = ctx.create(SimpleValueProxy.class);
    p.setString("Hello World!");
    ctx.getString().using(p).fire(new Receiver<String>() {
      @Override
      public void onSuccess(String response) {
        assertEquals("Hello World!", response);
        finishTestAndReset();
      }
    });
  }

  public void testValueObjectCreateSetRetrieveUpdate() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest req = simpleFooRequest();
    req.findSimpleFooById(1L).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        SimpleFooRequest req = simpleFooRequest();

        // Create
        final SimpleValueProxy created = req.create(SimpleValueProxy.class);
        created.setNumber(42);
        created.setString("Hello world!");
        created.setSimpleFoo(response);
        // Test cycles in value
        created.setSimpleValue(Arrays.asList(created));

        // Set
        response = req.edit(response);
        response.setSimpleValue(created);

        // Retrieve
        req.persistAndReturnSelf().using(response).with(
            "simpleValue.simpleFoo", "simpleValue.simpleValue").to(
            new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                SimpleValueProxy value = response.getSimpleValue();
                assertEquals(42, value.getNumber());
                assertEquals("Hello world!", value.getString());
                assertSame(response, value.getSimpleFoo());
                assertSame(value, value.getSimpleValue().get(0));

                try {
                  // Require owning object to be editable
                  response.getSimpleValue().setNumber(43);
                  fail("Should have thrown exception");
                } catch (IllegalStateException expected) {
                }

                // Update
                SimpleFooRequest req = simpleFooRequest();
                response = req.edit(response);
                response.getSimpleValue().setNumber(43);
                req.persistAndReturnSelf().using(response).with("simpleValue").to(
                    new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(43, response.getSimpleValue().getNumber());
                        finishTestAndReset();
                      }
                    }).fire();
              }
            }).fire();
      }
    });
  }

  public void testValueObjectCreateSetRetrieveUpdateViaList() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest req = simpleFooRequest();
    req.findSimpleFooById(1L).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        response = checkSerialization(response);
        SimpleFooRequest req = simpleFooRequest();

        // Create
        final SimpleValueProxy created = req.create(SimpleValueProxy.class);
        created.setNumber(42);
        created.setString("Hello world!");
        created.setSimpleFoo(response);

        // Set
        response = req.edit(response);
        response.setSimpleValues(Arrays.asList(created));

        // Retrieve
        req.persistAndReturnSelf().using(response).with("simpleValues").to(
            new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                response = checkSerialization(response);
                SimpleValueProxy value = response.getSimpleValues().get(0);
                assertEquals(42, value.getNumber());

                try {
                  // Require owning object to be editable
                  response.getSimpleValues().get(0).setNumber(43);
                  fail("Should have thrown exception");
                } catch (IllegalStateException expected) {
                }

                // Update
                SimpleFooRequest req = simpleFooRequest();
                response = req.edit(response);
                response.getSimpleValues().get(0).setNumber(43);
                req.persistAndReturnSelf().using(response).with("simpleValues").to(
                    new Receiver<SimpleFooProxy>() {
                      @Override
                      public void onSuccess(SimpleFooProxy response) {
                        response = checkSerialization(response);
                        assertEquals(43,
                            response.getSimpleValues().get(0).getNumber());
                        finishTestAndReset();
                      }
                    }).fire();
              }
            }).fire();
      }
    });
  }

  public void testValueObjectEquality() {
    SimpleFooRequest req = simpleFooRequest();
    SimpleValueProxy a = req.create(SimpleValueProxy.class);
    SimpleValueProxy b = req.create(SimpleValueProxy.class);
    checkEqualityAndHashcode(a, b);

    a.setString("Hello");
    assertFalse(a.equals(b));
    assertFalse(b.equals(a));

    b.setString("Hello");
    checkEqualityAndHashcode(a, b);

    a.setSimpleValue(Collections.singletonList(req.create(SimpleValueProxy.class)));
    assertFalse(a.equals(b));
    assertFalse(b.equals(a));
    b.setSimpleValue(Collections.singletonList(req.create(SimpleValueProxy.class)));
    checkEqualityAndHashcode(a, b);

    a.getSimpleValue().get(0).setNumber(55);
    assertFalse(a.equals(b));
    assertFalse(b.equals(a));
    b.getSimpleValue().get(0).setNumber(55);
    checkEqualityAndHashcode(a, b);
  }

  /**
   * Since a ValueProxy cannot be passed into RequestContext edit, a proxy
   * returned from a service method should be mutable by default.
   */
  public void testValueObjectReturnedFromRequestIsImmutable() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnValueProxy().fire(
        new Receiver<SimpleValueProxy>() {
          @Override
          public void onSuccess(SimpleValueProxy a) {
            a = checkSerialization(a);
            try {
              a.setNumber(77);
              fail();
            } catch (IllegalStateException expected) {
            }
            try {
              // Ensure Dates comply with ValueProxy mutation behaviors
              a.getDate().setTime(1);
              fail();
            } catch (IllegalStateException expected) {
            }
            SimpleFooRequest ctx = simpleFooRequest();
            final SimpleValueProxy toCheck = ctx.edit(a);
            toCheck.setNumber(77);
            toCheck.getDate().setTime(1);
            ctx.returnValueProxy().fire(new Receiver<SimpleValueProxy>() {
              @Override
              public void onSuccess(SimpleValueProxy b) {
                b = checkSerialization(b);
                b = simpleFooRequest().edit(b);
                // Now check that same value is equal across contexts
                b.setNumber(77);
                b.setDate(new Date(1));
                checkEqualityAndHashcode(toCheck, b);
                finishTestAndReset();
              }
            });
          }
        });
  }

  public void testValueObjectViolationsOnCreate() {
    delayTestFinish(DELAY_TEST_FINISH);
    SimpleFooRequest req = simpleFooRequest();
    final SimpleValueProxy value = req.create(SimpleValueProxy.class);
    value.setShouldBeNull("Hello world");

    SimpleFooProxy foo = req.create(SimpleFooProxy.class);
    foo.setSimpleValue(value);
    req.echo(foo).fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy response) {
        fail();
      }

      @Override
      public void onViolation(Set<Violation> errors) {
        assertEquals(1, errors.size());
        Violation v = errors.iterator().next();
        assertEquals(value, v.getInvalidProxy());
        assertNull(v.getOriginalProxy());
        assertEquals("shouldBeNull", v.getPath());
        assertNull(v.getProxyId());
        finishTestAndReset();
      }
    });
  }

  public void testValueObjectViolationsOnEdit() {
    delayTestFinish(DELAY_TEST_FINISH);
    simpleFooRequest().returnValueProxy().fire(
        new Receiver<SimpleValueProxy>() {
          @Override
          public void onSuccess(SimpleValueProxy response) {
            final SimpleValueProxy original = checkSerialization(response);
            SimpleFooRequest req = simpleFooRequest();
            final SimpleValueProxy value = req.edit(response);
            value.setShouldBeNull("Hello world");
            SimpleFooProxy foo = req.create(SimpleFooProxy.class);
            foo.setSimpleValue(value);
            req.echo(foo).fire(new Receiver<SimpleFooProxy>() {
              @Override
              public void onSuccess(SimpleFooProxy response) {
                fail();
              }

              @Override
              public void onViolation(Set<Violation> errors) {
                assertEquals(1, errors.size());
                Violation v = errors.iterator().next();
                assertEquals(value, v.getInvalidProxy());
                assertEquals(original, v.getOriginalProxy());
                assertEquals("shouldBeNull", v.getPath());
                assertNull(v.getProxyId());
                finishTestAndReset();
              }
            });
          }
        });
  }

  public void testViolationAbsent() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final Request<Void> fooReq = context.persist().using(newFoo);

    newFoo = context.edit(newFoo);
    newFoo.setUserName("Amit"); // will not cause violation.

    fooReq.fire(new Receiver<Void>() {
      @Override
      public void onSuccess(Void ignore) {
        finishTestAndReset();
      }
    });
  }

  public void testViolationsOnCreate() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> create = context.persistAndReturnSelf().using(
        newFoo);
    new FailFixAndRefire<SimpleFooProxy>(newFoo, context, create).doTest();
  }

  public void testViolationsOnCreateVoidReturn() {
    delayTestFinish(DELAY_TEST_FINISH);

    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
    final Request<Void> create = context.persist().using(newFoo);
    new FailFixAndRefire<Void>(newFoo, context, create).doVoidTest();
  }

  public void testViolationsOnEdit() {
    delayTestFinish(DELAY_TEST_FINISH);

    fooCreationRequest().fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy returned) {
        returned = checkSerialization(returned);
        SimpleFooRequest context = simpleFooRequest();
        Request<SimpleFooProxy> editRequest = context.persistAndReturnSelf().using(
            returned);
        new FailFixAndRefire<SimpleFooProxy>(returned, context, editRequest).doTest();
      }
    });
  }

  public void testViolationsOnEditVoidReturn() {
    delayTestFinish(DELAY_TEST_FINISH);

    fooCreationRequest().fire(new Receiver<SimpleFooProxy>() {
      @Override
      public void onSuccess(SimpleFooProxy returned) {
        returned = checkSerialization(returned);
        SimpleFooRequest context = simpleFooRequest();
        Request<Void> editRequest = context.persist().using(returned);
        new FailFixAndRefire<Void>(returned, context, editRequest).doVoidTest();
      }
    });
  }

  protected SimpleBarRequest simpleBarRequest() {
    return req.simpleBarRequest();
  }

  protected SimpleFooRequest simpleFooRequest() {
    return req.simpleFooRequest();
  }

  private void assertCannotFire(final Request<Long> mutateRequest) {
    try {
      mutateRequest.fire(new Receiver<Long>() {
        @Override
        public void onSuccess(Long response) {
          fail("Should not be called");
        }
      });
      fail("Expected IllegalStateException");
    } catch (IllegalStateException e) {
      /* cannot reuse a successful request, mores the pity */
    }
  }

  private Request<SimpleFooProxy> fooCreationRequest() {
    SimpleFooRequest context = simpleFooRequest();
    SimpleFooProxy originalFoo = context.create(SimpleFooProxy.class);
    final Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(
        originalFoo);
    originalFoo = context.edit(originalFoo);
    originalFoo.setUserName("GWT User");
    return fooReq;
  }
}
