| # Testing |
| |
| Drill makes extensive use of [JUnit](http://junit.org/junit4/) and other libraries for testing. This page provides pointers to the information you need to work with Drill tests. We don't repeat that information; you will want to follow the links and read the original material to get a complete understanding of the libraries that Drill uses. |
| |
| # Writing Tests |
| |
| ## General Testing Tools |
| |
| * [Test Data Sets](TestDataSets.md) |
| * [Temp Directory Utilities](TempDirectories.md) |
| * [Testing with JUnit4](JUnit4.md) |
| * [Test Logging](TestLogging.md) |
| |
| ## Deprecated Drill Testing Techniques |
| |
| This is a list of old Drill testing machinery that we have cleaner machinery for now. |
| |
| * [BaseTestQuery](BaseTestQuery.md): Deprecated, use [ClusterTest](ClusterTest.md) instead. |
| |
| ## Legacy Drill Testing Techniques |
| |
| This is a list of old Drill testing machinery for which there is no other alternative at the moment. |
| |
| * [Testing with Physical Plans and Mock Data](LegacyTestingFrameworks.md) |
| |
| ## Latest Drill Testing Techniques |
| |
| These are all the latest Drill testing Techniques that you should use. If you find one of these approaches insufficient for your use, please enhance them or |
| file a Jira so that they an be improved. |
| |
| * [RowSet Framework](RowSetFramework.md) |
| * [Cluster Fixture Framework](ClusterFixture.md) |
| * [Operator Fixture Framework](OperatorFixture.md) |
| * [ClusterTest](ClusterTest.md) |
| * [Single Operator Unit Test](PhysicalOpUnitTestBase.md) |
| * [Instantiating Components](InstantiatingComponents.md) |
| * [Generated Code](GeneratedCode.md) |
| * [MiniPlanUnitTestBase](../../exec/java-exec/src/test/java/org/apache/drill/exec/physical/unit/MiniPlanUnitTestBase.java) |
| |
| ## Testing Guidelines |
| |
| When testing an operator or a specific internal mechanism in Drill you should use unit tests and should avoid depending on integration tests. This |
| approach means that you will have to design your implementation to be decoupled from the rest of Drill. While this seems daunting, in reality it doesn't take |
| much time and you will spend much less time debugging and stressing about customer bug fixes. |
| |
| Drill provides several tools to facilitate unit testing. See: |
| |
| * [RowSet Framework](RowSetFramework.md) |
| * [Operator Fixture Framework](OperatorFixture.md) |
| * [Single Operator Unit Test](PhysicalOpUnitTestBase.md) |
| * [Instantiating Components](InstantiatingComponents.md) |
| * [Generated Code](GeneratedCode.md) |
| |
| The following are some examples of operators which have leveraged these techniques for unit testing: |
| |
| * [Lateral Join Operator](../../exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestLateralJoinCorrectness.java) |
| * [External Store Operator](../../exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestExternalSortInternals.java) |
| |
| After the unit tests are implemented and passing, use integration tests to ensure the whole system works. The standard tools for accomplishing integration |
| testing are: |
| |
| * [ClusterFixture](ClusterFixture.md) |
| |
| The general rule is: test as close to your code as possible, refactoring and breaking dependencies where needed to accomplish this. |
| On the other hand, if the test is more of a SQL or planner-level concept, then testing at the query level might be fine. |
| |
| ## Categories |
| |
| To mark a test with a category you can do the following: |
| |
| ``` |
| @Category(SlowTest.class) |
| public class MyTest { |
| // Testing code |
| } |
| ``` |
| |
| To mark a test with multiple categories you can do the following: |
| |
| ``` |
| @Category({SlowTest.class, SecurityTest.class}) |
| public class MyTest { |
| // Testing code |
| } |
| ``` |
| |
| # Running Tests |
| |
| Drill tests run in parallel. The model for parallel execution is to divide test classes between multiple |
| forked test processes. Each test process then runs the test classes assigned to it sequentially. |
| |
| ## Speeding Up Test Runs |
| |
| There are a couple knobs you can turn to make tests run faster on your machine. |
| |
| * **Maven Build Threads**: `-T <num>` |
| * **Sure Fire Fork Count**: `-DforkCount=<num>` |
| * **Test Categories** |
| |
| ### -T |
| |
| Maven allows you to use multiple threads to compile sub modules. Also when running tests each build |
| thread forks its own surefire process, so the tests for different submodules are run in parallel. In order |
| to leverage this use the `-T` flag. By default this option is effectively `1`, so there is only one build thread by default. |
| |
| Ex. In order to run the build using two maven threads use the following command. |
| |
| ``` |
| mvn -T 2 clean install |
| ``` |
| |
| ### -DforkCount |
| |
| To run tests within a submodule in parallel you can use the `-DforkCount` option. By default this `2`, so two surefire processes are forked for each build thread. |
| |
| Ex. Run 4 test processes in parallel |
| |
| ``` |
| mvn clean install -DforkCount=4 |
| ``` |
| |
| **Note:** The `-DforkCount` option interacts with `-T`. When used together each build thread (`-T`) gets |
| `-DforkCount` test processes. |
| |
| ### Running Categories |
| |
| You can leverage categories to run subsets of the tests. This is useful if you need to test something like a |
| storage plugin on a remote jenkins server. See the java docs [here](../../common/src/test/java/org/apache/drill/categories/package-info.java) for examples. For a list of all |
| the availabe categories go [here](../../common/src/test/java/org/apache/drill/categories). |
| |
| ## Maven |
| |
| It is often helpful to know the [set of properties](https://cwiki.apache.org/confluence/display/MAVEN/Maven+Properties+Guide) that Maven defines and are available for use in the POM file. |
| |
| ## Surefire Plugin |
| |
| Drill uses the [Maven Surefire plugin](http://maven.apache.org/components/surefire/maven-surefire-plugin/) to run tests. The root POM contains significant test configuration that you may or may not want to include when running tests in a debugger: |
| ``` |
| <configuration> |
| <argLine>-Xms512m -Xmx3g -Ddrill.exec.http.enabled=false |
| -Ddrill.exec.sys.store.provider.local.write=false |
| -Dorg.apache.drill.exec.server.Drillbit.system_options=\ |
| "org.apache.drill.exec.compile.ClassTransformer.scalar_replacement=on" |
| -Ddrill.catastrophic_to_standard_out=true |
| -XX:MaxPermSize=512M -XX:MaxDirectMemorySize=3072M |
| -Djava.net.preferIPv4Stack=true |
| -Djava.awt.headless=true |
| -XX:+CMSClassUnloadingEnabled -ea</argLine> |
| <forkCount>${forkCount}</forkCount> |
| <reuseForks>true</reuseForks> |
| <additionalClasspathElements> |
| <additionalClasspathElement>./exec/jdbc/src/test/resources/storage-plugins.json</additionalClasspathElement> |
| </additionalClasspathElements> |
| ``` |
| |
| You can [run individual tests](http://maven.apache.org/components/surefire/maven-surefire-plugin/examples/single-test.html) as follows. First, cd into the project that contains the test. Then, run the test. (You'll get an error if you try to run the test from the root Drill directory.) |
| ``` |
| cd /path/to/drill/project |
| mvn surefire:test -Dtest=TestCircle |
| ``` |
| |
| # Java Assertions |
| |
| Drill code makes sparse use of Java exceptions, preferring the Guava equivalents. One area that assertions (`-ea` option) does affect is performance: queries run about 10x slower with assertions enabled due to allocator logging. When doing any performance-related work, ensure that assertions are not enabled. |
| |
| ``` |
| class DrillBuf ... |
| public boolean release(int decrement) { |
| ... |
| if (BaseAllocator.DEBUG) { |
| historicalLog.recordEvent("release(%d). original value: %d", decrement, refCnt + decrement); |
| } |
| ``` |
| |
| # Simulating GitHub Actions |
| |
| Sometimes a test failure that occurs in the GitHub Actions CI cannot be reproduced locally. You can try to run the tests in a more similar environment using https://github.com/nektos/act |
| |
| 1. Install act according to its instructions |
| 2. Edit `.github/workflows/ci.yml` to remove extra "matrix" elements and adjust the maven command line to set the tests you are interested in: ```run: mvn install -Dsurefire.useFile=false -DtrimStackTrace=false -Dtest=org.apache.drill.exec.server.rest.TestQueryWrapper -DfailIfNoTests=false``` |
| 3. Run `act -P ubuntu-latest=nektos/act-environments-ubuntu:18.04 --job build` to run the build |
| |
| # IntelliJ |
| |
| IntelliJ IDEA has decent support for maven built in, IntelliJ IDEA users can use these steps to get up and running: |
| |
| First, import maven pom.xml as projects. |
| |
| Change settings in File > Settings > Build, Execution, Deployment > Build Tools > Maven: |
| |
| 1. Enable "Work Offline" to avoid checking for dependency updates on every run |
| 2. Increase the "Thread Count" to speed up builds - a reasonable default is the number of CPU cores you have |
| 3. Go to the "Runner" subsection |
| 4. Enable "Delegate IDE build/run actions to Maven". The IDE didn't seem to do things in a manner compatible with running the application |
| 5. Enable "skip tests" you will probably want to run tests manually rather than every time you try to run something |
| 6. To skip some uninteresting build steps, you can also set the following properties to `true`: `checkstyle.skip`, `findbugs.skip`, `license.skip`, `maven.javadoc.skip`, `rat.skip`, `skipIfEmpty` |
| |
| At this point you should be able to use the built-in IDE features to run tests |
| |
| Running/debugging Drillbit is also possible: |
| 1. Create a new run configuration on the class `org.apache.drill.exec.server.Drillbit` |
| 2. you have to create a run configuration and set the VM parameters: |
| |
| -Xms4G |
| -Xmx4G |
| -XX:MaxDirectMemorySize=8G |
| -XX:ReservedCodeCacheSize=1G |
| -Ddrill.exec.enable-epoll=false |
| -XX:MaxPermSize=512M |
| -XX:+CMSClassUnloadingEnabled |
| -XX:+UseG1GC |
| -Dlog.path=/opt/drill/log/drillbit.log |
| -Dlog.query.path=/opt/drill/log/drillbit_queries.json |
| -Xbootclasspath/a:/opt/drill/conf |
| |
| 3. Set environment variables: |
| |
| DRILL_HOST_NAME=localhost:8047 |
| DRILL_LOG_DIR=/opt/drill/log |
| |
| 4. Edit `/opt/drill/conf/drill-override.conf` to set some options: |
| |
| drill.exec: { |
| zk.connect: "localhost:2181", |
| allow_loopback_address_binding: true, |
| } |
| |
| 5. Install and run ZooKeeper on port 2181 (refer to ZooKeeper docs for this) |
| 6. Run the Drillbit. Note that which storage plugins are available depends on your classpath. |
| |