|
|
@@ -18,36 +18,142 @@
|
|
|
*/
|
|
|
package org.elasticsearch.script.mustache;
|
|
|
|
|
|
-import com.github.mustachejava.DefaultMustacheFactory;
|
|
|
import com.github.mustachejava.Mustache;
|
|
|
-import com.github.mustachejava.MustacheFactory;
|
|
|
+import org.elasticsearch.common.bytes.BytesReference;
|
|
|
+import org.elasticsearch.common.settings.Settings;
|
|
|
+import org.elasticsearch.script.CompiledScript;
|
|
|
+import org.elasticsearch.script.ExecutableScript;
|
|
|
+import org.elasticsearch.script.ScriptEngineService;
|
|
|
+import org.elasticsearch.script.ScriptService;
|
|
|
import org.elasticsearch.test.ESTestCase;
|
|
|
|
|
|
-import java.io.StringReader;
|
|
|
-import java.io.StringWriter;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.HashSet;
|
|
|
+
|
|
|
+import static java.util.Collections.singleton;
|
|
|
+import static java.util.Collections.singletonMap;
|
|
|
+import static org.elasticsearch.script.mustache.MustacheScriptEngineService.CONTENT_TYPE_PARAM;
|
|
|
+import static org.elasticsearch.script.mustache.MustacheScriptEngineService.JSON_CONTENT_TYPE;
|
|
|
+import static org.elasticsearch.script.mustache.MustacheScriptEngineService.PLAIN_TEXT_CONTENT_TYPE;
|
|
|
+import static org.hamcrest.Matchers.equalTo;
|
|
|
+import static org.hamcrest.Matchers.notNullValue;
|
|
|
+import static org.hamcrest.Matchers.instanceOf;
|
|
|
+import static org.hamcrest.Matchers.both;
|
|
|
+import static org.hamcrest.Matchers.containsString;
|
|
|
|
|
|
-/**
|
|
|
- * Figure out how Mustache works for the simplest use case. Leaving in here for now for reference.
|
|
|
- * */
|
|
|
public class MustacheTests extends ESTestCase {
|
|
|
- public void test() {
|
|
|
- HashMap<String, Object> scopes = new HashMap<>();
|
|
|
- scopes.put("boost_val", "0.2");
|
|
|
|
|
|
+ private ScriptEngineService engine = new MustacheScriptEngineService(Settings.EMPTY);
|
|
|
+
|
|
|
+ public void testBasics() {
|
|
|
String template = "GET _search {\"query\": " + "{\"boosting\": {"
|
|
|
- + "\"positive\": {\"match\": {\"body\": \"gift\"}},"
|
|
|
- + "\"negative\": {\"term\": {\"body\": {\"value\": \"solr\"}"
|
|
|
- + "}}, \"negative_boost\": {{boost_val}} } }}";
|
|
|
- MustacheFactory f = new DefaultMustacheFactory();
|
|
|
- Mustache mustache = f.compile(new StringReader(template), "example");
|
|
|
- StringWriter writer = new StringWriter();
|
|
|
- mustache.execute(writer, scopes);
|
|
|
- writer.flush();
|
|
|
+ + "\"positive\": {\"match\": {\"body\": \"gift\"}},"
|
|
|
+ + "\"negative\": {\"term\": {\"body\": {\"value\": \"solr\"}"
|
|
|
+ + "}}, \"negative_boost\": {{boost_val}} } }}";
|
|
|
+ Map<String, Object> params = Collections.singletonMap("boost_val", "0.2");
|
|
|
+
|
|
|
+ Mustache mustache = (Mustache) engine.compile(template, Collections.emptyMap());
|
|
|
+ CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "my-name", "mustache", mustache);
|
|
|
+ ExecutableScript result = engine.executable(compiledScript, params);
|
|
|
assertEquals(
|
|
|
"Mustache templating broken",
|
|
|
"GET _search {\"query\": {\"boosting\": {\"positive\": {\"match\": {\"body\": \"gift\"}},"
|
|
|
+ "\"negative\": {\"term\": {\"body\": {\"value\": \"solr\"}}}, \"negative_boost\": 0.2 } }}",
|
|
|
- writer.toString());
|
|
|
+ ((BytesReference) result.run()).toUtf8()
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testArrayAccess() throws Exception {
|
|
|
+ String template = "{{data.0}} {{data.1}}";
|
|
|
+ CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
|
|
+ Map<String, Object> vars = new HashMap<>();
|
|
|
+ Object data = randomFrom(
|
|
|
+ new String[] { "foo", "bar" },
|
|
|
+ Arrays.asList("foo", "bar"));
|
|
|
+ vars.put("data", data);
|
|
|
+ Object output = engine.executable(mustache, vars).run();
|
|
|
+ assertThat(output, notNullValue());
|
|
|
+ assertThat(output, instanceOf(BytesReference.class));
|
|
|
+ BytesReference bytes = (BytesReference) output;
|
|
|
+ assertThat(bytes.toUtf8(), equalTo("foo bar"));
|
|
|
+
|
|
|
+ // Sets can come out in any order
|
|
|
+ Set<String> setData = new HashSet<>();
|
|
|
+ setData.add("foo");
|
|
|
+ setData.add("bar");
|
|
|
+ vars.put("data", setData);
|
|
|
+ output = engine.executable(mustache, vars).run();
|
|
|
+ assertThat(output, notNullValue());
|
|
|
+ assertThat(output, instanceOf(BytesReference.class));
|
|
|
+ bytes = (BytesReference) output;
|
|
|
+ assertThat(bytes.toUtf8(), both(containsString("foo")).and(containsString("bar")));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testArrayInArrayAccess() throws Exception {
|
|
|
+ String template = "{{data.0.0}} {{data.0.1}}";
|
|
|
+ CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
|
|
+ Map<String, Object> vars = new HashMap<>();
|
|
|
+ Object data = randomFrom(
|
|
|
+ new String[][] { new String[] { "foo", "bar" }},
|
|
|
+ Collections.singletonList(new String[] { "foo", "bar" }),
|
|
|
+ singleton(new String[] { "foo", "bar" })
|
|
|
+ );
|
|
|
+ vars.put("data", data);
|
|
|
+ Object output = engine.executable(mustache, vars).run();
|
|
|
+ assertThat(output, notNullValue());
|
|
|
+ assertThat(output, instanceOf(BytesReference.class));
|
|
|
+ BytesReference bytes = (BytesReference) output;
|
|
|
+ assertThat(bytes.toUtf8(), equalTo("foo bar"));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testMapInArrayAccess() throws Exception {
|
|
|
+ String template = "{{data.0.key}} {{data.1.key}}";
|
|
|
+ CompiledScript mustache = new CompiledScript(ScriptService.ScriptType.INLINE, "inline", "mustache", engine.compile(template, Collections.emptyMap()));
|
|
|
+ Map<String, Object> vars = new HashMap<>();
|
|
|
+ Object data = randomFrom(
|
|
|
+ new Object[] { singletonMap("key", "foo"), singletonMap("key", "bar") },
|
|
|
+ Arrays.asList(singletonMap("key", "foo"), singletonMap("key", "bar")));
|
|
|
+ vars.put("data", data);
|
|
|
+ Object output = engine.executable(mustache, vars).run();
|
|
|
+ assertThat(output, notNullValue());
|
|
|
+ assertThat(output, instanceOf(BytesReference.class));
|
|
|
+ BytesReference bytes = (BytesReference) output;
|
|
|
+ assertThat(bytes.toUtf8(), equalTo("foo bar"));
|
|
|
+
|
|
|
+ // HashSet iteration order isn't fixed
|
|
|
+ Set<Object> setData = new HashSet<>();
|
|
|
+ setData.add(singletonMap("key", "foo"));
|
|
|
+ setData.add(singletonMap("key", "bar"));
|
|
|
+ vars.put("data", setData);
|
|
|
+ output = engine.executable(mustache, vars).run();
|
|
|
+ assertThat(output, notNullValue());
|
|
|
+ assertThat(output, instanceOf(BytesReference.class));
|
|
|
+ bytes = (BytesReference) output;
|
|
|
+ assertThat(bytes.toUtf8(), both(containsString("foo")).and(containsString("bar")));
|
|
|
}
|
|
|
+
|
|
|
+ public void testEscaping() {
|
|
|
+ // json string escaping enabled:
|
|
|
+ Map<String, String> params = randomBoolean() ? Collections.emptyMap() : Collections.singletonMap(CONTENT_TYPE_PARAM, JSON_CONTENT_TYPE);
|
|
|
+ Mustache mustache = (Mustache) engine.compile("{ \"field1\": \"{{value}}\"}", Collections.emptyMap());
|
|
|
+ CompiledScript compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "name", "mustache", mustache);
|
|
|
+ ExecutableScript executableScript = engine.executable(compiledScript, Collections.singletonMap("value", "a \"value\""));
|
|
|
+ BytesReference rawResult = (BytesReference) executableScript.run();
|
|
|
+ String result = rawResult.toUtf8();
|
|
|
+ assertThat(result, equalTo("{ \"field1\": \"a \\\"value\\\"\"}"));
|
|
|
+
|
|
|
+ // json string escaping disabled:
|
|
|
+ mustache = (Mustache) engine.compile("{ \"field1\": \"{{value}}\"}", Collections.singletonMap(CONTENT_TYPE_PARAM, PLAIN_TEXT_CONTENT_TYPE));
|
|
|
+ compiledScript = new CompiledScript(ScriptService.ScriptType.INLINE, "name", "mustache", mustache);
|
|
|
+ executableScript = engine.executable(compiledScript, Collections.singletonMap("value", "a \"value\""));
|
|
|
+ rawResult = (BytesReference) executableScript.run();
|
|
|
+ result = rawResult.toUtf8();
|
|
|
+ assertThat(result, equalTo("{ \"field1\": \"a \"value\"\"}"));
|
|
|
+ }
|
|
|
+
|
|
|
}
|