Repository: phoenix
Updated Branches:
  refs/heads/4.x-HBase-1.2 81c3f346a -> b53087734


PHOENIX-4832: Add Canary Test Tool for Phoenix Query Server.


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

Branch: refs/heads/4.x-HBase-1.2
Commit: b53087734f4ae3af13d87f3c5a5851667701c3ba
Parents: 81c3f34
Author: s.kadam <s.ka...@gus.com>
Authored: Wed Dec 5 16:11:07 2018 -0800
Committer: Vincent Poon <vincentp...@apache.org>
Committed: Fri Dec 7 16:22:49 2018 -0800

----------------------------------------------------------------------
 phoenix-core/pom.xml                            |   7 +
 .../apache/phoenix/tool/CanaryTestResult.java   |  86 ++++
 .../apache/phoenix/tool/PhoenixCanaryTool.java  | 477 +++++++++++++++++++
 .../phoenix-canary-file-sink.properties         |  17 +
 .../phoenix/tool/PhoenixCanaryToolTest.java     | 140 ++++++
 5 files changed, 727 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/b5308773/phoenix-core/pom.xml
----------------------------------------------------------------------
diff --git a/phoenix-core/pom.xml b/phoenix-core/pom.xml
index be557fb..dcdf86e 100644
--- a/phoenix-core/pom.xml
+++ b/phoenix-core/pom.xml
@@ -26,6 +26,7 @@
 
   <properties>
     <top.dir>${project.basedir}/..</top.dir>
+    <argparse4j.version>0.8.1</argparse4j.version>
   </properties>
 
   <build>
@@ -228,6 +229,12 @@
       <artifactId>sqlline</artifactId>
     </dependency>
     <dependency>
+      <groupId>net.sourceforge.argparse4j</groupId>
+      <artifactId>argparse4j</artifactId>
+      <version>${argparse4j.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b5308773/phoenix-core/src/main/java/org/apache/phoenix/tool/CanaryTestResult.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/tool/CanaryTestResult.java 
b/phoenix-core/src/main/java/org/apache/phoenix/tool/CanaryTestResult.java
new file mode 100644
index 0000000..b72439c
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/tool/CanaryTestResult.java
@@ -0,0 +1,86 @@
+/*
+ * 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.phoenix.tool;
+
+public class CanaryTestResult {
+
+    private boolean isSuccessful;
+    private long startTime;
+    private long executionTime;
+    private String message;
+    private String testName;
+    private String timestamp;
+    private Object miscellaneous;
+
+    public Object getMiscellaneous() {
+        return miscellaneous;
+    }
+
+    public void setMiscellaneous(Object miscellaneous) {
+        this.miscellaneous = miscellaneous;
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(String timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public boolean isSuccessful() {
+        return isSuccessful;
+    }
+
+    public void setSuccessful(boolean successful) {
+        isSuccessful = successful;
+    }
+
+    public long getExecutionTime() {
+        return executionTime;
+    }
+
+    public void setExecutionTime(long executionTime) {
+        this.executionTime = executionTime;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getTestName() {
+        return testName;
+    }
+
+    public void setTestName(String testName) {
+        this.testName = testName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b5308773/phoenix-core/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java 
b/phoenix-core/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
new file mode 100644
index 0000000..405f54f
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
@@ -0,0 +1,477 @@
+/*
+ * 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.phoenix.tool;
+
+import com.google.common.base.Throwables;
+import com.google.common.io.Files;
+import com.google.common.util.concurrent.SimpleTimeLimiter;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.ArgumentParserException;
+import net.sourceforge.argparse4j.inf.Namespace;
+import org.apache.hadoop.conf.Configured;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.util.Tool;
+import org.apache.hadoop.util.ToolRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A Canary Tool to perform synthetic tests for Query Server
+ */
+public class PhoenixCanaryTool extends Configured implements Tool {
+
+    private static String TEST_SCHEMA_NAME = "TEST";
+    private static String TEST_TABLE_NAME = "PQSTEST";
+    private static String FQ_TABLE_NAME = "TEST.PQSTEST";
+    private boolean USE_NAMESPACE = true;
+
+    private Sink sink = new StdOutSink();
+
+    /**
+     * Base class for a Canary Test
+     */
+    private abstract static class CanaryTest {
+
+        CanaryTestResult result = new CanaryTestResult();
+
+        Connection connection = null;
+
+        private void onCreate(Connection connection) {
+            result.setTimestamp(getCurrentTimestamp());
+            result.setStartTime(System.currentTimeMillis());
+            this.connection = connection;
+        }
+
+        abstract void onExecute() throws Exception;
+
+        private void onExit() {
+            result.setExecutionTime(System.currentTimeMillis() - 
result.getStartTime());
+        }
+
+        CanaryTestResult runTest(Connection connection) {
+            try {
+                onCreate(connection);
+                onExecute();
+                result.setSuccessful(true);
+                result.setMessage("Test " + result.getTestName() + " 
successful");
+            } catch (Exception e) {
+                result.setSuccessful(false);
+                result.setMessage(Throwables.getStackTraceAsString(e));
+            } finally {
+                onExit();
+            }
+            return result;
+        }
+    }
+
+    /**
+     * Test which prepares environment before other tests run
+     */
+    static class PrepareTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("prepare");
+            Statement statement = connection.createStatement();
+            DatabaseMetaData dbm = connection.getMetaData();
+            ResultSet tables = dbm.getTables(null, TEST_SCHEMA_NAME, 
TEST_TABLE_NAME, null);
+            if (tables.next()) {
+                // Drop test Table if exists
+                statement.executeUpdate("DROP TABLE IF EXISTS " + 
FQ_TABLE_NAME);
+            }
+
+            // Drop test schema if exists
+            if (TEST_SCHEMA_NAME != null) {
+                statement = connection.createStatement();
+                statement.executeUpdate("DROP SCHEMA IF EXISTS " + 
TEST_SCHEMA_NAME);
+            }
+        }
+    }
+
+    /**
+     * Create Schema Test
+     */
+    static class CreateSchemaTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("createSchema");
+            Statement statement = connection.createStatement();
+            statement.executeUpdate("CREATE SCHEMA IF NOT EXISTS " + 
TEST_SCHEMA_NAME);
+        }
+    }
+
+    /**
+     * Create Table Test
+     */
+    static class CreateTableTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("createTable");
+            Statement statement = connection.createStatement();
+            // Create Table
+            statement.executeUpdate("CREATE TABLE IF NOT EXISTS" + 
FQ_TABLE_NAME + " (mykey " + "INTEGER "
+                    + "NOT " + "NULL PRIMARY KEY, " + "mycolumn VARCHAR)");
+        }
+    }
+
+    /**
+     * Upsert Data into Table Test
+     */
+    static class UpsertTableTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("upsertTable");
+            // Insert data
+            Statement statement = connection.createStatement();
+            statement.executeUpdate("UPSERT INTO " + FQ_TABLE_NAME + " VALUES 
(1, " +
+                    "'Hello" + " World')");
+            connection.commit();
+        }
+    }
+
+    /**
+     * Read data from Table Test
+     */
+    static class ReadTableTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("readTable");
+            // Query for table
+            PreparedStatement ps = connection.prepareStatement("SELECT * FROM 
" + FQ_TABLE_NAME);
+            ResultSet rs = ps.executeQuery();
+
+            // Check correctness
+            int totalRows = 0;
+            while (rs.next()) {
+                totalRows += 1;
+                Integer myKey = rs.getInt(1);
+                String myColumn = rs.getString(2);
+                if (myKey != 1 || !myColumn.equals("Hello World")) {
+                    throw new Exception("Retrieved values do not match the 
inserted " + "values");
+                }
+            }
+            if (totalRows != 1) {
+                throw new Exception(totalRows + " rows fetched instead of just 
one.");
+            }
+            ps.close();
+            rs.close();
+        }
+    }
+
+    /**
+     * Delete test table Test
+     */
+    static class DeleteTableTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("deleteTable");
+            Statement statement = connection.createStatement();
+            statement.executeUpdate("DROP TABLE IF EXISTS" + FQ_TABLE_NAME);
+
+            // Check if table dropped
+            DatabaseMetaData dbm = connection.getMetaData();
+            ResultSet tables = dbm.getTables(null, TEST_SCHEMA_NAME, 
TEST_TABLE_NAME, null);
+            if (tables.next()) {
+                throw new Exception("Test Table could not be dropped");
+            }
+        }
+    }
+
+    /**
+     * Delete test Schema Test
+     */
+    static class DeleteSchemaTest extends CanaryTest {
+        void onExecute() throws Exception {
+            result.setTestName("deleteSchema");
+            Statement statement = connection.createStatement();
+            statement.executeUpdate("DROP SCHEMA IF EXISTS " + 
TEST_SCHEMA_NAME);
+        }
+    }
+
+    /**
+     * Sink interface used by the canary to output information
+     */
+    public interface Sink {
+        List<CanaryTestResult> getResults();
+
+        void updateResults(CanaryTestResult result);
+
+        void publishResults() throws Exception;
+
+        void clearResults();
+    }
+
+    /**
+     * Implementation of Std Out Sink
+     */
+    public static class StdOutSink implements Sink {
+        private List<CanaryTestResult> results = new ArrayList<>();
+
+        @Override
+        public void updateResults(CanaryTestResult result) {
+            results.add(result);
+        }
+
+        @Override
+        public List<CanaryTestResult> getResults() {
+            return results;
+        }
+
+        @Override
+        public void publishResults() throws Exception {
+
+            Gson gson = new GsonBuilder().setPrettyPrinting().create();
+            String resultJson = gson.toJson(results);
+            System.out.println(resultJson);
+        }
+
+        @Override
+        public void clearResults() {
+            results.clear();
+        }
+    }
+
+    /**
+     * Implementation of File Out Sink
+     */
+    public static class FileOutSink implements Sink {
+        private List<CanaryTestResult> results = new ArrayList<>();
+        File dir;
+        String logfileName;
+        String propFileName = "phoenix-canary-file-sink.properties";
+
+        public FileOutSink() throws Exception {
+            Properties prop = new Properties();
+            InputStream input = 
ClassLoader.getSystemResourceAsStream(propFileName);
+            if (input == null) {
+                throw new Exception("Cannot load " + propFileName + " file for 
" + "FileOutSink.");
+            }
+            prop.load(input);
+            logfileName = prop.getProperty("file.name");
+            dir = new File(prop.getProperty("file.location"));
+            dir.mkdirs();
+        }
+
+        @Override
+        public void updateResults(CanaryTestResult result) {
+            results.add(result);
+        }
+
+        @Override
+        public List<CanaryTestResult> getResults() {
+            return results;
+        }
+
+        @Override
+        public void publishResults() throws Exception {
+            Gson gson = new GsonBuilder().setPrettyPrinting().create();
+            String resultJson = gson.toJson(results);
+            String fileName = logfileName + "-" + new 
SimpleDateFormat("yyyy.MM.dd.HH" + ".mm" +
+                    ".ss").format(new Date()) + ".log";
+            File file = new File(dir, fileName);
+            Files.write(Bytes.toBytes(resultJson), file);
+        }
+
+        @Override
+        public void clearResults() {
+            results.clear();
+        }
+    }
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(PhoenixCanaryTool.class);
+
+    private static String getCurrentTimestamp() {
+        return new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.ms").format(new 
Date());
+    }
+
+    private static Namespace parseArgs(String[] args) {
+
+        ArgumentParser parser = ArgumentParsers.newFor("Phoenix Canary Test 
Tool").build()
+                .description("Phoenix Canary Test Tool");
+
+        parser.addArgument("--hostname", 
"-hn").type(String.class).nargs("?").help("Hostname on "
+                + "which Phoenix is running.");
+
+        parser.addArgument("--port", 
"-p").type(String.class).nargs("?").help("Port on " +
+                "which Phoenix is running.");
+
+        parser.addArgument("--constring", 
"-cs").type(String.class).nargs("?").help("Pass an " +
+                "explicit connection String to connect to Phoenix. " +
+                "default: 
jdbc:phoenix:thin:serialization=PROTOBUF;url=[hostName:port]");
+
+        parser.addArgument("--timeout", 
"-t").type(String.class).nargs("?").setDefault("60").help
+                ("Maximum time for which the app should run before returning 
error. default:" + "" +
+                        " 60 sec");
+
+        parser.addArgument("--testschema", 
"-ts").type(String.class).nargs("?").setDefault
+                (TEST_SCHEMA_NAME).help("Custom name for the test table. " + 
"default: " +
+                TEST_SCHEMA_NAME);
+
+        parser.addArgument("--testtable", 
"-tt").type(String.class).nargs("?").setDefault
+                (TEST_TABLE_NAME).help("Custom name for the test table." + " 
default: " +
+                TEST_TABLE_NAME);
+
+        parser.addArgument("--logsinkclass", 
"-lsc").type(String.class).nargs("?").setDefault
+                ("PhoenixCanaryTool$StdOutSink").help
+                ("Path to a Custom implementation for log sink class. default: 
stdout");
+
+        Namespace res = null;
+        try {
+            res = parser.parseKnownArgs(args, null);
+        } catch (ArgumentParserException e) {
+            parser.handleError(e);
+        }
+        return res;
+    }
+
+    private CanaryTestResult appInfo = new CanaryTestResult();
+    private Connection connection = null;
+
+    @Override
+    public int run(String[] args) throws Exception {
+
+        try {
+            Namespace cArgs = parseArgs(args);
+            if (cArgs == null) {
+                LOG.error("Argument parsing failed.");
+                throw new RuntimeException("Argument parsing failed");
+            }
+
+            final String hostName = cArgs.getString("hostname");
+            final String port = cArgs.getString("port");
+            final String timeout = cArgs.getString("timeout");
+            final String conString = cArgs.getString("constring");
+            final String testSchemaName = cArgs.getString("testschema");
+            final String testTableName = cArgs.getString("testtable");
+            final String logSinkClass = cArgs.getString("logsinkclass");
+
+            TEST_TABLE_NAME = testTableName;
+            TEST_SCHEMA_NAME = testSchemaName;
+            FQ_TABLE_NAME = testSchemaName + "." + testTableName;
+
+            // Check if at least one from host+port or con string is provided.
+            if ((hostName == null || port == null) && conString == null) {
+                throw new RuntimeException("Provide at least one from 
host+port or constring");
+            }
+
+            int timeoutVal = Integer.parseInt(timeout);
+
+            // Dynamically load a class for sink
+            sink = (Sink) 
ClassLoader.getSystemClassLoader().loadClass(logSinkClass).newInstance();
+
+            long startTime = System.currentTimeMillis();
+
+            String connectionURL = (conString != null) ? conString :
+                    "jdbc:phoenix:thin:serialization=PROTOBUF;url=" + hostName 
+ ":" + port;
+
+            appInfo.setTestName("appInfo");
+            appInfo.setMiscellaneous(connectionURL);
+
+            Properties connProps = new Properties();
+            connProps.setProperty("phoenix.schema.mapSystemTablesToNamespace", 
"true");
+            connProps.setProperty("phoenix.schema.isNamespaceMappingEnabled", 
"true");
+
+            try {
+                connection = DriverManager.getConnection(connectionURL, 
connProps);
+            } catch (Exception e) {
+                LOG.info("Namespace mapping cannot be set. Using default 
schema");
+                USE_NAMESPACE = false;
+                connection = DriverManager.getConnection(connectionURL);
+                TEST_SCHEMA_NAME = null;
+                FQ_TABLE_NAME = TEST_TABLE_NAME;
+            }
+
+            SimpleTimeLimiter limiter = new SimpleTimeLimiter();
+
+            limiter.callWithTimeout(new Callable<Void>() {
+
+                public Void call() {
+
+                    sink.clearResults();
+
+                    // Execute tests
+
+                    LOG.info("Starting PrepareTest");
+                    sink.updateResults(new PrepareTest().runTest(connection));
+
+                    if (USE_NAMESPACE) {
+                        LOG.info("Starting CreateSchemaTest");
+                        sink.updateResults(new 
CreateSchemaTest().runTest(connection));
+                    }
+
+                    LOG.info("Starting CreateTableTest");
+                    sink.updateResults(new 
CreateTableTest().runTest(connection));
+
+                    LOG.info("Starting UpsertTableTest");
+                    sink.updateResults(new 
UpsertTableTest().runTest(connection));
+
+                    LOG.info("Starting ReadTableTest");
+                    sink.updateResults(new 
ReadTableTest().runTest(connection));
+
+                    LOG.info("Starting DeleteTableTest");
+                    sink.updateResults(new 
DeleteTableTest().runTest(connection));
+
+                    if (USE_NAMESPACE) {
+                        LOG.info("Starting DeleteSchemaTest");
+                        sink.updateResults(new 
DeleteSchemaTest().runTest(connection));
+                    }
+                    return null;
+                }
+            }, timeoutVal, TimeUnit.SECONDS, true);
+
+            long estimatedTime = System.currentTimeMillis() - startTime;
+
+            appInfo.setExecutionTime(estimatedTime);
+            appInfo.setSuccessful(true);
+
+        } catch (Exception e) {
+            LOG.error(Throwables.getStackTraceAsString(e));
+            appInfo.setMessage(Throwables.getStackTraceAsString(e));
+            appInfo.setSuccessful(false);
+
+        } finally {
+            sink.updateResults(appInfo);
+            sink.publishResults();
+            connection.close();
+        }
+
+        return 0;
+    }
+
+    public static void main(final String[] args) {
+        int result = 0;
+        try {
+            LOG.info("Starting Phoenix Canary Test tool...");
+            result = ToolRunner.run(new PhoenixCanaryTool(), args);
+        } catch (Exception e) {
+            LOG.error("Error in running Phoenix Canary Test tool. " + e);
+        }
+        LOG.info("Exiting Phoenix Canary Test tool...");
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b5308773/phoenix-core/src/main/resources/phoenix-canary-file-sink.properties
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/resources/phoenix-canary-file-sink.properties 
b/phoenix-core/src/main/resources/phoenix-canary-file-sink.properties
new file mode 100644
index 0000000..3c1ebae
--- /dev/null
+++ b/phoenix-core/src/main/resources/phoenix-canary-file-sink.properties
@@ -0,0 +1,17 @@
+# 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.
+
+file.name=phoenix-canary-logfile
+file.location=/tmp/logs/phoenix
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/b5308773/phoenix-core/src/test/java/org/apache/phoenix/tool/PhoenixCanaryToolTest.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/tool/PhoenixCanaryToolTest.java 
b/phoenix-core/src/test/java/org/apache/phoenix/tool/PhoenixCanaryToolTest.java
new file mode 100644
index 0000000..bd2a3d1
--- /dev/null
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/tool/PhoenixCanaryToolTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.phoenix.tool;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import static org.mockito.Mockito.when;
+import org.mockito.MockitoAnnotations;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+public class PhoenixCanaryToolTest {
+
+    @Mock
+    private Connection connection;
+
+    @Mock
+    private Statement statement;
+
+    @Mock
+    private PreparedStatement ps;
+
+    @Mock
+    private ResultSet rs;
+
+    @Mock
+    private DatabaseMetaData dbm;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void prepareTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        when(connection.getMetaData()).thenReturn(dbm);
+        when(dbm.getTables(null, "TEST", "PQSTEST", null)).thenReturn(rs);
+        when(rs.next()).thenReturn(true).thenReturn(false);
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        CanaryTestResult result = new 
PhoenixCanaryTool.PrepareTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test prepare successful", result.getMessage());
+    }
+
+    @Test
+    public void createSchemaTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        CanaryTestResult result = new 
PhoenixCanaryTool.CreateSchemaTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test createSchema successful", result.getMessage());
+    }
+
+    @Test
+    public void createTableTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        CanaryTestResult result = new 
PhoenixCanaryTool.CreateTableTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test createTable successful", result.getMessage());
+    }
+
+    @Test
+    public void upsertTableTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(1);
+        CanaryTestResult result = new 
PhoenixCanaryTool.UpsertTableTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test upsertTable successful", result.getMessage());
+    }
+
+    @Test
+    public void readTableTest() throws Exception {
+        when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps);
+        when(ps.executeQuery()).thenReturn(rs);
+        when(rs.next()).thenReturn(true).thenReturn(false);
+        when(rs.getInt(1)).thenReturn(1);
+        when(rs.getString(2)).thenReturn("Hello World");
+        CanaryTestResult result = new 
PhoenixCanaryTool.ReadTableTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test readTable successful", result.getMessage());
+    }
+
+    @Test
+    public void deleteTableTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        when(connection.getMetaData()).thenReturn(dbm);
+        when(dbm.getTables(null, "TEST", "PQSTEST", null)).thenReturn(rs);
+        CanaryTestResult result = new 
PhoenixCanaryTool.DeleteTableTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test deleteTable successful", result.getMessage());
+    }
+
+    @Test
+    public void deleteSchemaTest() throws Exception {
+        when(connection.createStatement()).thenReturn(statement);
+        when(statement.executeUpdate(Mockito.anyString())).thenReturn(0);
+        CanaryTestResult result = new 
PhoenixCanaryTool.DeleteSchemaTest().runTest(connection);
+        assertEquals(true, result.isSuccessful());
+        assertEquals("Test deleteSchema successful", result.getMessage());
+    }
+
+    @Test
+    public void failTest() throws Exception {
+        when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps);
+        when(ps.executeQuery()).thenReturn(rs);
+        when(rs.getInt(1)).thenReturn(3);
+        when(rs.getString(2)).thenReturn("Incorrect data");
+        when(rs.next()).thenReturn(true).thenReturn(false);
+        CanaryTestResult result = new 
PhoenixCanaryTool.ReadTableTest().runTest(connection);
+        assertEquals(false, result.isSuccessful());
+        assert (result.getMessage().contains("Retrieved values do not match 
the inserted values"));
+    }
+}
\ No newline at end of file

Reply via email to