/*
Copyright 2013 Red Hat, Inc. and/or its affiliates.
This file is part of lightblue.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.redhat.lightblue.eval;
import org.junit.Test;
import org.junit.Assert;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.redhat.lightblue.eval.QueryEvaluationContext;
import com.redhat.lightblue.eval.QueryEvaluator;
import com.redhat.lightblue.util.JsonDoc;
import com.redhat.lightblue.util.Path;
import com.redhat.lightblue.util.JsonUtils;
import com.redhat.lightblue.util.test.AbstractJsonNodeTest;
import com.redhat.lightblue.metadata.EntityMetadata;
import com.redhat.lightblue.metadata.TypeResolver;
import com.redhat.lightblue.metadata.types.DefaultTypes;
import com.redhat.lightblue.metadata.parser.Extensions;
import com.redhat.lightblue.metadata.parser.JSONMetadataParser;
import com.redhat.lightblue.query.QueryExpression;
import com.redhat.lightblue.TestDataStoreParser;
import java.io.IOException;
public class QueryTest extends AbstractJsonNodeTest {
private static final JsonNodeFactory factory = JsonNodeFactory.withExactBigDecimals(true);
private static class QTestCase {
final QueryExpression query;
final boolean match;
public QTestCase(QueryExpression query, boolean match) {
this.query = query;
this.match = match;
}
public QTestCase(JsonNode query, boolean match) {
this(QueryExpression.fromJson(query), match);
}
public QTestCase(String query, boolean match) {
this(json(query), match);
}
}
private static Path[] path(String... s) {
Path[] ret;
if (s != null) {
ret = new Path[s.length];
for (int i = 0; i < s.length; i++) {
ret[i] = new Path(s[i]);
}
} else {
ret = null;
}
return ret;
}
private static JsonNode json(String q) {
try {
return JsonUtils.json(q.replace('\'', '\"'));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private EntityMetadata getMd(String fname) throws Exception {
JsonNode node = loadJsonNode(fname);
Extensions<JsonNode> extensions = new Extensions<>();
extensions.addDefaultExtensions();
extensions.registerDataStoreParser("mongo", new TestDataStoreParser<JsonNode>());
TypeResolver resolver = new DefaultTypes();
JSONMetadataParser parser = new JSONMetadataParser(extensions, resolver, factory);
return parser.parseEntityMetadata(node);
}
private JsonDoc getDoc(String fname) throws Exception {
JsonNode node = loadJsonNode(fname);
return new JsonDoc(node);
}
private QueryExpression query(String s) throws Exception {
return QueryExpression.fromJson(JsonUtils.json(s.replace('\'', '\"')));
}
private QueryEvaluationContext runQuery(EntityMetadata md,
JsonDoc doc,
QueryExpression query) throws Exception {
QueryEvaluator eval = QueryEvaluator.getInstance(query, md);
return eval.evaluate(doc);
}
private static final QTestCase[] fieldTests = new QTestCase[]{
new QTestCase("{'field':'field1','op':'$eq','rvalue':'value1'}", true),
new QTestCase("{'field':'field1','op':'$eq','rvalue':'value2'}", false),
new QTestCase("{'field':'field1','op':'$neq','rvalue':'value2'}", true),
new QTestCase("{'field':'field5','op':'$eq','rvalue':true}", true),
new QTestCase("{'field':'field5','op':'$eq','rvalue':'true'}", true),
new QTestCase("{'field':'field5','op':'$eq','rvalue':1}", true),
new QTestCase("{'$and': [ {'field':'field3','op':'$gt','rvalue':2},{'field':'field7.0.elemf1','op':'$eq','rvalue':'elvalue0_1'}]}",
true),
new QTestCase("{'field':'field7.0.elemf3','op':'<','rfield':'field7.1.elemf3'}", true),
new QTestCase("{'field':'field6.nf3','op':'$in','values':[1,2,3,4]}", true),
new QTestCase("{'field':'field6.nf3','op':'$nin','values':[1,2,3,4]}", false),
new QTestCase("{'field':'field6.nf1','op':'$in','values':['blah','yada','nvalue1']}", true),
new QTestCase("{'field':'field6.nf1','regex':'nvalue.*'}", true),
new QTestCase("{'field':'field6.nf1','regex':'Nvalue.*'}", false),
new QTestCase("{'field':'field6.nf1','regex':'Nvalue.*','caseInsensitive':true}", true)
};
@Test
public void simpleFieldTests() throws Exception {
EntityMetadata md = getMd("./testMetadata.json");
JsonDoc doc = getDoc("./sample1.json");
for (QTestCase t : fieldTests) {
System.out.println(t.query);
Assert.assertEquals(t.query.toString(), t.match, runQuery(md, doc, t.query).getResult());
}
}
private static final QTestCase[] arrayTests = new QTestCase[]{
new QTestCase("{'array':'field6.nf6','contains':'$any','values':['zero','one']}", true),
new QTestCase("{'array':'field6.nf6','contains':'$any','values':['zero','blah']}", false),
new QTestCase("{'array':'field6.nf6','contains':'$all','values':['zero','one']}", false),
new QTestCase("{'array':'field6.nf6','contains':'$all','values':['three','one']}", true),
new QTestCase("{'array':'field6.nf6','contains':'$none','values':['zero','one']}", false),
new QTestCase("{'array':'field6.nf6','contains':'$none','values':['zero','blah']}", true),
new QTestCase("{'array':'field7','elemMatch': { 'field':'elemf1','op':'$eq','rvalue':'elvalue1_1' }}", true)};
@Test
public void arrayFieldTests() throws Exception {
EntityMetadata md = getMd("./testMetadata.json");
JsonDoc doc = getDoc("./sample1.json");
for (QTestCase t : arrayTests) {
System.out.println(t.query);
QueryEvaluationContext ctx = runQuery(md, doc, t.query);
Assert.assertEquals(t.query.toString(), t.match, ctx.getResult());
}
}
}