Add integration tests for Hyracks' HTTP APIs
Change-Id: Ib135ead7896a2b66735eb7325babe15b18a29bed
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1498
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/aql/ResultExtractor.java b/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/aql/ResultExtractor.java
index 8399f7a..daea5cc 100644
--- a/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/aql/ResultExtractor.java
+++ b/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/aql/ResultExtractor.java
@@ -46,7 +46,6 @@
public static InputStream extract(InputStream resultStream) throws Exception {
ObjectMapper om = new ObjectMapper();
- StringWriter sw = new StringWriter();
String resultStr = IOUtils.toString(resultStream, Charset.defaultCharset());
PrettyPrinter singleLine = new SingleLinePrettyPrinter();
ObjectNode result = om.readValue(resultStr, ObjectNode.class);
diff --git a/hyracks-fullstack/hyracks/hyracks-api/pom.xml b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
index 2bb6cc2..cde607f 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
@@ -59,10 +59,11 @@
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <version>4.5.2</version>
- <type>jar</type>
- <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.hyracks</groupId>
@@ -74,11 +75,6 @@
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
- <version>4.4.5</version>
- </dependency>
- <dependency>
<groupId>org.apache.hyracks</groupId>
<artifactId>hyracks-util</artifactId>
<version>${project.version}</version>
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GatherStateDumpsWork.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GatherStateDumpsWork.java
index 7709a2b..d827eba 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GatherStateDumpsWork.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GatherStateDumpsWork.java
@@ -20,7 +20,9 @@
package org.apache.hyracks.control.cc.work;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
@@ -43,7 +45,9 @@
public void doRun() throws Exception {
ccs.addStateDumpRun(sdr.stateDumpId, sdr);
INodeManager nodeManager = ccs.getNodeManager();
- sdr.setNCs(nodeManager.getAllNodeIds());
+ Collection<String> nodeIds = new HashSet<>();
+ nodeIds.addAll(nodeManager.getAllNodeIds());
+ sdr.setNCs(nodeIds);
for (NodeControllerState ncs : nodeManager.getAllNodeControllerStates()) {
ncs.getNodeController().dumpState(sdr.stateDumpId);
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml
index 2f6bd31..08783cc 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/pom.xml
@@ -58,12 +58,10 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
- <version>4.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <version>4.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/dataset/ResultStateSweeper.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/dataset/ResultStateSweeper.java
index 67b87f5..cd2ebd4 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/dataset/ResultStateSweeper.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/dataset/ResultStateSweeper.java
@@ -59,7 +59,7 @@
Thread.sleep(resultSweepThreshold);
sweep();
} catch (InterruptedException e) {
- logger.log(Level.SEVERE, "Result cleaner thread interrupted, shutting down.", e);
+ logger.log(Level.WARNING, "Result cleaner thread interrupted, shutting down.");
break; // the interrupt was explicit from another thread. This thread should shut down...
}
}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/pom.xml b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/pom.xml
index 21e22ab..630b984 100644
--- a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/pom.xml
@@ -69,6 +69,11 @@
</dependency>
<dependency>
<groupId>org.apache.hyracks</groupId>
+ <artifactId>hyracks-storage-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hyracks</groupId>
<artifactId>hyracks-storage-am-btree</artifactId>
<version>${project.version}</version>
</dependency>
@@ -121,10 +126,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </dependency>
- <dependency>
<groupId>org.apache.hyracks</groupId>
<artifactId>hyracks-control-common</artifactId>
<version>${project.version}</version>
@@ -150,9 +151,24 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.hyracks</groupId>
- <artifactId>hyracks-storage-common</artifactId>
- <version>${project.version}</version>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/ApplicationDeploymentAPIIntegrationTest.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/ApplicationDeploymentAPIIntegrationTest.java
new file mode 100644
index 0000000..e1300a3
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/ApplicationDeploymentAPIIntegrationTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import static org.apache.hyracks.tests.integration.TestUtil.uri;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ApplicationDeploymentAPIIntegrationTest extends AbstractIntegrationTest {
+
+ @Test
+ public void testApplicationDeploymentSm() throws Exception {
+ final int dataSize = 100;
+ deployApplicationFile(dataSize, "small");
+ }
+
+ @Test
+ public void testApplicationDeploymentMd() throws Exception {
+ final int dataSize = 8 * 1024 * 1024;
+ deployApplicationFile(dataSize, "medium");
+ }
+
+ @Test
+ public void testApplicationDeploymentLg() throws Exception {
+ final int dataSize = 50 * 1024 * 1024;
+ deployApplicationFile(dataSize, "large");
+ }
+
+ protected void deployApplicationFile(int dataSize, String fileName) throws URISyntaxException, IOException {
+ final String deployid = "testApp";
+
+ String path = "/applications/" + deployid + "&" + fileName;
+ URI uri = uri(path);
+
+ byte[] data = new byte[dataSize];
+ for (int i = 0; i < data.length; ++i) {
+ data[i] = (byte) i;
+ }
+
+ HttpClient client = HttpClients.createMinimal();
+
+ // Put the data
+
+ HttpPut put = new HttpPut(uri);
+ HttpEntity entity = new ByteArrayEntity(data, ContentType.APPLICATION_OCTET_STREAM);
+ put.setEntity(entity);
+ client.execute(put);
+
+ // Get it back
+
+ HttpGet get = new HttpGet(uri);
+ HttpResponse response = client.execute(get);
+ HttpEntity respEntity = response.getEntity();
+ Header contentType = respEntity.getContentType();
+
+ // compare results
+
+ Assert.assertEquals(ContentType.APPLICATION_OCTET_STREAM.getMimeType(), contentType.getValue());
+ InputStream is = respEntity.getContent();
+
+ for (int i = 0; i < dataSize; ++i) {
+ Assert.assertEquals(data[i], (byte) is.read());
+ }
+ Assert.assertEquals(-1, is.read());
+ is.close();
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/JobStatusAPIIntegrationTest.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/JobStatusAPIIntegrationTest.java
new file mode 100644
index 0000000..dbc6151
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/JobStatusAPIIntegrationTest.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import static org.apache.hyracks.tests.integration.TestUtil.httpGetAsObject;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.apache.hyracks.api.constraints.PartitionConstraintHelper;
+import org.apache.hyracks.api.job.JobId;
+import org.apache.hyracks.api.job.JobSpecification;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class JobStatusAPIIntegrationTest extends AbstractIntegrationTest {
+
+ public static final String ROOT_PATH = "/rest/jobs";
+
+ @Test
+ public void testNoRunningJobs() throws Exception {
+ Assert.assertEquals(0, countJobs("RUNNING"));
+ }
+
+ @Test
+ public void testRunningJob() throws Exception {
+ JobId jId = startJob(); // startJob also checks that the job is running
+ stopJob(jId);
+ Assert.assertEquals("TERMINATED", getJobStatus(jId));
+ }
+
+ @Test
+ public void testJobActivityGraph() throws Exception {
+ JobId jId = startJob();
+ ObjectNode res = getJobActivityGraph(jId);
+ Assert.assertTrue(res.has("result"));
+ ObjectNode actGraph = (ObjectNode) res.get("result");
+ Assert.assertTrue(actGraph.has("version"));
+ checkActivityCluster(actGraph);
+ stopJob(jId);
+ Assert.assertEquals("TERMINATED", getJobStatus(jId));
+ }
+
+ @Test
+ public void testJobRun() throws Exception {
+ JobId jId = startJob();
+ ObjectNode res = getJobRun(jId);
+ Assert.assertTrue(res.has("result"));
+ ObjectNode jobRun = (ObjectNode) res.get("result");
+ Assert.assertTrue(jobRun.has("job-id"));
+ Assert.assertTrue(JobId.parse(jobRun.get("job-id").asText()).equals(jId));
+ checkActivityCluster(jobRun);
+ stopJob(jId);
+ Assert.assertEquals("TERMINATED", getJobStatus(jId));
+ }
+
+ protected void checkActivityCluster(ObjectNode result) {
+ Assert.assertTrue(result.has("activity-clusters"));
+ ArrayNode actClusters = (ArrayNode) result.get("activity-clusters");
+ Assert.assertEquals(1, actClusters.size());
+ ObjectNode actCluster = (ObjectNode) actClusters.get(0);
+ Assert.assertTrue(actCluster.has("activities"));
+ }
+
+ protected JobId startJob() throws Exception {
+ WaitingOperatorDescriptor.CONTINUE_RUNNING.setFalse();
+ JobSpecification spec = new JobSpecification();
+ WaitingOperatorDescriptor sourceOpDesc = new WaitingOperatorDescriptor(spec, 0, 0);
+ PartitionConstraintHelper.addPartitionCountConstraint(spec, sourceOpDesc, 1);
+ spec.addRoot(sourceOpDesc);
+ JobId jId = executeTest(spec);
+ // don't run for more than 100 s
+ int maxLoops = 1000;
+ while (maxLoops > 0 && !"RUNNING".equals(getJobStatus(jId))) {
+ Thread.sleep(100);
+ --maxLoops;
+ }
+ return jId;
+ }
+
+ protected void stopJob(JobId jId) throws Exception {
+ synchronized (WaitingOperatorDescriptor.CONTINUE_RUNNING) {
+ WaitingOperatorDescriptor.CONTINUE_RUNNING.setTrue();
+ WaitingOperatorDescriptor.CONTINUE_RUNNING.notify();
+ }
+ hcc.waitForCompletion(jId);
+ }
+
+ private int countJobs(String status) throws IOException, URISyntaxException {
+ int res = 0;
+ ArrayNode jobArray = getJobs();
+ for (JsonNode n : jobArray) {
+ ObjectNode o = (ObjectNode) n;
+ if (status.equals(o.get("status").asText())) {
+ ++res;
+ }
+ }
+ return res;
+ }
+
+ private String getJobStatus(JobId jid) throws IOException, URISyntaxException {
+ ArrayNode jobArray = getJobs();
+ for (JsonNode n : jobArray) {
+ ObjectNode o = (ObjectNode) n;
+ if (JobId.parse(o.get("job-id").asText()).equals(jid)) {
+ return o.get("status").asText();
+ }
+ }
+ return null;
+ }
+
+ protected ArrayNode getJobs() throws URISyntaxException, IOException {
+ return ((ArrayNode) httpGetAsObject(ROOT_PATH).get("result"));
+ }
+
+ protected ObjectNode getJobActivityGraph(JobId jId) throws URISyntaxException, IOException {
+ return httpGetAsObject(ROOT_PATH + "/" + jId.toString() + "/job-activity-graph");
+ }
+
+ protected ObjectNode getJobRun(JobId jId) throws URISyntaxException, IOException {
+ return httpGetAsObject(ROOT_PATH + "/" + jId.toString() + "/job-run");
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/NodesAPIIntegrationTest.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/NodesAPIIntegrationTest.java
new file mode 100644
index 0000000..ead70b1
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/NodesAPIIntegrationTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import static org.apache.hyracks.tests.integration.TestUtil.httpGetAsObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class NodesAPIIntegrationTest extends AbstractIntegrationTest {
+
+ static final String[] NODE_SUMMARY_FIELDS = { "node-id", "heap-used", "system-load-average" };
+
+ static final String[] NODE_DETAILS_FIELDS = { "node-id", "os-name", "arch", "os-version", "num-processors",
+ "vm-name", "vm-version", "vm-vendor", "classpath", "library-path", "boot-classpath", "input-arguments",
+ "system-properties", "pid", "date", "rrd-ptr", "heartbeat-times", "heap-init-sizes", "heap-used-sizes",
+ "heap-committed-sizes", "heap-max-sizes", "nonheap-init-sizes", "nonheap-used-sizes",
+ "nonheap-committed-sizes", "nonheap-max-sizes", "application-memory-budget", "application-cpu-core-budget",
+ "thread-counts", "peak-thread-counts", "system-load-averages", "gc-names", "gc-collection-counts",
+ "gc-collection-times", "net-payload-bytes-read", "net-payload-bytes-written", "net-signaling-bytes-read",
+ "net-signaling-bytes-written", "dataset-net-payload-bytes-read", "dataset-net-payload-bytes-written",
+ "dataset-net-signaling-bytes-read", "dataset-net-signaling-bytes-written", "ipc-messages-sent",
+ "ipc-message-bytes-sent", "ipc-messages-received", "ipc-message-bytes-received", "disk-reads",
+ "disk-writes", "ini" };
+
+ public static final String ROOT_PATH = "/rest/nodes";
+
+ @Test
+ public void testNodeSummaries() throws Exception {
+ ObjectNode res = httpGetAsObject(ROOT_PATH);
+ Assert.assertTrue(res.has("result"));
+ ArrayNode nodes = (ArrayNode) res.get("result");
+ final int size = nodes.size();
+ Assert.assertEquals(2, size);
+ for (int i = 0; i < size; ++i) {
+ checkNodeFields((ObjectNode) nodes.get(i), NODE_SUMMARY_FIELDS);
+ }
+ }
+
+ @Test
+ public void testNodeDetails() throws Exception {
+ List<String> nodeIds = getNodeIds();
+ for (String nodeId : nodeIds) {
+ ObjectNode res = httpGetAsObject(ROOT_PATH + "/" + nodeId);
+ checkNodeFields((ObjectNode) res.get("result"), NODE_DETAILS_FIELDS);
+ }
+ }
+
+ @Test
+ public void testStatedump() throws Exception {
+ List<String> nodeIds = getNodeIds();
+ ObjectNode res = httpGetAsObject("/rest/statedump");
+ for (String nodeId : nodeIds) {
+ Assert.assertTrue(res.has(nodeId));
+ File dumpFile = new File(res.get(nodeId).asText());
+ /* TODO(tillw) currently doesn't work in the integration tests ...
+ Assert.assertTrue("File '" + dumpFile + "' does not exist", dumpFile.exists());
+ Assert.assertTrue("File '" + dumpFile + "' is empty", dumpFile.length() > 0);
+ Assert.assertTrue("File '" + dumpFile + "' could not be deleted", dumpFile.delete());
+ */
+ }
+ }
+
+ private void checkNodeFields(ObjectNode node, String[] fieldNames) {
+ for (String field : fieldNames) {
+ Assert.assertTrue("field '" + field + "' not found", node.has(field));
+ }
+ }
+
+ private List<String> getNodeIds() throws IOException, URISyntaxException {
+ ObjectNode res = httpGetAsObject(ROOT_PATH);
+ Assert.assertTrue(res.has("result"));
+ ArrayNode nodes = (ArrayNode) res.get("result");
+ final int size = nodes.size();
+ List<String> nodeIds = new ArrayList<>();
+ for (int i = 0; i < size; ++i) {
+ nodeIds.add(nodes.get(i).get("node-id").asText());
+ }
+ return nodeIds;
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/StaticResourcesAPIIntegrationTest.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/StaticResourcesAPIIntegrationTest.java
new file mode 100644
index 0000000..b75c13e
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/StaticResourcesAPIIntegrationTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import static org.apache.hyracks.tests.integration.TestUtil.httpGetAsString;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StaticResourcesAPIIntegrationTest extends AbstractIntegrationTest {
+
+ public static final String ROOT_PATH = "/static/stylesheet/json.human.css";
+
+ @Test
+ public void testStaticResources() throws Exception {
+ String res = httpGetAsString(ROOT_PATH);
+ Assert.assertTrue(res.length() == 3167);
+ }
+
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/TestUtil.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/TestUtil.java
new file mode 100644
index 0000000..a855d53
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/TestUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.HttpClients;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+class TestUtil {
+
+ private static final String HOST = "127.0.0.1";
+ private static final int PORT = 16001;
+
+ static URI uri(String path) throws URISyntaxException {
+ return new URI("http", null, HOST, PORT, path, null, null);
+ }
+
+ static InputStream httpGetAsInputStream(String path) throws URISyntaxException, IOException {
+ HttpClient client = HttpClients.createMinimal();
+ HttpResponse response = client.execute(new HttpGet(uri(path)));
+ return response.getEntity().getContent();
+ }
+
+ static String httpGetAsString(String path) throws URISyntaxException, IOException {
+ InputStream resultStream = httpGetAsInputStream(path);
+ return IOUtils.toString(resultStream, Charset.defaultCharset());
+ }
+
+ static ObjectNode getResultAsJson(String resultStr) throws IOException {
+ return new ObjectMapper().readValue(resultStr, ObjectNode.class);
+ }
+
+ static ObjectNode httpGetAsObject(String path) throws URISyntaxException, IOException {
+ return getResultAsJson(httpGetAsString(path));
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/WaitingOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/WaitingOperatorDescriptor.java
new file mode 100644
index 0000000..6503b7b
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-examples/hyracks-integration-tests/src/test/java/org/apache/hyracks/tests/integration/WaitingOperatorDescriptor.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.tests.integration;
+
+import java.util.logging.Logger;
+
+import org.apache.commons.lang3.mutable.MutableBoolean;
+import org.apache.hyracks.api.comm.IFrameWriter;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.dataflow.IOperatorNodePushable;
+import org.apache.hyracks.api.dataflow.value.IRecordDescriptorProvider;
+import org.apache.hyracks.api.dataflow.value.RecordDescriptor;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
+import org.apache.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
+
+class WaitingOperatorDescriptor extends AbstractSingleActivityOperatorDescriptor {
+
+ public static final MutableBoolean CONTINUE_RUNNING = new MutableBoolean(false);
+
+ private static final long serialVersionUID = 1L;
+ private static Logger LOGGER = Logger.getLogger(WaitingOperatorDescriptor.class.getName());
+
+ public WaitingOperatorDescriptor(IOperatorDescriptorRegistry spec, int inputArity, int outputArity) {
+ super(spec, inputArity, outputArity);
+ }
+
+ @Override
+ public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
+ IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) throws HyracksDataException {
+ try {
+ return new IOperatorNodePushable() {
+ @Override
+ public void setOutputFrameWriter(int index, IFrameWriter writer, RecordDescriptor recordDesc)
+ throws HyracksDataException {
+ }
+
+ @Override
+ public void initialize() throws HyracksDataException {
+ synchronized (CONTINUE_RUNNING) {
+ while (!CONTINUE_RUNNING.booleanValue()) {
+ try {
+ CONTINUE_RUNNING.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ @Override
+ public IFrameWriter getInputFrameWriter(int index) {
+ return null;
+ }
+
+ @Override
+ public int getInputArity() {
+ return inputArity;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return WaitingOperatorDescriptor.class.getSimpleName() + ".OperatorNodePushable:" + partition;
+ }
+
+ @Override
+ public void deinitialize() throws HyracksDataException {
+ }
+ };
+ } finally {
+ }
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-server/pom.xml b/hyracks-fullstack/hyracks/hyracks-server/pom.xml
index 0cc47ca..ded28ad 100644
--- a/hyracks-fullstack/hyracks/hyracks-server/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-server/pom.xml
@@ -155,8 +155,11 @@
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <version>4.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -164,11 +167,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
- <version>4.4.5</version>
- </dependency>
- <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index 5ddbf92..f243f0c 100644
--- a/hyracks-fullstack/pom.xml
+++ b/hyracks-fullstack/pom.xml
@@ -151,6 +151,16 @@
<version>3.5</version>
</dependency>
<dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>4.4.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.2</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<version>0.12</version>