Skip to content

Commit 1d3c515

Browse files
author
Robert Hou
committed
Added a new failure type, ORDERBY_FAILURE, which occurs if a SQL statement has
an order-by clause that cannot be validated by the Test Framework. Please see the README.md file for information on how to construct a SQL statement with an order-by clause that can be validated by the Test Framework. Added a new verification method, "text", which checks if the actual output and expected output are exactly the same, byte by byte. It verifies content as well as order. Every row that is returned must be returned in the same order as in the expected output. Added a whitelist file for orderby tests. Tests that are listed in this file are SQL statements with an order-by clause. The order-by clause cannot be validated. Instead of marking these tests as failed, they are PASSED until they can be fixed in the future. There are 302 tests that are currently failing at the time of this commit. They will need to be fixed at some piont in the future.
1 parent 3549fae commit 1d3c515

File tree

6 files changed

+123
-20
lines changed

6 files changed

+123
-20
lines changed

framework/src/main/java/org/apache/drill/test/framework/DrillTestJdbc.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.drill.test.framework.TestCaseModeler.TestMatrix;
2323
import org.apache.drill.test.framework.TestVerifier.TestStatus;
2424
import org.apache.drill.test.framework.TestVerifier.VerificationException;
25+
import org.apache.drill.test.framework.TestVerifier.OrderbyException;
2526
import org.apache.log4j.Logger;
2627

2728
import java.io.BufferedWriter;
@@ -103,9 +104,17 @@ public void run() {
103104
testVerifier = new TestVerifier(columnTypes, query, columnLabels, matrix.verificationTypes);
104105
if (query.startsWith("explain") || matrix.verificationTypes.get(0).equalsIgnoreCase("regex") ||
105106
matrix.verificationTypes.get(0).equalsIgnoreCase("regex-no-order") ||
107+
// for explain plans where the patterns may match in a different order than
108+
// specified in the expected results file
106109
matrix.verificationTypes.get(0).equalsIgnoreCase("filter-ratio")) {
110+
// special verification method for statistics feature implemented in
111+
// Drill 1.9 where two steps in the explain plan have to be
112+
// evaluated together
107113
setTestStatus(testVerifier.verifyTextPlan(modeler.expectedFilename, outputFilename));
114+
} else if (matrix.verificationTypes.get(0).equalsIgnoreCase("text") ) {
115+
setTestStatus(testVerifier.verifyText(modeler.expectedFilename, outputFilename));
108116
} else {
117+
// "in-memory"
109118
setTestStatus(testVerifier.verifyResultSet(modeler.expectedFilename, outputFilename));
110119
}
111120

@@ -115,6 +124,16 @@ public void run() {
115124
}
116125
} catch (VerificationException e) {
117126
fail(TestStatus.VERIFICATION_FAILURE, e);
127+
} catch (OrderbyException e) {
128+
// check if test is white-listed, in which case the orderby clause is not validated
129+
if (!Utils.isOrderbyWhitelist(modeler.queryFilename)) {
130+
// test is not white-listed, so the orderby clause needs to be validated
131+
fail(TestStatus.ORDERBY_FAILURE, e);
132+
} else {
133+
// test is white-listed, so the orderby clause is not validated, and is skipped
134+
// pass the test for now until the orderby clause can be validated
135+
setTestStatus(TestStatus.PASS);
136+
}
118137
} catch (Exception e) {
119138
fail(TestStatus.EXECUTION_FAILURE, e);
120139
} finally {

framework/src/main/java/org/apache/drill/test/framework/DrillTestOdbc.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.drill.test.framework.TestCaseModeler.TestMatrix;
2323
import org.apache.drill.test.framework.TestVerifier.TestStatus;
2424
import org.apache.drill.test.framework.TestVerifier.VerificationException;
25+
import org.apache.drill.test.framework.TestVerifier.OrderbyException;
2526
import org.apache.log4j.Logger;
2627

2728
import java.io.BufferedWriter;
@@ -84,6 +85,8 @@ public void run() {
8485
setTestStatus(testVerifier.verifyResultSet(modeler.expectedFilename, outputFilename));
8586
} catch (VerificationException e) {
8687
fail(TestStatus.VERIFICATION_FAILURE, e);
88+
} catch (OrderbyException e) {
89+
fail(TestStatus.ORDERBY_FAILURE, e);
8790
};
8891
break;
8992
case 1:
@@ -100,6 +103,8 @@ public void run() {
100103
break;
101104
case 5:
102105
setTestStatus(TestStatus.CANCELED);
106+
case 6:
107+
setTestStatus(TestStatus.ORDERBY_FAILURE);
103108
default:
104109
setTestStatus(TestStatus.EXECUTION_FAILURE);
105110
}

framework/src/main/java/org/apache/drill/test/framework/DrillTestScript.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ public void run() {
9898
break;
9999
case 5:
100100
setTestStatus(TestStatus.CANCELED);
101+
case 6:
102+
setTestStatus(TestStatus.ORDERBY_FAILURE);
101103
default:
102104
setTestStatus(TestStatus.EXECUTION_FAILURE);
103105
}

framework/src/main/java/org/apache/drill/test/framework/TestDriver.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public class TestDriver {
6868
private String version;
6969
private long [][] memUsage = new long[2][3];
7070
private String memUsageFilename = null;
71+
private static String orderbyWhitelistFile = drillProperties.get("DRILL_ORDERBY_WHITELIST_FILE");
72+
public static Set<String> orderbyWhitelist = null;
7173

7274
private static Configuration conf = new Configuration();
7375
public static final Options OPTIONS = new Options();
@@ -207,7 +209,8 @@ public void generateReports(List<DrillTest> tests, int iteration) {
207209
}
208210
document.set("query", query);
209211
document.set("status", test.getTestStatus().toString());
210-
if(test.getTestStatus().equals(TestStatus.EXECUTION_FAILURE) || test.getTestStatus().equals(TestStatus.VERIFICATION_FAILURE)) {
212+
if(test.getTestStatus().equals(TestStatus.EXECUTION_FAILURE) || test.getTestStatus().equals(TestStatus.VERIFICATION_FAILURE) ||
213+
test.getTestStatus().equals(TestStatus.ORDERBY_FAILURE)) {
211214
document.set("errorMessage", test.getException().toString().replaceAll("\n",""));
212215
}else{
213216
document.set("errorMessage", "N/A");
@@ -287,6 +290,7 @@ public int runTests() throws Exception {
287290
int totalVerificationFailure = 0;
288291
int totalCanceledTest = 0;
289292
int totalTimeoutFailure = 0;
293+
int totalOrderbyFailure = 0;
290294
int i = 0;
291295
LOG.info("> TOOK " + stopwatch + " TO SETUP.");
292296

@@ -316,6 +320,7 @@ public int runTests() throws Exception {
316320
List<DrillTest> executionFailures = Lists.newArrayList();
317321
List<DrillTest> timeoutFailures = Lists.newArrayList();
318322
List<DrillTest> canceledTests = Lists.newArrayList();
323+
List<DrillTest> orderbyFailures = Lists.newArrayList();
319324

320325
for (DrillTest test : tests) {
321326
TestStatus testStatus = test.getTestStatus();
@@ -335,6 +340,9 @@ public int runTests() throws Exception {
335340
case CANCELED:
336341
canceledTests.add(test);
337342
break;
343+
case ORDERBY_FAILURE:
344+
orderbyFailures.add(test);
345+
break;
338346
default:
339347
executionFailures.add(test);
340348
}
@@ -361,6 +369,12 @@ public int runTests() throws Exception {
361369
LOG.info("Query: \n" + test.getQuery());
362370
LOG.info(test.getException().getMessage());
363371
}
372+
LOG.info("Orderby Failures:");
373+
for (DrillTest test : orderbyFailures) {
374+
LOG.info(test.getInputFile());
375+
LOG.info("Query: \n" + test.getQuery());
376+
LOG.info(test.getException().getMessage());
377+
}
364378
LOG.info("Timeout Failures:");
365379
for (DrillTest test : timeoutFailures) {
366380
LOG.info(test.getInputFile());
@@ -377,14 +391,18 @@ public int runTests() throws Exception {
377391
for (DrillTest test : verificationFailures) {
378392
LOG.info(test.getInputFile());
379393
}
394+
LOG.info("Orderby Failures:");
395+
for (DrillTest test : orderbyFailures) {
396+
LOG.info(test.getInputFile());
397+
}
380398
LOG.info("Timeout Failures:");
381399
for (DrillTest test : timeoutFailures) {
382400
LOG.info(test.getInputFile());
383401
}
384402
LOG.info(LINE_BREAK);
385-
LOG.info(String.format("\nPassing tests: %d\nExecution Failures: %d\nVerificationFailures: %d" +
386-
"\nTimeouts: %d\nCanceled: %d", passingTests.size(), executionFailures.size(),
387-
verificationFailures.size(), timeoutFailures.size(), canceledTests.size()));
403+
LOG.info(String.format("\nPassing tests: %d\nExecution Failures: %d\nVerification Failures: %d" +
404+
"\nTimeouts: %d\nCanceled: %d\nOrderby Failures: %d", passingTests.size(), executionFailures.size(),
405+
verificationFailures.size(), timeoutFailures.size(), canceledTests.size(), orderbyFailures.size()));
388406

389407
if (OPTIONS.trackMemory) {
390408
LOG.info(LINE_BREAK);
@@ -398,26 +416,33 @@ public int runTests() throws Exception {
398416
totalVerificationFailure += verificationFailures.size();
399417
totalTimeoutFailure += timeoutFailures.size();
400418
totalCanceledTest += canceledTests.size();
419+
totalOrderbyFailure += orderbyFailures.size();
401420
}
402421

403422
if (i > 2) {
404423
LOG.info(LINE_BREAK);
405-
LOG.info(String.format("\nCompleted %d iterations.\n Passing tests: %d\n Execution Failures: %d\n VerificationFailures: %d" +
406-
"\n Timeouts: %d\n Canceled: %d", i-1, totalPassingTest, totalExecutionFailure,
407-
totalVerificationFailure, totalTimeoutFailure, totalCanceledTest));
424+
LOG.info(String.format("\nCompleted %d iterations.\n Passing tests: %d\n Execution Failures: %d\n Verification Failures: %d" +
425+
"\n Timeouts: %d\n Canceled: %d\n Orderby Failures: %d", i-1, totalPassingTest, totalExecutionFailure,
426+
totalVerificationFailure, totalTimeoutFailure, totalCanceledTest, totalOrderbyFailure));
408427
LOG.info("\n> TEARING DOWN..");
409428
}
410429
teardown();
411430
executor.close();
412431
connectionPool.close();
413432

414-
return totalExecutionFailure + totalVerificationFailure + totalTimeoutFailure;
433+
return totalExecutionFailure + totalVerificationFailure + totalTimeoutFailure + totalOrderbyFailure;
415434
}
416435

417436
public void setup() throws IOException, InterruptedException {
418437
if (!new File(drillOutputDirName).exists()) {
419438
new File(drillOutputDirName).mkdir();
420439
}
440+
// Load orderby white-list file. These tests have orderby clauses
441+
// that cannot be validated. Validation of the orderby clause will be
442+
// skipped for now.
443+
if (new File(orderbyWhitelistFile).exists()) {
444+
orderbyWhitelist = Utils.readOrderbyWhitelistFile(orderbyWhitelistFile);
445+
}
421446

422447
String templatePath = CWD + "/conf/plugin-templates/";
423448
LOG.info(templatePath);

framework/src/main/java/org/apache/drill/test/framework/TestVerifier.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,17 @@ public class TestVerifier {
6262

6363
public enum TestStatus {
6464
PENDING, RUNNING, PASS, EXECUTION_FAILURE, VERIFICATION_FAILURE, ORDER_MISMATCH, TIMEOUT,
65-
CANCELED
65+
CANCELED, ORDERBY_FAILURE
6666
};
6767

6868
public TestVerifier(List<Integer> types, String query, List<String> columnLabels, List<String> verificationType) {
6969
this.types = types;
7070
this.query = query;
7171
this.columnLabels = columnLabels;
7272
this.verificationTypes = verificationType;
73+
if (verificationType.get(0).equalsIgnoreCase("text")) {
74+
this.checkType = false;
75+
}
7376
}
7477

7578
public TestVerifier() {
@@ -90,7 +93,7 @@ public TestVerifier() {
9093
*/
9194
public TestStatus verifySqllineResult(String expectedOutput,
9295
String actualOutput, boolean verifyOrderBy) throws IOException, VerificationException,
93-
IllegalAccessException {
96+
IllegalAccessException, OrderbyException {
9497
String cleanedUpFile = cleanUpSqllineOutputFile(actualOutput);
9598
return verifyResultSet(expectedOutput, cleanedUpFile, verifyOrderBy);
9699
}
@@ -128,7 +131,7 @@ private String cleanUpSqllineOutputFile(String actualOutput) throws IOException
128131
* @throws Exception
129132
*/
130133
public TestStatus verifyResultSet(String expectedOutput, String actualOutput)
131-
throws IllegalAccessException, IOException, VerificationException {
134+
throws IllegalAccessException, IOException, VerificationException, OrderbyException {
132135
return verifyResultSet(expectedOutput, actualOutput, false);
133136
}
134137

@@ -146,7 +149,7 @@ public TestStatus verifyResultSet(String expectedOutput, String actualOutput)
146149
* @throws Exception
147150
*/
148151
public TestStatus verifyResultSet(String expectedOutput, String actualOutput, boolean verifyOrderBy)
149-
throws IOException, VerificationException, IllegalAccessException {
152+
throws IOException, VerificationException, IllegalAccessException, OrderbyException {
150153
if (testStatus == TestStatus.EXECUTION_FAILURE
151154
|| testStatus == TestStatus.CANCELED) {
152155
return testStatus;
@@ -540,15 +543,15 @@ private static class IndexAndOrder {
540543
*/
541544
public TestStatus verifyResultSetOrders(String filename,
542545
List<String> columnLabels, Map<String, String> orderByColumns)
543-
throws IOException, VerificationException, IllegalAccessException {
546+
throws IOException, VerificationException, IllegalAccessException, OrderbyException {
544547
loadFromFileToMap(filename, true);
545548
List<IndexAndOrder> columnIndexAndOrder = getColumnIndexAndOrderList(
546549
columnLabels, orderByColumns, true);
547550
// if one or more order-by columns is not present in the result set,
548551
// then skip this part of the verification.
549552
if (columnIndexAndOrder == null) {
550553
LOG.debug("skipping order verification");
551-
return TestStatus.PASS;
554+
throw new OrderbyException("Order mismatch ");
552555
}
553556
if (!isOrdered(columnIndexAndOrder, orderByColumns)) {
554557
LOG.info("\nOrder mismatch in actual result set.");
@@ -558,7 +561,7 @@ public TestStatus verifyResultSetOrders(String filename,
558561
}
559562

560563
private Map<Integer, String> getColumnIndexAndOrder(
561-
List<String> columnLabels, Map<String, String> orderByColumns) {
564+
List<String> columnLabels, Map<String, String> orderByColumns) throws OrderbyException {
562565
List<IndexAndOrder> result = getColumnIndexAndOrderList(columnLabels,
563566
orderByColumns, false);
564567
if (result == null) {
@@ -586,7 +589,7 @@ private Map<Integer, String> getColumnIndexAndOrder(
586589
*/
587590
private List<IndexAndOrder> getColumnIndexAndOrderList(
588591
List<String> columnLabels, Map<String, String> orderByColumns,
589-
boolean checkForFields) {
592+
boolean checkForFields) throws OrderbyException {
590593
List<IndexAndOrder> columnIndexAndOrder = new ArrayList<IndexAndOrder>();
591594
List<Integer> indicesOfOrderByColumns = getIndicesOfOrderByColumns(
592595
columnLabels, orderByColumns, checkForFields);
@@ -603,7 +606,7 @@ private List<IndexAndOrder> getColumnIndexAndOrderList(
603606
}
604607

605608
private List<Integer> getIndicesOfOrderByColumns(
606-
List<String> columnLabels, Map<String, String> orderByColumns) {
609+
List<String> columnLabels, Map<String, String> orderByColumns) throws OrderbyException {
607610
return getIndicesOfOrderByColumns(columnLabels, orderByColumns, false);
608611
}
609612

@@ -621,7 +624,7 @@ private List<Integer> getIndicesOfOrderByColumns(
621624
private List<Integer> getIndicesOfOrderByColumns(
622625
List<String> columnLabels,
623626
Map<String, String> orderByColumns,
624-
boolean checkForFields) {
627+
boolean checkForFields) throws OrderbyException {
625628
List<Integer> indices = new ArrayList<Integer>();
626629
for (Map.Entry<String, String> entry : orderByColumns.entrySet()) {
627630
String entryKey = entry.getKey();
@@ -631,10 +634,10 @@ private List<Integer> getIndicesOfOrderByColumns(
631634
}
632635
// verify that each order by column is present in the result set by
633636
// checking columnLabels, which represents the columns in the result set.
634-
// if an order by column is not in the result set, return null.
637+
// if an order by column is not in the result set, throw OrderbyException
635638
int index = columnLabels.indexOf(entryKey);
636639
if (index < 0) {
637-
return null;
640+
throw new OrderbyException ("Order by key " + entryKey + " is not projected.");
638641
}
639642
indices.add(index);
640643
}
@@ -832,6 +835,23 @@ private static boolean matchAndCompareAll(String actual, String expected) {
832835
return true;
833836
}
834837

838+
public TestStatus verifyText(String expectedOutput,
839+
String actualOutput) throws IOException, VerificationException {
840+
if (testStatus == TestStatus.EXECUTION_FAILURE
841+
|| testStatus == TestStatus.CANCELED) {
842+
return testStatus;
843+
}
844+
String expected = new String(Files.readAllBytes(Paths.get(expectedOutput)));
845+
String actual = new String(Files.readAllBytes(Paths.get(actualOutput)));
846+
if (!expected.equals(actual)) {
847+
StringBuilder sb = new StringBuilder();
848+
sb.append ("\nExpected and Actual output are different.\n");
849+
throw new VerificationException(sb.toString());
850+
} else {
851+
return TestStatus.PASS;
852+
}
853+
}
854+
835855
/**
836856
* Create a map containing the names of the columns in the order-by clause and
837857
* whether they are being ordered in ascending or descending order.
@@ -915,4 +935,11 @@ public VerificationException(String message) {
915935
super(message);
916936
}
917937
}
938+
939+
public static class OrderbyException extends Exception {
940+
941+
public OrderbyException(String message) {
942+
super(message);
943+
}
944+
}
918945
}

framework/src/main/java/org/apache/drill/test/framework/Utils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
import java.sql.ResultSetMetaData;
3939
import java.util.ArrayList;
4040
import java.util.Date;
41+
import java.util.HashSet;
4142
import java.util.List;
4243
import java.util.Map;
4344
import java.util.PropertyResourceBundle;
4445
import java.util.ResourceBundle;
4546
import java.util.regex.Matcher;
4647
import java.util.regex.Pattern;
48+
import java.util.Set;
4749

4850
import com.fasterxml.jackson.core.JsonParseException;
4951
import com.fasterxml.jackson.databind.JsonNode;
@@ -604,4 +606,27 @@ public static JsonNode getJsonValue(String jsonString, String key)
604606
return rootNode.at(ptrExpr);
605607
}
606608

609+
/**
610+
* Load orderby tests from orderby white-list file
611+
* These tests have orderby clauses which cannnot be validated and therefore need to be skipped.
612+
* They will be passed for now until the orderby clause can be validated
613+
*/
614+
public static Set<String> readOrderbyWhitelistFile(String whitelistFile) throws IOException {
615+
BufferedReader reader = new BufferedReader(new FileReader(new File (whitelistFile)));
616+
String line = null;
617+
Set<String> whitelist = new HashSet<>();
618+
while ((line = reader.readLine()) != null) {
619+
whitelist.add(line);
620+
}
621+
return whitelist;
622+
}
623+
624+
/**
625+
* Check if this test is white-listed.
626+
* If so, this test will be passed for now until the orderby clause can be validated
627+
*/
628+
public static boolean isOrderbyWhitelist(String queryFile) {
629+
return TestDriver.orderbyWhitelist.contains(queryFile);
630+
}
631+
607632
}

0 commit comments

Comments
 (0)