diff options
| author | Phil Harvey <philharveyonline@apache.org> | 2013-01-30 09:15:18 +0000 |
|---|---|---|
| committer | Phil Harvey <philharveyonline@apache.org> | 2013-01-30 09:15:18 +0000 |
| commit | d823317a94c57493ec30d773ab36aee7749992d0 (patch) | |
| tree | 3e622a87a8533a71dd780e7d6addb705f9e1b8dd /java/perftests | |
| parent | 41089d48d77d29b69c0c7d473615c629a8a5f30c (diff) | |
| download | qpid-python-d823317a94c57493ec30d773ab36aee7749992d0.tar.gz | |
QPID-4533: Modified perftests to support writing results to a database, and enhanced visualisation-jfc to allow it to read these results.
Previously only CSV output/input was supported by these modules respectively.
Also modified files in perftests/etc/ to allow convenient running of perftests.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1440312 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/perftests')
29 files changed, 1197 insertions, 172 deletions
diff --git a/java/perftests/etc/perftests-jndi.properties b/java/perftests/etc/perftests-jndi.properties index f33af6fdd5..ce6493b49a 100644 --- a/java/perftests/etc/perftests-jndi.properties +++ b/java/perftests/etc/perftests-jndi.properties @@ -20,3 +20,7 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true' + +jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver +# writes to a results database in ./perftestResultsDb by default. +jdbcUrl=jdbc:derby:perftestResultsDb;create=true diff --git a/java/perftests/etc/run-perftests.sh b/java/perftests/etc/run-perftests.sh new file mode 100755 index 0000000000..f963879e7e --- /dev/null +++ b/java/perftests/etc/run-perftests.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# 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. +# + +# Runs the perftests using a typical configuration. + +BASE_DIR=`dirname $0` +DURATION=${1:-5000} +AMQP_VERSION=${2:-0-91} + +echo Will run perftests using a maximum duration of ${DURATION}ms and AMQP protocol version ${AMQP_VERSION}. +echo + +java -cp "${BASE_DIR}:${BASE_DIR}/../../build/lib/*" \ + -Dqpid.amqp.version=${AMQP_VERSION} -Dqpid.dest_syntax=BURL \ + -Dqpid.disttest.duration=$DURATION \ + org.apache.qpid.disttest.ControllerRunner \ + jndi-config=${BASE_DIR}/perftests-jndi.properties \ + test-config=${BASE_DIR}/testdefs \ + distributed=false \ + writeToDb=true diff --git a/java/perftests/etc/visualisation.sh b/java/perftests/etc/visualisation.sh new file mode 100755 index 0000000000..6d4719db16 --- /dev/null +++ b/java/perftests/etc/visualisation.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# 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. +# + +# Runs the visualisation tool against perftest CSV output assumed to be in the current directory + +BASE_DIR=`dirname $0` + +# Uncomment to read perftest data from a Derby database +# JDBC_URL=jdbcUrl=jdbc:derby:perftestResultsDb +# JDBC_DRIVER=jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver + +java -cp "${BASE_DIR}:${BASE_DIR}/../../build/lib/*" \ + -Djava.awt.headless=true -Dlog4j.configuration=file:log4j.properties \ + org.apache.qpid.disttest.charting.ChartingUtil \ + chart-defs=chartdefs \ + ${JDBC_DRIVER} ${JDBC_URL} diff --git a/java/perftests/example/perftests-jndi.properties b/java/perftests/example/perftests-jndi.properties index 04a8ad9101..1c0fd57663 100644 --- a/java/perftests/example/perftests-jndi.properties +++ b/java/perftests/example/perftests-jndi.properties @@ -24,3 +24,6 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true' + +driverName=org.apache.derby.jdbc.EmbeddedDriver +jdbcUrl=jdbc:derby:/tmp/perftestResultsDb;create=true diff --git a/java/perftests/example/run.sh b/java/perftests/example/run.sh index cb68c52853..31124a060a 100755 --- a/java/perftests/example/run.sh +++ b/java/perftests/example/run.sh @@ -18,5 +18,5 @@ # under the License. # -java -cp ".:${QPID_HOME}/lib/*" -Dqpid.dest_syntax=BURL org.apache.qpid.disttest.ControllerRunner jndi-config=perftests-jndi.properties test-config=$1 distributed=false +java -cp ".:${QPID_HOME}/lib/*" -Dqpid.dest_syntax=BURL org.apache.qpid.disttest.ControllerRunner jndi-config=perftests-jndi.properties test-config=$1 distributed=false writeToDb=true diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java index 8c1f8675e3..e962bfe799 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java @@ -34,10 +34,14 @@ public class ArgumentParser throw new IllegalArgumentException("arguments must have format <name>=<value>: " + arg); } - if(initialValues.put(splitArg[0], splitArg[1]) == null) + + String argumentKey = splitArg[0]; + String argumentValue = splitArg[1]; + if(!initialValues.containsKey(argumentKey)) { throw new IllegalArgumentException("not a valid configuration property: " + arg); } + initialValues.put(argumentKey, argumentValue); } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java index a0e949bddc..449130a328 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java @@ -30,6 +30,7 @@ import org.apache.qpid.disttest.controller.Controller; import org.apache.qpid.disttest.controller.ResultsForAllTests; import org.apache.qpid.disttest.controller.config.Config; import org.apache.qpid.disttest.controller.config.ConfigReader; +import org.apache.qpid.disttest.db.ResultsDbWriter; import org.apache.qpid.disttest.jms.ControllerJmsDelegate; import org.apache.qpid.disttest.results.aggregation.Aggregator; import org.slf4j.Logger; @@ -42,22 +43,29 @@ public class ControllerRunner extends AbstractRunner public static final String TEST_CONFIG_PROP = "test-config"; public static final String DISTRIBUTED_PROP = "distributed"; public static final String OUTPUT_DIR_PROP = "outputdir"; + public static final String WRITE_TO_DB = "writeToDb"; + public static final String RUN_ID = "runId"; private static final String TEST_CONFIG_DEFAULT = "perftests-config.json"; private static final String DISTRIBUTED_DEFAULT = "false"; private static final String OUTPUT_DIR_DEFAULT = "."; + public static final String WRITE_TO_DB_DEFAULT = "false"; private final Aggregator _aggregator = new Aggregator(); private final ConfigFileHelper _configFileHelper = new ConfigFileHelper(); - private ResultsFileWriter _resuResultsFileWriter; + private ResultsFileWriter _resultsFileWriter; + + private ResultsDbWriter _resultsDbWriter; public ControllerRunner() { getCliOptions().put(TEST_CONFIG_PROP, TEST_CONFIG_DEFAULT); getCliOptions().put(DISTRIBUTED_PROP, DISTRIBUTED_DEFAULT); getCliOptions().put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); + getCliOptions().put(WRITE_TO_DB, WRITE_TO_DB_DEFAULT); + getCliOptions().put(RUN_ID, null); } public static void main(String[] args) throws Exception @@ -70,7 +78,8 @@ public class ControllerRunner extends AbstractRunner public void runController() throws Exception { Context context = getContext(); - setUpResultsWriter(); + setUpResultFilesWriter(); + setUpResultsDbWriter(); ControllerJmsDelegate jmsDelegate = new ControllerJmsDelegate(context); @@ -84,11 +93,22 @@ public class ControllerRunner extends AbstractRunner } } - void setUpResultsWriter() + private void setUpResultsDbWriter() + { + String writeToDbStr = getCliOptions().get(WRITE_TO_DB); + if(Boolean.valueOf(writeToDbStr)) + { + String runId = getCliOptions().get(RUN_ID); + _resultsDbWriter = new ResultsDbWriter(getContext(), runId); + _resultsDbWriter.createResultsTableIfNecessary(); + } + } + + void setUpResultFilesWriter() { String outputDirString = getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP); File outputDir = new File(outputDirString); - _resuResultsFileWriter = new ResultsFileWriter(outputDir); + _resultsFileWriter = new ResultsFileWriter(outputDir); } private void runTests(ControllerJmsDelegate jmsDelegate) @@ -115,7 +135,7 @@ public class ControllerRunner extends AbstractRunner results.add(testResult); } - _resuResultsFileWriter.writeResultsSummary(results); + _resultsFileWriter.writeResultsSummary(results); } catch(Exception e) { @@ -135,7 +155,12 @@ public class ControllerRunner extends AbstractRunner ResultsForAllTests rawResultsForAllTests = controller.runAllTests(); ResultsForAllTests resultsForAllTests = _aggregator.aggregateResults(rawResultsForAllTests); - _resuResultsFileWriter.writeResultsToFile(resultsForAllTests, testConfigFile); + _resultsFileWriter.writeResultsToFile(resultsForAllTests, testConfigFile); + if(_resultsDbWriter != null) + { + _resultsDbWriter.writeResults(resultsForAllTests); + } + return resultsForAllTests; } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java index 8d25f86b77..d3a5e30191 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java @@ -35,7 +35,6 @@ import javax.jms.MessageListener; import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.jms.ClientJmsDelegate; -import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.ParticipantResult; import org.slf4j.Logger; @@ -113,7 +112,7 @@ public class ConsumerParticipant implements Participant getName(), numberOfMessagesReceived); } - ConsumerParticipantResult result = _resultFactory.createForConsumer( + ParticipantResult result = _resultFactory.createForConsumer( getName(), registeredClientName, _command, diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java b/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java new file mode 100644 index 0000000000..bd3405eadf --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java @@ -0,0 +1,435 @@ +/* + * 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.qpid.disttest.db; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.*; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Date; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.log4j.Logger; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +/** + * Intended call sequence: + * <ul> + * <li>{@link #ResultsDbWriter(Context, String)}</li> + * <li>{@link #createResultsTableIfNecessary()}</li> + * <li>{@link #writeResults(ResultsForAllTests)} (usually multiple times)</li> + * </ul> + */ +public class ResultsDbWriter +{ + private static final Logger _logger = Logger.getLogger(ResultsDbWriter.class); + + private static final String RESULTS_TABLE_NAME = "RESULTS"; + + /** column name */ + static final String INSERTED_TIMESTAMP = "insertedTimestamp"; + /** column name */ + static final String RUN_ID = "runId"; + + private static final String TABLE_EXISTENCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?"; + + private static final String CREATE_RESULTS_TABLE = String.format( + "CREATE TABLE %1$s (" + + "%2$s varchar(200) not null" + // TEST_NAME + ", %3$s bigint not null" + // ITERATION_NUMBER + ", %4$s varchar(200) not null" + // PARTICIPANT_NAME + ", %5$s double not null" + // THROUGHPUT + ", %6$s double" + // AVERAGE_LATENCY + ", %7$s varchar(200)" + // CONFIGURED_CLIENT_NAME + ", %8$s bigint" + // NUMBER_OF_MESSAGES_PROCESSED + ", %9$s bigint" + // PAYLOAD_SIZE + ", %10$s bigint" + // PRIORITY + ", %11$s bigint" + // TIME_TO_LIVE + ", %12$s bigint" + // ACKNOWLEDGE_MODE + ", %13$s bigint" + // DELIVERY_MODE + ", %14$s bigint" + // BATCH_SIZE + ", %15$s bigint" + // MAXIMUM_DURATION + ", %16$s bigint" + // PRODUCER_START_DELAY + ", %17$s bigint" + // PRODUCER_INTERVAL + ", %18$s bigint" + // IS_TOPIC + ", %19$s bigint" + // IS_DURABLE_SUBSCRIPTION + ", %20$s bigint" + // IS_BROWSING_SUBSCRIPTION + ", %21$s bigint" + // IS_SELECTOR + ", %22$s bigint" + // IS_NO_LOCAL + ", %23$s bigint" + // IS_SYNCHRONOUS_CONSUMER + ", %24$s bigint" + // TOTAL_NUMBER_OF_CONSUMERS + ", %25$s bigint" + // TOTAL_NUMBER_OF_PRODUCERS + ", %26$s bigint" + // TOTAL_PAYLOAD_PROCESSED + ", %27$s bigint" + // TIME_TAKEN + ", %28$s varchar(2000)" + // ERROR_MESSAGE + ", %29$s bigint" + // MIN_LATENCY + ", %30$s bigint" + // MAX_LATENCY + ", %31$s double" + // LATENCY_STANDARD_DEVIATION + ", %32$s varchar(200) not null" + + ", %33$s timestamp not null" + + ")", + RESULTS_TABLE_NAME, + TEST_NAME.getDisplayName(), + ITERATION_NUMBER.getDisplayName(), + PARTICIPANT_NAME.getDisplayName(), + THROUGHPUT.getDisplayName(), + AVERAGE_LATENCY.getDisplayName(), + CONFIGURED_CLIENT_NAME.getDisplayName(), + NUMBER_OF_MESSAGES_PROCESSED.getDisplayName(), + PAYLOAD_SIZE.getDisplayName(), + PRIORITY.getDisplayName(), + TIME_TO_LIVE.getDisplayName(), + ACKNOWLEDGE_MODE.getDisplayName(), + DELIVERY_MODE.getDisplayName(), + BATCH_SIZE.getDisplayName(), + MAXIMUM_DURATION.getDisplayName(), + PRODUCER_START_DELAY.getDisplayName(), + PRODUCER_INTERVAL.getDisplayName(), + IS_TOPIC.getDisplayName(), + IS_DURABLE_SUBSCRIPTION.getDisplayName(), + IS_BROWSING_SUBSCRIPTION.getDisplayName(), + IS_SELECTOR.getDisplayName(), + IS_NO_LOCAL.getDisplayName(), + IS_SYNCHRONOUS_CONSUMER.getDisplayName(), + TOTAL_NUMBER_OF_CONSUMERS.getDisplayName(), + TOTAL_NUMBER_OF_PRODUCERS.getDisplayName(), + TOTAL_PAYLOAD_PROCESSED.getDisplayName(), + TIME_TAKEN.getDisplayName(), + ERROR_MESSAGE.getDisplayName(), + MIN_LATENCY.getDisplayName(), + MAX_LATENCY.getDisplayName(), + LATENCY_STANDARD_DEVIATION.getDisplayName(), + RUN_ID, + INSERTED_TIMESTAMP + ); + + public static final String DRIVER_NAME = "jdbcDriverClass"; + public static final String URL = "jdbcUrl"; + + private final String _url; + private final String _runId; + + private final Clock _clock; + + /** + * @param runId may be null, in which case a default value is chosen based on current time. + * @param context must contain environment entries {@value #DRIVER_NAME} and {@value #URL}. + */ + public ResultsDbWriter(Context context, String runId) + { + this(context, runId, new Clock()); + } + + /** only call directly from tests */ + ResultsDbWriter(Context context, String runId, Clock clock) + { + _clock = clock; + _runId = defaultIfNullRunId(runId); + + _url = initialiseJdbc(context); + } + + private String defaultIfNullRunId(String runId) + { + if(runId == null) + { + Date dateNow = new Date(_clock.currentTimeMillis()); + return String.format("run %1$tF %1$tT.%tL", dateNow); + } + else + { + return runId; + } + } + + public String getRunId() + { + return _runId; + } + + /** + * Uses the context's environment to load the JDBC driver class and return the + * JDBC URL specified therein. + * @return the JDBC URL + */ + private String initialiseJdbc(Context context) + { + Hashtable<?, ?> environment = null; + try + { + environment = context.getEnvironment(); + + String driverName = (String) environment.get(DRIVER_NAME); + if(driverName == null) + { + throw new IllegalArgumentException("JDBC driver name " + DRIVER_NAME + + " missing from context environment: " + environment); + } + + @SuppressWarnings("unchecked") + Class<? extends Driver> driverClass = (Class<? extends Driver>) Class.forName(driverName); + + Object url = environment.get(URL); + if(url == null) + { + throw new IllegalArgumentException("JDBC URL " + URL + " missing from context environment: " + environment); + } + return (String) url; + } + catch (NamingException e) + { + throw constructorRethrow(e, environment); + } + catch (ClassNotFoundException e) + { + throw constructorRethrow(e, environment); + } + } + + private RuntimeException constructorRethrow(Exception e, Hashtable<?, ?> environment) + { + return new RuntimeException("Couldn't initialise ResultsDbWriter from context with environment" + environment, e); + } + + public void createResultsTableIfNecessary() + { + try + { + Connection connection = null; + try + { + connection = DriverManager.getConnection(_url); + if(!tableExists(RESULTS_TABLE_NAME, connection)) + { + Statement statement = connection.createStatement(); + try + { + _logger.info("About to create results table using SQL: " + CREATE_RESULTS_TABLE); + statement.execute(CREATE_RESULTS_TABLE); + } + finally + { + statement.close(); + } + } + } + finally + { + if(connection != null) + { + connection.close(); + } + } + } + catch (SQLException e) + { + throw new RuntimeException("Couldn't create results table", e); + } + + } + + private boolean tableExists(final String tableName, final Connection conn) throws SQLException + { + PreparedStatement stmt = conn.prepareStatement(TABLE_EXISTENCE_QUERY); + try + { + stmt.setString(1, tableName); + ResultSet rs = stmt.executeQuery(); + try + { + return rs.next(); + } + finally + { + rs.close(); + } + } + finally + { + stmt.close(); + } + } + + public void writeResults(ResultsForAllTests results) + { + try + { + writeResultsThrowingException(results); + } + catch (SQLException e) + { + throw new RuntimeException("Couldn't write results " + results, e); + } + _logger.info(this + " wrote " + results.getTestResults().size() + " results to database"); + } + + private void writeResultsThrowingException(ResultsForAllTests results) throws SQLException + { + Connection connection = null; + try + { + connection = DriverManager.getConnection(_url); + + for (ITestResult testResult : results.getTestResults()) + { + for (ParticipantResult participantResult : testResult.getParticipantResults()) + { + writeParticipantResult(connection, participantResult); + } + } + } + finally + { + if(connection != null) + { + connection.close(); + } + } + } + + private void writeParticipantResult(Connection connection, ParticipantResult participantResult) throws SQLException + { + if(_logger.isDebugEnabled()) + { + _logger.debug("About to write to DB the following participant result: " + participantResult); + } + + PreparedStatement statement = null; + try + { + String sqlTemplate = String.format( + "INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) " + + "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + RESULTS_TABLE_NAME, + TEST_NAME.getDisplayName(), + ITERATION_NUMBER.getDisplayName(), + PARTICIPANT_NAME.getDisplayName(), + THROUGHPUT.getDisplayName(), + AVERAGE_LATENCY.getDisplayName(), + CONFIGURED_CLIENT_NAME.getDisplayName(), + NUMBER_OF_MESSAGES_PROCESSED.getDisplayName(), + PAYLOAD_SIZE.getDisplayName(), + PRIORITY.getDisplayName(), + TIME_TO_LIVE.getDisplayName(), + ACKNOWLEDGE_MODE.getDisplayName(), + DELIVERY_MODE.getDisplayName(), + BATCH_SIZE.getDisplayName(), + MAXIMUM_DURATION.getDisplayName(), + PRODUCER_START_DELAY.getDisplayName(), + PRODUCER_INTERVAL.getDisplayName(), + IS_TOPIC.getDisplayName(), + IS_DURABLE_SUBSCRIPTION.getDisplayName(), + IS_BROWSING_SUBSCRIPTION.getDisplayName(), + IS_SELECTOR.getDisplayName(), + IS_NO_LOCAL.getDisplayName(), + IS_SYNCHRONOUS_CONSUMER.getDisplayName(), + TOTAL_NUMBER_OF_CONSUMERS.getDisplayName(), + TOTAL_NUMBER_OF_PRODUCERS.getDisplayName(), + TOTAL_PAYLOAD_PROCESSED.getDisplayName(), + TIME_TAKEN.getDisplayName(), + ERROR_MESSAGE.getDisplayName(), + MIN_LATENCY.getDisplayName(), + MAX_LATENCY.getDisplayName(), + LATENCY_STANDARD_DEVIATION.getDisplayName(), + RUN_ID, + INSERTED_TIMESTAMP + ); + statement = connection.prepareStatement(sqlTemplate); + + int columnIndex = 1; + statement.setString(columnIndex++, participantResult.getTestName()); + statement.setInt(columnIndex++, participantResult.getIterationNumber()); + statement.setString(columnIndex++, participantResult.getParticipantName()); + statement.setDouble(columnIndex++, participantResult.getThroughput()); + statement.setDouble(columnIndex++, participantResult.getAverageLatency()); + statement.setString(columnIndex++, participantResult.getConfiguredClientName()); + statement.setLong(columnIndex++, participantResult.getNumberOfMessagesProcessed()); + statement.setLong(columnIndex++, participantResult.getPayloadSize()); + statement.setLong(columnIndex++, participantResult.getPriority()); + statement.setLong(columnIndex++, participantResult.getTimeToLive()); + statement.setLong(columnIndex++, participantResult.getAcknowledgeMode()); + statement.setLong(columnIndex++, participantResult.getDeliveryMode()); + statement.setLong(columnIndex++, participantResult.getBatchSize()); + statement.setLong(columnIndex++, participantResult.getMaximumDuration()); + statement.setLong(columnIndex++, 0 /* TODO PRODUCER_START_DELAY*/); + statement.setLong(columnIndex++, 0 /* TODO PRODUCER_INTERVAL*/); + statement.setLong(columnIndex++, 0 /* TODO IS_TOPIC*/); + statement.setLong(columnIndex++, 0 /* TODO IS_DURABLE_SUBSCRIPTION*/); + statement.setLong(columnIndex++, 0 /* TODO IS_BROWSING_SUBSCRIPTION*/); + statement.setLong(columnIndex++, 0 /* TODO IS_SELECTOR*/); + statement.setLong(columnIndex++, 0 /* TODO IS_NO_LOCAL*/); + statement.setLong(columnIndex++, 0 /* TODO IS_SYNCHRONOUS_CONSUMER*/); + statement.setLong(columnIndex++, participantResult.getTotalNumberOfConsumers()); + statement.setLong(columnIndex++, participantResult.getTotalNumberOfProducers()); + statement.setLong(columnIndex++, participantResult.getTotalPayloadProcessed()); + statement.setLong(columnIndex++, participantResult.getTimeTaken()); + statement.setString(columnIndex++, participantResult.getErrorMessage()); + statement.setLong(columnIndex++, participantResult.getMinLatency()); + statement.setLong(columnIndex++, participantResult.getMaxLatency()); + statement.setDouble(columnIndex++, participantResult.getLatencyStandardDeviation()); + + statement.setString(columnIndex++, _runId); + statement.setTimestamp(columnIndex++, new Timestamp(_clock.currentTimeMillis())); + + statement.execute(); + connection.commit(); + } + finally + { + if (statement != null) + { + statement.close(); + } + } + } + + public static class Clock + { + public long currentTimeMillis() + { + return System.currentTimeMillis(); + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("runId", _runId) + .append("url", _url) + .toString(); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java index ad9aa31472..e78f6965d2 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java @@ -134,6 +134,7 @@ public class ConsumerParticipantResult extends ParticipantResult _messageLatencies = messageLatencies; } + @Override @OutputAttribute(attribute=ParticipantAttribute.MIN_LATENCY) public long getMinLatency() { @@ -145,6 +146,7 @@ public class ConsumerParticipantResult extends ParticipantResult _minLatency = minLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.MAX_LATENCY) public long getMaxLatency() { @@ -156,6 +158,7 @@ public class ConsumerParticipantResult extends ParticipantResult _maxLatency = maxLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.AVERAGE_LATENCY) public double getAverageLatency() { @@ -167,6 +170,7 @@ public class ConsumerParticipantResult extends ParticipantResult _averageLatency = averageLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.LATENCY_STANDARD_DEVIATION) public double getLatencyStandardDeviation() { diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java index efd248b6de..0a824a316b 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java @@ -22,12 +22,12 @@ import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MESSAGE_THROUGHPUT; import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; -import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.MESSAGE_THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; import java.util.Comparator; import java.util.Date; @@ -282,4 +282,41 @@ public class ParticipantResult extends Response _acknowledgeMode = acknowledgeMode; } + public double getLatencyStandardDeviation() + { + return 0.0; + } + + @OutputAttribute(attribute = ParticipantAttribute.MIN_LATENCY) + public long getMinLatency() + { + return 0; + } + + @OutputAttribute(attribute = ParticipantAttribute.MAX_LATENCY) + public long getMaxLatency() + { + return 0; + } + + @OutputAttribute(attribute = ParticipantAttribute.AVERAGE_LATENCY) + public double getAverageLatency() + { + return 0; + } + + public int getPriority() + { + return 0; + } + + public long getTimeToLive() + { + return 0; + } + + public int getDeliveryMode() + { + return 0; + } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java index 766c90eec8..2d9399a3d3 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java @@ -42,6 +42,7 @@ public class ProducerParticipantResult extends ParticipantResult setParticipantName(participantName); } + @Override @OutputAttribute(attribute=PRIORITY) public int getPriority() { @@ -53,6 +54,7 @@ public class ProducerParticipantResult extends ParticipantResult _priority = priority; } + @Override @OutputAttribute(attribute=TIME_TO_LIVE) public long getTimeToLive() { @@ -86,6 +88,7 @@ public class ProducerParticipantResult extends ParticipantResult _interval = producerInterval; } + @Override @OutputAttribute(attribute=DELIVERY_MODE) public int getDeliveryMode() { @@ -96,5 +99,4 @@ public class ProducerParticipantResult extends ParticipantResult { this._deliveryMode = deliveryMode; } - } diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java new file mode 100644 index 0000000000..e2a211911e --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java @@ -0,0 +1,145 @@ +/* + * 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.qpid.disttest.db; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.test.utils.TestFileUtils.createTestDirectory; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingException; + +import junit.framework.TestCase; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.db.ResultsDbWriter.Clock; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.ResultsTestFixture; +import org.apache.qpid.util.FileUtils; + +public class ResultsDbWriterTest extends TestCase +{ + + private static final long _dummyTimestamp = 1234; + + private File _tempDbDirectory; + private Clock _clock = mock(Clock.class); + private ResultsTestFixture _resultsTestFixture = new ResultsTestFixture(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _tempDbDirectory = createTestDirectory(); + when(_clock.currentTimeMillis()).thenReturn(_dummyTimestamp); + } + + + @Override + protected void tearDown() throws Exception + { + try + { + FileUtils.deleteDirectory(_tempDbDirectory.getAbsolutePath()); + } + finally + { + super.tearDown(); + } + } + + + public void testWriteResults() throws Exception + { + Context context = getContext(); + ResultsForAllTests results = _resultsTestFixture.createResultsForAllTests(); + String runId = "myRunId"; + + ResultsDbWriter resultsDbWriter = new ResultsDbWriter(context, runId, _clock); + resultsDbWriter.createResultsTableIfNecessary(); + + resultsDbWriter.writeResults(results); + + ParticipantResult expectedResult = _resultsTestFixture.getFirstParticipantResult(results); + assertResultsAreInDb(context, expectedResult, runId); + } + + public void testDefaultRunId() throws Exception + { + ResultsDbWriter resultsDbWriter = new ResultsDbWriter(getContext(), null, _clock); + assertEquals("run 1970-01-01 01:00:01.234", resultsDbWriter.getRunId()); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private Context getContext() throws NamingException + { + Context context = mock(Context.class); + Hashtable environment = new Hashtable(); + + environment.put(ResultsDbWriter.DRIVER_NAME, "org.apache.derby.jdbc.EmbeddedDriver"); + environment.put(ResultsDbWriter.URL, "jdbc:derby:" + _tempDbDirectory + "perftestResultsDb;create=true"); + + when(context.getEnvironment()).thenReturn(environment); + return context; + } + + @SuppressWarnings("unchecked") + private void assertResultsAreInDb(Context context, ParticipantResult participantResult, String expectedRunId) throws Exception + { + String driverName = (String) context.getEnvironment().get(ResultsDbWriter.DRIVER_NAME); + Class<? extends Driver> driverClass = (Class<? extends Driver>) Class.forName(driverName); + driverClass.newInstance(); + String url = (String) context.getEnvironment().get(ResultsDbWriter.URL); + + Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery( + "SELECT * FROM results WHERE testName='" + participantResult.getTestName() + + "' AND runId='" + expectedRunId + "'"); + + try + { + rs.next(); + assertEquals(participantResult.getTestName(), rs.getString(TEST_NAME.getDisplayName())); + assertEquals(participantResult.getIterationNumber(), rs.getInt(ITERATION_NUMBER.getDisplayName())); + assertEquals(participantResult.getParticipantName(), rs.getString(PARTICIPANT_NAME.getDisplayName())); + assertEquals(participantResult.getThroughput(), rs.getDouble(THROUGHPUT.getDisplayName())); + assertEquals(expectedRunId, rs.getString(ResultsDbWriter.RUN_ID)); + assertEquals(new Timestamp(_dummyTimestamp), rs.getTimestamp(ResultsDbWriter.INSERTED_TIMESTAMP)); + } + finally + { + connection.close(); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java new file mode 100644 index 0000000000..1edef031bf --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java @@ -0,0 +1,138 @@ +/* + * 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.qpid.disttest.results; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.ACKNOWLEDGE_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.AVERAGE_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.LATENCY_STANDARD_DEVIATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAX_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MESSAGE_THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MIN_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.controller.TestResult; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +public class ResultsTestFixture +{ + public static final double THROUGHPUT_VALUE = 2048.49; + + private static final String TEST1 = "TEST1"; + private static final String PARTICIPANT = "PARTICIPANT"; + private static final String CONFIGURED_CLIENT1 = "CONFIGURED_CLIENT1"; + + public ResultsForAllTests createResultsForAllTests() + { + ParticipantResult participantResult = mock(ParticipantResult.class); + Map<ParticipantAttribute, Object> participantAttributes = getParticipantAttributes(); + + when(participantResult.getAttributes()).thenReturn(participantAttributes); + when(participantResult.getParticipantName()).thenReturn(PARTICIPANT); + when(participantResult.getTestName()).thenReturn(TEST1); + when(participantResult.getIterationNumber()).thenReturn(0); + when(participantResult.getThroughput()).thenReturn(THROUGHPUT_VALUE); + + TestResult testResult = new TestResult(TEST1); + testResult.addParticipantResult(participantResult); + + ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); + resultsForAllTests.add(testResult); + return resultsForAllTests; + } + + private Map<ParticipantAttribute, Object> getParticipantAttributes() + { + Map<ParticipantAttribute, Object> participantAttributes = new HashMap<ParticipantAttribute, Object>(); + + participantAttributes.put(TEST_NAME, TEST1); + participantAttributes.put(ITERATION_NUMBER, 0); + participantAttributes.put(CONFIGURED_CLIENT_NAME, CONFIGURED_CLIENT1); + participantAttributes.put(PARTICIPANT_NAME, PARTICIPANT); + participantAttributes.put(NUMBER_OF_MESSAGES_PROCESSED, 2); + participantAttributes.put(PAYLOAD_SIZE, 1); + participantAttributes.put(PRIORITY, 2); + participantAttributes.put(TIME_TO_LIVE, 3); + participantAttributes.put(ACKNOWLEDGE_MODE, 4); + participantAttributes.put(DELIVERY_MODE, 5); + participantAttributes.put(BATCH_SIZE, 6); + participantAttributes.put(MAXIMUM_DURATION, 7); + participantAttributes.put(PRODUCER_START_DELAY, 8); + participantAttributes.put(PRODUCER_INTERVAL, 9); + participantAttributes.put(IS_TOPIC, true); + participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false); + participantAttributes.put(IS_BROWSING_SUBSCRIPTION, true); + participantAttributes.put(IS_SELECTOR, false); + participantAttributes.put(IS_NO_LOCAL, true); + participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false); + participantAttributes.put(TOTAL_NUMBER_OF_CONSUMERS, 1); + participantAttributes.put(TOTAL_NUMBER_OF_PRODUCERS, 2); + participantAttributes.put(TOTAL_PAYLOAD_PROCESSED, 1024); + participantAttributes.put(THROUGHPUT, THROUGHPUT_VALUE); + participantAttributes.put(TIME_TAKEN, 1000); + participantAttributes.put(ERROR_MESSAGE, "error"); + participantAttributes.put(MIN_LATENCY, 2l); + participantAttributes.put(MAX_LATENCY, 9l); + participantAttributes.put(AVERAGE_LATENCY, 4.6f); + participantAttributes.put(LATENCY_STANDARD_DEVIATION, 2.0f); + participantAttributes.put(MESSAGE_THROUGHPUT, 2); + return participantAttributes; + } + + public ParticipantResult getFirstParticipantResult(ResultsForAllTests results) + { + List<ITestResult> testResults = results.getTestResults(); + ITestResult testResult = testResults.iterator().next(); + List<ParticipantResult> participantResults = testResult.getParticipantResults(); + return participantResults.iterator().next(); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java index 8d598a8095..8d41c8a852 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java @@ -18,68 +18,23 @@ */ package org.apache.qpid.disttest.results.formatting; -import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.*; -import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; -import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; -import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; import junit.framework.TestCase; import org.apache.qpid.disttest.controller.ResultsForAllTests; -import org.apache.qpid.disttest.controller.TestResult; -import org.apache.qpid.disttest.message.ParticipantAttribute; -import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.ResultsTestFixture; public class CSVFormatterTest extends TestCase { - private static final String TEST1 = "TEST1"; - private static final String PARTICIPANT = "PARTICIPANT"; - private static final String CONFIGURED_CLIENT1 = "CONFIGURED_CLIENT1"; - private CSVFormatter _formatter = new CSVFormatter(); public void testResultsFileWithWithOneRow() throws Exception { - ParticipantResult participantResult = mock(ParticipantResult.class); - Map<ParticipantAttribute, Object> participantAttributes = getParticipantAttributes(); - - when(participantResult.getAttributes()).thenReturn(participantAttributes); - when(participantResult.getParticipantName()).thenReturn(PARTICIPANT); - - TestResult testResult = new TestResult(TEST1); - testResult.addParticipantResult(participantResult); - - ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); - resultsForAllTests.add(testResult); + ResultsTestFixture resultsTestFixture = new ResultsTestFixture(); + ResultsForAllTests resultsForAllTests = resultsTestFixture.createResultsForAllTests(); String output = _formatter.format(resultsForAllTests); @@ -88,44 +43,6 @@ public class CSVFormatterTest extends TestCase assertEquals(expectedOutput, output); } - private Map<ParticipantAttribute, Object> getParticipantAttributes() - { - Map<ParticipantAttribute, Object> participantAttributes = new HashMap<ParticipantAttribute, Object>(); - - participantAttributes.put(TEST_NAME, TEST1); - participantAttributes.put(ITERATION_NUMBER, 0); - participantAttributes.put(CONFIGURED_CLIENT_NAME, CONFIGURED_CLIENT1); - participantAttributes.put(PARTICIPANT_NAME, PARTICIPANT); - participantAttributes.put(NUMBER_OF_MESSAGES_PROCESSED, 2); - participantAttributes.put(PAYLOAD_SIZE, 1); - participantAttributes.put(PRIORITY, 2); - participantAttributes.put(TIME_TO_LIVE, 3); - participantAttributes.put(ACKNOWLEDGE_MODE, 4); - participantAttributes.put(DELIVERY_MODE, 5); - participantAttributes.put(BATCH_SIZE, 6); - participantAttributes.put(MAXIMUM_DURATION, 7); - participantAttributes.put(PRODUCER_START_DELAY, 8); - participantAttributes.put(PRODUCER_INTERVAL, 9); - participantAttributes.put(IS_TOPIC, true); - participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false); - participantAttributes.put(IS_BROWSING_SUBSCRIPTION, true); - participantAttributes.put(IS_SELECTOR, false); - participantAttributes.put(IS_NO_LOCAL, true); - participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false); - participantAttributes.put(TOTAL_NUMBER_OF_CONSUMERS, 1); - participantAttributes.put(TOTAL_NUMBER_OF_PRODUCERS, 2); - participantAttributes.put(TOTAL_PAYLOAD_PROCESSED, 1024); - participantAttributes.put(THROUGHPUT, 2048.49); - participantAttributes.put(TIME_TAKEN, 1000); - participantAttributes.put(ERROR_MESSAGE, "error"); - participantAttributes.put(MIN_LATENCY, 2l); - participantAttributes.put(MAX_LATENCY, 9l); - participantAttributes.put(AVERAGE_LATENCY, 4.6f); - participantAttributes.put(LATENCY_STANDARD_DEVIATION, 2.0f); - participantAttributes.put(MESSAGE_THROUGHPUT, 2); - return participantAttributes; - } - private String readCsvOutputFileAsString(String filename) throws Exception { InputStream is = getClass().getResourceAsStream(filename); diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java index 75242e06cc..6076272b6b 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java @@ -20,7 +20,7 @@ package org.apache.qpid.systest.disttest.endtoend; import static org.apache.qpid.disttest.AbstractRunner.JNDI_CONFIG_PROP; import static org.apache.qpid.disttest.ControllerRunner.OUTPUT_DIR_PROP; -import static org.apache.qpid.disttest.ControllerRunner.TEST_CONFIG_PROP; +import static org.apache.qpid.disttest.ControllerRunner.*; import java.io.File; import java.io.IOException; @@ -36,6 +36,7 @@ public class EndToEndTest extends QpidBrokerTestCase private ControllerRunner _runner; private static final String TEST_CONFIG = "perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json"; private static final String JNDI_CONFIG_FILE = "perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties"; + private static final String RUN1 = "run1"; public void testRunner() throws Exception { @@ -44,6 +45,8 @@ public class EndToEndTest extends QpidBrokerTestCase final String[] args = new String[] {TEST_CONFIG_PROP + "=" + TEST_CONFIG, JNDI_CONFIG_PROP + "=" + JNDI_CONFIG_FILE, + WRITE_TO_DB + "=true", + RUN_ID + "=" + RUN1, OUTPUT_DIR_PROP + "=" + csvOutputDir.getAbsolutePath()}; _runner = new ControllerRunner(); _runner.parseArgumentsIntoConfig(args); diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties index b5d053227c..149e632048 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties @@ -24,3 +24,6 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:15672' destination.controllerqueue = direct://amq.direct//controllerqueue + +jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver +jdbcUrl=jdbc:derby:/tmp/tempDbDirectory/perftestResultsDb;create=true diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java index a329f33b00..e1403be397 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java @@ -30,7 +30,7 @@ import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilder; import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilderFactory; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator; -import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcSeriesBuilder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; import org.apache.qpid.disttest.charting.writer.ChartWriter; import org.jfree.chart.JFreeChart; @@ -44,28 +44,46 @@ import org.slf4j.LoggerFactory; * The following arguments are understood: * </p> * <ol> - * <li>chart-defs=<i>directory contain chartdef file(s)</i></li> - * <li>output-dir=<i>directory in which to produce the PNGs</i></li> + * <li>{@link #OUTPUT_DIR_PROP}</li> + * <li>{@link #CHART_DEFINITIONS_PROP}</li> + * <li>{@link #SUMMARY_TITLE_PROP}</li> + * <li>{@link #JDBC_DRIVER_NAME_PROP}</li> + * <li>{@link #JDBC_URL_PROP}</li> * </ol> + * Default values are indicated by the similarly named constants in this class. */ public class ChartingUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ChartingUtil.class); + /** directory in which to produce the PNGs */ public static final String OUTPUT_DIR_PROP = "outputdir"; public static final String OUTPUT_DIR_DEFAULT = "."; + /** the path to the directory containing the chart definition files */ public static final String CHART_DEFINITIONS_PROP = "chart-defs"; public static final String CHART_DEFINITIONS_DEFAULT = "."; public static final String SUMMARY_TITLE_PROP = "summary-title"; public static final String SUMMARY_TITLE_DEFAULT = "Performance Charts"; + /** the class name of the JDBC driver to use for reading the chart data */ + public static final String JDBC_DRIVER_NAME_PROP = "jdbcDriverClass"; + public static final String JDBC_DRIVER_NAME_DEFAULT = JdbcSeriesBuilder.DEFAULT_JDBC_DRIVER_NAME; + + /** the JDBC URL of the data to be charted */ + public static final String JDBC_URL_PROP = "jdbcUrl"; + public static final String JDBC_URL_DEFAULT = JdbcSeriesBuilder.DEFAULT_JDBC_URL; + + private Map<String,String> _cliOptions = new HashMap<String, String>(); + { _cliOptions.put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); _cliOptions.put(CHART_DEFINITIONS_PROP, CHART_DEFINITIONS_DEFAULT); _cliOptions.put(SUMMARY_TITLE_PROP, SUMMARY_TITLE_DEFAULT); + _cliOptions.put(JDBC_DRIVER_NAME_PROP, JDBC_DRIVER_NAME_DEFAULT); + _cliOptions.put(JDBC_URL_PROP, JDBC_URL_DEFAULT); } public static void main(String[] args) throws Exception @@ -86,21 +104,20 @@ public class ChartingUtil private void produceAllCharts() { - final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); - final File chartDirectory = new File(_cliOptions.get(OUTPUT_DIR_PROP)); - LOGGER.info("Chart chartdef directory/file: {} output directory : {}", chartingDefsDir, chartDirectory); - - List<ChartingDefinition> definitions = loadChartDefinitions(chartingDefsDir); - - LOGGER.info("There are {} chart(s) to produce", definitions.size()); final ChartWriter writer = new ChartWriter(); - writer.setOutputDirectory(chartDirectory); + writer.setOutputDirectory(new File(_cliOptions.get(OUTPUT_DIR_PROP))); + + SeriesBuilder seriesBuilder = new JdbcSeriesBuilder( + _cliOptions.get(JDBC_DRIVER_NAME_PROP), + _cliOptions.get(JDBC_URL_PROP)); - final SeriesBuilder seriesBuilder = new JdbcCsvSeriesBuilder(); - for (ChartingDefinition chartingDefinition : definitions) + for (ChartingDefinition chartingDefinition : loadChartDefinitions()) { - ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType(), seriesBuilder); + ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder( + chartingDefinition.getChartType(), + seriesBuilder); + JFreeChart chart = chartBuilder.buildChart(chartingDefinition); writer.writeChartToFileSystem(chart, chartingDefinition); } @@ -109,6 +126,18 @@ public class ChartingUtil writer.writeHtmlSummaryToFileSystem(summaryChartTitle); } + private List<ChartingDefinition> loadChartDefinitions() + { + final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); + + LOGGER.info("Chart chartdef directory/file: {}", chartingDefsDir); + + List<ChartingDefinition> definitions = loadChartDefinitions(chartingDefsDir); + + LOGGER.info("There are {} chart(s) to produce", definitions.size()); + return definitions; + } + private List<ChartingDefinition> loadChartDefinitions(String chartingDefsDir) { ChartingDefinitionCreator chartingDefinitionLoader = new ChartingDefinitionCreator(); diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java index ba027d9d93..ffa85d5c50 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java @@ -27,6 +27,7 @@ import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.data.category.DefaultCategoryDataset; @@ -52,11 +53,11 @@ public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() { @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - String x = String.valueOf(row[0]); - double y = Double.parseDouble(row[1].toString()); - dataset.addValue( y, seriesDefinition.getSeriesLegend(), x); + String x = row.dimensionAsString(0); + double y = row.dimensionAsDouble(1); + dataset.addValue(y, seriesDefinition.getSeriesLegend(), x); } @Override @@ -71,6 +72,12 @@ public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder // unused } + @Override + public int getNumberOfDimensions() + { + return 2; + } + }); _seriesBuilder.build(chartingDefinition.getSeries()); diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java index 1669ee1bb2..61acc8cfdf 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java @@ -28,6 +28,7 @@ import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; @@ -62,11 +63,11 @@ public class StatisticalBarCharBuilder extends BaseChartBuilder _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() { @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - String x = String.valueOf(row[0]); - double mean = Double.parseDouble(row[1].toString()); - double stdDev = Double.parseDouble(row[2].toString()); + String x = row.dimensionAsString(0); + double mean = row.dimensionAsDouble(1); + double stdDev = row.dimensionAsDouble(2); dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x); } @@ -82,6 +83,12 @@ public class StatisticalBarCharBuilder extends BaseChartBuilder // unused } + @Override + public int getNumberOfDimensions() + { + return 3; + } + }); _seriesBuilder.build(chartingDefinition.getSeries()); diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java index 168794be50..46b6ac6fab 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java @@ -29,6 +29,7 @@ import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.data.xy.DefaultXYDataset; @@ -61,11 +62,10 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder } @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, - Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - double x = Double.parseDouble(row[0].toString()); - double y = Double.parseDouble(row[1].toString()); + double x = row.dimensionAsDouble(0); + double y = row.dimensionAsDouble(1); _xyPairs.add(new Double[] {x, y}); } @@ -77,6 +77,12 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData); } + @Override + public int getNumberOfDimensions() + { + return 2; + } + private double[][] listToSeriesDataArray() { double[][] seriesData = new double[2][_xyPairs.size()]; diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java index a9adce0afc..2cd8d9951f 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java @@ -19,7 +19,6 @@ */ package org.apache.qpid.disttest.charting.seriesbuilder; -import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -28,19 +27,35 @@ import java.sql.Statement; import java.util.Iterator; import java.util.List; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; import org.apache.qpid.disttest.charting.ChartingException; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class JdbcCsvSeriesBuilder implements SeriesBuilder +/** + * A {@link SeriesBuilder} that uses JDBC to read series data + */ +public class JdbcSeriesBuilder implements SeriesBuilder { + private static final Logger LOGGER = LoggerFactory.getLogger(JdbcSeriesBuilder.class); - static - { - registerCsvDriver(); - } + public static final String DEFAULT_JDBC_DRIVER_NAME = "org.relique.jdbc.csv.CsvDriver"; + + /** the dot at the end denotes the current directory */ + public static final String DEFAULT_JDBC_URL = "jdbc:relique:csv:."; + private final String _jdbcUrl; private SeriesBuilderCallback _callback; + public JdbcSeriesBuilder(String jdbcDriverClass, String jdbcUrl) + { + registerDriver(jdbcDriverClass); + _jdbcUrl = jdbcUrl; + LOGGER.info("Created: " + this); + } + @Override public void setSeriesBuilderCallback(SeriesBuilderCallback callback) { @@ -63,9 +78,7 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder Statement stmt = null; try { - File seriesDir = getValidatedSeriesDirectory(seriesDefinition); - - conn = DriverManager.getConnection("jdbc:relique:csv:" + seriesDir.getAbsolutePath()); + conn = DriverManager.getConnection(_jdbcUrl); final String seriesStatement = seriesDefinition.getSeriesStatement(); @@ -81,7 +94,8 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder row[i] = results.getObject(i+1); } - _callback.addDataPointToSeries(seriesDefinition, row); + SeriesRow seriesRow = SeriesRow.createValidSeriesRow(_callback.getNumberOfDimensions(), row); + _callback.addDataPointToSeries(seriesDefinition, seriesRow); } _callback.endSeries(seriesDefinition); } @@ -116,26 +130,22 @@ public class JdbcCsvSeriesBuilder implements SeriesBuilder } } - private File getValidatedSeriesDirectory(SeriesDefinition series) - { - File seriesDir = new File(series.getSeriesDirectory()); - if (!seriesDir.isDirectory()) - { - throw new ChartingException("seriesDirectory must be a directory : " + seriesDir); - } - return seriesDir; - } - - private static void registerCsvDriver() throws ExceptionInInitializerError + private void registerDriver(String driverClassName) throws ExceptionInInitializerError { try { - Class.forName("org.relique.jdbc.csv.CsvDriver"); + Class.forName(driverClassName); + LOGGER.info("Loaded JDBC driver class " + driverClassName); } catch (ClassNotFoundException e) { - throw new RuntimeException("Could not load CSV/JDBC driver", e); + throw new RuntimeException("Could not load JDBC driver " + driverClassName, e); } } + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("jdbcUrl", _jdbcUrl).toString(); + } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java index 86e471efaf..0dfba304a9 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java @@ -25,8 +25,15 @@ import org.apache.qpid.disttest.charting.definition.SeriesDefinition; public interface SeriesBuilder { + /** + * Uses the supplied {@link SeriesDefinition}s to read the series data + * and pass it to the callback set up in {@link #setSeriesBuilderCallback(SeriesBuilderCallback)}. + */ void build(List<SeriesDefinition> seriesDefinitions); + /** + * Stores the supplied callback so it can be used in {@link #build(List)}. + */ void setSeriesBuilderCallback(SeriesBuilderCallback seriesBuilderCallback); }
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java index 7e23953fdb..c9c35d26b4 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java @@ -24,7 +24,8 @@ import org.apache.qpid.disttest.charting.definition.SeriesDefinition; public interface SeriesBuilderCallback { public void beginSeries(SeriesDefinition seriesDefinition); - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row); - public void endSeries(SeriesDefinition seriesDefinition); + public int getNumberOfDimensions(); + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row); + public void endSeries(SeriesDefinition seriesDefinition); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java new file mode 100644 index 0000000000..6c87b88c45 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java @@ -0,0 +1,92 @@ +/* + * 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.qpid.disttest.charting.seriesbuilder; + +import java.util.Arrays; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * A data point in a chart. Thinly wraps an array to provide a convenient place to validate the number of dimensions, + * and to access dimensions in a typesafe manner. + */ +public class SeriesRow +{ + private final Object[] _dimensions; + + public static SeriesRow createValidSeriesRow(int expectedNumberOfDimensions, Object[] dimensions) + { + int actualNumberOfDimensions = dimensions.length; + if(expectedNumberOfDimensions != actualNumberOfDimensions) + { + throw new IllegalArgumentException("Expected " + expectedNumberOfDimensions + + " dimensions but found " + actualNumberOfDimensions + + " in: " + Arrays.asList(dimensions)); + } + return new SeriesRow(dimensions); + } + + public SeriesRow(Object... dimensions) + { + _dimensions = dimensions; + } + + public Object dimension(int dimension) + { + return _dimensions[dimension]; + } + + public String dimensionAsString(int dimension) + { + return String.valueOf(dimension(dimension)); + } + + public double dimensionAsDouble(int dimension) + { + return Double.parseDouble(dimensionAsString(dimension)); + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(_dimensions).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + SeriesRow rhs = (SeriesRow) obj; + return new EqualsBuilder().append(_dimensions, rhs._dimensions).isEquals(); + } + + +}
\ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java index 888d7dc3d7..341f01ccd1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java @@ -153,5 +153,6 @@ public class ChartWriter public void setOutputDirectory(final File chartDirectory) { _chartDirectory = chartDirectory; + LOGGER.info("Set chart directory: {}", chartDirectory); } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java index 96ec917932..fe9cb2aefe 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java @@ -31,6 +31,7 @@ import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.apache.qpid.disttest.charting.writer.ChartWriter; import org.apache.qpid.test.utils.TestFileUtils; import org.jfree.chart.JFreeChart; @@ -143,11 +144,11 @@ public class ChartProductionTest extends TestCase { SeriesDefinition seriesDefinition = iterator.next(); _dataPointCallback.beginSeries(seriesDefinition); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d, 0.5d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d, 0.4d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d, 0.3d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d, 0.2d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d, 0.1d}); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(1d, 1d, 0.5d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(2d, 2d, 0.4d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(4d, 4d, 0.3d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(5d, 5d, 0.2d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(6d, 3d, 0.1d)); _dataPointCallback.endSeries(seriesDefinition); } } @@ -192,11 +193,11 @@ public class ChartProductionTest extends TestCase { SeriesDefinition seriesDefinition = iterator.next(); _dataPointCallback.beginSeries(seriesDefinition); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d}); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(1d, 1d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(2d, 2d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(4d, 4d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(5d, 5d)); + _dataPointCallback.addDataPointToSeries(seriesDefinition, new SeriesRow(6d, 3d)); _dataPointCallback.endSeries(seriesDefinition); } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java index dfe35ee199..bd66e8e888 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java @@ -21,6 +21,7 @@ package org.apache.qpid.disttest.charting.seriesbuilder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.BufferedWriter; import java.io.File; @@ -31,9 +32,9 @@ import java.util.Collections; import junit.framework.TestCase; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcSeriesBuilder; -public class JdbcCsvSeriesBuilderTest extends TestCase +public class JdbcSeriesBuilderTest extends TestCase { private static final String TEST_SERIES_1_SELECT_STATEMENT = "SELECT A, B FROM test"; private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; @@ -41,7 +42,6 @@ public class JdbcCsvSeriesBuilderTest extends TestCase private static final Integer TEST_SERIES1_STROKE_WIDTH = 3; private SeriesBuilderCallback _seriesWalkerCallback = mock(SeriesBuilderCallback.class); - private JdbcCsvSeriesBuilder _seriesBuilder = new JdbcCsvSeriesBuilder(); private File _testTempDir; @@ -49,21 +49,27 @@ public class JdbcCsvSeriesBuilderTest extends TestCase protected void setUp() throws Exception { super.setUp(); - _seriesBuilder.setSeriesBuilderCallback(_seriesWalkerCallback); + when(_seriesWalkerCallback.getNumberOfDimensions()).thenReturn(2); _testTempDir = createTestTemporaryDirectory(); + createTestCsvIn(_testTempDir); } public void testBuildOneSeries() throws Exception { - createTestCsvIn(_testTempDir); SeriesDefinition seriesDefinition = createTestSeriesDefinition(); - _seriesBuilder.build(Collections.singletonList(seriesDefinition)); + JdbcSeriesBuilder seriesBuilder = new JdbcSeriesBuilder( + "org.relique.jdbc.csv.CsvDriver", + "jdbc:relique:csv:" + _testTempDir.getAbsolutePath()); + + seriesBuilder.setSeriesBuilderCallback(_seriesWalkerCallback); + + seriesBuilder.build(Collections.singletonList(seriesDefinition)); verify(_seriesWalkerCallback).beginSeries(seriesDefinition); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"elephant", "2"}); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"lion", "3"}); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"tiger", "4"}); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("elephant", "2")); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("lion", "3")); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("tiger", "4")); verify(_seriesWalkerCallback).endSeries(seriesDefinition); } @@ -81,7 +87,12 @@ public class JdbcCsvSeriesBuilderTest extends TestCase private SeriesDefinition createTestSeriesDefinition() { - SeriesDefinition definition = new SeriesDefinition(TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, _testTempDir.getAbsolutePath(), TEST_SERIES1_COLOUR_NAME, TEST_SERIES1_STROKE_WIDTH); + SeriesDefinition definition = new SeriesDefinition( + TEST_SERIES_1_SELECT_STATEMENT, + TEST_SERIES_1_LEGEND, + _testTempDir.getAbsolutePath(), + TEST_SERIES1_COLOUR_NAME, + TEST_SERIES1_STROKE_WIDTH); return definition; } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java new file mode 100644 index 0000000000..645d443f13 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java @@ -0,0 +1,64 @@ +/* + * 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.qpid.disttest.charting.seriesbuilder; + +import junit.framework.TestCase; + +public class SeriesRowTest extends TestCase +{ + private static final Integer[] PAIR = new Integer[] {10, 11}; + + public void testValidSeriesRow() + { + assertEquals(11, SeriesRow.createValidSeriesRow(2, PAIR).dimension(1)); + } + + public void testValidSeriesRowThrowsExceptionIfArrayTooSmall() + { + try + { + SeriesRow.createValidSeriesRow(1, PAIR); + fail("Expected exception not thrown"); + } + catch(IllegalArgumentException e) + { + // pass + } + } + + public void testDimension() + { + SeriesRow seriesRow = new SeriesRow(10, 11); + assertEquals(10, seriesRow.dimension(0)); + assertEquals(11, seriesRow.dimension(1)); + } + + public void testDimensionAsString() + { + SeriesRow seriesRow = new SeriesRow(10); + assertEquals("10", seriesRow.dimensionAsString(0)); + } + + public void testDimensionAsDouble() + { + SeriesRow seriesRow = new SeriesRow(10.1); + assertEquals(10.1, seriesRow.dimensionAsDouble(0), 0.0); + } + +} |
