Skip to content

Commit c0276df

Browse files
committed
[test] specify compiled script "local-var" behavior
when pre-parsing (compiling) scripts the parser will assume potential loval variables to be method calls, since the eval scope won't provide any local variable names (compared to directly eval-ing with bindings passed in). see jrubyGH-5876
1 parent 840c922 commit c0276df

File tree

1 file changed

+82
-48
lines changed

1 file changed

+82
-48
lines changed

core/src/test/java/org/jruby/embed/jsr223/JRubyCompiledScriptTest.java

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
package org.jruby.embed.jsr223;
3131

3232
import java.io.StringWriter;
33+
import java.util.Objects;
3334
import javax.script.Bindings;
3435
import javax.script.Compilable;
36+
import javax.script.CompiledScript;
3537
import javax.script.ScriptContext;
3638
import javax.script.ScriptEngine;
3739
import javax.script.ScriptEngineManager;
@@ -106,66 +108,98 @@ public void testEval_context() throws Exception {
106108
context.setWriter(writer);
107109
context.setErrorWriter(errorWriter);
108110

109-
context.setAttribute("message", "Hello World!!!!!", ScriptContext.ENGINE_SCOPE);
110-
engine.setContext(context);
111-
JRubyCompiledScript script = (JRubyCompiledScript) engine.compile("puts message");
112-
Object expResult = "Hello World!!!!!";
113-
script.eval(context);
114-
assertEquals(expResult, writer.toString().trim());
115-
writer.close();
116-
117-
writer = new StringWriter();
118-
context.setWriter(writer);
119-
context.setAttribute("@message", "Say Hey.", ScriptContext.ENGINE_SCOPE);
120-
engine.setContext(context);
121-
script = (JRubyCompiledScript) engine.compile("puts @message");
122-
script.eval(context);
123-
assertEquals("Say Hey.", writer.toString().trim());
124-
125-
context.setAttribute("@message", "Yeah!", ScriptContext.ENGINE_SCOPE);
126-
engine.setContext(context);
127-
script.eval(context);
128-
assertEquals("Say Hey.\nYeah!", writer.toString().trim());
129-
writer.close();
130-
131-
writer = new StringWriter();
132-
context.setWriter(writer);
133-
context.setAttribute("$message", "Hiya.", ScriptContext.ENGINE_SCOPE);
134-
engine.setContext(context);
135-
script = (JRubyCompiledScript) engine.compile("puts $message");
136-
script.eval(context);
137-
assertEquals("Hiya.", writer.toString().trim());
138-
writer.close();
139-
errorWriter.close();
111+
try {
112+
context.setAttribute("message", "Hello World!!!!!", ScriptContext.ENGINE_SCOPE);
113+
engine.setContext(context);
114+
JRubyCompiledScript script = (JRubyCompiledScript) engine.compile("puts message");
115+
Object expResult = "Hello World!!!!!";
116+
script.eval(context);
117+
assertEquals(expResult, writer.toString().trim());
118+
writer.close();
119+
context.removeAttribute("message", ScriptContext.ENGINE_SCOPE);
120+
121+
writer = new StringWriter();
122+
context.setWriter(writer);
123+
context.setAttribute("@message", "Say Hey.", ScriptContext.ENGINE_SCOPE);
124+
engine.setContext(context);
125+
script = (JRubyCompiledScript) engine.compile("puts @message");
126+
script.eval(context);
127+
assertEquals("Say Hey.", writer.toString().trim());
128+
129+
context.setAttribute("@message", "Yeah!", ScriptContext.ENGINE_SCOPE);
130+
engine.setContext(context);
131+
script.eval(context);
132+
assertEquals("Say Hey.\nYeah!", writer.toString().trim());
133+
writer.close();
134+
135+
writer = new StringWriter();
136+
context.setWriter(writer);
137+
context.setAttribute("$message", "Hiya.", ScriptContext.ENGINE_SCOPE);
138+
engine.setContext(context);
139+
script = (JRubyCompiledScript) engine.compile("puts $message");
140+
script.eval(context);
141+
assertEquals("Hiya.", writer.toString().trim());
142+
writer.close();
143+
} finally {
144+
engine.eval("remove_instance_variable :@message");
145+
engine.eval("$message = nil");
146+
errorWriter.close();
147+
}
140148
}
141149

142150
/**
143151
* Test of eval method, of class Jsr223JRubyCompiledScript.
144152
*/
145153
@Test
146-
public void testEval_bindings() throws Exception {
154+
public void testEvalWithBindings() throws Exception {
155+
System.setProperty("org.jruby.embed.localvariable.behavior", "transient");
156+
157+
JRubyEngineFactory factory = new JRubyEngineFactory();
158+
JRubyEngine engine = (JRubyEngine) factory.getScriptEngine();
159+
160+
try {
161+
CompiledScript script = engine.compile("'I heard, '.concat @the_message.to_s");
162+
Bindings bindings = new SimpleBindings();
163+
Object result = script.eval(bindings);
164+
assertEquals("I heard, ", result);
165+
166+
bindings.put("@the_message", "Saaaay Heeeey.");
167+
result = script.eval(bindings);
168+
assertEquals("I heard, Saaaay Heeeey.", result);
169+
170+
script = engine.compile("'I heard: ' + $a_message.inspect");
171+
result = script.eval(bindings);
172+
assertEquals("I heard: nil", result);
173+
174+
bindings = new SimpleBindings();
175+
bindings.put("$a_message", "Hiya, hiya, hiya");
176+
result = script.eval(bindings);
177+
assertEquals("I heard: \"Hiya, hiya, hiya\"", result);
178+
} finally {
179+
engine.eval("remove_instance_variable :@the_message");
180+
engine.eval("$a_message = nil");
181+
}
182+
}
183+
184+
@Test
185+
public void testEvalWithBindingsLocalVar() throws Exception {
147186
System.setProperty("org.jruby.embed.localvariable.behavior", "transient");
148187

149188
JRubyEngineFactory factory = new JRubyEngineFactory();
150189
JRubyEngine engine = (JRubyEngine) factory.getScriptEngine();
151190
Bindings bindings = new SimpleBindings();
152-
bindings.put("message", "Helloooo Woooorld!");
153191
engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
154-
JRubyCompiledScript script = (JRubyCompiledScript) engine.compile("\"I heard, \"#{message}\"\"");
155-
Object result = script.eval(bindings);
156-
// Bug? a local variable isn't shared.
157-
//assertEquals("I heard, Helloooo Woooorld!", result);
158-
159-
script = (JRubyCompiledScript) engine.compile("'I heard, '.concat @message");
160-
bindings = new SimpleBindings();
161-
bindings.put("@message", "Saaaay Heeeey.");
162-
result = script.eval(bindings);
163-
assertEquals("I heard, Saaaay Heeeey.", result);
164-
165-
bindings.put("$message", "Hiya, hiya, hiya");
166-
script = (JRubyCompiledScript) engine.compile("'I heard, ' + $message");
167-
result = script.eval(bindings);
168-
assertEquals("I heard, Hiya, hiya, hiya", result);
192+
JRubyCompiledScript script = (JRubyCompiledScript) engine.compile("sprintf(\"%4s\", sample_message)");
193+
Object result;
194+
// NOTE: compiled script can not know sample_message is meant as a local variable (isn't a method invocation)
195+
try {
196+
bindings.put("sample_message", "foo"); // no effect since script was 'compiled' (parsed) already
197+
result = script.eval(bindings);
198+
fail("script expected to fail but returned: " + result);
199+
} catch (ScriptException e) {
200+
assertTrue(Objects.toString(e.getCause()), e.getCause() instanceof org.jruby.exceptions.NameError);
201+
assertTrue(e.getCause().getMessage(), e.getCause().getMessage().contains("undefined local variable or method `sample_message'"));
202+
}
169203
}
170204

171205
/**

0 commit comments

Comments
 (0)