Skip to content

Commit d342499

Browse files
committed
refactor and improve testing infrastructure
externalize hadoop settings to allow testing against remote clusters add provisioning of wrap tests + libs as jars for remote execution add special handling of Win for remote execution (w/o using Cygwin)
1 parent ca046e9 commit d342499

28 files changed

+405
-98
lines changed

build.gradle

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ task javadocJar(type: Jar) {
224224
from javadoc
225225
}
226226

227+
// jar used for testing Hadoop remotely (es-hadoop + tests)
228+
task hadoopTestingJar(type: Jar) {
229+
classifier = 'testing'
230+
from sourceSets.test.output
231+
from sourceSets.main.output
232+
}
227233

228234
jar {
229235
manifest.attributes["Created-By"] = "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
@@ -266,5 +272,6 @@ task wrapper(type: Wrapper) {
266272
gradleVersion = '1.4'
267273
}
268274

269-
assemble.dependsOn = ['jar', 'sourcesJar']
275+
// skip creation of javadoc jars
276+
assemble.dependsOn = ['jar', 'hadoopTestingJar']
270277
defaultTasks 'build'

src/main/java/org/elasticsearch/hadoop/cfg/PropertiesSettings.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525
public class PropertiesSettings extends Settings {
2626

27-
private final Properties props;
27+
protected final Properties props;
2828

2929
public PropertiesSettings(Properties props) {
3030
Assert.notNull(props, "Non-null properties expected");
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
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+
package org.elasticsearch.hadoop;
17+
18+
import org.elasticsearch.hadoop.integration.HdpBootstrap;
19+
import org.elasticsearch.hadoop.integration.Provisioner;
20+
import org.junit.Test;
21+
22+
public class ProvisionerTest {
23+
24+
@Test
25+
public void testBasicProvisier() {
26+
Provisioner.provision(HdpBootstrap.hadoopConfig());
27+
}
28+
}

src/test/java/org/elasticsearch/hadoop/integration/TestSettings.java renamed to src/test/java/org/elasticsearch/hadoop/integration/HdfsUtils.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,24 @@
1515
*/
1616
package org.elasticsearch.hadoop.integration;
1717

18-
import java.util.Properties;
18+
import java.io.IOException;
1919

20-
import org.elasticsearch.hadoop.cfg.PropertiesSettings;
20+
import org.apache.hadoop.fs.FileSystem;
21+
import org.apache.hadoop.fs.Path;
22+
import org.apache.hadoop.mapred.JobConf;
2123

2224
/**
23-
* Tweaked settings for testing.
25+
*
2426
*/
25-
public class TestSettings extends PropertiesSettings {
26-
27-
public final static Properties TESTING_PROPS = new Properties();
28-
29-
static {
30-
TESTING_PROPS.put(ES_BATCH_SIZE_BYTES, "8kb");
31-
// see TestSettings
32-
TESTING_PROPS.put(ES_PORT, "9500");
33-
}
27+
public class HdfsUtils {
3428

35-
public TestSettings() {
36-
super(new Properties(TESTING_PROPS));
29+
public static void copyFromLocal(String localPath) throws IOException {
30+
copyFromLocal(localPath, localPath);
3731
}
3832

39-
public TestSettings(String uri) {
40-
this();
41-
setProperty(ES_RESOURCE, uri);
33+
public static void copyFromLocal(String localPath, String destination) throws IOException {
34+
JobConf hadoopConfig = HdpBootstrap.hadoopConfig();
35+
FileSystem fs = FileSystem.get(hadoopConfig);
36+
fs.copyFromLocalFile(false, true, new Path(localPath), new Path(destination));
4237
}
4338
}

src/test/java/org/elasticsearch/hadoop/util/TestUtils.java renamed to src/test/java/org/elasticsearch/hadoop/integration/HdpBootstrap.java

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,30 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.elasticsearch.hadoop.util;
16+
package org.elasticsearch.hadoop.integration;
1717

18-
import java.io.File;
18+
import java.util.Map;
1919
import java.util.Map.Entry;
2020
import java.util.Properties;
2121

2222
import org.apache.commons.lang.reflect.FieldUtils;
2323
import org.apache.commons.logging.LogFactory;
2424
import org.apache.hadoop.conf.Configuration;
2525
import org.apache.hadoop.fs.permission.FsPermission;
26+
import org.apache.hadoop.mapred.JobConf;
2627
import org.apache.hadoop.mapreduce.JobSubmissionFiles;
28+
import org.elasticsearch.hadoop.util.TestSettings;
2729

28-
public class TestUtils {
30+
public class HdpBootstrap {
31+
32+
private static boolean hackVerified = false;
2933

3034
/**
3135
* Hack to allow Hadoop client to run on windows (which otherwise fails due to some permission problem).
3236
*/
33-
public static void hackHadoopStagingOnWin() {
37+
private static void hackHadoopStagingOnWin() {
3438
// do the assignment only on Windows systems
35-
if (isWindows()) {
39+
if (TestUtils.isWindows()) {
3640
// 0655 = -rwxr-xr-x
3741
JobSubmissionFiles.JOB_DIR_PERMISSION.fromShort((short) 0650);
3842
JobSubmissionFiles.JOB_FILE_PERMISSION.fromShort((short) 0650);
@@ -51,29 +55,40 @@ public static void hackHadoopStagingOnWin() {
5155
}
5256
}
5357

54-
public static boolean isWindows() {
55-
return System.getProperty("os.name").toLowerCase().startsWith("win");
56-
}
57-
58-
public static boolean delete(File file) {
59-
if (file == null || !file.exists()) {
60-
return false;
58+
public static JobConf addProperties(JobConf conf, Properties props) {
59+
for (Entry<Object, Object> entry : props.entrySet()) {
60+
conf.set(entry.getKey().toString(), entry.getValue().toString());
6161
}
62+
return conf;
63+
}
6264

63-
boolean result = true;
64-
if (file.isDirectory()) {
65-
String[] children = file.list();
66-
for (int i = 0; i < children.length; i++) {
67-
result &= delete(new File(file, children[i]));
65+
public static JobConf hadoopConfig() {
66+
if (!hackVerified) {
67+
hackVerified = true;
68+
// check local execution
69+
if ("local".equals(TestSettings.TESTING_PROPS.get("mapred.job.tracker"))) {
70+
hackHadoopStagingOnWin();
6871
}
72+
// damn HADOOP-9123
73+
System.setProperty("path.separator", ":");
6974
}
70-
return file.delete() & result;
75+
76+
JobConf conf = addProperties(new JobConf(), TestSettings.TESTING_PROPS);
77+
// provision by default
78+
Provisioner.provision(conf);
79+
80+
return conf;
7181
}
7282

73-
public static Configuration addProperties(Configuration conf, Properties props) {
74-
for (Entry<Object, Object> entry : props.entrySet()) {
75-
conf.set(entry.getKey().toString(), entry.getValue().toString());
83+
public static Properties asProperties(Configuration cfg) {
84+
Properties props = new Properties();
85+
86+
if (cfg != null) {
87+
for (Map.Entry<String, String> entry : cfg) {
88+
props.setProperty(entry.getKey(), entry.getValue());
89+
}
7690
}
77-
return conf;
91+
92+
return props;
7893
}
7994
}

src/test/java/org/elasticsearch/hadoop/integration/LocalES.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import java.io.File;
1919

20-
import org.elasticsearch.hadoop.util.TestUtils;
2120
import org.junit.rules.ExternalResource;
2221

2322
public class LocalES extends ExternalResource {
@@ -36,7 +35,7 @@ public class LocalES extends ExternalResource {
3635

3736
@Override
3837
protected void before() throws Throwable {
39-
TestUtils.hackHadoopStagingOnWin();
38+
//TestUtils.hackHadoopStagingOnWin();
4039

4140
if (master == null) {
4241
System.out.println("Starting Elasticsearch Master...");
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
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+
package org.elasticsearch.hadoop.integration;
17+
18+
import java.io.File;
19+
import java.io.FileFilter;
20+
import java.io.IOException;
21+
import java.net.URL;
22+
import java.util.ArrayList;
23+
import java.util.Arrays;
24+
import java.util.Enumeration;
25+
import java.util.List;
26+
27+
import org.apache.hadoop.conf.Configuration;
28+
import org.apache.hadoop.mapred.JobConf;
29+
import org.apache.hadoop.util.GenericOptionsParser;
30+
import org.elasticsearch.hadoop.util.Assert;
31+
32+
/**
33+
* Builder class for adding jars to the Hadoop environment.
34+
*/
35+
public abstract class Provisioner {
36+
37+
private static final String ESHADOOP_TESTING_JAR;
38+
private static final String[] CASCADING_JARS;
39+
40+
static {
41+
// init ES-Hadoop JAR
42+
// expect the jar under build\libs
43+
try {
44+
File folder = new File("." + File.separator + "build" + File.separator + "libs" + File.separator).getCanonicalFile();
45+
// find proper jar
46+
File[] files = folder.listFiles(new FileFilter() {
47+
48+
@Override
49+
public boolean accept(File pathname) {
50+
return pathname.getName().contains("-testing");
51+
}
52+
});
53+
Assert.isTrue(files != null && files.length == 1,
54+
String.format("Cannot find elasticsearch hadoop jar;%s", Arrays.toString(files)));
55+
ESHADOOP_TESTING_JAR = files[0].getAbsoluteFile().toURI().toString();
56+
57+
} catch (IOException ex) {
58+
throw new RuntimeException("Cannot find required files", ex);
59+
}
60+
61+
// initialize cascading jars
62+
// read them from the classpath
63+
64+
List<String> jars = new ArrayList<String>();
65+
// cascading-core
66+
jars.add(findContainingJar("cascading/cascade/Cascade.class"));
67+
// cascading-hadoop
68+
jars.add(findContainingJar("cascading/flow/hadoop/HadoopFlow.class"));
69+
// jgrapht
70+
jars.add(findContainingJar("org/jgrapht/Graph.class"));
71+
jars.add(findContainingJar("riffle/process/Process.class"));
72+
// riffle
73+
jars.add(findContainingJar("org/codehaus/janino/Java.class"));
74+
// janino commons-compiler
75+
jars.add(findContainingJar("org/codehaus/commons/compiler/CompileException.class"));
76+
77+
CASCADING_JARS = jars.toArray(new String[jars.size()]);
78+
}
79+
80+
81+
public static JobConf provision(JobConf conf) {
82+
// set job jar
83+
conf.set("mapred.jar", ESHADOOP_TESTING_JAR);
84+
return conf;
85+
}
86+
87+
public static JobConf cascading(JobConf conf) {
88+
addLibs(conf, CASCADING_JARS);
89+
return conf;
90+
}
91+
92+
protected static void addLibs(Configuration configuration, String... libs) {
93+
addResource(configuration, libs, "-libjars");
94+
}
95+
96+
private static void addResource(Configuration cfg, String[] locations, String param) {
97+
Assert.notNull(cfg, "a non-null configuration is required");
98+
99+
List<String> list = new ArrayList<String>();
100+
101+
try {
102+
if (locations != null) {
103+
int count = locations.length;
104+
list.add(param);
105+
106+
StringBuilder sb = new StringBuilder();
107+
for (String location : locations) {
108+
if (location != null) {
109+
sb.append(location);
110+
if (--count > 0) {
111+
sb.append(",");
112+
}
113+
}
114+
}
115+
list.add(sb.toString());
116+
}
117+
118+
new GenericOptionsParser(cfg, list.toArray(new String[list.size()]));
119+
} catch (IOException ex) {
120+
throw new IllegalStateException(ex);
121+
}
122+
}
123+
124+
private static String findContainingJar(String binaryName) {
125+
ClassLoader loader = Provisioner.class.getClassLoader();
126+
127+
try {
128+
for (Enumeration<URL> urls = loader.getResources(binaryName); urls.hasMoreElements();) {
129+
URL url = urls.nextElement();
130+
// remove jar:
131+
if ("jar".equals(url.getProtocol())) {
132+
return url.getPath().replaceAll("!.*$", "");
133+
}
134+
}
135+
} catch (IOException ex) {
136+
throw new IllegalArgumentException("Cannot find jar for class " + binaryName, ex);
137+
}
138+
throw new IllegalArgumentException("Cannot find class " + binaryName);
139+
}
140+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
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+
package org.elasticsearch.hadoop.integration;
17+
18+
import java.io.File;
19+
20+
public class TestUtils {
21+
22+
public static boolean delete(File file) {
23+
if (file == null || !file.exists()) {
24+
return false;
25+
}
26+
27+
boolean result = true;
28+
if (file.isDirectory()) {
29+
String[] children = file.list();
30+
for (int i = 0; i < children.length; i++) {
31+
result &= delete(new File(file, children[i]));
32+
}
33+
}
34+
return file.delete() & result;
35+
}
36+
37+
public static boolean isWindows() {
38+
return System.getProperty("os.name").toLowerCase().startsWith("win");
39+
}
40+
}

0 commit comments

Comments
 (0)