Package fr.insalyon.citi.golo.runtime

Source Code of fr.insalyon.citi.golo.runtime.MethodInvocationSupportTest

/*
* Copyright 2012-2014 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
*
* 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 fr.insalyon.citi.golo.runtime;

import gololang.DynamicObject;
import org.testng.annotations.Test;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;

import static java.lang.invoke.MethodHandles.lookup;
import static java.lang.invoke.MethodType.methodType;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;


public class MethodInvocationSupportTest {

  public static class Person {
    String name;
    String email;

    public Person(String name, String email) {
      this.name = name;
      this.email = email;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getEmail() {
      return email;
    }

    public void setEmail(String email) {
      this.email = email;
    }

    public String greet(Person... people) {
      StringBuilder builder = new StringBuilder("Hello");
      for (Person p : people) {
        builder.append(" ").append(p.name).append("!");
      }
      return builder.toString();
    }

    @Override
    public String toString() {
      return "Person{" +
          "name='" + name + '\'' +
          ", email='" + email + '\'' +
          '}';
    }
  }

  public static class VarargsChecking {

    public String concat(String separator, String... values) {
      if (values.length == 0) {
        return "";
      }
      String result = values[0];
      for (int i = 1; i < values.length; i++) {
        result = result + separator + values[i];
      }
      return result;
    }

    public String defaultConcat(String... values) {
      return concat("-", values);
    }
  }

  public static class FieldAccessors {
    public Object property;
  }

  public static class Ploper {

    public String plop(Object obj) {
      return obj.toString();
    }
  }

  public Person julien() {
    return new Person("Julien", "julien.ponge@insa-lyon.fr");
  }

  public VarargsChecking varargsChecking() {
    return new VarargsChecking();
  }

  @Test
  public void check_to_string() throws Throwable {
    CallSite toString = MethodInvocationSupport.bootstrap(lookup(), "toString", methodType(Object.class, Object.class), 0);
    String result = (String) toString.dynamicInvoker().invokeWithArguments(julien());
    assertThat(result, notNullValue());
    assertThat(result, is("Person{name='Julien', email='julien.ponge@insa-lyon.fr'}"));
  }

  @Test
  public void check_set_name() throws Throwable {
    CallSite setName = MethodInvocationSupport.bootstrap(lookup(), "setName", methodType(Object.class, Object.class, Object.class), 0);
    Person julien = julien();
    setName.dynamicInvoker().invokeWithArguments(julien, "Julien Ponge");
    assertThat(julien.name, is("Julien Ponge"));
  }

  @Test
  public void check_equals() throws Throwable {
    CallSite equals = MethodInvocationSupport.bootstrap(lookup(), "equals", methodType(Object.class, Object.class, Object.class), 0);
    Person julien = julien();
    Boolean result = (Boolean) equals.dynamicInvoker().invokeWithArguments(julien, julien);
    assertThat(result, is(true));
  }

  @Test
  public void check_field_read() throws Throwable {
    CallSite name = MethodInvocationSupport.bootstrap(lookup(), "name", methodType(Object.class, Object.class), 0);
    String result = (String) name.dynamicInvoker().invokeWithArguments(julien());
    assertThat(result, notNullValue());
    assertThat(result, is("Julien"));
  }

  @Test(expectedExceptions = NoSuchMethodError.class)
  public void check_bogus() throws Throwable {
    CallSite bogus = MethodInvocationSupport.bootstrap(lookup(), "bogus", methodType(Object.class, Object.class), 0);
    bogus.dynamicInvoker().invokeWithArguments(julien());
  }

  @Test
  public void check_many_to_string() throws Throwable {
    CallSite toString = MethodInvocationSupport.bootstrap(lookup(), "toString", methodType(Object.class, Object.class), 0);
    MethodHandle toStringMH = toString.dynamicInvoker();

    for (int i = 0; i < 5; i++) {
      String result = (String) toStringMH.invokeWithArguments(julien());
      assertThat(result, is("Person{name='Julien', email='julien.ponge@insa-lyon.fr'}"));

      result = (String) toStringMH.invokeWithArguments("foo");
      assertThat(result, is("foo"));

      result = (String) toStringMH.invokeWithArguments(666);
      assertThat(result, is("666"));

      result = (String) toStringMH.invokeWithArguments(666L);
      assertThat(result, is("666"));

      result = (String) toStringMH.invokeWithArguments("foo");
      assertThat(result, is("foo"));

      result = (String) toStringMH.invokeWithArguments(new BigInteger("1234"));
      assertThat(result, is("1234"));

      result = (String) toStringMH.invokeWithArguments(new Object() {
        @Override
        public String toString() {
          return "Damn";
        }
      });
      assertThat(result, is("Damn"));

      result = (String) toStringMH.invokeWithArguments(new Object() {
        @Override
        public String toString() {
          return "Plop";
        }
      });
      assertThat(result, is("Plop"));

      result = (String) toStringMH.invokeWithArguments(new Object() {
        @Override
        public String toString() {
          return "Hey!";
        }
      });
      assertThat(result, is("Hey!"));
    }
  }

  @Test
  public void check_primitive_argument_allowance() throws Throwable {
    List<String> list = Arrays.asList("a", "b", "c");
    CallSite get = MethodInvocationSupport.bootstrap(lookup(), "get", methodType(Object.class, Object.class, Object.class), 0);

    MethodHandle handle = get.dynamicInvoker();
    assertThat(((String) handle.invokeWithArguments(list, 0)), is("a"));
    assertThat(((String) handle.invokeWithArguments(list, 1)), is("b"));
    assertThat(((String) handle.invokeWithArguments(list, 2)), is("c"));
  }

  @Test
  public void check_varags() throws Throwable {
    CallSite concat = MethodInvocationSupport.bootstrap(lookup(), "concat", methodType(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class), 0);
    VarargsChecking receiver = varargsChecking();

    Object result = concat.dynamicInvoker().invokeWithArguments(receiver, "-", "a", "b", "c");
    assertThat(result, notNullValue());
    assertThat(result, instanceOf(String.class));
    assertThat((String) result, is("a-b-c"));

    concat = MethodInvocationSupport.bootstrap(lookup(), "concat", methodType(Object.class, Object.class, Object.class, Object.class), 0);
    result = concat.dynamicInvoker().invokeWithArguments(receiver, "-", new String[]{"a", "b", "c"});
    assertThat(result, notNullValue());
    assertThat(result, instanceOf(String.class));
    assertThat((String) result, is("a-b-c"));
  }

  @Test
  public void check_varags_only() throws Throwable {
    CallSite concat = MethodInvocationSupport.bootstrap(lookup(), "defaultConcat", methodType(Object.class, Object.class, Object.class, Object.class, Object.class), 0);
    VarargsChecking receiver = varargsChecking();

    Object result = concat.dynamicInvoker().invokeWithArguments(receiver, "a", "b", "c");
    assertThat(result, notNullValue());
    assertThat(result, instanceOf(String.class));
    assertThat((String) result, is("a-b-c"));

    concat = MethodInvocationSupport.bootstrap(lookup(), "defaultConcat", methodType(Object.class, Object.class, Object.class), 0);
    result = concat.dynamicInvoker().invokeWithArguments(receiver, new String[]{"a", "b", "c"});
    assertThat(result, notNullValue());
    assertThat(result, instanceOf(String.class));
    assertThat((String) result, is("a-b-c"));

    concat = MethodInvocationSupport.bootstrap(lookup(), "defaultConcat", methodType(Object.class, Object.class, Object.class), 0);
    receiver = varargsChecking();
    assertThat((String) concat.dynamicInvoker().invokeWithArguments(receiver, "a"), is("a"));

    concat = MethodInvocationSupport.bootstrap(lookup(), "defaultConcat", methodType(Object.class, Object.class), 0);
    receiver = varargsChecking();
    assertThat((String) concat.dynamicInvoker().invokeWithArguments(receiver), is(""));
  }

  @Test
  public void check_field_getter() throws Throwable {
    CallSite property = MethodInvocationSupport.bootstrap(lookup(), "property", methodType(Object.class, Object.class), 0);
    FieldAccessors receiver = new FieldAccessors();
    receiver.property = "foo";

    Object result = property.dynamicInvoker().invokeWithArguments(receiver);
    assertThat(result, notNullValue());
    assertThat(result, instanceOf(String.class));
    assertThat((String) result, is("foo"));
  }

  @Test
  public void check_field_setter() throws Throwable {
    CallSite property = MethodInvocationSupport.bootstrap(lookup(), "property", methodType(Object.class, Object.class, Object.class), 0);
    FieldAccessors receiver = new FieldAccessors();
    receiver.property = "undefined";

    property.dynamicInvoker().invokeWithArguments(receiver, "foo");
    assertThat((String) receiver.property, is("foo"));
  }

  @Test(expectedExceptions = NullPointerException.class)
  public void not_nullsafe_invocation() throws Throwable {
    CallSite toString = MethodInvocationSupport.bootstrap(lookup(), "toString", methodType(Object.class, Object.class), 0);
    toString.dynamicInvoker().invoke(null);
  }

  @Test
  public void nullsafe_invocation() throws Throwable {
    CallSite toString = MethodInvocationSupport.bootstrap(lookup(), "toString", methodType(Object.class, Object.class), 1);

    MethodHandle invoker = toString.dynamicInvoker();
    assertThat(invoker.invoke(null), nullValue());
    assertThat((String) invoker.invoke("a"), is("a"));
    assertThat((String) invoker.invoke("b"), is("b"));
    assertThat(invoker.invoke(null), nullValue());
  }

  @Test
  public void nullsafe_megamorphic_invocation() throws Throwable {
    CallSite toString = MethodInvocationSupport.bootstrap(lookup(), "toString", methodType(Object.class, Object.class), 1);
    MethodInvocationSupport.InlineCache pic = (MethodInvocationSupport.InlineCache) toString;
    pic.depth = MethodInvocationSupport.InlineCache.MEGAMORPHIC_THRESHOLD + 10;

    MethodHandle invoker = toString.dynamicInvoker();
    assertThat(invoker.invoke(null), nullValue());
    assertThat((String) invoker.invoke("a"), is("a"));
    assertThat((String) invoker.invoke(1), is("1"));
    assertThat((String) invoker.invoke(1L), is("1"));
    assertThat((String) invoker.invoke(Arrays.asList()), is("[]"));
    assertThat((String) invoker.invoke(new Object()), startsWith("java.lang.Object"));
    assertThat(invoker.invoke(null), nullValue());
  }

  @Test
  public void dynamic_object_smoke_tests() throws Throwable {
    DynamicObject a = new DynamicObject();
    DynamicObject b = new DynamicObject();
    CallSite plopper = MethodInvocationSupport.bootstrap(lookup(), "plop", methodType(Object.class, Object.class, Object.class), 1);
    MethodHandle invoker = plopper.dynamicInvoker();

    invoker.invoke(a, 1);
    assertThat(a.get("plop"), is((Object) 1));

    invoker.invoke(b, 1);
    assertThat(b.get("plop"), is((Object) 1));

    invoker.invoke(a, 10);
    assertThat(a.get("plop"), is((Object) 10));
    assertThat(b.get("plop"), is((Object) 1));

    assertThat(invoker.invoke(new Ploper(), 666), is((Object) "666"));

    b.undefine("plop");
    Object result = invoker.invoke(b, 1);
    assertThat(result, is((Object) b));
    assertThat(b.get("plop"), is((Object) 1));
  }
}
TOP

Related Classes of fr.insalyon.citi.golo.runtime.MethodInvocationSupportTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.