private void testResolveTargetMethodSignature(
      String runnerMethodName, Type expectedReturnType, Type... expectedParamTypes) {

    SootMethod m = toSootClass(Runners.class).getMethodByName(runnerMethodName);
    SootMethodType mType = new SootMethodType(m);
    SootMethod target = ObjCBlockPlugin.getBlockTargetMethod(m, 0);
    Type[] types =
        ObjCBlockPlugin.resolveTargetMethodSignature(
            m, target, mType.getGenericParameterTypes()[0]);
    assertEquals(target.getParameterCount() + 1, types.length);
    assertEquals(expectedReturnType, types[0]);
    for (int i = 0; i < types.length - 1; i++) {
      assertEquals(expectedParamTypes[i], types[i + 1]);
    }
  }
 @Test
 public void testGetTargetBlockMethodInSuperInterface() throws Exception {
   assertEquals(
       toSootClass(F.class).getMethodByName("run"),
       ObjCBlockPlugin.getBlockTargetMethod(
           toSootClass(Runners.class).getMethodByName("runner2"), 0));
 }
 @Test
 public void testGetTargetBlockMethodDirect2() throws Exception {
   assertEquals(
       toSootClass(Runnable.class).getMethodByName("run"),
       ObjCBlockPlugin.getBlockTargetMethod(
           toSootClass(Runners.class).getMethodByName("runner9"), 0));
 }
 @Test(expected = CompilerException.class)
 public void testResolveTargetMethodSignatureGenericWithUnresolvedDirectTypeVariable()
     throws Exception {
   SootMethod target = toSootClass(F.class).getMethodByName("run");
   SootMethod m = toSootClass(Runners.class).getMethodByName("runner8");
   SootMethodType mType = new SootMethodType(m);
   ObjCBlockPlugin.resolveTargetMethodSignature(m, target, mType.getGenericParameterTypes()[0]);
 }
 @Test(expected = CompilerException.class)
 public void testParseTargetMethodAnnotationsInvalid4() throws Exception {
   SootMethod m = toSootClass(Runners.class).getMethodByName("runner1");
   ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, "@ByVal(");
 }
  @Test
  public void testParseTargetMethodAnnotations() throws Exception {
    SootMethod m = toSootClass(Runners.class).getMethodByName("runner1");

    assertArrayEquals(new String[][] {{}}, ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, ""));
    assertArrayEquals(
        new String[][] {{}}, ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, "  "));
    assertArrayEquals(
        new String[][] {{}}, ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, "()"));
    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, "@Pointer@ByVal"));
    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(m, 0, "@Pointer  @ByVal ()"));

    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}, {BY_REF}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(m, 1, "@Pointer  @ByVal (@ByRef)"));
    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}, {BY_REF, POINTER}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(
            m, 1, "@Pointer  @ByVal (  @ByRef  @Pointer  )"));
    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}, {BY_REF, POINTER}, {MACHINE_SIZED_S_INT}, {}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(
            m, 3, "@Pointer  @ByVal (  @ByRef  @Pointer , @MachineSizedSInt , )"));
    assertArrayEquals(
        new String[][] {{BY_VAL, POINTER}, {}, {BY_REF, POINTER}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(m, 2, "@Pointer @ByVal(,@ByRef @Pointer)"));
    assertArrayEquals(
        new String[][] {{}, {BY_REF, POINTER}},
        ObjCBlockPlugin.parseTargetMethodAnnotations(m, 1, "(@ByRef @Pointer)  "));

    assertArrayEquals(
        new String[][] {
          {},
          {
            BLOCK,
            BY_REF,
            BY_VAL,
            MACHINE_SIZED_FLOAT,
            MACHINE_SIZED_S_INT,
            MACHINE_SIZED_U_INT,
            POINTER
          }
        },
        ObjCBlockPlugin.parseTargetMethodAnnotations(
            m,
            1,
            "(@ByRef @ByVal @Pointer @MachineSizedFloat @MachineSizedSInt "
                + "@MachineSizedUInt @Block)  "));
  }
 @Test(expected = CompilerException.class)
 public void testGetTargetBlockMethodNoMethods() throws Exception {
   ObjCBlockPlugin.getBlockTargetMethod(toSootClass(Runners.class).getMethodByName("runner12"), 0);
 }