问题描述
我正在Graal之上编写一个应用程序,它将能够执行不同语言的小脚本.
I am writing an application ontop of Graal that will be able to execute small scripts in different languages.
我正在尝试为用于将Context.eval()调用(类型:Value)的结果转换/处理为Java对象的类编写一些单元测试.我从文档中知道Value实例始终绑定到Context,因此当我尝试编写如下内容时:
I am trying to write some unit tests for a class I am using to convert/process the result of a Context.eval() call (type: Value) to a Java object. I know from the documentation that a Value instance is always bound to a Context, so when I try to write something like this:
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
我收到以下错误:
java.lang.IllegalStateException: No current context is available. Make sure the Java method is invoked by a Graal guest language or a context is entered using Context.enter().
我想从概念上讲,没有关联的来宾代码就没有"Value"实例是没有意义的,所以我的问题是:
I guess that conceptually it does not make sense to have a "Value" instance without an associated bit of guest code, so my question is:
如何测试GuestLanguageResultProcessor类?创建上下文时,我是否必须膨胀"我的单元测试?
How can I go about testing my GuestLanguageResultProcessor class? Do I have to "bloat" my unit test with the creation of a context?
专家的附加问题:我也使用此类(GuestLanguageResultProcessor)从多语言Value实例中提取Java值,以便我可以关闭上下文.换句话说,在我看来,在能够执行Context.close()之前,我需要调用[值实例] .asString()或.asWhatever()以便获得结果并能够关闭上下文而无需如文档.
Side question for the experts: I am using this class (GuestLanguageResultProcessor) also to extract a Java value from the polyglot Value instance so that I can close the context. In other words it looks to me that before being able to do Context.close() I need to call [value instance].asString() or .asWhatever() in order to get the result out and being able to close the context without getting an IllegalStateException as it says in the docs.
我做对了吗?有没有更好的方法来处理获取结果并安全地关闭上下文的问题?
Am I doing it right? Is there a better way to handle getting the result and closing the context safely?
谢谢!
推荐答案
我担心有点胀气是必要的.我建议使用以下代码来进行测试.也可以在测试基类中完成此操作,以避免重复.
I fear a bit of bloating is necessary. I'd recommend to use the following code to make your test work. This can also be done in a test base class, to avoid repetition.
Context context;
@Before
public void setup() {
context = Context.create();
context.enter();
}
@After
public void setup() {
context.leave();
context.close();
}
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
值实例可能绑定到来宾语言对象,例如JavaScript对象,一旦上下文关闭,它们就无效.并非总是可能将来宾语言对象转换为永久Java表示形式.例如,polyglot值可能引用JavaScript对象的整个图.
Value instances may be bound to guest language objects, like JavaScript objects which are invalid as soon as their context is closed. It is not always possible to convert guest language objects to a permanent Java representation. For example polyglot values might refer to an entire graph of JavaScript objects.
如果可能的话,我建议保持上下文开放,只要需要值就可以,因为它不需要任何转换.
If possible, I would recommend to keep the context open as long as values are needed as it does not require any conversions.
如果这是不可能的,并且您仅处理基元和数组,则可以尝试使用以下方法.您也可以尝试通过访问Java成员来将其复制到Java Land.
If that is not possible and you are only dealing with primitives and Arrays you can try using the following method. You may also try to copy objects into Java land by accessing its members.
Object copyToJavaLand(Value value) {
if (value.isBoolean()) {
return value.asBoolean();
} else if (value.isString()) {
return value.asString();
} else if (value.isNumber()) {
return value.as(Number.class);
} else if (value.isHostObject()) {
return value.asHostObject();
} else if (value.isProxyObject()) {
return value.asProxyObject();
} else if (value.hasArrayElements()) {
Object[] array = new Object[(int) value.getArraySize()];
for (int i = 0; i < array.length; i++) {
array[i] = copyToJavaLand(value.getArrayElement(i));
}
return array;
}
throw new IllegalArgumentException("Cannot copy value " + value + ".");
}
请注意,此方法并不总是安全的.例如,如果数组引用自身,则此方法将因堆栈溢出错误而崩溃.
Please note that this method is not always safe. For example if arrays refer to themselves, this method would crash with a stack-overflow error.
这篇关于GraalVM-在没有上下文的情况下使用Polyglot值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!