Revert "Delete DX Tests"
This reverts commit 9ba909f8ab7f3abd082bfdf7ffcdeba930ed1b9a.
diff --git a/tools/dx-tests/src/dxconvext/ClassFileParser.java b/tools/dx-tests/src/dxconvext/ClassFileParser.java
new file mode 100644
index 0000000..8a43396
--- /dev/null
+++ b/tools/dx-tests/src/dxconvext/ClassFileParser.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed 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 dxconvext;
+
+import com.android.dx.cf.direct.ClassPathOpener;
+import com.android.dx.cf.direct.DirectClassFile;
+import com.android.dx.cf.direct.StdAttributeFactory;
+import com.android.dx.cf.iface.Member;
+import com.android.dx.cf.iface.ParseObserver;
+import com.android.dx.util.ByteArray;
+import com.android.dx.util.FileUtils;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+public class ClassFileParser {
+
+ private BufferedWriter bw; // the writer to write the result to.
+
+ /**
+ * Parses a .class file and outputs a .cfh (class file in hex format) file.
+ *
+ * args[0] is the absolute path to the java src directory e.g.
+ * /home/fjost/android/workspace/dxconverter/src
+ *
+ * args[1] is the absolute path to the classes directory e.g.
+ * /home/fjost/android/workspace/out/classes_javac this is the place where
+ *
+ * args[2] is the absolute path to the java source file, e.g.
+ * /home/fjost/android/workspace/dxconverter/src/test/MyTest.java
+ *
+ *
+ *
+ * @param args
+ */
+ public static void main(String[] args) throws IOException {
+ ClassFileParser cfp = new ClassFileParser();
+ cfp.process(args[0], args[1], args[2]);
+ }
+
+ private void process(final String srcDir, final String classesDir,
+ final String absSrcFilePath) throws IOException {
+ ClassPathOpener opener;
+
+ String fileName = absSrcFilePath;
+ // e.g. test/p1/MyTest.java
+ String pckPath = fileName.substring(srcDir.length() + 1);
+ // e.g. test/p1
+ String pck = pckPath.substring(0, pckPath.lastIndexOf("/"));
+ // e.g. MyTest
+ String cName = pckPath.substring(pck.length() + 1);
+ cName = cName.substring(0, cName.lastIndexOf("."));
+ String cfName = pck+"/"+cName+".class";
+ // 2. calculate the target file name:
+ // e.g. <out-path>/test/p1/MyTest.class
+ String inFile = classesDir + "/" + pck + "/" + cName + ".class";
+ if (!new File(inFile).exists()) {
+ throw new RuntimeException("cannot read:" + inFile);
+ }
+ byte[] bytes = FileUtils.readFile(inFile);
+ // write the outfile to the same directory as the corresponding .java
+ // file
+ String outFile = absSrcFilePath.substring(0, absSrcFilePath
+ .lastIndexOf("/"))+ "/" + cName + ".cfh";
+ Writer w;
+ try {
+ w = new OutputStreamWriter(new FileOutputStream(new File(outFile)));
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("cannot write to file:"+outFile, e);
+ }
+ // Writer w = new OutputStreamWriter(System.out);
+ ClassFileParser.this.processFileBytes(w, cfName, bytes);
+
+ }
+
+ /**
+ *
+ * @param w the writer to write the generated .cfh file to
+ * @param name the relative name of the java src file, e.g.
+ * dxc/util/Util.java
+ * @param allbytes the bytes of this java src file
+ * @return true if everthing went alright
+ */
+ void processFileBytes(Writer w, String name, final byte[] allbytes) throws IOException {
+ String fixedPathName = fixPath(name);
+ DirectClassFile cf = new DirectClassFile(allbytes, fixedPathName, true);
+ bw = new BufferedWriter(w);
+ String className = fixedPathName.substring(0, fixedPathName.lastIndexOf("."));
+ out("//@class:" + className, 0);
+ cf.setObserver(new ParseObserver() {
+ private int cur_indent = 0;
+ private int checkpos = 0;
+
+ /**
+ * Indicate that the level of indentation for a dump should increase
+ * or decrease (positive or negative argument, respectively).
+ *
+ * @param indentDelta the amount to change indentation
+ */
+ public void changeIndent(int indentDelta) {
+ cur_indent += indentDelta;
+ }
+
+ /**
+ * Indicate that a particular member is now being parsed.
+ *
+ * @param bytes non-null; the source that is being parsed
+ * @param offset offset into <code>bytes</code> for the start of
+ * the member
+ * @param name non-null; name of the member
+ * @param descriptor non-null; descriptor of the member
+ */
+ public void startParsingMember(ByteArray bytes, int offset,
+ String name, String descriptor) {
+ // ByteArray ba = bytes.slice(offset, bytes.size());
+ out("// ========== start-ParseMember:" + name + ", offset "
+ + offset + ", len:" + (bytes.size() - offset)
+ + ",desc: " + descriptor);
+ // out("// "+dumpReadableString(ba));
+ // out(" "+dumpBytes(ba));
+ }
+
+ /**
+ * Indicate that a particular member is no longer being parsed.
+ *
+ * @param bytes non-null; the source that was parsed
+ * @param offset offset into <code>bytes</code> for the end of the
+ * member
+ * @param name non-null; name of the member
+ * @param descriptor non-null; descriptor of the member
+ * @param member non-null; the actual member that was parsed
+ */
+ public void endParsingMember(ByteArray bytes, int offset,
+ String name, String descriptor, Member member) {
+ ByteArray ba = bytes.slice(offset, bytes.size());
+ out("// ========== end-ParseMember:" + name + ", desc: "
+ + descriptor);
+ // out("// "+dumpReadableString(ba));
+ // out(" "+dumpBytes(ba));
+ }
+
+ /**
+ * Indicate that some parsing happened.
+ *
+ * @param bytes non-null; the source that was parsed
+ * @param offset offset into <code>bytes</code> for what was
+ * parsed
+ * @param len number of bytes parsed
+ * @param human non-null; human form for what was parsed
+ */
+ public void parsed(ByteArray bytes, int offset, int len,
+ String human) {
+ human = human.replace('\n', ' ');
+ out("// parsed:" + ", offset " + offset + ", len " + len
+ + ", h: " + human);
+ if (len > 0) {
+ ByteArray ba = bytes.slice(offset, offset + len);
+ check(ba);
+ out("// " + dumpReadableString(ba));
+ out(" " + dumpBytes(ba));
+ }
+ }
+
+ private void out(String msg) {
+ ClassFileParser.this.out(msg, cur_indent);
+
+ }
+
+ private void check(ByteArray ba) {
+ int len = ba.size();
+ int offset = checkpos;
+ for (int i = 0; i < len; i++) {
+ int b = ba.getByte(i);
+ byte b2 = allbytes[i + offset];
+ if (b != b2)
+ throw new RuntimeException("byte dump mismatch at pos "
+ + (i + offset));
+ }
+ checkpos += len;
+ }
+
+
+
+ private String dumpBytes(ByteArray ba) {
+ String s = "";
+ for (int i = 0; i < ba.size(); i++) {
+ int byt = ba.getUnsignedByte(i);
+ String hexVal = Integer.toHexString(byt);
+ if (hexVal.length() == 1) {
+ hexVal = "0" + hexVal;
+ }
+ s += hexVal + " ";
+ }
+ return s;
+ }
+
+ private String dumpReadableString(ByteArray ba) {
+ String s = "";
+ for (int i = 0; i < ba.size(); i++) {
+ int bb = ba.getUnsignedByte(i);
+ if (bb > 31 && bb < 127) {
+ s += (char) bb;
+ } else {
+ s += ".";
+ }
+ s += " ";
+ }
+ return s;
+ }
+
+
+ });
+ cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
+ // what is needed to force parsing to the end?
+ cf.getMagic();
+ // cf.getFields();
+ // cf.getAttributes();
+ // cf.getMethods();
+ bw.close();
+ }
+
+
+ private String getIndent(int indent) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < indent * 4; i++) {
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+
+ private void out(String msg, int cur_indent) {
+ try {
+ bw.write(getIndent(cur_indent) + msg);
+ bw.newLine();
+ } catch (IOException ioe) {
+ throw new RuntimeException("error while writing to the writer", ioe);
+ }
+ }
+
+ private static String fixPath(String path) {
+ /*
+ * If the path separator is \ (like on windows), we convert the path to
+ * a standard '/' separated path.
+ */
+ if (File.separatorChar == '\\') {
+ path = path.replace('\\', '/');
+ }
+
+ int index = path.lastIndexOf("/./");
+
+ if (index != -1) {
+ return path.substring(index + 3);
+ }
+
+ if (path.startsWith("./")) {
+ return path.substring(2);
+ }
+
+ return path;
+ }
+
+
+
+}