abdullah alamoudi has uploaded a new change for review.
https://asterix-gerrit.ics.uci.edu/2438
Change subject: [NO ISSUE][TEST] Introduce dynamic expected result poll test
type
......................................................................
[NO ISSUE][TEST] Introduce dynamic expected result poll test type
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- This change allows for a new type of tests. The new test can
poll for both expected results and a query and compare the two
values.
- A test case is added.
Change-Id: Ifc132b2d2286eea1d1e119984c33ca5eef9be92a
---
A
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IExpectedResultPoller.java
M
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/poll-dynamic/poll-dynamic.1.polldynamic.sqlpp
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
4 files changed, 167 insertions(+), 3 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/38/2438/1
diff --git
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IExpectedResultPoller.java
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IExpectedResultPoller.java
new file mode 100644
index 0000000..5d7be49
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/IExpectedResultPoller.java
@@ -0,0 +1,9 @@
+package org.apache.asterix.test.common;
+
+@FunctionalInterface
+public interface IExpectedResultPoller {
+ /**
+ * @return the expected result as a string
+ */
+ String poll();
+}
diff --git
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index e39a9f3..f53628d 100644
---
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -460,6 +460,20 @@
}
}
+ private static void writeOutputToFile(File actualFile, String result)
throws Exception {
+ final File parentDir = actualFile.getParentFile();
+ if (!parentDir.isDirectory()) {
+ if (parentDir.exists()) {
+ LOGGER.warn("Actual file parent \"" + parentDir + "\" exists
but is not a directory");
+ } else if (!parentDir.mkdirs()) {
+ LOGGER.warn("Unable to create actual file parent dir: " +
parentDir);
+ }
+ }
+ try (FileOutputStream out = new FileOutputStream(actualFile)) {
+ out.write(result.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
protected HttpResponse executeAndCheckHttpRequest(HttpUriRequest method)
throws Exception {
return checkResponse(executeHttpRequest(method), code -> code ==
HttpStatus.SC_OK);
}
@@ -888,6 +902,10 @@
poll(testCaseCtx, ctx, variableCtx, statement,
isDmlRecoveryTest, pb, cUnit, queryCount,
expectedResultFileCtxs, testFile, actualPath);
break;
+ case "polldynamic":
+ polldynamic(testCaseCtx, ctx, variableCtx, statement,
isDmlRecoveryTest, pb, cUnit, queryCount,
+ expectedResultFileCtxs, testFile, actualPath);
+ break;
case "query":
case "async":
case "deferred":
@@ -1003,7 +1021,7 @@
ctx.extension(), cUnit.getOutputDir().getCompare());
break;
case "server": // (start <test server name> <port>
- // [<arg1>][<arg2>][<arg3>]...|stop
(<port>|all))
+ // [<arg1>][<arg2>][<arg3>]...|stop (<port>|all))
try {
lines = statement.trim().split("\n");
String[] command = lines[lines.length - 1].trim().split("
");
@@ -1051,7 +1069,7 @@
}
break;
case "lib": // expected format <dataverse-name> <library-name>
- // <library-directory>
+ // <library-directory>
// TODO: make this case work well with entity names
containing spaces by
// looking for \"
lines = statement.split("\n");
@@ -1259,6 +1277,117 @@
actualResultFile.getParentFile().delete();
}
+ private void polldynamic(TestCaseContext testCaseCtx, TestFileContext ctx,
Map<String, Object> variableCtx,
+ String statement, boolean isDmlRecoveryTest, ProcessBuilder pb,
CompilationUnit cUnit,
+ MutableInt queryCount, List<TestFileContext>
expectedResultFileCtxs, File testFile, String actualPath)
+ throws Exception {
+ IExpectedResultPoller poller = getExpectedResultPoller(statement);
+ final String key = getKey(statement);
+ int timeoutSecs = getTimeoutSecs(statement);
+ int retryDelaySecs = getRetryDelaySecs(statement);
+ long startTime = System.currentTimeMillis();
+ long limitTime = startTime + TimeUnit.SECONDS.toMillis(timeoutSecs);
+ ctx.setType("validate");
+ try {
+ boolean expectedException = false;
+ Exception finalException = null;
+ LOGGER.debug("polling for up to " + timeoutSecs + " seconds w/ " +
retryDelaySecs + " second(s) delay");
+ int responsesReceived = 0;
+ final ExecutorService executorService =
Executors.newSingleThreadExecutor();
+ while (true) {
+ try {
+ Future<Void> execution = executorService.submit(() -> {
+ File actualResultFile = new File(actualPath,
testCaseCtx.getTestCase().getFilePath()
+ + File.separatorChar + cUnit.getName() + '.' +
ctx.getSeqNum() + ".polled.adm");
+ if (actualResultFile.exists() &&
!actualResultFile.delete()) {
+ throw new Exception(
+ "Failed to delete an existing result file:
" + actualResultFile.getAbsolutePath());
+ }
+ writeOutputToFile(actualResultFile, poller.poll());
+ variableCtx.put(key, actualResultFile);
+ actualResultFile = new File(actualPath,
testCaseCtx.getTestCase().getFilePath()
+ + File.separatorChar + cUnit.getName() + '.' +
ctx.getSeqNum() + ".adm");
+ executeTestFile(testCaseCtx, ctx, variableCtx,
statement, isDmlRecoveryTest, pb, cUnit,
+ queryCount, expectedResultFileCtxs, testFile,
actualPath);
+ return null;
+ });
+ execution.get(limitTime - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
+ responsesReceived++;
+ finalException = null;
+ break;
+ } catch (TimeoutException e) {
+ if (responsesReceived == 0) {
+ throw new Exception("Poll limit (" + timeoutSecs
+ + "s) exceeded without obtaining *any* result
from server");
+ } else if (finalException != null) {
+ throw new Exception(
+ "Poll limit (" + timeoutSecs
+ + "s) exceeded without obtaining
expected result; last exception:",
+ finalException);
+ } else {
+ throw new Exception(
+ "Poll limit (" + timeoutSecs + "s) exceeded
without obtaining expected result");
+
+ }
+ } catch (ExecutionException ee) {
+ Exception e;
+ if (ee.getCause() instanceof Exception) {
+ e = (Exception) ee.getCause();
+ } else {
+ e = ee;
+ }
+ if (e instanceof ComparisonException) {
+ LOGGER.info("Comparison failure on poll: {}",
e::getMessage);
+ } else if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Received exception on poll", e);
+ } else {
+ LOGGER.info("Received exception on poll: {}",
e::toString);
+ }
+ responsesReceived++;
+ if (isExpected(e, cUnit)) {
+ expectedException = true;
+ finalException = e;
+ break;
+ }
+ if ((System.currentTimeMillis() > limitTime)) {
+ finalException = e;
+ break;
+ }
+ LOGGER.debug("sleeping " + retryDelaySecs + " second(s)
before polling again");
+ TimeUnit.SECONDS.sleep(retryDelaySecs);
+ }
+ }
+ if (expectedException) {
+ throw finalException;
+ } else if (finalException != null) {
+ throw new Exception("Poll limit (" + timeoutSecs + "s)
exceeded without obtaining expected result",
+ finalException);
+ }
+ } finally {
+ ctx.setType("polldynamic");
+ }
+ }
+
+ protected IExpectedResultPoller getExpectedResultPoller(String statement) {
+ String key = "poller=";
+ String value = null;
+ String[] lines = statement.split("\n");
+ for (String line : lines) {
+ if (line.contains(key)) {
+ value = line.substring(line.indexOf(key) +
key.length()).trim();
+ }
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("ERROR: poller=<...> must be
present in poll-dynamic file");
+ }
+ String staticPoller = "static:";
+ if (value.startsWith(staticPoller)) {
+ String polled = value.substring(staticPoller.length());
+ return () -> polled;
+ }
+ throw new IllegalArgumentException("ERROR: unknown poller: " + value);
+ }
+
private void poll(TestCaseContext testCaseCtx, TestFileContext ctx,
Map<String, Object> variableCtx,
String statement, boolean isDmlRecoveryTest, ProcessBuilder pb,
CompilationUnit cUnit,
MutableInt queryCount, List<TestFileContext>
expectedResultFileCtxs, File testFile, String actualPath)
@@ -1338,7 +1467,6 @@
} finally {
ctx.setType("poll" + ctx.getType());
}
-
}
public InputStream executeSqlppUpdateOrDdl(String statement, OutputFormat
outputFormat) throws Exception {
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/poll-dynamic/poll-dynamic.1.polldynamic.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/poll-dynamic/poll-dynamic.1.polldynamic.sqlpp
new file mode 100644
index 0000000..e8dc9e8
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/poll-dynamic/poll-dynamic.1.polldynamic.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+-- key=aKey
+-- poller=static:{ "one": 1 }
+-- polltimeoutsecs=120
+select 1 as one;
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 4265163..cf01567 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -3538,6 +3538,11 @@
</test-group>
<test-group name="misc">
<test-case FilePath="misc">
+ <compilation-unit name="poll-dynamic">
+ <output-dir compare="Text">poll-dynamic</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="misc">
<compilation-unit name="validate-expected">
<output-dir compare="Text">validate-expected</output-dir>
</compilation-unit>
--
To view, visit https://asterix-gerrit.ics.uci.edu/2438
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifc132b2d2286eea1d1e119984c33ca5eef9be92a
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: abdullah alamoudi <[email protected]>