├── .travis.yml ├── DCO ├── LICENSE ├── README.md ├── pom.xml ├── src ├── main │ └── java │ │ └── org │ │ └── finra │ │ └── hiveqlunit │ │ ├── resources │ │ ├── InputStreamResource.java │ │ ├── LocalFileResource.java │ │ ├── ResourceFolderResource.java │ │ ├── TextLiteralResource.java │ │ ├── TextResource.java │ │ └── manipulation │ │ │ ├── Dos2UnixResource.java │ │ │ ├── SubstituteVariableResource.java │ │ │ └── VariableConfigResource.java │ │ ├── rules │ │ ├── SetUpHql.java │ │ ├── TearDownHql.java │ │ ├── TestDataLoader.java │ │ └── TestHiveServer.java │ │ └── script │ │ ├── HqlScript.java │ │ ├── MultiExpressionScript.java │ │ ├── ScriptSplitter.java │ │ └── SingleExpressionScript.java └── test │ ├── java │ └── org │ │ └── finra │ │ └── hiveqlunit │ │ ├── resources │ │ ├── InputStreamResourceTest.java │ │ ├── LocalFileResourceTest.java │ │ ├── ResourceFolderResourceTest.java │ │ ├── TextLiteralResourceTest.java │ │ └── manipulation │ │ │ ├── Dos2UnixResourceTest.java │ │ │ ├── SubstituteVariableResourceTest.java │ │ │ └── VariableConfigResourceTest.java │ │ ├── rules │ │ ├── SetUpHqlTest.java │ │ ├── TearDownHqlTest.java │ │ ├── TestDataLoaderTest.java │ │ └── TestHiveServerTest.java │ │ └── script │ │ ├── MultiExpressionScriptTest.java │ │ ├── ScriptSplitterTest.java │ │ └── SingleExpressionScriptTest.java │ └── resources │ └── testResource.txt └── userguides ├── MakingAnHiveQLUnitProject.md ├── RunningHiveQLUnitTests.md └── WritingHiveQLUnitTests.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: mvn package 3 | 4 | after_success: 5 | - bash <(curl -s https://copilot.blackducksoftware.com/ci/travis/scripts/upload) 6 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Contributions require sign-off. The sign-off is required for all patch or pull requests, which certifies the following agreement given below. 2 | 3 | Contributor Agreement 4 | --------------------- 5 | 6 | By making a contribution to this project, I certify that: 7 | 8 | (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or 9 | 10 | (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or 11 | 12 | (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. 13 | 14 | (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. 15 | 16 | (e) I also agree to the following terms and conditions: 17 | 18 | (1) Grant of Copyright License. Subject to the terms and conditions of this agreement, You hereby grant to the maintainer and to recipients of software distributed by the maintainer a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute your contributions and such derivative works. 19 | 20 | (2) Grant of Patent License. Subject to the terms and conditions of this agreement, You hereby grant to the maintainer and to recipients of software distributed by the maintainer a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the work, where such license applies only to those patent claims licensable by you that are necessarily infringed by your contribution(s) alone or by combination of your contribution(s) with the work to which such contribution(s) was submitted. If any entity institutes patent litigation against you or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your contribution, or the work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this agreement for that contribution or work shall terminate as of the date such litigation is filed. 21 | 22 | Committing 23 | ---------- 24 | 25 | Add a line stating 26 | 27 | Signed-off-by: Random J Developer 28 | 29 | When committing using the command line you can sign off using the --signoff or -s flag. This adds a Signed-off-by line by the committer at the end of the commit log message. 30 | 31 | git commit -s -m "Commit message" 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Black Duck Security Risk](https://copilot.blackducksoftware.com/github/repos/FINRAOS/HiveQLUnit/branches/master/badge-risk.svg)](https://copilot.blackducksoftware.com/github/repos/FINRAOS/HiveQLUnit/branches/master) 2 | 3 | # HiveQLUnit # 4 | 5 | HiveQLUnit is a unit testing framework for Hive HQL scripts. HiveQLUnit is low installation, managing the testing Hive Server for the user, and fully integrates with the JUnit unit testing framework. 6 | 7 | ## License ## 8 | 9 | The HiveQLUnit project is licensed under Apache License Version 2.0 10 | 11 | ## User Guides ## 12 | 13 | * [Making an HQL Unit Project](userguides/MakingAnHiveQLUnitProject.md) 14 | * [Running HQL Unit Tests](userguides/RunningHiveQLUnitTests.md) 15 | * [Writing HQL Unit Tests](userguides/WritingHiveQLUnitTests.md) 16 | * [Example of writing a HQL Unit Test](http://technology.finra.org/code/unit-testing-hive-scripts-with-hiveqlunit.html) 17 | 18 | ## Project Site ## 19 | 20 | http://finraos.github.io/HiveQLUnit/ 21 | 22 | ## Current Release ## 23 | 24 | The latest release version is 1.0. 25 | 26 | 27 | org.finra.hiveqlunit 28 | hiveQLUnit 29 | 1.0 30 | 31 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | org.finra.hiveqlunit 6 | hiveQLUnit 7 | 1.2-SNAPSHOT 8 | jar 9 | 10 | HiveQLUnit 11 | Built on top of spark, HiveQLUnit is a unit testing framework for Hive HQL scripts 12 | 13 | 14 | The Apache Software License, Version 2.0 15 | http://www.apache.org/licenses/LICENSE-2.0.txt 16 | 17 | 18 | http://github.com/FINRAOS/HiveQLUnit 19 | 20 | scm:git:http://github.com/FINRAOS/HiveQLUnit 21 | scm:git:http://github.com/FINRAOS/HiveQLUnit 22 | http://github.com/FINRAOS/HiveQLUnit 23 | 24 | 25 | 26 | mpeter28 27 | Marcie Peters 28 | marciepeters28@yahoo.com 29 | 30 | 31 | 32 | 33 | UTF-8 34 | 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-compiler-plugin 41 | 2.1 42 | 43 | 1.7 44 | 1.7 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-source-plugin 51 | 2.2.1 52 | 53 | 54 | attach-sources 55 | 56 | jar 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-javadoc-plugin 65 | 2.9.1 66 | 67 | 68 | attach-javadocs 69 | 70 | jar 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.jacoco 78 | jacoco-maven-plugin 79 | 0.7.6.201602180812 80 | 81 | 82 | jacoco-initialize 83 | 84 | prepare-agent 85 | 86 | 87 | 88 | jacoco-site 89 | package 90 | 91 | report 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | junit 102 | junit 103 | 4.12 104 | 105 | 106 | 107 | org.apache.commons 108 | commons-io 109 | 1.3.2 110 | 111 | 112 | 113 | org.apache.spark 114 | spark-core_2.10 115 | 2.2.1 116 | 117 | 118 | 119 | org.apache.spark 120 | spark-sql_2.10 121 | 2.2.1 122 | 123 | 124 | 125 | org.apache.spark 126 | spark-hive_2.10 127 | 2.2.1 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/InputStreamResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import org.apache.commons.io.IOUtils; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.StringWriter; 24 | 25 | /** 26 | * Provides an abstract TextResource for building TextResource classes that access InputStream 27 | * accessible resources. InputStreamResource handles the utility of reading out the content of 28 | * an InputStream into a String. Child classes provide the InputStream to read from. 29 | */ 30 | public abstract class InputStreamResource implements TextResource { 31 | 32 | /** 33 | * Provides an InputStream with the text content of the TextResource. 34 | * 35 | * @return an InputStream to read the text content of the TextResource from 36 | * @throws IOException if the InputStream can not be constructed 37 | */ 38 | public abstract InputStream resourceStream() throws IOException; 39 | 40 | /** 41 | * Provides the text content of the TextResource by reading out the content of the resource's 42 | * InputStream. 43 | * 44 | * @return the text content of the TextResource, as contained in its provided InputStream 45 | */ 46 | @Override 47 | public String resourceText() { 48 | try { 49 | StringWriter writer = new StringWriter(); 50 | IOUtils.copy(resourceStream(), writer, "UTF-8"); 51 | return writer.getBuffer().toString(); 52 | } catch (IOException e) { 53 | throw new RuntimeException("Failure to load resource"); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/LocalFileResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import java.io.File; 20 | import java.io.FileInputStream; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | 24 | /** 25 | * Handles access to text resources contained in files on the local file system. 26 | */ 27 | public class LocalFileResource extends InputStreamResource { 28 | 29 | private String filePath; 30 | 31 | /** 32 | * Constructs a TextResource that reads out the content of a file on the local file system. 33 | * 34 | * @param filePath the file system path of the file 35 | */ 36 | public LocalFileResource(String filePath) { 37 | this.filePath = filePath; 38 | } 39 | 40 | /** 41 | * Files on the local file system are easily accessed as InputStreams. 42 | * 43 | * @return an InputStream with the contents of the local file 44 | */ 45 | @Override 46 | public InputStream resourceStream() throws IOException{ 47 | return new FileInputStream(new File(filePath)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/ResourceFolderResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import java.io.InputStream; 20 | 21 | /** 22 | * Jars can have files packaged into the resources folder of the jar. This TextResource handles 23 | * access to said resource folder files. 24 | */ 25 | public class ResourceFolderResource extends InputStreamResource { 26 | 27 | private String resourcePath; 28 | 29 | /** 30 | * Constructs a TextResource that reads out the content of a file in the resources folder 31 | * of a jar. 32 | * 33 | * @param resourcePath the full path of the resource folder file, ie '/foo/bar/file.dat' 34 | */ 35 | public ResourceFolderResource(String resourcePath) { 36 | this.resourcePath = resourcePath; 37 | } 38 | 39 | /** 40 | * Files in the resource folder are easily accessed as InputStreams. 41 | * 42 | * @return an InputStream with the contents of the resource folder file 43 | */ 44 | @Override 45 | public InputStream resourceStream() { 46 | return ResourceFolderResource.class.getResourceAsStream(resourcePath); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/TextLiteralResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | /** 20 | * The most basic TextResource - wraps text literals or Java strings as a TextResource. 21 | */ 22 | public class TextLiteralResource implements TextResource { 23 | 24 | private String resourceText; 25 | 26 | /** 27 | * Constructs a TextResource that wraps a string value, which is the resources' text content. 28 | * 29 | * @param resourceText the resources' text content 30 | */ 31 | public TextLiteralResource(String resourceText) { 32 | this.resourceText = resourceText; 33 | } 34 | 35 | /** 36 | * This TextResource wraps a string value, which is the resource's text content. 37 | * 38 | * @return the resourceText param passed to the constructor 39 | */ 40 | @Override 41 | public String resourceText() { 42 | return resourceText; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/TextResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | /** 20 | * Abstracts access to textual resources needed during testing, such as test data or hql scripts. 21 | * By using this interface, code that uses testing resources can be written agnostic to the 22 | * origin or nature of the resource. 23 | */ 24 | public interface TextResource { 25 | 26 | /** 27 | * Provides the text content of the resource the TextResource object represents. 28 | * 29 | * @return the text content of the resource the TextResource object represents 30 | */ 31 | public String resourceText(); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/manipulation/Dos2UnixResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources.manipulation; 18 | 19 | import org.finra.hiveqlunit.resources.TextResource; 20 | 21 | /** 22 | * Replaces \r\n line endings in a wrapped TextResource with \n line endings. The 23 | * wrapped resource is not actually altered, it only looks different to calling code. 24 | */ 25 | public class Dos2UnixResource implements TextResource { 26 | 27 | private TextResource baseResource; 28 | 29 | /** 30 | * Constructs a TextResource that disguises Windows line endings in a wrapped resource with 31 | * Unix line endings. 32 | * 33 | * @param baseResource the TextResource to wrap 34 | */ 35 | public Dos2UnixResource(TextResource baseResource) { 36 | this.baseResource = baseResource; 37 | } 38 | 39 | /** 40 | * Reads the text content of the wrapped TextResource, then changes the line endings of what 41 | * was read. 42 | * 43 | * @return the text content of the wrapped TextResource, but with Unix line endings 44 | */ 45 | @Override 46 | public String resourceText() { 47 | return baseResource.resourceText().replaceAll("\r\n", "\n"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/manipulation/SubstituteVariableResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources.manipulation; 18 | 19 | import org.finra.hiveqlunit.resources.TextResource; 20 | 21 | /** 22 | * Substitutes variables in a wrapped TextResource's content represented by ${variableName} 23 | * with a desired value. Replaces all such instances of ${variableName} with the desired value. 24 | * The wrapped resource is not actually altered, it only looks different to calling code. 25 | */ 26 | public class SubstituteVariableResource implements TextResource { 27 | 28 | private String variableName; 29 | private String replacementValue; 30 | private TextResource baseResource; 31 | 32 | /** 33 | * Constructs a TextResource that substitutes variables with values in a wrapped TextResource. 34 | * 35 | * @param variableName the variable name, as seen within ${}, ie ${variableName} 36 | * @param replacementValue the value to replace ${variableName} with 37 | * @param baseResource the wrapped TextResource 38 | */ 39 | public SubstituteVariableResource(String variableName, String replacementValue, TextResource baseResource) { 40 | this.variableName = variableName; 41 | this.replacementValue = replacementValue; 42 | this.baseResource = baseResource; 43 | } 44 | 45 | /** 46 | * Reads the text content of the wrapped TextResource, then substitutes variable instances 47 | * with the correct value. 48 | * 49 | * @return the text content of the wrapped TextResource, but with variable substitution 50 | */ 51 | @Override 52 | public String resourceText() { 53 | return baseResource.resourceText().replaceAll("\\$\\{" + variableName + "\\}", replacementValue); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/resources/manipulation/VariableConfigResource.java: -------------------------------------------------------------------------------- 1 | package org.finra.hiveqlunit.resources.manipulation; 2 | 3 | import org.finra.hiveqlunit.resources.TextResource; 4 | import scala.Tuple2; 5 | 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | /** 10 | * Substitutes variables in a wrapped TextResource's content represented by ${variableName} 11 | * with a desired value. Replaces all such instances of ${variableName} with the desired value. 12 | * Similar to SubstituteVariableResource, but can perform multiple substitutions with one wrapper. 13 | * The wrapped resource is not actually altered, it only looks different to calling code. 14 | */ 15 | public class VariableConfigResource implements TextResource { 16 | 17 | private List> variableSubstitutions; 18 | private TextResource baseResource; 19 | 20 | /** 21 | * Constructs a TextResource that substitutes variables with values in a wrapped TextResource. 22 | * 23 | * @param baseResource the wrapped resource 24 | */ 25 | public VariableConfigResource(TextResource baseResource) { 26 | variableSubstitutions = new LinkedList<>(); 27 | this.baseResource = baseResource; 28 | } 29 | 30 | /** 31 | * Constructs a TextResource that substitutes variables with values in a wrapped TextResource. 32 | * Configures using a configuration file, with lines of variableName=value. 33 | * 34 | * @param configuration the text of a configuration file, best acquired through another TextResource 35 | * @param baseResource the wrapped resource 36 | */ 37 | public VariableConfigResource(String configuration, TextResource baseResource) { 38 | this(baseResource); 39 | 40 | for (String configurationLine : configuration.split("\n|\r\n")) { 41 | String[] configSplit = configurationLine.split("="); 42 | addConfig(configSplit[0], configSplit[1]); 43 | } 44 | } 45 | 46 | /** 47 | * Adds additional variable substitutions to the configuration. 48 | * 49 | * @param variableName the variable to substitute, ie ${variableName} in a script 50 | * @param variableValue the substitution value 51 | * @return cascades to makes adding many configurations easy 52 | */ 53 | public VariableConfigResource addConfig(String variableName, String variableValue) { 54 | variableSubstitutions.add(new Tuple2<>(variableName, variableValue)); 55 | return this; 56 | } 57 | 58 | /** 59 | * Reads the text content of the wrapped TextResource, then substitutes variable instances 60 | * with the correct values. 61 | * 62 | * @return the text content of the wrapped TextResource, but with variable substitutions 63 | */ 64 | @Override 65 | public String resourceText() { 66 | String substitutedBase = baseResource.resourceText(); 67 | for (Tuple2 variableSubstitution : variableSubstitutions) { 68 | String variableName = variableSubstitution._1(); 69 | String replacementValue = variableSubstitution._2(); 70 | substitutedBase = substitutedBase 71 | .replaceAll("\\$\\{" + variableName + "\\}", replacementValue); 72 | } 73 | 74 | return substitutedBase; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/rules/SetUpHql.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.finra.hiveqlunit.script.HqlScript; 20 | import org.junit.rules.TestRule; 21 | import org.junit.runner.Description; 22 | import org.junit.runners.model.Statement; 23 | 24 | /** 25 | * A TestRule which executes hive scripts before the test is executed as part of a set up effort. 26 | * The order of evaluation amongst multiple SetUpHql rules is *NON DETERMINISTIC*. If evaluation 27 | * order matters, use the same rule to execute multiple set up commands as part of the same script. 28 | */ 29 | public class SetUpHql implements TestRule { 30 | 31 | private TestHiveServer testingHiveServer; 32 | private HqlScript setUpHql; 33 | 34 | /** 35 | * Constructs a SetUpHql object. 36 | * 37 | * @param testingHiveServer the TestHiveServer to run the set up on 38 | * @param setUpHql a TextResource containing with the set up script to run 39 | */ 40 | public SetUpHql(TestHiveServer testingHiveServer, HqlScript setUpHql) { 41 | this.testingHiveServer = testingHiveServer; 42 | this.setUpHql = setUpHql; 43 | } 44 | 45 | /** 46 | * Wraps a given Statement with a RunSetUpHqlStatement instance. When the nested Statement 47 | * chain is evaluated, set up script is run, and then the wrapped Statement is evaluated. 48 | * 49 | * @param statement the Statement to run the set up script before evaluation of 50 | * @param description ignored 51 | * @return the given Statement wrapped with a RunSetUpHqlStatement 52 | */ 53 | @Override 54 | public Statement apply(Statement statement, Description description) { 55 | return new RunSetUpHqlStatement(statement, testingHiveServer, setUpHql); 56 | } 57 | 58 | /** 59 | * A Statement that does the actual heavy lifting for SetUpHql. 60 | */ 61 | public static class RunSetUpHqlStatement extends Statement { 62 | 63 | private Statement wrappedStatement; 64 | private TestHiveServer testingHiveServer; 65 | private HqlScript setUpHql; 66 | 67 | /** 68 | * When evaluated this Statement runs a hive script as set up code and then evaluates a 69 | * wrapped Statement. 70 | * 71 | * @param wrappedStatement the Statement to execute the set up script before evaluation of 72 | * @param testingHiveServer the TestHiveServer to run the set up script on 73 | * @param setUpHql a TextResource containing the hql script to perform set up with 74 | */ 75 | public RunSetUpHqlStatement(Statement wrappedStatement, TestHiveServer testingHiveServer, HqlScript setUpHql) { 76 | this.wrappedStatement = wrappedStatement; 77 | this.testingHiveServer = testingHiveServer; 78 | this.setUpHql = setUpHql; 79 | } 80 | 81 | /** 82 | * Executes the set up hql script, and then evaluates the wrapped Statement. 83 | * 84 | * @throws Throwable as required by the Statement class 85 | */ 86 | @Override 87 | public void evaluate() throws Throwable { 88 | setUpHql.runScript(testingHiveServer.getSqlContext()); 89 | wrappedStatement.evaluate(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/rules/TearDownHql.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.finra.hiveqlunit.script.HqlScript; 20 | import org.junit.rules.TestRule; 21 | import org.junit.runner.Description; 22 | import org.junit.runners.model.Statement; 23 | 24 | /** 25 | * A TestRule which executes hive scripts after the test is done as part of a clean up effort. 26 | * The order of evaluation amongst multiple TearDownHql rules is *NON DETERMINISTIC*. If 27 | * evaluation order matters, use the same rule to execute multiple tear down commands as 28 | * part of the same script. If the test method (annotated with @Test) fails, the tear down 29 | * script will still be run. 30 | */ 31 | public class TearDownHql implements TestRule { 32 | 33 | private TestHiveServer testingHiveServer; 34 | private HqlScript tearDownHql; 35 | 36 | /** 37 | * Constructs a TearDownHql object. 38 | * 39 | * @param testingHiveServer the TestHiveServer to run the tear down script on 40 | * @param tearDownHql a TextResource containing with the tear down script to run 41 | */ 42 | public TearDownHql(TestHiveServer testingHiveServer, HqlScript tearDownHql) { 43 | this.testingHiveServer = testingHiveServer; 44 | this.tearDownHql = tearDownHql; 45 | } 46 | 47 | /** 48 | * Wraps a given Statement with a RunTearDownHqlStatement instance. When the nested Statement 49 | * chain is evaluated, the tear down script will run after the wrapped statement is evaluated. 50 | * 51 | * @param statement the Statement to run the tear down script after evaluation of 52 | * @param description ignored 53 | * @return the given Statement wrapped with a RunTearDownHqlStatement 54 | */ 55 | @Override 56 | public Statement apply(Statement statement, Description description) { 57 | return new RunTearDownHqlStatement(statement, testingHiveServer, tearDownHql); 58 | } 59 | 60 | /** 61 | * A Statement that does the actual heavy lifting for TearDownHql. 62 | */ 63 | public static class RunTearDownHqlStatement extends Statement { 64 | 65 | private Statement wrappedStatement; 66 | private TestHiveServer testingHiveServer; 67 | private HqlScript tearDownHql; 68 | 69 | /** 70 | * When evaluated this Statement evaluates a wrapped statement and then runs an hql 71 | * script as testing tear down. 72 | * 73 | * @param wrappedStatement the Statement to execute the tear down script after evaluation of 74 | * @param testingHiveServer the TestHiveServer to run the tear down script on 75 | * @param tearDownHql a TextResource containing the hql script to perform tear down with 76 | */ 77 | public RunTearDownHqlStatement(Statement wrappedStatement, TestHiveServer testingHiveServer, HqlScript tearDownHql) { 78 | this.wrappedStatement = wrappedStatement; 79 | this.testingHiveServer = testingHiveServer; 80 | this.tearDownHql = tearDownHql; 81 | } 82 | 83 | /** 84 | * Evaluates the wrapped statement, followed by executing the tear down script. 85 | * The script will always be executed even if a test fails or an error has been thrown. 86 | * 87 | * @throws Throwable as required by the Statement class 88 | */ 89 | @Override 90 | public void evaluate() throws Throwable { 91 | try { 92 | wrappedStatement.evaluate(); 93 | } finally { 94 | tearDownHql.runScript(testingHiveServer.getSqlContext()); 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/rules/TestDataLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.finra.hiveqlunit.resources.TextResource; 20 | import org.junit.rules.TemporaryFolder; 21 | import org.junit.rules.TestRule; 22 | import org.junit.runner.Description; 23 | import org.junit.runners.model.Statement; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.io.PrintWriter; 28 | 29 | /** 30 | * This TestRule class provides utility functions for extracting testing data from resources 31 | * and loading it into Hive tables. 32 | */ 33 | public class TestDataLoader implements TestRule { 34 | 35 | private TestHiveServer hiveServer; 36 | private TemporaryFolder stagingLocation; 37 | 38 | /** 39 | * Constructs a new TestDataLoader. 40 | * 41 | * @param hiveServer the TestHiveServer to load data into 42 | */ 43 | public TestDataLoader(TestHiveServer hiveServer) { 44 | this.hiveServer = hiveServer; 45 | stagingLocation = new TemporaryFolder(); 46 | } 47 | 48 | /** 49 | * Uses a TemporaryFolder rule to process a given statement. The TemporaryFolder will be 50 | * used to construct staging files for loading data into Hive. 51 | * 52 | * @param base the statement to apply a TemporaryFolder to 53 | * @param description the description to apply a TemporaryFolder to 54 | * @return the output of the TemporaryFolder rule 55 | */ 56 | @Override 57 | public Statement apply(Statement base, Description description) { 58 | return stagingLocation.apply(base, description); 59 | } 60 | 61 | /** 62 | * Loads data from a TextResource into a hive table. A temporary file on the local file 63 | * system is used as a staging ground for the data. 64 | * 65 | * @param tableName the name of the table 66 | * @param tableDataResource the resource to extract data from 67 | */ 68 | public void loadDataIntoTable(String tableName, TextResource tableDataResource) { 69 | loadDataIntoTable(tableName, tableDataResource, ""); 70 | } 71 | 72 | /** 73 | * Loads data from a TextResource into a hive table. A temporary file on the local file 74 | * system is used as a staging ground for the data. 75 | * 76 | * @param tableName the name of the table 77 | * @param tableDataResource the resource to extract data from 78 | * @param partitionInfo the optional partitioning commands at the end of a 'LOAD DATA' query 79 | */ 80 | public void loadDataIntoTable(String tableName, TextResource tableDataResource, String partitionInfo) { 81 | try { 82 | File stagingFile = stagingLocation.newFile(tableName + ".dat"); 83 | String tableData = tableDataResource.resourceText(); 84 | PrintWriter writer = new PrintWriter(stagingFile.getAbsoluteFile()); 85 | writer.print(tableData); 86 | writer.close(); 87 | 88 | hiveServer.getSqlContext().sql("LOAD DATA LOCAL INPATH '" 89 | + stagingFile.getAbsolutePath().replace("\\", "/") 90 | + "' INTO TABLE " 91 | + tableName 92 | + " " 93 | + partitionInfo); 94 | } catch (IOException e) { 95 | throw new RuntimeException("Failure to load table data"); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/rules/TestHiveServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.apache.spark.SparkConf; 20 | import org.apache.spark.sql.SQLContext; 21 | import org.apache.spark.sql.SparkSession; 22 | import org.junit.rules.TestRule; 23 | import org.junit.runner.Description; 24 | import org.junit.runners.model.Statement; 25 | 26 | /** 27 | * TestHiveServer is a TestRule responsible for constructing a HiveContext for use in testing 28 | * hql scripts. *MUST* be used with the @ClassRule annotation - other HiveQLUnit provided TestRules 29 | * require this rule to run first. Many classes take a TestHiveServer as an input even though 30 | * they just need the HiveContext. TestHiveServer serves as a passable reference to the 31 | * HiveContext before the context has actually been made. 32 | */ 33 | public class TestHiveServer implements TestRule { 34 | 35 | private String serverAddress; 36 | private ConstructHiveContextStatement constructContext; 37 | 38 | /** 39 | * Makes a TestHiveServer backed with a local spark instance on one thread. 40 | */ 41 | public TestHiveServer() { 42 | this(1); 43 | } 44 | 45 | /** 46 | * Makes a TestHiveServer backed with a local spark instance on a requested number of threads. 47 | * 48 | * @param localThreadCount the desired number of local threads 49 | */ 50 | public TestHiveServer(int localThreadCount) { 51 | serverAddress = "local[" + localThreadCount + "]"; 52 | } 53 | 54 | /** 55 | * Makes a TestHiveServer backed with a given spark cluster. 56 | * 57 | * @param serverAddress the address of the spark cluster 58 | */ 59 | public TestHiveServer(String serverAddress) { 60 | this.serverAddress = serverAddress; 61 | } 62 | 63 | /** 64 | * Wraps a given statement with a ConstructHiveContextStatement. 65 | * 66 | * @param statement the base statement to be wrapped 67 | * @param description ignored 68 | * @return a ConstructHiveContextStatement instance which wraps the provided statement 69 | */ 70 | @Override 71 | public Statement apply(Statement statement, Description description) { 72 | constructContext = new ConstructHiveContextStatement(serverAddress, statement); 73 | return constructContext; 74 | } 75 | 76 | /** 77 | * Provides access to the HiveContext produced by this TestRule. 78 | * 79 | * @return the HiveContext produced by this TestRule 80 | */ 81 | public SQLContext getSqlContext() { 82 | return constructContext.getSqlContext(); 83 | } 84 | 85 | /** 86 | * A Statement that performs most of the work for TestHiveServer. 87 | */ 88 | public static class ConstructHiveContextStatement extends Statement { 89 | 90 | private static SQLContext sparkSqlContextSingleton; 91 | private String serverAddress; 92 | private Statement wrappedStatement; 93 | 94 | /** 95 | * This Statement constructs the all important HiveContext, then evaluates the 96 | * wrapped Statement. 97 | * 98 | * @param serverAddress the address of the backing spark cluster 99 | * @param wrappedStatement the statement to wrap, which will be evaluated after the 100 | * HiveContext is made 101 | */ 102 | public ConstructHiveContextStatement(String serverAddress, Statement wrappedStatement) { 103 | this.serverAddress = serverAddress; 104 | this.wrappedStatement = wrappedStatement; 105 | } 106 | 107 | /** 108 | * Constructs the all important HiveContext, then evaluates the wrapped Statement. 109 | * Currently, the HiveContext is made as a singleton. 110 | * 111 | * @throws Throwable as required by the Statement class 112 | */ 113 | @Override 114 | public void evaluate() throws Throwable { 115 | if (sparkSqlContextSingleton == null) { 116 | SparkConf sparkConf = new SparkConf().setAppName("HiveQLUnit").setMaster(serverAddress); 117 | SparkSession sparkSession = SparkSession.builder().config(sparkConf).enableHiveSupport().getOrCreate(); 118 | sparkSqlContextSingleton = sparkSession.sqlContext(); 119 | } 120 | 121 | wrappedStatement.evaluate(); 122 | } 123 | 124 | /** 125 | * Provides access to the HiveContext produced by this Statement. 126 | * 127 | * @return the HiveContext produced by this TestRule 128 | */ 129 | public SQLContext getSqlContext() { 130 | return sparkSqlContextSingleton; 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/script/HqlScript.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | import org.apache.spark.sql.Row; 20 | import org.apache.spark.sql.SQLContext; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Abstracts the execution of hql scripts or expressions. How to handle comments in scripts, 26 | * or split scripts into runnable expressions is handled here. This is separate from acquiring 27 | * the text representing the hql script or expression, TextResources better handle that. 28 | */ 29 | public interface HqlScript { 30 | 31 | /** 32 | * Runs the sql script or expressions represented by this HqlScript using a HiveContext. 33 | * 34 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 35 | */ 36 | public void runScript(SQLContext sqlContext); 37 | 38 | /** 39 | * Runs the hql script or expressions represented by this HqlScript using a HiveContext, 40 | * returning a results set from the script. 41 | * 42 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 43 | * @return a result set of Rows produced by running the hql script or expressions represented by this HqlScript 44 | */ 45 | public List runScriptReturnResults(SQLContext sqlContext); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/script/MultiExpressionScript.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | import org.apache.spark.sql.Row; 20 | import org.apache.spark.sql.SQLContext; 21 | import org.finra.hiveqlunit.resources.TextResource; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * Runs an hql script containing multiple expressions, using the ScriptSplitter utility to 27 | * derive individual expressions. 28 | */ 29 | public class MultiExpressionScript implements HqlScript { 30 | 31 | private String script; 32 | 33 | /** 34 | * Constructs a MultiExpressionScript. 35 | * 36 | * @param expressionResource a TextResource containing an hql script for MultiExpressionScript to run 37 | */ 38 | public MultiExpressionScript(TextResource expressionResource) { 39 | script = expressionResource.resourceText(); 40 | } 41 | 42 | /** 43 | * Splits the bundled hql script into multiple expressions using ScriptSlitter utility class. 44 | * Each expression is run on the provided HiveContext. 45 | * 46 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 47 | */ 48 | @Override 49 | public void runScript(SQLContext sqlContext) { 50 | String[] expressions = ScriptSplitter.splitScriptIntoExpressions(script); 51 | for (String expression : expressions) { 52 | sqlContext.sql(expression); 53 | } 54 | } 55 | 56 | /** 57 | * Splits the bundled hql script into multiple expressions using ScriptSlitter utility class. 58 | * Each expression is run on the provided HiveContext. 59 | * 60 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 61 | * @return the row results acquired from the last executed expression 62 | */ 63 | @Override 64 | public List runScriptReturnResults(SQLContext sqlContext) { 65 | String[] expressions = ScriptSplitter.splitScriptIntoExpressions(script); 66 | for (int i = 0; i < expressions.length - 1; i++) { 67 | String expression = expressions[i]; 68 | sqlContext.sql(expression); 69 | } 70 | 71 | List rows = sqlContext.sql(expressions[expressions.length - 1]).collectAsList(); 72 | return rows; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/script/ScriptSplitter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | /** 20 | * A static only utility class with functionality to split hql scripts into multiple expressions. 21 | * Needs some work, the quality of the split it not great; many legal scripts might be parsed 22 | * wrong. 23 | */ 24 | public final class ScriptSplitter { 25 | 26 | private ScriptSplitter() { 27 | 28 | } 29 | 30 | /** 31 | * Takes an hql script represented as a String and splits it into multiple hql expressions. 32 | * Expressions are assumed to end with a semi colon followed by a new line (unix style \n 33 | * or windows style \r\n). Comments and redundant new lines are removed as a preliminary 34 | * step before splitting. 35 | * 36 | * @param script the hql script to split into an expression 37 | * @return an array of String hql expressions 38 | */ 39 | public static String[] splitScriptIntoExpressions(String script) { 40 | String scriptNoExtraLines = script.replaceAll("\n(\n|\r\n)+", "\n"); 41 | String scriptNoComments = scriptNoExtraLines.replaceAll("--.*(\n|\r\n|$)", ""); 42 | return scriptNoComments.split(";\n|;\r\n|;$"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/finra/hiveqlunit/script/SingleExpressionScript.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | import org.apache.spark.sql.Row; 20 | import org.apache.spark.sql.SQLContext; 21 | import org.finra.hiveqlunit.resources.TextResource; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * Runs a single hql expression, with no heed for comments or scripts with multiple expressions 27 | * in them. 28 | */ 29 | public class SingleExpressionScript implements HqlScript { 30 | 31 | private String expression; 32 | 33 | /** 34 | * The provided hql script will be run as a single expression with no pre-processing. 35 | * 36 | * @param expressionResource a TextResource, properly containing one hql expression with no comments or such 37 | */ 38 | public SingleExpressionScript(TextResource expressionResource) { 39 | expression = expressionResource.resourceText(); 40 | } 41 | 42 | /** 43 | * Runs the hql contained in the constructor given TextResource, treating it as a single 44 | * expression with no comments. 45 | * 46 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 47 | */ 48 | @Override 49 | public void runScript(SQLContext sqlContext) { 50 | sqlContext.sql(expression); 51 | } 52 | 53 | /** 54 | * Runs the hql contained in the constructor given TextResource, treating it as a single 55 | * expression with no comments. 56 | * 57 | * @param sqlContext an SQLContext, as provided by spark through the TestHiveServer TestRule, used to run hql expressions 58 | * @return a result set of Rows produced by running the hql script or expressions represented by this HqlScript 59 | */ 60 | @Override 61 | public List runScriptReturnResults(SQLContext sqlContext) { 62 | return sqlContext.sql(expression).collectAsList(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/InputStreamResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.PipedInputStream; 25 | import java.io.PipedOutputStream; 26 | import java.io.PrintStream; 27 | 28 | public class InputStreamResourceTest { 29 | 30 | @Test 31 | public void readsResourceFromInputStreamTest() { 32 | InputStreamResource resource = new InputStreamResource() { 33 | @Override 34 | public InputStream resourceStream() throws IOException { 35 | PipedOutputStream outputStream = new PipedOutputStream(); 36 | PipedInputStream inputStream = new PipedInputStream(outputStream); 37 | PrintStream printer = new PrintStream(outputStream); 38 | printer.print("Lorem ipsum doler sit amet"); 39 | printer.close(); 40 | 41 | return inputStream; 42 | } 43 | }; 44 | 45 | Assert.assertEquals("Lorem ipsum doler sit amet", resource.resourceText()); 46 | } 47 | 48 | @Test 49 | public void throwsRunTimeErrorOnExceptionTest() { 50 | InputStreamResource resource = new InputStreamResource() { 51 | @Override 52 | public InputStream resourceStream() throws IOException { 53 | return new InputStream() { 54 | @Override 55 | public int read() throws IOException { 56 | throw new IOException("The stream is inherently broken"); 57 | } 58 | }; 59 | } 60 | }; 61 | 62 | try { 63 | resource.resourceText(); 64 | Assert.fail(); 65 | } catch (Exception e) { 66 | Assert.assertEquals("Failure to load resource", e.getMessage()); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/LocalFileResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Rule; 21 | import org.junit.Test; 22 | import org.junit.rules.TemporaryFolder; 23 | 24 | import java.io.File; 25 | import java.io.FileOutputStream; 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.OutputStream; 29 | import java.io.PrintStream; 30 | 31 | public class LocalFileResourceTest { 32 | 33 | @Rule 34 | public TemporaryFolder testFolder = new TemporaryFolder(); 35 | 36 | @Test 37 | public void providesCorrectInputStreamTest() { 38 | try { 39 | File testData = testFolder.newFile("testData.txt"); 40 | OutputStream fileOutput = new FileOutputStream(testData); 41 | PrintStream printStream = new PrintStream(fileOutput); 42 | printStream.print("ABC"); 43 | printStream.close(); 44 | 45 | InputStreamResource fileResource = new LocalFileResource(testData.getAbsolutePath()); 46 | InputStream resourceStream = fileResource.resourceStream(); 47 | 48 | int firstByte = resourceStream.read(); 49 | org.junit.Assert.assertEquals((int) 'A', firstByte); 50 | 51 | int secondByte = resourceStream.read(); 52 | org.junit.Assert.assertEquals((int) 'B', secondByte); 53 | 54 | int thirdByte = resourceStream.read(); 55 | org.junit.Assert.assertEquals((int) 'C', thirdByte); 56 | } catch (IOException e) { 57 | Assert.fail(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/ResourceFolderResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | public class ResourceFolderResourceTest { 26 | 27 | @Test 28 | public void providesCorrectInputStreamTest() { 29 | InputStreamResource resource = new ResourceFolderResource("/testResource.txt"); 30 | try { 31 | InputStream resourceStream = resource.resourceStream(); 32 | 33 | int firstByte = resourceStream.read(); 34 | Assert.assertEquals((int) 'A', firstByte); 35 | 36 | int secondByte = resourceStream.read(); 37 | Assert.assertEquals((int) 'B', secondByte); 38 | 39 | int thirdByte = resourceStream.read(); 40 | Assert.assertEquals((int) 'C', thirdByte); 41 | } catch (IOException e) { 42 | Assert.fail(); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/TextLiteralResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | public class TextLiteralResourceTest { 23 | 24 | @Test 25 | public void constructorSetsResourceTextTest() { 26 | TextLiteralResource textLiteralResource = new TextLiteralResource("Foo Bar Resource"); 27 | Assert.assertEquals("Foo Bar Resource", textLiteralResource.resourceText()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/manipulation/Dos2UnixResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources.manipulation; 18 | 19 | import org.junit.Assert; 20 | import org.finra.hiveqlunit.resources.TextLiteralResource; 21 | import org.finra.hiveqlunit.resources.TextResource; 22 | import org.junit.Test; 23 | 24 | public class Dos2UnixResourceTest { 25 | 26 | @Test 27 | public void lineEndingCorrectionTest() { 28 | TextResource resource = new Dos2UnixResource( 29 | new TextLiteralResource("Lorem ipsum doler sit amet\r\nLorem \ripsum doler sit\r\n") 30 | ); 31 | 32 | Assert.assertEquals("Lorem ipsum doler sit amet\nLorem \ripsum doler sit\n", resource.resourceText()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/manipulation/SubstituteVariableResourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.resources.manipulation; 18 | 19 | import org.junit.Assert; 20 | import org.finra.hiveqlunit.resources.TextLiteralResource; 21 | import org.finra.hiveqlunit.resources.TextResource; 22 | import org.junit.Test; 23 | 24 | public class SubstituteVariableResourceTest { 25 | 26 | @Test 27 | public void variableSubstitutionTest() { 28 | TextResource resource = new SubstituteVariableResource( 29 | "variable1", 30 | "value", 31 | new TextLiteralResource("${variable1}Foo${variable2}Bar${variable1}") 32 | ); 33 | 34 | Assert.assertEquals("valueFoo${variable2}Barvalue", resource.resourceText()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/resources/manipulation/VariableConfigResourceTest.java: -------------------------------------------------------------------------------- 1 | package org.finra.hiveqlunit.resources.manipulation; 2 | 3 | import org.junit.Assert; 4 | import org.finra.hiveqlunit.resources.TextLiteralResource; 5 | import org.finra.hiveqlunit.resources.TextResource; 6 | import org.junit.Test; 7 | 8 | public class VariableConfigResourceTest { 9 | 10 | @Test 11 | public void substitutionsTest() { 12 | TextResource baseResource = new TextLiteralResource( 13 | "${variable1} ${variable2} ${variable3} ${variable2}"); 14 | 15 | VariableConfigResource configured = new VariableConfigResource(baseResource) 16 | .addConfig("variable1", "foo") 17 | .addConfig("variable2", "bar") 18 | .addConfig("variable3", "lorem"); 19 | 20 | Assert.assertEquals("foo bar lorem bar", configured.resourceText()); 21 | } 22 | 23 | @Test 24 | public void configureFileConstructorTest() { 25 | String config = "variable1=foo\n" 26 | + "variable2=bar\r\n" 27 | + "variable3=lorem"; 28 | 29 | TextResource baseResource = new TextLiteralResource( 30 | "${variable1} ${variable2} ${variable3} ${variable2}"); 31 | 32 | VariableConfigResource configured = new VariableConfigResource(config, baseResource); 33 | Assert.assertEquals("foo bar lorem bar", configured.resourceText()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/rules/SetUpHqlTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.junit.Assert; 20 | import org.apache.spark.sql.Row; 21 | import org.apache.spark.sql.SQLContext; 22 | import org.finra.hiveqlunit.script.HqlScript; 23 | import org.junit.Test; 24 | import org.junit.runners.model.Statement; 25 | 26 | import java.util.List; 27 | import java.util.concurrent.atomic.AtomicBoolean; 28 | 29 | public class SetUpHqlTest { 30 | 31 | @Test 32 | public void setUpHqlRunBeforeStatementTest() { 33 | final AtomicBoolean scriptRun = new AtomicBoolean(false); 34 | final AtomicBoolean statementCalled = new AtomicBoolean(false); 35 | 36 | Statement dummyStatement = new Statement() { 37 | @Override 38 | public void evaluate() throws Throwable { 39 | Assert.assertTrue(scriptRun.get()); 40 | Assert.assertFalse(statementCalled.get()); 41 | 42 | statementCalled.set(true); 43 | } 44 | }; 45 | 46 | TestHiveServer dummyServer = new TestHiveServer() { 47 | @Override 48 | public SQLContext getSqlContext() { 49 | return null; 50 | } 51 | }; 52 | 53 | HqlScript dummyScript = new HqlScript() { 54 | @Override 55 | public void runScript(SQLContext sqlContext) { 56 | Assert.assertFalse(scriptRun.get()); 57 | Assert.assertFalse(statementCalled.get()); 58 | 59 | scriptRun.set(true); 60 | } 61 | 62 | @Override 63 | public List runScriptReturnResults(SQLContext sqlContext) { 64 | Assert.fail(); 65 | return null; 66 | } 67 | }; 68 | 69 | SetUpHql setUpHql = new SetUpHql(dummyServer, dummyScript); 70 | try { 71 | setUpHql.apply(dummyStatement, null).evaluate(); 72 | } catch (Throwable throwable) { 73 | Assert.fail(); 74 | } 75 | 76 | Assert.assertTrue(scriptRun.get()); 77 | Assert.assertTrue(statementCalled.get()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/rules/TearDownHqlTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | import org.junit.Assert; 20 | import org.apache.spark.sql.Row; 21 | import org.apache.spark.sql.SQLContext; 22 | import org.finra.hiveqlunit.script.HqlScript; 23 | import org.junit.Test; 24 | import org.junit.runners.model.Statement; 25 | 26 | import java.util.List; 27 | import java.util.concurrent.atomic.AtomicBoolean; 28 | 29 | public class TearDownHqlTest { 30 | 31 | @Test 32 | public void tearDownHqlRunAfterStatement() { 33 | final AtomicBoolean scriptRun = new AtomicBoolean(false); 34 | final AtomicBoolean statementCalled = new AtomicBoolean(false); 35 | 36 | Statement dummyStatement = new Statement() { 37 | @Override 38 | public void evaluate() throws Throwable { 39 | Assert.assertFalse(scriptRun.get()); 40 | Assert.assertFalse(statementCalled.get()); 41 | 42 | statementCalled.set(true); 43 | } 44 | }; 45 | 46 | TestHiveServer dummyServer = new TestHiveServer() { 47 | @Override 48 | public SQLContext getSqlContext() { 49 | return null; 50 | } 51 | }; 52 | 53 | HqlScript dummyScript = new HqlScript() { 54 | @Override 55 | public void runScript(SQLContext sqlContext) { 56 | Assert.assertFalse(scriptRun.get()); 57 | Assert.assertTrue(statementCalled.get()); 58 | 59 | scriptRun.set(true); 60 | } 61 | 62 | @Override 63 | public List runScriptReturnResults(SQLContext sqlContext) { 64 | Assert.fail(); 65 | return null; 66 | } 67 | }; 68 | 69 | TearDownHql tearDownHql = new TearDownHql(dummyServer, dummyScript); 70 | try { 71 | tearDownHql.apply(dummyStatement, null).evaluate(); 72 | } catch (Throwable throwable) { 73 | Assert.fail(); 74 | } 75 | 76 | Assert.assertTrue(scriptRun.get()); 77 | Assert.assertTrue(statementCalled.get()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/rules/TestDataLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | public class TestDataLoaderTest { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/rules/TestHiveServerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.rules; 18 | 19 | public class TestHiveServerTest { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/script/MultiExpressionScriptTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | public class MultiExpressionScriptTest { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/script/ScriptSplitterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | public class ScriptSplitterTest { 23 | 24 | @Test 25 | public void unixStyleLineEndings() { 26 | String testScript = "SELECT foo FROM bar;\n" 27 | + "SELECT lorem FROM ipsum;\n"; 28 | 29 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 30 | 31 | Assert.assertEquals(2, statements.length); 32 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 33 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 34 | } 35 | 36 | @Test 37 | public void unixEndingInsideExpressionIgnored() { 38 | String testScript = "SELECT foo\n FROM bar;\n"; 39 | 40 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 41 | 42 | Assert.assertEquals(1, statements.length); 43 | Assert.assertEquals("SELECT foo\n FROM bar", statements[0]); 44 | } 45 | 46 | @Test 47 | public void windowsStyleLineEndings() { 48 | String testScript = "SELECT foo FROM bar;\r\n" 49 | + "SELECT lorem FROM ipsum;\r\n"; 50 | 51 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 52 | 53 | Assert.assertEquals(2, statements.length); 54 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 55 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 56 | } 57 | 58 | @Test 59 | public void windowsEndingInsideExpressionIgnored() { 60 | String testScript = "SELECT foo\r\n FROM bar;\n"; 61 | 62 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 63 | 64 | Assert.assertEquals(1, statements.length); 65 | Assert.assertEquals("SELECT foo\r\n FROM bar", statements[0]); 66 | } 67 | 68 | @Test 69 | public void terminalLineEndingOptional() { 70 | String testScript = "SELECT foo FROM bar;\n" 71 | + "SELECT lorem FROM ipsum;"; 72 | 73 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 74 | 75 | Assert.assertEquals(2, statements.length); 76 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 77 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 78 | } 79 | 80 | @Test 81 | public void trailingSemiColonNotPartOfScript() { 82 | String testScript = "SELECT foo FROM bar;\n"; 83 | 84 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 85 | 86 | Assert.assertEquals(1, statements.length); 87 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 88 | } 89 | 90 | @Test 91 | public void excludesCommentedLines() { 92 | String testScript = "SELECT foo FROM bar;\n" 93 | + "-- COMMENT COMMENT COMMENT\n" 94 | + "-- COMMENT2 COMMENT2 COMMENT2\r\n" 95 | + "SELECT lorem FROM ipsum;\n"; 96 | 97 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 98 | 99 | Assert.assertEquals(2, statements.length); 100 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 101 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 102 | } 103 | 104 | @Test 105 | public void commentedLinesWithSemiColons() { 106 | String testScript = "SELECT foo FROM bar;\n" 107 | + "-- COMMENT COMMENT COMMENT;\n" 108 | + "-- COMMENT2 COMMENT2 COMMENT2;\r\n" 109 | + "SELECT lorem FROM ipsum;\n"; 110 | 111 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 112 | 113 | Assert.assertEquals(2, statements.length); 114 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 115 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 116 | } 117 | 118 | @Test 119 | public void commentsAtEndOfScript() { 120 | String testScript = "SELECT foo FROM bar;\n" 121 | + "SELECT lorem FROM ipsum;\n" 122 | + "-- COMMENT COMMENT COMMENT\n" 123 | + "-- COMMENT2 COMMENT2 COMMENT2\r\n" 124 | + "-- COMMENT3 COMMENT3 COMMENT3"; 125 | 126 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 127 | 128 | Assert.assertEquals(2, statements.length); 129 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 130 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 131 | } 132 | 133 | @Test 134 | public void commentsStartsMidLine() { 135 | String testScript = "SELECT foo --FOO is Important\n" 136 | + "FROM bar;\n" 137 | + "SELECT lorem FROM ipsum;\n"; 138 | 139 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 140 | 141 | Assert.assertEquals(2, statements.length); 142 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 143 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[1]); 144 | } 145 | 146 | @Test 147 | public void stripsExtraNewLines() { 148 | String testScript = "SELECT foo FROM bar;\n" 149 | + "\n" 150 | + "\r\n" 151 | + "SELECT bar FROM foo;\r\n" 152 | + "\r\n" 153 | + "\n" 154 | + "SELECT lorem FROM ipsum;\n" 155 | + "\r\n" 156 | + "\n"; 157 | 158 | String[] statements = ScriptSplitter.splitScriptIntoExpressions(testScript); 159 | 160 | Assert.assertEquals(3, statements.length); 161 | Assert.assertEquals("SELECT foo FROM bar", statements[0]); 162 | Assert.assertEquals("SELECT bar FROM foo", statements[1]); 163 | Assert.assertEquals("SELECT lorem FROM ipsum", statements[2]); 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/test/java/org/finra/hiveqlunit/script/SingleExpressionScriptTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 HiveQLUnit Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.finra.hiveqlunit.script; 18 | 19 | public class SingleExpressionScriptTest { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/testResource.txt: -------------------------------------------------------------------------------- 1 | ABC -------------------------------------------------------------------------------- /userguides/MakingAnHiveQLUnitProject.md: -------------------------------------------------------------------------------- 1 | # Making an HiveQLUnit Project # 2 | 3 | This user guide covers the steps required to start a new test suite with HiveQLUnit. 4 | 5 | ## Required Tools ## 6 | 7 | HiveQLUnit is developed with git as source control and is intended for use as a maven dependency in a Java maven project. Users who do not have these tools or are not familiar with them will have a harder time using HiveQLUnit in their projects. Before proceeding further though the user guides, a user should make sure they have these tools and are comfortable with them, 8 | 9 | 1. Java, at least version 7 10 | 2. Git 11 | 3. Maven 12 | 13 | ## Installing HiveQLUnit ## 14 | 15 | Releases of HiveQLUnit can be found in Maven Central, and Maven should automatically handle acquiring HiveQLUnit releases to use as a dependency. 16 | 17 | ## Structuring an HiveQLUnit Project ## 18 | 19 | HiveQLUnit is intended for use as a Maven dependency in a Java maven project. A test suite built with HiveQLUnit needs to be structured like any other Maven project. The test suite needs a 'java' and a 'resources' folder, 20 | 21 | ./src/test/java 22 | ./src/test/resources 23 | 24 | Classes with testing code go in src/test/java, and resources (data, scripts, ect) needed during testing go in src/test/resources. 25 | 26 | Configuration settings go in a pom.xml file in the root folder of the project. 27 | 28 | ./pom.xml 29 | 30 | ## Configuring the Pom File ## 31 | 32 | The pom.xml file of the new test suite must be configured to work with HiveQLUnit. HiveQLUnit must be added as a dependency. The dependency info for the latest 1.0 release is 33 | 34 | 35 | 36 | ... 37 | 38 | 39 | org.finra.hiveqlunit 40 | hiveQLUnit 41 | 1.0 42 | 43 | 44 | 45 | Unit tests run with HiveQLUnit need at least 128 MB of PermGen space. When running the test suite from the command line (say with mvn clean test), the following pom.xml configuration will configure the surefire plugin to use the correct PermGen space size for unit tests 46 | 47 | 48 | 49 | 50 | ... 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-surefire-plugin 55 | 2.18.1 56 | 57 | -XX:MaxPermSize=128m 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /userguides/RunningHiveQLUnitTests.md: -------------------------------------------------------------------------------- 1 | # Running HiveQLUnit Tests # 2 | 3 | This user guide explains how to run unit test suites constructed with HiveQLUnit. The environment does matter; different steps are needed based on operating system for example. 4 | 5 | ## Needed JVM Arguments ## 6 | 7 | Several JVM arguments are needed to make HiveQLUnit test suites correctly work. This section lists the needed arguments, and the below sections 'Running from Command Line' and 'Running in an IDE' will explain how to correctly pass in the needed JVM arguments. 8 | 9 | ### Windows ### 10 | 11 | Running Hive on Windows requires a number of dynamic link libraries for Hadoop. These dlls need to be present for HiveQLUnit to work properly. A full set of these dlls can be downloaded precompiled from https://codeload.github.com/srccodes/hadoop-common-2.2.0-bin/zip/master. The unziped folder can be placed anywhere, the path to it needed as a JVM argument, 12 | 13 | -Dhadoop.home.dir="FULL FILE PATH TO HADOOP DLLS FOLDER" 14 | -Dhadoop.home.dir="C:/Users/k00001/hadoop/hadoop-common-2.2.0-bin-master" 15 | 16 | Even though the full file path is on a Windows style file system, the backslashes need to be substituted with forward slashes, or Hive will not read the file path correctly. 17 | 18 | C:\Users\k00001\hadoop\hadoop-common-2.2.0-bin-master -> C:/Users/k00001/hadoop/hadoop-common-2.2.0-bin-master 19 | 20 | ### Mac/Linux ### 21 | 22 | Running Hive on *nix requires an extant (733 permissions) folder to use as the Hive metastore. 23 | 24 | -Dhive.metastore.warehouse.dir=/tmp/foo 25 | 26 | ### PermGen Space ### 27 | 28 | Regardless of operating system, unit tests run with HiveQLUnit need at least 128 MB of PermGen space, 29 | 30 | -XX:MaxPermSize=128m 31 | 32 | ## Running from Command Line ## 33 | 34 | Test suites built with HiveQLUnit can be run from the command line with 35 | 36 | mvn clean test 37 | 38 | To run from the command line (or as part of a Maven build) JVM command line arguments need to be specified in the pom.xml file to the surefire plugin: 39 | 40 | 41 | 42 | 43 | ... 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-surefire-plugin 48 | 2.18.1 49 | 50 | ARGUMENTS GO HERE 51 | 52 | 53 | 54 | 55 | 56 | -XX:MaxPermSize=128m -Dhive.metastore.warehouse.dir=/tmp/foo 57 | 58 | ## Running in an IDE ## 59 | 60 | When unit tests are run from inside an IDE, the IDE will ignore any JVM arguments specified in the pom.xml file to the surefire plugin. The JVM arguments need to be configured into the IDE itself. 61 | 62 | ### Intellij IDEA ### 63 | 64 | 1. Go to 'Run' in the top bar menu 65 | 2. Under 'Run' select 'Edit Configurations...' - a menu will pop up 66 | 3. Select 'Junit' under the Defaults heading in the left side bar of the pop up menu 67 | 4. Add the needed JVM arguments to the 'VM Options' text bar 68 | 5. Click the 'Apply' button 69 | 6. Delete any configurations for individual unit tests, forcing them to all use the defaults 70 | 71 | ### Eclipse ### 72 | 73 | TO DO. 74 | -------------------------------------------------------------------------------- /userguides/WritingHiveQLUnitTests.md: -------------------------------------------------------------------------------- 1 | # Writing HiveQLUnit Tests # 2 | 3 | This user guide explains how to write a unit test using the tools provided by HiveQLUnit. HiveQLUnit unit tests are built just like any other JUnit unit tests, with a dedicated testing class containing test methods annotated with @Test. HiveQLUnit provides a number of TestRules which integrate with the JUnit framework along with other utilities for writing JUnit tests focused around Hive. 4 | 5 | ## Resources ## 6 | 7 | HiveQLUnit provides utilities to access scripts and data needed during testing. 8 | 9 | ### TextResource ### 10 | 11 | The TextResource interface abstracts access to resources like scripts and testing data needed in a unit test. Resources can be pulled from the src/test/resources folder bundled into the jar, from the local file system, or passed as raw text programatically. 12 | 13 | public interface TextResource { 14 | 15 | public String resourceText(); 16 | } 17 | 18 | new TextLiteralResource("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)") 19 | new LocalFileResource("C:/cygwin64/home/K00001/testdata.txt") 20 | new ResourceFolderResource("/testdata.txt") 21 | 22 | Many other tools provided by HiveQLUnit take a TextResource as an input. Because of this, these tools can work with many different data sources. 23 | 24 | ### HqlScript ### 25 | 26 | The HqlScript interface abstracts how to parse and run an hql script on a hive server. All implimentations of HqlScript take in a TextResource object containing the script to execute. 27 | 28 | new MultiExpressionScript( 29 | new TextLiteralResource("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)") 30 | ) 31 | 32 | new SingleExpressionScript( 33 | new TextLiteralResource("DROP TABLE IF EXISTS src") 34 | ) 35 | 36 | ## JUnit Integration ## 37 | 38 | @ClassRule 39 | public static TestHiveServer hiveServer = new TestHiveServer(); 40 | 41 | @Rule 42 | public TestDataLoader loader = new TestDataLoader(hiveServer); 43 | 44 | @Rule 45 | public SetUpHql prepSrc = 46 | new SetUpHql( 47 | hiveServer, 48 | new MultiExpressionScript( 49 | new TextLiteralResource("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)") 50 | ) 51 | ); 52 | 53 | @Rule 54 | public TearDownHql cleanSrc = 55 | new TearDownHql( 56 | hiveServer, 57 | new SingleExpressionScript( 58 | new TextLiteralResource("DROP TABLE IF EXISTS src") 59 | ) 60 | ); 61 | 62 | TestRules are java objects which integrate with the JUnit framework and alter how unit tests are run. HiveQLUnit provides a number of TestRules which support unit tests focused around Hive. 63 | 64 | ### TestHiveServer ### 65 | 66 | @ClassRule 67 | public static TestHiveServer hiveServer = new TestHiveServer(); 68 | 69 | The TestHiveServer constructs an instance of HiveContext, which provides access to a disposable Hive cluster created just for testing by means of Spark. TestHiveServer needs to be the first TestRule used in a given test class, and must be annotated with the @ClassRule annotation. 70 | 71 | ### TestDataLoader ### 72 | 73 | @Rule 74 | public TestDataLoader loader = new TestDataLoader(hiveServer); 75 | 76 | The TestDataLoader provides utility methods accesible from within test methods for loading data out of a TextResource and into a Hive table. 77 | 78 | @Test 79 | public void test() { 80 | loader.loadDataIntoTable("src", new LocalFileResource("C:/cygwin64/home/K00001/testdata.txt"), ""); 81 | 82 | SQLContext sqlContext = hiveServer.getSqlContext(); 83 | List results = sqlContext.sql("SELECT key FROM src WHERE key = 5").collectAsList(); 84 | Assert.assertEquals(3, results.size()); 85 | } 86 | 87 | ### SetUpHql ### 88 | 89 | A test class can have multiple SetUpHql test rules. Each one takes in an HqlScript with a TextResource and runs the given script on the Hive server before every test method. All SetUpHqls are run before a @Test method, but the execution order of the different SetUpHqls is non deterministic. Be sure each SetUpHql can run independently of the others. 90 | 91 | ### TearDownHql ### 92 | 93 | TearDownHql is exactly like SetUpHql, except it runs after a @Test method executes. Though the Hive server created by HiveQLUnit is disposable, things like the metastore often persist and need to be cleaned between tests. Be sure to drop tables and such after after every test to keep Hive clean. 94 | --------------------------------------------------------------------------------