Author: cutting
Date: Thu Dec 31 19:23:02 2009
New Revision: 894929
URL: http://svn.apache.org/viewvc?rev=894929&view=rev
Log:
AVRO-269. Use java compielr to validate specific compiler's output.
Contributed by Philip Zeyliger.
Modified:
hadoop/avro/trunk/CHANGES.txt
hadoop/avro/trunk/build.xml
hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java
hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
Modified: hadoop/avro/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=894929&r1=894928&r2=894929&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Thu Dec 31 19:23:02 2009
@@ -156,6 +156,9 @@
AVRO-260. Upgrade to Jackson 1.4.0. (cutting)
+ AVRO-269. Use java compiler to validate specific compiler's output.
+ (Philip Zeyliger via cutting)
+
OPTIMIZATIONS
AVRO-172. More efficient schema processing (massie)
Modified: hadoop/avro/trunk/build.xml
URL:
http://svn.apache.org/viewvc/hadoop/avro/trunk/build.xml?rev=894929&r1=894928&r2=894929&view=diff
==============================================================================
--- hadoop/avro/trunk/build.xml (original)
+++ hadoop/avro/trunk/build.xml Thu Dec 31 19:23:02 2009
@@ -316,6 +316,7 @@
<junit showoutput="yes"
printsummary="withOutAndErr"
haltonfailure="no"
+ fork="yes" forkMode="once"
errorProperty="tests.failed" failureProperty="tests.failed">
<sysproperty key="test.count" value="${test.count}"/>
<sysproperty key="test.dir" value="${test.java.build.dir}"/>
Modified:
hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
URL:
http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java?rev=894929&r1=894928&r2=894929&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
(original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificCompiler.java
Thu Dec 31 19:23:02 2009
@@ -80,10 +80,10 @@
/**
* Writes output to path destination directory, creating directories as
- * necessary.
+ * necessary. Returns the created file.
*/
- void writeToDestination(File dest) throws IOException {
- File f = new File(dest, path);
+ File writeToDestination(File destDir) throws IOException {
+ File f = new File(destDir, path);
f.getParentFile().mkdirs();
FileWriter fw = new FileWriter(f);
try {
@@ -91,6 +91,7 @@
} finally {
fw.close();
}
+ return f;
}
}
@@ -175,10 +176,11 @@
private OutputFile compileInterface(Protocol protocol) {
OutputFile outputFile = new OutputFile();
- outputFile.path = makePath(protocol.getName(), protocol.getNamespace());
+ String mangledName = mangle(protocol.getName());
+ outputFile.path = makePath(mangledName, protocol.getNamespace());
StringBuilder out = new StringBuilder();
header(out, protocol.getNamespace());
- line(out, 0, "public interface "+mangle(protocol.getName())+" {");
+ line(out, 0, "public interface " + mangledName + " {");
line(out, 1, "public static final org.apache.avro.Protocol PROTOCOL =
org.apache.avro.Protocol.parse(\""
+esc(protocol)+"\");");
for (Map.Entry<String,Message> e : protocol.getMessages().entrySet()) {
@@ -197,10 +199,10 @@
static String makePath(String name, String space) {
if (space == null || space.isEmpty()) {
- return cap(name) + ".java";
+ return name + ".java";
} else {
return space.replace('.', File.separatorChar) + File.separatorChar
- + cap(name) + ".java";
+ + name + ".java";
}
}
@@ -271,7 +273,7 @@
line(out, 2, "switch (field$) {");
i = 0;
for (Map.Entry<String, Schema> field : schema.getFieldSchemas())
- line(out, 2, "case "+(i++)+": "+field.getKey()+" = ("+
+ line(out, 2, "case "+(i++)+": "+mangle(field.getKey())+" = ("+
type(field.getValue())+")value$; break;");
line(out, 2, "default: throw new
org.apache.avro.AvroRuntimeException(\"Bad index\");");
line(out, 2, "}");
@@ -352,10 +354,6 @@
out.append("\n");
}
- static String cap(String name) {
- return name.substring(0,1).toUpperCase()+name.substring(1,name.length());
- }
-
static String esc(Object o) {
return o.toString().replace("\"", "\\\"");
}
Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java
URL:
http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java?rev=894929&r1=894928&r2=894929&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java Thu Dec 31
19:23:02 2009
@@ -262,9 +262,8 @@
new GenericDatumWriter<Object>(),
new GenericDatumReader<Object>());
- // Check that we can generate the code for every
- // schema we see.
- assertTrue(null !=
TestSpecificCompiler.compileWithSpecificCompiler(schema));
+ // Check that we can generate the code for every schema we see.
+ TestSpecificCompiler.assertCompiles(schema, false);
}
}
Modified:
hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
URL:
http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java?rev=894929&r1=894928&r2=894929&view=diff
==============================================================================
---
hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
(original)
+++
hadoop/avro/trunk/src/test/java/org/apache/avro/specific/TestSpecificCompiler.java
Thu Dec 31 19:23:02 2009
@@ -21,9 +21,18 @@
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+import javax.tools.JavaCompiler.CompilationTask;
+
+import org.apache.avro.AvroTestUtil;
import org.apache.avro.Protocol;
import org.apache.avro.Schema;
import org.apache.avro.TestSchema;
@@ -38,16 +47,9 @@
}
@Test
- public void testCap() {
- assertEquals("Foobar", SpecificCompiler.cap("foobar"));
- assertEquals("F", SpecificCompiler.cap("f"));
- assertEquals("F", SpecificCompiler.cap("F"));
- }
-
- @Test
public void testMakePath() {
- assertEquals("foo/bar/Baz.java".replace("/", File.separator),
SpecificCompiler.makePath("baz", "foo.bar"));
- assertEquals("Baz.java", SpecificCompiler.makePath("baz", ""));
+ assertEquals("foo/bar/Baz.java".replace("/", File.separator),
SpecificCompiler.makePath("Baz", "foo.bar"));
+ assertEquals("baz.java", SpecificCompiler.makePath("baz", ""));
}
@Test
@@ -56,12 +58,13 @@
}
@Test
- public void testSimpleEnumSchema() {
+ public void testSimpleEnumSchema() throws IOException {
Collection<OutputFile> outputs = new
SpecificCompiler(Schema.parse(TestSchema.BASIC_ENUM_SCHEMA)).compile();
assertEquals(1, outputs.size());
OutputFile o = outputs.iterator().next();
assertEquals(o.path, "Test.java");
assertTrue(o.contents.contains("public enum Test"));
+ assertCompilesWithJavaCompiler(outputs);
}
@Test
@@ -71,7 +74,7 @@
}
@Test
- public void testManglingForProtocols() {
+ public void testManglingForProtocols() throws IOException {
String protocolDef = "" +
"{ \"protocol\": \"default\",\n" +
" \"types\":\n" +
@@ -89,8 +92,9 @@
" }" +
" }\n" +
"}\n";
- Iterator<OutputFile> i =
- new SpecificCompiler(Protocol.parse(protocolDef)).compile().iterator();
+ Collection<OutputFile> c =
+ new SpecificCompiler(Protocol.parse(protocolDef)).compile();
+ Iterator<OutputFile> i = c.iterator();
String errType = i.next().contents;
String protocol = i.next().contents;
@@ -100,11 +104,13 @@
assertTrue(protocol.contains("org.apache.avro.util.Utf8
goto$(org.apache.avro.util.Utf8 break$)"));
assertTrue(protocol.contains("public interface default$"));
assertTrue(protocol.contains("throws
org.apache.avro.ipc.AvroRemoteException, finally$"));
+
+ assertCompilesWithJavaCompiler(c);
}
@Test
- public void testManglingForRecords() {
+ public void testManglingForRecords() throws IOException {
String schema = "" +
"{ \"name\": \"volatile\", \"type\": \"record\", " +
" \"fields\": [ {\"name\": \"package\", \"type\": \"string\" }," +
@@ -117,10 +123,12 @@
assertTrue(contents.contains("public org.apache.avro.util.Utf8
package$;"));
assertTrue(contents.contains("class volatile$ extends"));
assertTrue(contents.contains("volatile$ short$;"));
+
+ assertCompilesWithJavaCompiler(c);
}
@Test
- public void testManglingForEnums() {
+ public void testManglingForEnums() throws IOException {
String enumSchema = "" +
"{ \"name\": \"instanceof\", \"type\": \"enum\"," +
" \"symbols\": [\"new\", \"super\", \"switch\"] }";
@@ -130,13 +138,59 @@
String contents = c.iterator().next().contents;
assertTrue(contents.contains("new$"));
+
+ assertCompilesWithJavaCompiler(c);
}
/**
- * Called from TestSchema as part of its comprehensive checks.
+ * Checks that a schema passes through the SpecificCompiler, and,
+ * optionally, uses the system's Java compiler to check
+ * that the generated code is valid.
+ */
+ public static void
+ assertCompiles(Schema schema, boolean useJavaCompiler)
+ throws IOException {
+ Collection<OutputFile> outputs = new SpecificCompiler(schema).compile();
+ assertTrue(null != outputs);
+ if (useJavaCompiler) {
+ assertCompilesWithJavaCompiler(outputs);
+ }
+ }
+
+ /**
+ * Checks that a protocol passes through the SpecificCompiler,
+ * and, optionally, uses the system's Java compiler to check
+ * that the generated code is valid.
*/
- public static Collection<OutputFile>
- compileWithSpecificCompiler(Schema schema) {
- return new SpecificCompiler(schema).compile();
+ public static void assertCompiles(Protocol protocol, boolean useJavaCompiler)
+ throws IOException {
+ Collection<OutputFile> outputs = new SpecificCompiler(protocol).compile();
+ assertTrue(null != outputs);
+ if (useJavaCompiler) {
+ assertCompilesWithJavaCompiler(outputs);
+ }
+ }
+
+ /** Uses the system's java compiler to actually compile the generated code.
*/
+ static void assertCompilesWithJavaCompiler(Collection<OutputFile> outputs)
+ throws IOException {
+ if (outputs.isEmpty()) {
+ return; // Nothing to compile!
+ }
+ File dstDir = AvroTestUtil.tempFile("realCompiler");
+ List<File> javaFiles = new ArrayList<File>();
+ for (OutputFile o : outputs) {
+ javaFiles.add(o.writeToDestination(dstDir));
+ }
+
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fileManager =
+ compiler.getStandardFileManager(null, null, null);
+
+ CompilationTask cTask = compiler.getTask(null, fileManager, null, null,
+ null,
+ fileManager.getJavaFileObjects(
+ javaFiles.toArray(new File[javaFiles.size()])));
+ assertTrue(cTask.call());
}
}