├── src
├── test
│ ├── resources
│ │ └── testResource.txt
│ └── java
│ │ └── org
│ │ └── finra
│ │ └── hiveqlunit
│ │ ├── rules
│ │ ├── TestDataLoaderTest.java
│ │ ├── TestHiveServerTest.java
│ │ ├── SetUpHqlTest.java
│ │ └── TearDownHqlTest.java
│ │ ├── script
│ │ ├── MultiExpressionScriptTest.java
│ │ ├── SingleExpressionScriptTest.java
│ │ └── ScriptSplitterTest.java
│ │ └── resources
│ │ ├── TextLiteralResourceTest.java
│ │ ├── manipulation
│ │ ├── Dos2UnixResourceTest.java
│ │ ├── VariableConfigResourceTest.java
│ │ └── SubstituteVariableResourceTest.java
│ │ ├── ResourceFolderResourceTest.java
│ │ ├── LocalFileResourceTest.java
│ │ └── InputStreamResourceTest.java
└── main
│ └── java
│ └── org
│ └── finra
│ └── hiveqlunit
│ ├── resources
│ ├── TextResource.java
│ ├── TextLiteralResource.java
│ ├── LocalFileResource.java
│ ├── ResourceFolderResource.java
│ ├── manipulation
│ │ ├── Dos2UnixResource.java
│ │ ├── SubstituteVariableResource.java
│ │ └── VariableConfigResource.java
│ └── InputStreamResource.java
│ ├── script
│ ├── ScriptSplitter.java
│ ├── HqlScript.java
│ ├── SingleExpressionScript.java
│ └── MultiExpressionScript.java
│ └── rules
│ ├── SetUpHql.java
│ ├── TestDataLoader.java
│ ├── TearDownHql.java
│ └── TestHiveServer.java
├── .travis.yml
├── README.md
├── userguides
├── MakingAnHiveQLUnitProject.md
├── RunningHiveQLUnitTests.md
└── WritingHiveQLUnitTests.md
├── DCO
├── pom.xml
└── LICENSE
/src/test/resources/testResource.txt:
--------------------------------------------------------------------------------
1 | ABC
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------