วิธีใช้ selenium webdriver 2

ตามนี้

def seleniumVer = "2.12.0"
def groupId = "org.seleniumhq.selenium"
test("${groupId}:selenium-java:${seleniumVer}") {
    export = false
}
test("${groupId}:selenium-chrome-driver:${seleniumVer}") {
    export = false
}
test("${groupId}:selenium-server:${seleniumVer}") {
    export = false
}

รื้อ tumblr ใหม่

My below POC is based on Alex T. implementation. But instead of showing all kind of callsite, I show you here only statically resolved callsite. This callsite is surely fast (I hope it’s gonna be at the same level of Java) because it’s compile-time thing. The interesting point is that, I have a special class loader for these callsites, namely StaticCallSiteClassLoader. What does it do? This class loader allows re-definition of these callsites.

What I have observed so far is that All of my callsite classes (_0_println, _1_ctor, _2_render and _3_index) have not been loaded when there is no “direct” reference to them. So they can be fully lazy loading using the StaticCallSiteClassLoader. (I’ve checked this with java —verbose)

How could these callsites are changed at runtime? You may see the acallsite, an CallSite array that hold all callsites in the example class. It’s intended to be public and can be accessed by, for example, a virtual meta-class. So what’s a virtual meta-class? It’s kind of meta-class, but in this case, it’s not for controlling behaviour of the class (because all dispatch are static). It’s for changing behaviour of callsite by reassigning new callsites object to the callsite array.

Notic that I use WeakReference to hold a callsite class loader. This will be making the class loader GC-able. That’s it, after deferenceing all old callsites out of the callsite array, the class loader can be unloaded. Therefore, all callsite class definition are gone as well. Then, we can create a new set of callsites for the current class. This technique would be flexible enough for:

  • changing a static call to be a dynamic call
  • changing a dynamic call back to a static call
  • installing a woven callsite with before, after advice (it features dynamic AOP)
  • inserting type advice, which can lead to bytecode inlining
  • design a hybrid type system to support both static and dynamic typing in the same system.

Here’s code:

import java.lang.ref.WeakReference;

import runtime.CallSite;
import classloader.StaticCallSiteClassLoader;
import dm.Render;

public class TestController {

    /* synthetic */
    private static WeakReference<StaticCallSiteClassLoader> cl;

    /* synthetic normal callsite */
    public static class _0_println extends CallSite {...}

    /* synthetic constructor */
    public static class _1_ctor extends CallSite {...}

    /* synthetic inter-type declaration callsite. statically resolved */
    public static class _2_render extends CallSite {...}

    /* synthetic property callsite */
    public static class _3_index extends CallSite {...}

    /* synthetic */
    public static CallSite[] acallsite;

    static {
        cl = new WeakReference<StaticCallSiteClassLoader>(
                    new StaticCallSiteClassLoader(TestController.class)
        );
        acallsite = new CallSite[4];
        acallsite[0] = cl.get().get("_0_println");
        acallsite[1] = cl.get().get("_1_ctor");
        acallsite[2] = cl.get().get("_2_render");
        acallsite[3] = cl.get().get("_3_index");
    }

    public TestController(){
        super();
    }

    public int getIndex() {
        return 10;
    }

    public static void main(String[] args) {
        acallsite[0].callStatic("hello world");
        TestController t = (TestController)(acallsite[1].callConstructor());
        acallsite[2].call(t, "hello world");
        acallsite[0].callStatic(acallsite[3].callGetProperty(t, "index"));
    }

}

Virtual MetaClass

What is it? It’s a runtime behaviour that acts like meta-class, but there is no the real one controlling a class. It converted to be a callsite trick instead.

For example,

A.metaClass.insert = { i ->
  println "test:" + i
}

This turns to be

class A_vmc_insert extends CallSite {
  public Object call(Object arg0, Object arg1) {
    acallsite[1].callStatic(acallsite[0].plus("test:", arg1))
  }
}

Typing concern คืออะไร typing concern เป็น concern ที่มีผลกับระบบ type ของภาษา สามารถพบได้ในภาษาโปรแกรมที่มีระบบไทพ์ งานนี้แสดงการแยก typing concern ออกมากจากภาษา dynamic

ระบบไทพ์ เป็นองค์ประกอบหลักของภาษาโปรแกรม เป็นตัวควบคุมชนิดของตัวแปร เป็นตัวที่ส่งผลต่อ type safety property ของภาษา เป็นตัวที่ส่งผลโดยอ้อมกับประสิทธิภาพและ productivity ของภาษา

ภาษา dynamic คืออะไร คือภาษาที่ resolve type ของตัวแปรหรือวัตถุ ในขณะรัน ตรงข้ามกับภาษา static ที่ resolve type ขณะ compile นิยามที่ใช้ในงานนี้จะครอบคลุมภาษาที่มีความสามารถในการทำ dynamic dispatch ด้วย

dynamic dispatch คือการบวนการเลือก method ที่จะ call ด้วยข้อมูลของ type ของ argument ในขณะรัน ภาษากลุ่มนี้เช่น Ruby, Python, Smalltalk และ Groovy

typing concern เกี่ยวข้องกับ dynamic dispatch อย่างไร เกี่ยวข้องในส่วนของกระบวนการเลือก method เพื่อ dispatch

Typing Concerns

  • Introduction
    • Background
    • Contribution
  • Featherweight Groovy เป็นภาษาฐาน ใช้อธิบาย call site, การแทนที่ call site
    • Call site
    • Dynamic call site เพื่อสนับสนุน type advice
  • Join point models for Typing Concerns
    • Background: Pointcut-advice model of AspectJ
    • Join point models
    • Type Advice
    • Implementation
    • Typesheet Language
    • Pointcut Designators
    • Class Structure for Typing Concerns
    • Examples

อธิบาย implicit conversion

อธิบาย implicit conversion
===============

as is a define implicit conversion.
Based on Scala, 
as is working like an implicit conversion
for a term e if e is not compatible with its expected type


@Implicit (precendence=100) class Convert {
  static String asType (Integer int) {
  }
}

return invoke(Pair#setFirst as m', new C(e*) as B, x* as B*) as B



Reduction Rules

R-CALLSITE:

callsite(m, E, C) = S
-------------------------------------------------------------
(new C(e*)).m(d*) -> new S(m).call(new C(e*), d*)

R-INVK-1:

mbody(m, C) = x*.e0
----------------------------------------------------------
(new C(e*)).m(d*) -> [new C(e*)/this, d*/x*]e0


R-INVK-2:

mbody(m, C) = x*.e0
------------------------------------------------------------------
invoke(m, new C(e*), d*) -> [new C(e*)/this, d*/x*]e0


R-CALLSITE:

callsite(m, E, C) = m'.c.x*.s0
--------------------------------------
(new C(e*)).m(d*) -> [m/m', new C(e*)/c, d*/x*]s0


mbody(m, C) =  x*.e0



R-EXEC:
mbody(m, C) =  x*.e0
-------------------------------------
invoke(m, new C(e*), d*) -> [d*/x*, new C(e*)/this]e0

===========================================

reduction rules may be applied at any point in an expression
so we need obvious congruence rules 

S { Object call(c, e*) { return invoke(m, c, e*); } }

new Pair(new A(), new B()).setFst(new B())
-> [Pair#setFst/m, new Pair(new A(), new B())/c, new B()/e*] new S(m).call(c, e*)
new S(Pair#setFst).call(new Pair(new A(), new B()), new B())
-> [Pair#setFst/m, new Pair(new A(), new B())/c, new B()/e*] invoke(m, c, e*)
invoke(Pair#setFst, new Pair(new A(), new B()), new B())
-> [new B()/newfst, new Pair(new A(), new B())/this] new Pair(newfst, this.snd)


Reduction rules

// mbody(m, C) = x*.e0
callsite(m, E, C) = new S(m').call(e0, x*)
----------------------------------------------------
(new C(e*)).m(d*) -> [d*/x*, new C(e*)/e0, m/m']new S(m).call(e0, x*)


x*.e0 = m(x*) {return e0;}

mbody(m, C) = x*.e0
----------------------------------------------------
invoke(m, e, d*) -> [d*/x*, e/this]e0

11.42

refactored, optimized, -server : 273.39

./ab.exe -n 20000 -c 50 http://localhost:8080/b/test/index

เอา RenderDynamicMethod มา parse แล้ว จะได้ RenderDynamicMethod_2 ที่มี code ชุดเดิม กับ โค้ดใหม่ที่ specialize แล้วอยู่ด้วย - ก็จะเข้าถึง private method ของ class เดิมได้ปกติ - ให้อยู่ใน package เดิมก็จะใช้ resource อื่นได้ด้วย

แล้วให้ตัว controller ใช้ RDM_2 แทน

ใช้อะไรเป็นเงื่อนไขการแยก ?

+104-115, -116 +117-119 GOTO L20

test picking methods

def mc0 = TestController.metaClass
def mc1 = TestController$_closure1.metaClass
def c0 = mc0.pickMethod("render", [String] as Class[])
def c1 = mc1.pickMethod("render", [String] as Class[])
//println c0
//println c1
c0.properties.each {
 println it
}

rename recursively

find . -name “*.java” -exec rename .java .groovy {} \;