package com.oracle.truffle.api.instrumentation.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.graalvm.options.OptionCategory;
import org.graalvm.options.OptionDescriptors;
import org.graalvm.options.OptionKey;
import org.graalvm.options.OptionStability;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.PolyglotException;
import org.junit.Test;
import com.oracle.truffle.api.Option;
import com.oracle.truffle.api.TruffleContext;
import com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest;
import com.oracle.truffle.api.test.polyglot.ProxyInstrument;
public class InstrumentOptionsTest extends AbstractPolyglotTest {
static final String DEFAULT_OPTION_VALUE = "default";
public InstrumentOptionsTest() {
cleanupOnSetup = false;
}
static class TestInstrument extends ProxyInstrument {
private boolean created;
@Override
protected void onCreate(Env env) {
super.onCreate(env);
created = true;
}
@Override
protected OptionDescriptors getOptionDescriptors() {
return new EngineOptionsOptionDescriptors();
}
@Override
protected OptionDescriptors getContextOptionDescriptors() {
return new ContextOptionsOptionDescriptors();
}
}
@Test
public void testOptions() {
TruffleContext tc;
setupEnv(Context.newBuilder(), new TestInstrument());
tc = languageEnv.getContext();
assertEquals(DEFAULT_OPTION_VALUE, instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals(DEFAULT_OPTION_VALUE, instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
setupEnv(Context.newBuilder().
option(ProxyInstrument.ID + ".EngineOption1", "engineValue").
option(ProxyInstrument.ID + ".ContextOption1", "contextValue"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValue", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
setupEnv(Context.newBuilder().option(ProxyInstrument.ID + ".ContextOption1", "contextValue"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("default", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValue", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
setupEnv(Context.newBuilder().option(ProxyInstrument.ID + ".EngineOption1", "engineValue"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("default", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
Engine engine = Engine.newBuilder().option(ProxyInstrument.ID + ".EngineOption1", "engineValue").build();
setupEnv(Context.newBuilder().engine(engine).option(ProxyInstrument.ID + ".ContextOption1", "contextValue1"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValue1", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
setupEnv(Context.newBuilder().engine(engine).option(ProxyInstrument.ID + ".ContextOption1", "contextValue2"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValue2", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
engine.close();
engine = Engine.newBuilder().
option(ProxyInstrument.ID + ".ContextOption1", "contextValue").
option(ProxyInstrument.ID + ".EngineOption1", "engineValue").build();
setupEnv(Context.newBuilder().engine(engine), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValue", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
setupEnv(Context.newBuilder().engine(engine).option(ProxyInstrument.ID + ".ContextOption1", "contextValueOverride"), new TestInstrument());
tc = languageEnv.getContext();
assertEquals("engineValue", instrumentEnv.getOptions().get(EngineOptions.EngineOption1));
assertEquals("contextValueOverride", instrumentEnv.getOptions(tc).get(ContextOptions.ContextOption1));
context.close();
engine.close();
}
@Test
public void testInitializeByContextOption() {
TestInstrument instrument = new TestInstrument();
ProxyInstrument.setDelegate(instrument);
Engine engine = Engine.create();
Context c = Context.newBuilder().engine(engine).option(ProxyInstrument.ID + ".ContextOption1", "contextValue").build();
assertTrue(instrument.created);
c.close();
engine.close();
}
@Option.Group(ProxyInstrument.ID)
static class EngineOptions {
@Option(category = OptionCategory.USER, help = "HelpText", stability = OptionStability.STABLE)
static final OptionKey<String> EngineOption1 = new OptionKey<>(DEFAULT_OPTION_VALUE);
}
@Option.Group(ProxyInstrument.ID)
static class ContextOptions {
@Option(category = OptionCategory.USER, help = "HelpText", stability = OptionStability.STABLE)
static final OptionKey<String> ContextOption1 = new OptionKey<>(DEFAULT_OPTION_VALUE);
}
@Test
public void testInvalidOptions() {
ProxyInstrument.setDelegate(new InvalidInstrument());
Context.Builder contextBuilder = Context.newBuilder().option(ProxyInstrument.ID + ".ContextOption1", "contextValue");
assertFails(() -> contextBuilder.build(), PolyglotException.class, (e) -> {
assertTrue(e.isInternalError());
});
}
static class InvalidInstrument extends ProxyInstrument {
@Override
protected OptionDescriptors getOptionDescriptors() {
return new ContextOptionsOptionDescriptors();
}
@Override
protected OptionDescriptors getContextOptionDescriptors() {
return new ContextOptionsOptionDescriptors();
}
}
}