@Test
  public void testStaticField() {
    Class<?> c = ClassWithFields.class;
    try {

      StaticField sf = new StaticField(c.getField("fourField"));
      FieldGetter rhs = new FieldGetter(sf);

      // types
      assertTrue("Should be no input types", rhs.getInputTypes().isEmpty());
      assertEquals("Output type should match type of field", sf.getType(), rhs.getOutputType());

      // code generation
      String expected = "int i0 = randoop.operation.ClassWithFields.fourField;" + Globals.lineSep;
      Statement st = new Statement(rhs);
      Sequence seq = new Sequence().extend(rhs, new ArrayList<Variable>());
      Variable var = new Variable(seq, 0);
      StringBuilder b = new StringBuilder();
      st.appendCode(var, new ArrayList<Variable>(), b);
      assertEquals("Expect initialization of variable from static field", expected, b.toString());

      // execution - should be 4 (haven't changed value yet)
      NormalExecution expectedExec = new NormalExecution(4, 0);
      NormalExecution actualExec = (NormalExecution) rhs.execute(new Object[0], null);
      assertTrue(
          "Execution should simply return value",
          expectedExec.getRuntimeValue().equals(actualExec.getRuntimeValue())
              && expectedExec.getExecutionTime() == actualExec.getExecutionTime());

    } catch (NoSuchFieldException e) {
      fail("test failed because field in test class not found");
    } catch (SecurityException e) {
      fail("test failed because of unexpected security exception");
    }
  }
  @Test
  public void getReturnType_whenNoModifierAndFieldIsArray_thenReturnTheArrayType() {
    FieldGetter getter = new FieldGetter(null, limbArrayField, null, null);
    Class returnType = getter.getReturnType();

    assertEquals(Limb[].class, returnType);
  }
  @Test
  public void getReturnType_whenSetExplicitly_thenReturnIt() {
    FieldGetter getter = new FieldGetter(null, limbCollectionField, "[any]", Limb.class);
    Class returnType = getter.getReturnType();

    assertEquals(Limb.class, returnType);
  }
  @Test
  public void getReturnType_whenModifierIsStarAndFieldIsArray_thenInferReturnTypeFromTheArray() {
    FieldGetter getter = new FieldGetter(null, limbArrayField, "[any]", null);
    Class returnType = getter.getReturnType();

    assertEquals(Limb.class, returnType);
  }
  @Test
  public void getValue_whenNoModifierOnArray_thenReturnTheArray() throws Exception {
    FieldGetter getter = new FieldGetter(null, limbArrayField, null, null);
    Limb[] result = (Limb[]) getter.getValue(body);

    assertSame(body.limbArray, result);
  }
  @Test
  public void getValue_whenInputIsNull_thenReturnNull() throws Exception {
    FieldGetter getter = new FieldGetter(null, limbArrayField, null, null);
    Limb[] result = (Limb[]) getter.getValue(null);

    assertNull(result);
  }
  @Test
  public void getValue_whenNoModifierOnCollection_thenReturnTheCollection() throws Exception {
    FieldGetter getter = new FieldGetter(null, limbCollectionField, null, null);
    Collection<Limb> result = (Collection<Limb>) getter.getValue(body);

    assertSame(body.limbCollection, result);
  }
  @Test
  public void getValue_whenModifierOnCollectionIsStar_thenReturnMultiValueResultWithAllItems()
      throws Exception {
    FieldGetter getter = new FieldGetter(null, limbCollectionField, "[any]", Limb.class);
    MultiResult result = (MultiResult) getter.getValue(body);

    assertContainsInAnyOrder(result, leg, hand, unnamedLimb);
  }
  @Test
  public void
      getValue_whenModifierOnCollectionIsPositionAndElementAtGivenPositionDoesNotExist_thenReturnNull()
          throws Exception {
    FieldGetter getter = new FieldGetter(null, limbCollectionField, "[3]", Limb.class);
    Limb result = (Limb) getter.getValue(body);

    assertNull(result);
  }
  @Test
  public void
      getValue_whenModifierOnCollectionIsPositionAndElementAtGivenPositionExist_thenReturnTheItem()
          throws Exception {
    FieldGetter getter = new FieldGetter(null, limbCollectionField, "[0]", Limb.class);
    Limb result = (Limb) getter.getValue(body);

    assertSame(leg, result);
  }
  @Test
  public void
      getValue_whenParentIsMultiResultAndNoModifier_thenReturnTheMultiResultContainingCurrentObjects()
          throws Exception {
    FieldGetter limbGetter = new FieldGetter(null, limbArrayField, "[any]", null);
    Field limbNameField = Limb.class.getDeclaredField("name");
    FieldGetter nailNameGetter = new FieldGetter(limbGetter, limbNameField, null, null);
    MultiResult result = (MultiResult) nailNameGetter.getValue(body);

    assertContainsInAnyOrder(result, "leg", "hand");
  }
  @Test
  public void
      getValue_whenParentIsMultiValueAndModifierOnCollectionIsPosition_thenReturnMultiValueResultWithItemsAtPosition()
          throws Exception {
    FieldGetter limbGetter = new FieldGetter(null, limbArrayField, "[any]", null);
    FieldGetter nailGetter = new FieldGetter(limbGetter, nailArrayField, "[0]", Nail.class);

    MultiResult result = (MultiResult) nailGetter.getValue(body);

    assertContainsInAnyOrder(result, redNail, whiteNail, null);
  }
  @Test
  public void
      getValue_whenParentIsMultiValueAndModifierOnArrayIsStar_thenReturnMultiValueResultWithAllItems()
          throws Exception {
    FieldGetter limbGetter = new FieldGetter(null, limbArrayField, "[any]", null);
    FieldGetter nailGetter = new FieldGetter(limbGetter, nailArrayField, "[any]", null);

    MultiResult result = (MultiResult) nailGetter.getValue(body);

    assertContainsInAnyOrder(result, whiteNail, blackNail, redNail, greenNail);
  }
 @Test
 public void parseable() {
   String getterDescr = "<get>(int:randoop.operation.ClassWithFields.oneField)";
   try {
     FieldGetter getter = FieldGetter.parse(getterDescr);
     assertEquals(
         "parse should return object that converts to string",
         getterDescr,
         getter.toParseableString());
   } catch (OperationParseException e) {
     fail("Parse error: " + e.getMessage());
   }
 }
  @Test
  public void testInstanceField() {
    Class<?> c = ClassWithFields.class;
    try {

      InstanceField f = new InstanceField(c.getField("oneField"));
      FieldGetter rhs = new FieldGetter(f);

      // types
      List<Class<?>> inputTypes = new ArrayList<>();
      inputTypes.add(c);
      assertEquals("Input types should just be declaring class", inputTypes, rhs.getInputTypes());
      assertEquals("Output type should match type of field", f.getType(), rhs.getOutputType());

      // code generation
      String expected = "int i1 = classWithFields0.oneField;" + Globals.lineSep;

      // first need a variable referring to an instance
      // - sequence where one is declared and initialized by constructed object
      ConstructorCall cons =
          new ConstructorCall(
              ConstructorSignatures.getConstructorForSignatureString(
                  "randoop.operation.ClassWithFields.ClassWithFields()"));
      Sequence seqInit = new Sequence().extend(cons, new ArrayList<Variable>());
      ArrayList<Variable> vars = new ArrayList<>();
      vars.add(new Variable(seqInit, 0));
      // bind getter "call" to initialization
      Statement st_rhs = new Statement(rhs);
      Sequence seq = seqInit.extend(rhs, vars);
      // - first variable is object
      Variable var1 = new Variable(seq, 0);
      // - second variable is for value
      Variable var2 = new Variable(seq, 1);
      vars = new ArrayList<>();
      vars.add(var1);
      StringBuilder b = new StringBuilder();
      st_rhs.appendCode(var2, vars, b);
      assertEquals("Expect initialization of variable from static field", expected, b.toString());

      // execution
      // null object
      ExecutionOutcome nullOutcome = rhs.execute(new Object[0], null);
      assertTrue(
          "Expect null pointer exception",
          nullOutcome instanceof ExceptionalExecution
              && ((ExceptionalExecution) nullOutcome).getException()
                  instanceof NullPointerException);

      // actual object
      NormalExecution expectedExec = new NormalExecution(1, 0);
      Object[] inputs = new Object[1];
      inputs[0] = c.newInstance();
      NormalExecution actualExec = (NormalExecution) rhs.execute(inputs, null);
      assertTrue(
          "Execution should simply return value",
          expectedExec.getRuntimeValue().equals(actualExec.getRuntimeValue())
              && expectedExec.getExecutionTime() == actualExec.getExecutionTime());

    } catch (NoSuchFieldException e) {
      fail("test failed because field in test class not found");
    } catch (SecurityException e) {
      fail("test failed because of unexpected security exception");
    } catch (InstantiationException e) {
      fail("test failed because of unexpected exception creating class instance");
    } catch (IllegalAccessException e) {
      fail("test failed because of unexpected access exception when creating instance");
      e.printStackTrace();
    } catch (OperationParseException e) {
      fail("test failed because ClassWithFields constructor not found");
    }
  }