先看个典型的grinder脚本
from net.grinder.script.Grinder import grinder
from net.grinder.script import Test
from net.grinder.plugin.http import HTTPRequest
test1 = Test(1, "Request resource")
request1 = test1.wrap(HTTPRequest())
from net.grinder.script import Test
from net.grinder.plugin.http import HTTPRequest
test1 = Test(1, "Request resource")
request1 = test1.wrap(HTTPRequest())
class TestRunner:
def __call__(self):
result = request1.GET("http://www.google.com.hk)
def __call__(self):
result = request1.GET("http://www.google.com.hk)
脚本解析的入口:Test 类。
1. 解析脚本:test1 = Test(1, "Request resource")
// number=1,description="Request resource"
public class Test extends AbstractTestSemantics implements Serializable{
public Test( int number, String description) {
m_number = number;
m_description = description;
//Test类在初始化的时候,向registeredTest注册该测试对象Test
m_registeredTest = Grinder.grinder .getTestRegistry().register(this);
}
class TestRegistryImplementation
public RegisteredTest register(Test test) {
//先判断instrumenter是否为空
if ( m_instrumenter == null) {
throw new AssertionError("Instrumenter not set");
}
// 创建测试业务实现对象, TestData可以包装关联被测目标对象 /方法,同时实现计时功能
final TestData newTestData;
//同步信息,从testMap中查询是否存在这个test,如果存在就直接返回。保证test在testMap中的唯一性。
synchronized ( this) {
final TestData existing = m_testMap .get(test);
if (existing != null) {
return existing;
}
//如果不存在,new 一个TestData对象。
newTestData = new TestData(m_threadContextLocator ,
m_statisticsSetFactory,
m_testStatisticsHelper,
m_timeAuthority,
m_instrumenter,
test);
// 把test和newTestData放入testMap 中进行管理。
m_testMap.put(test, newTestData);
m_testStatisticsMap.put(test, newTestData.getTestStatistics());
if (m_newTests == null) {
m_newTests = new ArrayList<Test>();
}
// To avoid many minor console updates we store a collection of
// the new tests which is periodically read and sent to the
// console by the scheduled reporter task.
//Collection<Test> 中新增这个test
m_newTests.add(test);
}
return newTestData;
}
2. 解析脚本:request1 = test1.wrap(HTTPRequest())
//Test类的wrap方法,传入参数 Object对象"HTTPRequest()",返回registerTest的创建proxy方法。
public final Object
wrap(Object target) throws NotWrappableTypeException {
return m_registeredTest.createProxy(target);
}
TestData类,TestData实现了RegisteredTest和recorder类。
//传入object对象,实现创建proxy。
public Object
createProxy(Object o)
throws NotWrappableTypeException
{
//传入 test,testData,object,返回instrumenter的创建instrumentedProxy方法。
return m_instrumenter .createInstrumentedProxy(getTest(), this,
o);
}
class TraditionalJythonInstrumenter
//传入test,recoder,因为TestData类实现recoder类,所以这里传入testData。
public Object
createInstrumentedProxy(Test test,
Recorder recorder,
Object o)
throws NotWrappableTypeException
{
// 返回instrumentObject。
return instrumentObject(test, new PyDispatcher(recorder),
o);
}
// instrumentObject 是个pyobject对象了。
private PyObject
instrumentObject(Test test,
PyDispatcher pyDispatcher,
Object o)
throws NotWrappableTypeException
{
//对Object o 进行判定。如果是python对象。。。。
if (o instanceof PyObject)
{
// Jython object.
if (o instanceof PyInstance)
{
final PyInstance
pyInstance = (PyInstance)o;
final PyClass
pyClass =
m_versionAdapter .getClassForInstance(pyInstance);
return new InstrumentedPyInstance(
test, pyClass, pyInstance, pyDispatcher);
}
else if (o instanceof PyFunction)
{
return new InstrumentedPyJavaInstanceForPyFunctions(
test, (PyFunction)o, pyDispatcher);
}
else if (o instanceof PyMethod)
{
return new InstrumentedPyJavaInstanceForPyMethods(
test, (PyMethod)o, pyDispatcher);
}
else if (o instanceof PyReflectedFunction)
{
return new InstrumentedPyReflectedFunction(
test, (PyReflectedFunction)o, pyDispatcher);
}
else {
// Fail, rather than guess a generic
approach.
throw new NotWrappableTypeException( "Unknown
PyObject: " +
o.getClass());
}
}
else if (o instanceof PyProxy)
{
// Jython object
that extends a Java class.
final PyInstance
pyInstance = ((PyProxy)o)._getPyInstance();
final PyClass
pyClass =
m_versionAdapter.getClassForInstance(pyInstance);
return new InstrumentedPyInstance(
test, pyClass, pyInstance, pyDispatcher);
}
//如果O是java class<?>,实现这段逻辑。
else if (o instanceof Class<?>)
{
return new InstrumentedPyJavaClass(test,
(Class<?>)o, pyDispatcher);
}
else if (o
!= null) {
// Java object.
// NB Jython uses
Java types for some primitives and strings.
if (!o.getClass().isArray()
&&
!(o instanceof Number)
&&
!(o instanceof String))
{
//如果是java 对象,返回InstrumentedPyJavaInstanceForJavaInstances
return new InstrumentedPyJavaInstanceForJavaInstances(
test, o, pyDispatcher);
}
}
return null;
}
class InstrumentedPyJavaInstanceForJavaInstances
//脚本: request.GET("http://www.google.com.hk/")
public PyObject
invoke( final String name, final PyObject
arg1) {
//调用
return getInstrumentationHelper().dispatch(
new PyDispatcher.Callable()
{
public PyObject
call() {
//invoke后,脚本变成request(GET,"http://www.google.com.hk/")
//name=GET,arg1="http://www.google.com.hk/"
return InstrumentedPyJavaInstanceForJavaInstances.super.invoke(
name, arg1);
//
}
}
);
}
//class InstrumentationHelper
//invoke后的PyDispatcher.Callable() ,传入getInstrumentationHelper().dispatch
public PyObject dispatch(PyDispatcher.Callable callable) {
return m_dispatcher.dispatch(callable);
}
return m_dispatcher.dispatch(callable);
}
class PyDispatcher
public PyObject dispatch(Callable callable) {
try {
//开始计时,这里涉及到grinder的数据统计。另外分析。
try {
//开始计时,这里涉及到grinder的数据统计。另外分析。
//计时最小单位是一个request。
m_recorder.start();
boolean success = false;
try {
final PyObject result = callable.call();
success = true;
return result;
}
finally {
m_recorder.start();
boolean success = false;
try {
final PyObject result = callable.call();
success = true;
return result;
}
finally {
//计时结束。
m_recorder.end(success);
}
}
m_recorder.end(success);
}
}