You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rj...@apache.org on 2014/07/10 01:18:58 UTC
svn commit: r1609337 [2/2] - in /lucene/dev/trunk/lucene: ./
expressions/src/java/org/apache/lucene/expressions/
expressions/src/java/org/apache/lucene/expressions/js/
expressions/src/test/org/apache/lucene/expressions/
expressions/src/test/org/apache/...
Modified: lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/TestDemoExpressions.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/TestDemoExpressions.java?rev=1609337&r1=1609336&r2=1609337&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/TestDemoExpressions.java (original)
+++ lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/TestDemoExpressions.java Wed Jul 9 23:18:58 2014
@@ -4,9 +4,13 @@ import org.apache.lucene.document.Docume
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.expressions.js.JavascriptCompiler;
+import org.apache.lucene.expressions.js.VariableContext;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.DoubleConstValueSource;
+import org.apache.lucene.queries.function.valuesource.IntFieldSource;
import org.apache.lucene.search.CheckHits;
import org.apache.lucene.search.FieldDoc;
import org.apache.lucene.search.IndexSearcher;
@@ -19,6 +23,10 @@ import org.apache.lucene.search.TopField
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
+import static org.apache.lucene.expressions.js.VariableContext.Type.MEMBER;
+import static org.apache.lucene.expressions.js.VariableContext.Type.STR_INDEX;
+import static org.apache.lucene.expressions.js.VariableContext.Type.INT_INDEX;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -224,4 +232,71 @@ public class TestDemoExpressions extend
d = (FieldDoc) td.scoreDocs[2];
assertEquals(5.2842D, (Double)d.fields[0], 1E-4);
}
+
+ public void testStaticExtendedVariableExample() throws Exception {
+ Expression popularity = JavascriptCompiler.compile("doc[\"popularity\"].value");
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("doc['popularity'].value", new IntFieldSource("popularity"));
+ Sort sort = new Sort(popularity.getSortField(bindings, true));
+ TopFieldDocs td = searcher.search(new MatchAllDocsQuery(), null, 3, sort);
+
+ FieldDoc d = (FieldDoc)td.scoreDocs[0];
+ assertEquals(20D, (Double)d.fields[0], 1E-4);
+
+ d = (FieldDoc)td.scoreDocs[1];
+ assertEquals(5D, (Double)d.fields[0], 1E-4);
+
+ d = (FieldDoc)td.scoreDocs[2];
+ assertEquals(2D, (Double)d.fields[0], 1E-4);
+ }
+
+ public void testDynamicExtendedVariableExample() throws Exception {
+ Expression popularity = JavascriptCompiler.compile("doc['popularity'].value + magicarray[0] + fourtytwo");
+
+ // The following is an example of how to write bindings which parse the variable name into pieces.
+ // Note, however, that this requires a lot of error checking. Each "error case" below should be
+ // filled in with proper error messages for a real use case.
+ Bindings bindings = new Bindings() {
+ @Override
+ public ValueSource getValueSource(String name) {
+ VariableContext[] var = VariableContext.parse(name);
+ assert var[0].type == MEMBER;
+ String base = var[0].text;
+ if (base.equals("doc")) {
+ if (var.length > 1 && var[1].type == STR_INDEX) {
+ String field = var[1].text;
+ if (var.length > 2 && var[2].type == MEMBER && var[2].text.equals("value")) {
+ return new IntFieldSource(field);
+ } else {
+ fail("member: " + var[2].text);// error case, non/missing "value" member access
+ }
+ } else {
+ fail();// error case, doc should be a str indexed array
+ }
+ } else if (base.equals("magicarray")) {
+ if (var.length > 1 && var[1].type == INT_INDEX) {
+ return new DoubleConstValueSource(2048);
+ } else {
+ fail();// error case, magic array isn't an array
+ }
+ } else if (base.equals("fourtytwo")) {
+ return new DoubleConstValueSource(42);
+ } else {
+ fail();// error case (variable doesn't exist)
+ }
+ throw new IllegalArgumentException("Illegal reference '" + name + "'");
+ }
+ };
+ Sort sort = new Sort(popularity.getSortField(bindings, false));
+ TopFieldDocs td = searcher.search(new MatchAllDocsQuery(), null, 3, sort);
+
+ FieldDoc d = (FieldDoc)td.scoreDocs[0];
+ assertEquals(2092D, (Double)d.fields[0], 1E-4);
+
+ d = (FieldDoc)td.scoreDocs[1];
+ assertEquals(2095D, (Double)d.fields[0], 1E-4);
+
+ d = (FieldDoc)td.scoreDocs[2];
+ assertEquals(2110D, (Double)d.fields[0], 1E-4);
+ }
}
Modified: lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java?rev=1609337&r1=1609336&r2=1609337&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java (original)
+++ lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestJavascriptCompiler.java Wed Jul 9 23:18:58 2014
@@ -18,6 +18,7 @@ package org.apache.lucene.expressions.js
import java.text.ParseException;
+import org.apache.lucene.expressions.Expression;
import org.apache.lucene.util.LuceneTestCase;
public class TestJavascriptCompiler extends LuceneTestCase {
@@ -29,39 +30,60 @@ public class TestJavascriptCompiler exte
assertNotNull(JavascriptCompiler.compile("logn(2, 20+10-5.0)"));
}
- public void testValidNamespaces() throws Exception {
- assertNotNull(JavascriptCompiler.compile("object.valid0"));
- assertNotNull(JavascriptCompiler.compile("object0.object1.valid1"));
+ public void testValidVariables() throws Exception {
+ doTestValidVariable("object.valid0");
+ doTestValidVariable("object0.object1.valid1");
+ doTestValidVariable("array0[1]");
+ doTestValidVariable("array0[1].x");
+ doTestValidVariable("multiarray[0][0]");
+ doTestValidVariable("multiarray[0][0].x");
+ doTestValidVariable("strindex['hello']");
+ doTestValidVariable("strindex[\"hello\"]", "strindex['hello']");
+ doTestValidVariable("empty['']");
+ doTestValidVariable("empty[\"\"]", "empty['']");
+ doTestValidVariable("strindex['\u304A\u65E9\u3046\u3054\u3056\u3044\u307E\u3059']");
+ doTestValidVariable("strindex[\"\u304A\u65E9\u3046\u3054\u3056\u3044\u307E\u3059\"]",
+ "strindex['\u304A\u65E9\u3046\u3054\u3056\u3044\u307E\u3059']");
+ doTestValidVariable("escapes['\\\\\\'']");
+ doTestValidVariable("escapes[\"\\\\\\\"\"]", "escapes['\\\\\"']");
+ doTestValidVariable("mixed[23]['key'].sub.sub");
+ doTestValidVariable("mixed[23]['key'].sub.sub[1]");
+ doTestValidVariable("mixed[23]['key'].sub.sub[1].sub");
+ doTestValidVariable("mixed[23]['key'].sub.sub[1].sub['abc']");
+ }
+
+ void doTestValidVariable(String variable) throws Exception {
+ doTestValidVariable(variable, variable);
+ }
+
+ void doTestValidVariable(String variable, String output) throws Exception {
+ Expression e = JavascriptCompiler.compile(variable);
+ assertNotNull(e);
+ assertEquals(1, e.variables.length);
+ assertEquals(output, e.variables[0]);
+ }
+
+ public void testInvalidVariables() throws Exception {
+ doTestInvalidVariable("object.0invalid");
+ doTestInvalidVariable("0.invalid");
+ doTestInvalidVariable("object..invalid");
+ doTestInvalidVariable(".invalid");
+ doTestInvalidVariable("negative[-1]");
+ doTestInvalidVariable("float[1.0]");
+ doTestInvalidVariable("missing_end['abc]");
+ doTestInvalidVariable("missing_end[\"abc]");
+ doTestInvalidVariable("missing_begin[abc']");
+ doTestInvalidVariable("missing_begin[abc\"]");
+ doTestInvalidVariable("dot_needed[1]sub");
+ doTestInvalidVariable("dot_needed[1]sub");
+ doTestInvalidVariable("opposite_escape['\\\"']");
+ doTestInvalidVariable("opposite_escape[\"\\'\"]");
}
- public void testInvalidNamespaces() throws Exception {
+ void doTestInvalidVariable(String variable) {
try {
- JavascriptCompiler.compile("object.0invalid");
- fail();
- }
- catch (ParseException expected) {
- //expected
- }
-
- try {
- JavascriptCompiler.compile("0.invalid");
- fail();
- }
- catch (ParseException expected) {
- //expected
- }
-
- try {
- JavascriptCompiler.compile("object..invalid");
- fail();
- }
- catch (ParseException expected) {
- //expected
- }
-
- try {
- JavascriptCompiler.compile(".invalid");
- fail();
+ JavascriptCompiler.compile(variable);
+ fail("\"" + variable + " should have failed to compile");
}
catch (ParseException expected) {
//expected
@@ -152,4 +174,30 @@ public class TestJavascriptCompiler exte
assertTrue(expected.getMessage().contains("arguments for method call"));
}
}
+
+ public void testVariableNormalization() throws Exception {
+ // multiple double quotes
+ Expression x = JavascriptCompiler.compile("foo[\"a\"][\"b\"]");
+ assertEquals("foo['a']['b']", x.variables[0]);
+
+ // single and double in the same var
+ x = JavascriptCompiler.compile("foo['a'][\"b\"]");
+ assertEquals("foo['a']['b']", x.variables[0]);
+
+ // escapes remain the same in single quoted strings
+ x = JavascriptCompiler.compile("foo['\\\\\\'\"']");
+ assertEquals("foo['\\\\\\'\"']", x.variables[0]);
+
+ // single quotes are escaped
+ x = JavascriptCompiler.compile("foo[\"'\"]");
+ assertEquals("foo['\\'']", x.variables[0]);
+
+ // double quotes are unescaped
+ x = JavascriptCompiler.compile("foo[\"\\\"\"]");
+ assertEquals("foo['\"']", x.variables[0]);
+
+ // backslash escapes are kept the same
+ x = JavascriptCompiler.compile("foo['\\\\'][\"\\\\\"]");
+ assertEquals("foo['\\\\']['\\\\']", x.variables[0]);
+ }
}
Added: lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestVariableContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestVariableContext.java?rev=1609337&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestVariableContext.java (added)
+++ lucene/dev/trunk/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestVariableContext.java Wed Jul 9 23:18:58 2014
@@ -0,0 +1,69 @@
+package org.apache.lucene.expressions.js;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.LuceneTestCase;
+
+import static org.apache.lucene.expressions.js.VariableContext.Type.MEMBER;
+import static org.apache.lucene.expressions.js.VariableContext.Type.STR_INDEX;
+import static org.apache.lucene.expressions.js.VariableContext.Type.INT_INDEX;
+
+public class TestVariableContext extends LuceneTestCase {
+
+ public void testSimpleVar() {
+ VariableContext[] x = VariableContext.parse("foo");
+ assertEquals(1, x.length);
+ assertEquals(x[0].type, MEMBER);
+ assertEquals(x[0].text, "foo");
+ }
+
+ public void testEmptyString() {
+ VariableContext[] x = VariableContext.parse("foo['']");
+ assertEquals(2, x.length);
+ assertEquals(x[1].type, STR_INDEX);
+ assertEquals(x[1].text, "");
+ }
+
+ public void testUnescapeString() {
+ VariableContext[] x = VariableContext.parse("foo['\\'\\\\']");
+ assertEquals(2, x.length);
+ assertEquals(x[1].type, STR_INDEX);
+ assertEquals(x[1].text, "'\\");
+ }
+
+ public void testMember() {
+ VariableContext[] x = VariableContext.parse("foo.bar");
+ assertEquals(2, x.length);
+ assertEquals(x[1].type, MEMBER);
+ assertEquals(x[1].text, "bar");
+ }
+
+ public void testMemberFollowedByMember() {
+ VariableContext[] x = VariableContext.parse("foo.bar.baz");
+ assertEquals(3, x.length);
+ assertEquals(x[2].type, MEMBER);
+ assertEquals(x[2].text, "baz");
+ }
+
+ public void testMemberFollowedByIntArray() {
+ VariableContext[] x = VariableContext.parse("foo.bar[1]");
+ assertEquals(3, x.length);
+ assertEquals(x[2].type, INT_INDEX);
+ assertEquals(x[2].integer, 1);
+ }
+}