You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by ja...@apache.org on 2015/09/14 07:28:53 UTC

[06/15] drill git commit: DRILL-1666: Add test code for mongo storage plugin

DRILL-1666: Add test code for mongo storage plugin


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/197d972f
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/197d972f
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/197d972f

Branch: refs/heads/master
Commit: 197d972fa42aa4cd2897d347a9bac58052a30c99
Parents: e12cd47
Author: akumarb2010 <ak...@gmail.com>
Authored: Mon Jul 6 22:35:25 2015 +0530
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Sun Sep 13 18:36:25 2015 -0700

----------------------------------------------------------------------
 contrib/storage-mongo/pom.xml                   |  13 +
 .../drill/exec/store/mongo/MongoTestBase.java   |  88 +++++++
 .../exec/store/mongo/MongoTestConstants.java    |  70 ++++++
 .../drill/exec/store/mongo/MongoTestSuit.java   | 245 +++++++++++++++++++
 .../store/mongo/TestMongoFilterPushDown.java    |  55 +++++
 .../store/mongo/TestMongoProjectPushDown.java   |  48 ++++
 .../exec/store/mongo/TestMongoQueries.java      |  55 +++++
 .../exec/store/mongo/TestTableGenerator.java    |  65 +++++
 .../src/test/resources/donuts.json              | 127 ++++++++++
 .../storage-mongo/src/test/resources/emp.json   |  19 ++
 10 files changed, 785 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/pom.xml b/contrib/storage-mongo/pom.xml
index 9a6a0b3..6efaf25 100644
--- a/contrib/storage-mongo/pom.xml
+++ b/contrib/storage-mongo/pom.xml
@@ -28,6 +28,10 @@
 
   <name>contrib/mongo-storage-plugin</name>
 
+  <properties>
+     <mongo.TestSuite>**/MongoTestSuit.class</mongo.TestSuite>
+  </properties>
+  
   <dependencies>
     <dependency>
       <groupId>org.apache.drill.exec</groupId>
@@ -63,6 +67,12 @@
       <version>2.1.1</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>de.flapdoodle.embed</groupId>
+      <artifactId>de.flapdoodle.embed.mongo</artifactId>
+      <version>1.48.0</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -71,6 +81,9 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
+	  <includes>
+	    <include>${mongo.TestSuite}</include>
+	  </includes>
           <systemProperties>
             <property>
               <name>logback.log.dir</name>

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestBase.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestBase.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestBase.java
new file mode 100644
index 0000000..cf3ca61
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestBase.java
@@ -0,0 +1,88 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.apache.drill.PlanTestBase;
+import org.apache.drill.common.exceptions.ExecutionSetupException;
+import org.apache.drill.exec.exception.SchemaChangeException;
+import org.apache.drill.exec.rpc.user.QueryDataBatch;
+import org.apache.drill.exec.store.StoragePluginRegistry;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+public class MongoTestBase extends PlanTestBase implements MongoTestConstants {
+  protected static MongoStoragePlugin storagePlugin;
+  protected static MongoStoragePluginConfig storagePluginConfig;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    initMongoStoragePlugin();
+  }
+
+  public static void initMongoStoragePlugin() throws ExecutionSetupException {
+    final StoragePluginRegistry pluginRegistry = getDrillbitContext()
+        .getStorage();
+    storagePlugin = (MongoStoragePlugin) pluginRegistry
+        .getPlugin(MongoStoragePluginConfig.NAME);
+    storagePluginConfig = storagePlugin.getConfig();
+    storagePluginConfig.setEnabled(true);
+    pluginRegistry.createOrUpdate(MongoStoragePluginConfig.NAME,
+        storagePluginConfig, true);
+  }
+
+  public List<QueryDataBatch> runMongoSQLWithResults(String sql)
+      throws Exception {
+    return testSqlWithResults(sql);
+  }
+
+  public void runMongoSQLVerifyCount(String sql, int expectedRowCount)
+      throws Exception {
+    List<QueryDataBatch> results = runMongoSQLWithResults(sql);
+    printResultAndVerifyRowCount(results, expectedRowCount);
+  }
+
+  public void printResultAndVerifyRowCount(List<QueryDataBatch> results,
+      int expectedRowCount) throws SchemaChangeException {
+    int rowCount = printResult(results);
+    if (expectedRowCount != -1) {
+      Assert.assertEquals(expectedRowCount, rowCount);
+    }
+  }
+
+  public void testHelper(String query, String expectedExprInPlan,
+      int expectedRecordCount) throws Exception {
+    testPhysicalPlan(query, expectedExprInPlan);
+    int actualRecordCount = testSql(query);
+    assertEquals(
+        String.format(
+            "Received unexpected number of rows in output: expected=%d, received=%s",
+            expectedRecordCount, actualRecordCount), expectedRecordCount,
+        actualRecordCount);
+  }
+
+  @AfterClass
+  public static void tearDownMongoTestBase() throws Exception {
+    storagePlugin = null;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestConstants.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestConstants.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestConstants.java
new file mode 100644
index 0000000..d6d83d1
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestConstants.java
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+public interface MongoTestConstants {
+
+  public static final String LOCALHOST = "localhost";
+  public static final int CONFIG_SERVER_PORT = 27019;
+  public static final int MONGOD_1_PORT = 27020;
+  public static final int MONGOD_2_PORT = 27021;
+  public static final int MONGOD_3_PORT = 27022;
+
+  public static final int MONGOD_4_PORT = 27023;
+  public static final int MONGOD_5_PORT = 27024;
+  public static final int MONGOD_6_PORT = 27025;
+
+  public static final int MONGOS_PORT = 27017;
+
+  public static final String CONFIG_DB = "config";
+  public static final String ADMIN_DB = "admin";
+
+  public static final String TEST_DB = "testDB";
+  public static final String EMPLOYEE_DB = "employee";
+
+  public static final String DONUTS_COLLECTION = "donuts";
+  public static final String EMPINFO_COLLECTION = "empinfo";
+
+  public static final String DONUTS_DATA = "donuts.json";
+  public static final String EMP_DATA = "emp.json";
+
+  public static final String REPLICA_SET_1_NAME = "shard_1_replicas";
+  public static final String REPLICA_SET_2_NAME = "shard_2_replicas";
+
+  // test queries
+  public static final String TEST_QUERY_1 = "SELECT * FROM mongo.employee.`empinfo` limit 5";
+  public static final String TEST_QUERY_LIMIT = "SELECT first_name, last_name FROM mongo.employee.`empinfo` limit 2;";
+
+  // test query template1
+  public static final String TEST_QUERY_PROJECT_PUSH_DOWN_TEMPLATE_1 = "SELECT `employee_id` FROM mongo.%s.`%s`";
+  public static final String TEST_QUERY_PROJECT_PUSH_DOWN__TEMPLATE_2 = "select `employee_id`, `rating` from mongo.%s.`%s`";
+  public static final String TEST_QUERY_PROJECT_PUSH_DOWN__TEMPLATE_3 = "select * from mongo.%s.`%s`";
+  public static final String TEST_FILTER_PUSH_DOWN_IS_NULL_QUERY_TEMPLATE_1 = "SELECT `employee_id` FROM mongo.%s.`%s` where position_id is null";
+  public static final String TEST_FILTER_PUSH_DOWN_IS_NOT_NULL_QUERY_TEMPLATE_1 = "SELECT `employee_id` FROM mongo.%s.`%s` where position_id is not null";
+  public static final String TEST_FILTER_PUSH_DOWN_EQUAL_QUERY_TEMPLATE_1 = "SELECT `full_name` FROM mongo.%s.`%s` where rating = 52.17";
+  public static final String TEST_FILTER_PUSH_DOWN_NOT_EQUAL_QUERY_TEMPLATE_1 = "SELECT `employee_id` FROM mongo.%s.`%s` where rating != 52.17";
+  public static final String TEST_FILTER_PUSH_DOWN_LESS_THAN_QUERY_TEMPLATE_1 = "SELECT `full_name` FROM mongo.%s.`%s` where rating < 52.17";
+  public static final String TEST_FILTER_PUSH_DOWN_GREATER_THAN_QUERY_TEMPLATE_1 = "SELECT `full_name` FROM mongo.%s.`%s` where rating > 52.17";
+  public static final String TEST_EMPTY_TABLE_QUERY_TEMPLATE = "select count(*) from mongo.%s.`%s`";
+
+  public static final String TEST_BOOLEAN_FILTER_QUERY_TEMPLATE1 = "select `employee_id` from mongo.%s.`%s` where isFTE = true";
+  public static final String TEST_BOOLEAN_FILTER_QUERY_TEMPLATE2 = "select `employee_id` from mongo.%s.`%s` where isFTE = false";
+  public static final String TEST_BOOLEAN_FILTER_QUERY_TEMPLATE3 = "select `employee_id` from mongo.%s.`%s` where position_id = 16 and isFTE = true";
+  public static final String TEST_BOOLEAN_FILTER_QUERY_TEMPLATE4 = "select `employee_id` from mongo.%s.`%s` where (position_id = 16 and isFTE = true) or last_name = 'Yonce'";
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestSuit.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestSuit.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestSuit.java
new file mode 100644
index 0000000..c52df63
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/MongoTestSuit.java
@@ -0,0 +1,245 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.mongodb.MongoClient;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.IndexOptions;
+
+import de.flapdoodle.embed.mongo.Command;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.IMongoCmdOptions;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.IMongosConfig;
+import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.MongosConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Storage;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.mongo.tests.MongosSystemForTestFactory;
+import de.flapdoodle.embed.process.config.IRuntimeConfig;
+import de.flapdoodle.embed.process.runtime.Network;
+
+@RunWith(Suite.class)
+@SuiteClasses({ TestMongoFilterPushDown.class, TestMongoProjectPushDown.class,
+    TestMongoQueries.class, TestMongoChunkAssignment.class })
+public class MongoTestSuit implements MongoTestConstants {
+
+  private static final Logger logger = LoggerFactory
+      .getLogger(MongoTestSuit.class);
+
+  protected static MongoClient mongoClient;
+
+  private static boolean distMode = System.getProperty(
+      "drill.mongo.tests.shardMode", "true").equalsIgnoreCase("true");
+  private static boolean authEnabled = System.getProperty(
+      "drill.mongo.tests.authEnabled", "false").equalsIgnoreCase("true");
+
+  private static class DistributedMode {
+    private static MongosSystemForTestFactory mongosTestFactory;
+
+    private static void setup() throws Exception {
+      // creating configServers
+      List<IMongodConfig> configServers = new ArrayList<IMongodConfig>(1);
+      IMongodConfig configIMongodConfig = crateConfigServerConfig(
+          CONFIG_SERVER_PORT, true);
+      configServers.add(configIMongodConfig);
+
+      // creating replicaSets
+      Map<String, List<IMongodConfig>> replicaSets = new HashMap<String, List<IMongodConfig>>();
+      List<IMongodConfig> replicaSet1 = new ArrayList<IMongodConfig>();
+      replicaSet1.add(crateIMongodConfig(MONGOD_1_PORT, false,
+          REPLICA_SET_1_NAME));
+      replicaSet1.add(crateIMongodConfig(MONGOD_2_PORT, false,
+          REPLICA_SET_1_NAME));
+      replicaSet1.add(crateIMongodConfig(MONGOD_3_PORT, false,
+          REPLICA_SET_1_NAME));
+      replicaSets.put(REPLICA_SET_1_NAME, replicaSet1);
+      List<IMongodConfig> replicaSet2 = new ArrayList<IMongodConfig>();
+      replicaSet2.add(crateIMongodConfig(MONGOD_4_PORT, false,
+          REPLICA_SET_2_NAME));
+      replicaSet2.add(crateIMongodConfig(MONGOD_5_PORT, false,
+          REPLICA_SET_2_NAME));
+      replicaSet2.add(crateIMongodConfig(MONGOD_6_PORT, false,
+          REPLICA_SET_2_NAME));
+      replicaSets.put(REPLICA_SET_2_NAME, replicaSet2);
+
+      // create mongos
+      IMongosConfig mongosConfig = createIMongosConfig();
+      mongosTestFactory = new MongosSystemForTestFactory(mongosConfig,
+          replicaSets, configServers, EMPLOYEE_DB, EMPINFO_COLLECTION,
+          "employee_id");
+
+      try {
+        mongosTestFactory.start();
+        mongoClient = (MongoClient) mongosTestFactory.getMongo();
+      } catch (Throwable e) {
+        logger.error(" Error while starting shrded cluster. ", e);
+        throw new Exception(" Error while starting shrded cluster. ", e);
+      }
+    }
+
+    private static IMongodConfig crateConfigServerConfig(int configServerPort,
+        boolean flag) throws UnknownHostException, IOException {
+      IMongoCmdOptions cmdOptions = new MongoCmdOptionsBuilder().verbose(false)
+          .build();
+
+      IMongodConfig mongodConfig = new MongodConfigBuilder()
+          .version(Version.Main.PRODUCTION)
+          .net(new Net(LOCALHOST, configServerPort, Network.localhostIsIPv6()))
+          .configServer(flag).cmdOptions(cmdOptions).build();
+      return mongodConfig;
+    }
+
+    private static IMongodConfig crateIMongodConfig(int mongodPort,
+        boolean flag, String replicaName) throws UnknownHostException,
+        IOException {
+      IMongoCmdOptions cmdOptions = new MongoCmdOptionsBuilder().verbose(false)
+          .build();
+
+      Storage replication = new Storage(null, replicaName, 0);
+      IMongodConfig mongodConfig = new MongodConfigBuilder()
+          .version(Version.Main.PRODUCTION)
+          .net(new Net(LOCALHOST, mongodPort, Network.localhostIsIPv6()))
+          .configServer(flag).replication(replication).cmdOptions(cmdOptions)
+          .build();
+      return mongodConfig;
+    }
+
+    private static IMongosConfig createIMongosConfig()
+        throws UnknownHostException, IOException {
+      IMongoCmdOptions cmdOptions = new MongoCmdOptionsBuilder().verbose(false)
+          .build();
+
+      IMongosConfig mongosConfig = new MongosConfigBuilder()
+          .version(Version.Main.PRODUCTION)
+          .net(new Net(LOCALHOST, MONGOS_PORT, Network.localhostIsIPv6()))
+          .configDB(LOCALHOST + ":" + CONFIG_SERVER_PORT)
+          .cmdOptions(cmdOptions).build();
+      return mongosConfig;
+    }
+
+    private static void cleanup() {
+      if (mongosTestFactory != null) {
+        mongosTestFactory.stop();
+      }
+    }
+
+  }
+
+  private static class SingleMode {
+
+    private static MongodExecutable mongodExecutable;
+    private static MongodProcess mongod;
+
+    private static void setup() throws UnknownHostException, IOException {
+      IMongoCmdOptions cmdOptions = new MongoCmdOptionsBuilder().verbose(false)
+          .enableAuth(authEnabled).build();
+
+      IMongodConfig mongodConfig = new MongodConfigBuilder()
+          .version(Version.Main.PRODUCTION)
+          .net(new Net(LOCALHOST, MONGOS_PORT, Network.localhostIsIPv6()))
+          .cmdOptions(cmdOptions).build();
+
+      IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder().defaults(
+          Command.MongoD).build();
+      mongodExecutable = MongodStarter.getInstance(runtimeConfig).prepare(
+          mongodConfig);
+      mongod = mongodExecutable.start();
+      mongoClient = new MongoClient(new ServerAddress(LOCALHOST, MONGOS_PORT));
+      createDbAndCollections(EMPLOYEE_DB, EMPINFO_COLLECTION, "employee_id");
+    }
+
+    private static void cleanup() {
+      if (mongod != null) {
+        mongod.stop();
+      }
+      if (mongodExecutable != null) {
+        mongodExecutable.cleanup();
+      }
+    }
+  }
+
+  @BeforeClass
+  public static void initMongo() throws Exception {
+    synchronized (MongoTestSuit.class) {
+      if (distMode) {
+        logger.info("Executing tests in distributed mode");
+        DistributedMode.setup();
+      } else {
+        logger.info("Executing tests in single mode");
+        SingleMode.setup();
+      }
+      TestTableGenerator.importData(EMPLOYEE_DB, EMPINFO_COLLECTION, EMP_DATA);
+    }
+  }
+
+  private static void createDbAndCollections(String dbName,
+      String collectionName, String indexFieldName) {
+    MongoDatabase db = mongoClient.getDatabase(dbName);
+    MongoCollection<Document> mongoCollection = db
+        .getCollection(collectionName);
+    if (mongoCollection == null) {
+      db.createCollection(collectionName);
+      mongoCollection = db.getCollection(collectionName);
+    }
+    IndexOptions indexOptions = new IndexOptions().unique(true)
+        .background(false).name(indexFieldName);
+    Bson keys = new Document(indexFieldName, Integer.valueOf(1));
+    mongoCollection.createIndex(keys, indexOptions);
+  }
+
+  @AfterClass
+  public static void tearDownCluster() throws Exception {
+    if (mongoClient != null) {
+      mongoClient.dropDatabase(TEST_DB);
+      mongoClient.dropDatabase(EMPLOYEE_DB);
+      mongoClient.close();
+    }
+    synchronized (MongoTestSuit.class) {
+      if (distMode) {
+        DistributedMode.cleanup();
+      } else {
+        SingleMode.cleanup();
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoFilterPushDown.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoFilterPushDown.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoFilterPushDown.java
new file mode 100644
index 0000000..633d0a9
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoFilterPushDown.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import org.junit.Test;
+
+public class TestMongoFilterPushDown extends MongoTestBase {
+
+  @Test
+  public void testFilterPushDownIsEqual() throws Exception {
+    String queryString = String.format(
+        TEST_FILTER_PUSH_DOWN_EQUAL_QUERY_TEMPLATE_1, EMPLOYEE_DB,
+        EMPINFO_COLLECTION);
+    String expectedExpr = "\"$eq\" : 52.17";
+    testHelper(queryString, expectedExpr, 1);
+  }
+
+  @Test
+  public void testFilterPushDownLessThanWithSingleField() throws Exception {
+    String queryString = String.format(
+        TEST_FILTER_PUSH_DOWN_LESS_THAN_QUERY_TEMPLATE_1, EMPLOYEE_DB,
+        EMPINFO_COLLECTION);
+    System.out.println("testFilterPushDownLessThanWithSingleField Query: "
+        + queryString);
+    String expectedExpr = "\"$lt\" : 52.17";
+    testHelper(queryString, expectedExpr, 9);
+  }
+
+  @Test
+  public void testFilterPushDownGreaterThanWithSingleField() throws Exception {
+    String queryString = String.format(
+        TEST_FILTER_PUSH_DOWN_GREATER_THAN_QUERY_TEMPLATE_1, EMPLOYEE_DB,
+        EMPINFO_COLLECTION);
+    System.out.println("testFilterPushDownGreaterThanWithSingleField Query: "
+        + queryString);
+    String expectedExpr = "\"$gt\" : 52.17";
+    testHelper(queryString, expectedExpr, 9);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoProjectPushDown.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoProjectPushDown.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoProjectPushDown.java
new file mode 100644
index 0000000..54ace3f
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoProjectPushDown.java
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import org.junit.Test;
+
+public class TestMongoProjectPushDown extends MongoTestBase {
+
+  @Test
+  public void testSingleColumnProject() throws Exception {
+    String query = String.format(TEST_QUERY_PROJECT_PUSH_DOWN_TEMPLATE_1,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    String expectedColNames = " \"columns\" : [ \"`employee_id`\" ]";
+    testHelper(query, expectedColNames, 19);
+  }
+
+  @Test
+  public void testMultipleColumnsProject() throws Exception {
+    String query = String.format(TEST_QUERY_PROJECT_PUSH_DOWN__TEMPLATE_2,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    String expectedColNames = "\"columns\" : [ \"`employee_id`\", \"`rating`\" ]";
+    testHelper(query, expectedColNames, 19);
+  }
+
+  @Test
+  public void testStarProject() throws Exception {
+    String query = String.format(TEST_QUERY_PROJECT_PUSH_DOWN__TEMPLATE_3,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    String expectedColNames = "*";
+    testHelper(query, expectedColNames, 19);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoQueries.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoQueries.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoQueries.java
new file mode 100644
index 0000000..f7e502a
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestMongoQueries.java
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import org.junit.Test;
+
+public class TestMongoQueries extends MongoTestBase {
+
+  @Test
+  public void testBooleanFilter() throws Exception {
+    String queryString = String.format(TEST_BOOLEAN_FILTER_QUERY_TEMPLATE1,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    runMongoSQLVerifyCount(queryString, 11);
+    queryString = String.format(TEST_BOOLEAN_FILTER_QUERY_TEMPLATE2,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    runMongoSQLVerifyCount(queryString, 8);
+  }
+
+  @Test
+  public void testWithANDOperator() throws Exception {
+    String queryString = String.format(TEST_BOOLEAN_FILTER_QUERY_TEMPLATE3,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    runMongoSQLVerifyCount(queryString, 4);
+  }
+
+  @Test
+  public void testWithOROperator() throws Exception {
+    String queryString = String.format(TEST_BOOLEAN_FILTER_QUERY_TEMPLATE3,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    runMongoSQLVerifyCount(queryString, 4);
+  }
+
+  @Test
+  public void testResultCount() throws Exception {
+    String queryString = String.format(TEST_BOOLEAN_FILTER_QUERY_TEMPLATE4,
+        EMPLOYEE_DB, EMPINFO_COLLECTION);
+    runMongoSQLVerifyCount(queryString, 5);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestTableGenerator.java
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestTableGenerator.java b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestTableGenerator.java
new file mode 100644
index 0000000..62e1204
--- /dev/null
+++ b/contrib/storage-mongo/src/test/java/org/apache/drill/exec/store/mongo/TestTableGenerator.java
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.store.mongo;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Resources;
+
+import de.flapdoodle.embed.mongo.MongoImportExecutable;
+import de.flapdoodle.embed.mongo.MongoImportStarter;
+import de.flapdoodle.embed.mongo.config.IMongoImportConfig;
+import de.flapdoodle.embed.mongo.config.MongoImportConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+
+public class TestTableGenerator implements MongoTestConstants {
+
+  private static final Logger logger = LoggerFactory
+      .getLogger(TestTableGenerator.class);
+
+  public static void importData(String dbName, String collectionName,
+      String fileName) throws IOException {
+    String jsonFile = Resources.getResource(fileName).toString();
+    jsonFile = jsonFile.replaceFirst("file:", StringUtils.EMPTY);
+    generateTable(dbName, collectionName, jsonFile, true, true, false);
+  }
+
+  public static void generateTable(String dbName, String collection,
+      String jsonFile, Boolean jsonArray, Boolean upsert, Boolean drop)
+      throws UnknownHostException, IOException {
+    logger.info("Started importing file {} into collection {} ", jsonFile,
+        collection);
+    IMongoImportConfig mongoImportConfig = new MongoImportConfigBuilder()
+        .version(Version.Main.PRODUCTION)
+        .net(new Net(MONGOS_PORT, Network.localhostIsIPv6())).db(dbName)
+        .collection(collection).upsert(upsert).dropCollection(drop)
+        .jsonArray(jsonArray).importFile(jsonFile).build();
+    MongoImportExecutable importExecutable = MongoImportStarter
+        .getDefaultInstance().prepare(mongoImportConfig);
+    importExecutable.start();
+    logger.info("Imported file {} into collection {} ", jsonFile, collection);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/resources/donuts.json
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/resources/donuts.json b/contrib/storage-mongo/src/test/resources/donuts.json
new file mode 100644
index 0000000..45beeb8
--- /dev/null
+++ b/contrib/storage-mongo/src/test/resources/donuts.json
@@ -0,0 +1,127 @@
+[
+{
+    "id": "0001",
+    "type": "donut",
+    "name": "Cake",
+    "ppu": 0.55,
+    "sales": 35,
+
+    "batters":
+      {
+        "batter":
+          [
+            { "id": "1001", "type": "Regular" },
+            { "id": "1002", "type": "Chocolate" },
+            { "id": "1003", "type": "Blueberry" },
+            { "id": "1004", "type": "Devil's Food" }
+          ]
+      },
+    "topping":
+      [
+        { "id": "5001", "type": "None" },
+        { "id": "5002", "type": "Glazed" },
+        { "id": "5005", "type": "Sugar" },
+        { "id": "5007", "type": "Powdered Sugar" },
+        { "id": "5006", "type": "Chocolate with Sprinkles" },
+        { "id": "5003", "type": "Chocolate" },
+        { "id": "5004", "type": "Maple" }
+      ]
+},
+{
+    "id": "0002",
+    "type": "donut",
+    "name": "Raised",
+    "ppu": 0.69,
+    "sales": 145,
+    "batters":
+      {
+        "batter":
+          [
+            { "id": "1001", "type": "Regular" }
+          ]
+      },
+    "topping":
+      [
+        { "id": "5001", "type": "None" },
+        { "id": "5002", "type": "Glazed" },
+        { "id": "5005", "type": "Sugar" },
+        { "id": "5003", "type": "Chocolate" },
+        { "id": "5004", "type": "Maple" }
+      ]
+},
+{
+    "id": "0003",
+    "type": "donut",
+    "name": "Old Fashioned",
+    "ppu": 0.55,
+    "sales": 300,
+    "batters":
+      {
+        "batter":
+          [
+            { "id": "1001", "type": "Regular" },
+            { "id": "1002", "type": "Chocolate" }
+          ]
+      },
+    "topping":
+      [
+        { "id": "5001", "type": "None" },
+        { "id": "5002", "type": "Glazed" },
+        { "id": "5003", "type": "Chocolate" },
+        { "id": "5004", "type": "Maple" }
+      ]
+},
+{
+    "id": "0004",
+    "type": "donut",
+    "name": "Filled",
+    "ppu": 0.69,
+    "sales": 14,
+
+    "batters":
+      {
+        "batter":
+          [
+            { "id": "1001", "type": "Regular" },
+            { "id": "1002", "type": "Chocolate" },
+            { "id": "1003", "type": "Blueberry" },
+            { "id": "1004", "type": "Devil's Food" }
+          ]
+      },
+    "topping":
+      [
+        { "id": "5001", "type": "None" },
+        { "id": "5002", "type": "Glazed" },
+        { "id": "5005", "type": "Sugar" },
+        { "id": "5007", "type": "Powdered Sugar" },
+        { "id": "5006", "type": "Chocolate with Sprinkles" },
+        { "id": "5003", "type": "Chocolate" },
+        { "id": "5004", "type": "Maple" }
+      ],
+    "filling":
+      [
+        { "id": "6001", "type": "None" },
+        { "id": "6002", "type": "Raspberry" },
+        { "id": "6003", "type": "Lemon" },
+        { "id": "6004", "type": "Chocolate" },
+        { "id": "6005", "type": "Kreme" }
+      ]
+},
+{
+    "id": "0005",
+    "type": "donut",
+    "name": "Apple Fritter",
+    "sales": 700,
+    "batters":
+      {
+        "batter":
+          [
+            { "id": "1001", "type": "Regular" }
+          ]
+      },
+    "topping":
+      [
+        { "id": "5002", "type": "Glazed" }
+      ]
+}
+]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/197d972f/contrib/storage-mongo/src/test/resources/emp.json
----------------------------------------------------------------------
diff --git a/contrib/storage-mongo/src/test/resources/emp.json b/contrib/storage-mongo/src/test/resources/emp.json
new file mode 100644
index 0000000..5b786d5
--- /dev/null
+++ b/contrib/storage-mongo/src/test/resources/emp.json
@@ -0,0 +1,19 @@
+[{"employee_id":1101,"full_name":"Steve Eurich","first_name":"Steve","last_name":"Eurich","position_id":16,"rating":23.0,"position":"Store T","isFTE":true},
+{"employee_id":1102,"full_name":"Mary Pierson","first_name":"Mary","last_name":"Pierson","position_id":16,"rating":45.6,"position":"Store T","isFTE":true},
+{"employee_id":1103,"full_name":"Leo Jones","first_name":"Leo","last_name":"Jones","position_id":16,"position":"Store Tem","rating":85.94,"isFTE":true},
+{"employee_id":1104,"full_name":"Nancy Beatty","first_name":"Nancy","last_name":"Beatty","position_id":16,"position":"Store T","rating":97.16,"isFTE":false},
+{"employee_id":1105,"full_name":"Clara McNight","first_name":"Clara","last_name":"McNight","position_id":16,"position":"Store","rating":81.25,"isFTE":true},
+{"employee_id":1106,"first_name":"Marcella","last_name":"Isaacs","position_id":17,"position":"Stor","rating":67.86,"isFTE":false},
+{"employee_id":1107,"full_name":"Charlotte Yonce","first_name":"Charlotte","last_name":"Yonce","position_id":17,"position":"Stor","rating":52.17,"isFTE":true},
+{"employee_id":1108,"full_name":"Benjamin Foster","first_name":"Benjamin","last_name":"Foster","position_id":17,"position":"Stor","rating":89.8,"isFTE":false},
+{"employee_id":1109,"full_name":"John Reed","first_name":"John","last_name":"Reed","position_id":17,"position":"Store Per","rating":12.9,"isFTE":false},
+{"employee_id":1110,"full_name":"Lynn Kwiatkowski","first_name":"Lynn","last_name":"Kwiatkowski","position_id":17,"position":"St","rating":25.76,"isFTE":true},
+{"employee_id":1111,"full_name":"Donald Vann","first_name":"Donald","last_name":"Vann","position_id":17,"position":"Store Per","rating":34.86,"isFTE":false},
+{"employee_id":1112,"first_name":"William","last_name":"Smith","position":"St","rating":79.06,"isFTE":true},
+{"employee_id":1113,"full_name":"Amy Hensley","first_name":"Amy","last_name":"Hensley","position_id":17,"position":"Store Pe","rating":82.96,"isFTE":false},
+{"employee_id":1114,"full_name":"Judy Owens","first_name":"Judy","last_name":"Owens","position_id":17,"position":"Store Per","rating":24.6,"isFTE":true},
+{"employee_id":1115,"full_name":"Frederick Castillo","first_name":"Frederick","last_name":"Castillo","position_id":17,"position":"S","rating":82.36,"isFTE":false},
+{"employee_id":1116,"full_name":"Phil Munoz","first_name":"Phil","last_name":"Munoz","position_id":17,"position":"Store Per","rating":97.63,"isFTE":false},
+{"employee_id":1117,"full_name":"Lori Lightfoot","first_name":"Lori","last_name":"Lightfoot","position_id":17,"position":"Store","rating":39.16,"isFTE":true},
+{"employee_id":1,"full_name":"Kumar","first_name":"Anil","last_name":"B","position_id":19,"position":"Store","rating":45.45,"isFTE":true},
+{"employee_id":2,"full_name":"Kamesh","first_name":"Bh","last_name":"Venkata","position":"Store","rating":32.89,"isFTE":true}]