1/***
2 * ASM tests
3 * Copyright (c) 2002-2005 France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.objectweb.asm;
31
32import java.io.File;
33import java.io.FileInputStream;
34import java.io.InputStream;
35import java.io.PrintWriter;
36import java.io.StringWriter;
37import java.util.Arrays;
38import java.util.Enumeration;
39import java.util.zip.ZipEntry;
40import java.util.zip.ZipFile;
41
42import org.objectweb.asm.util.TraceClassVisitor;
43
44import junit.framework.TestCase;
45import junit.framework.TestSuite;
46
47/**
48 * Super class for test suites based on a jar file.
49 *
50 * @author Eugene Kuleshov
51 * @author Eric Bruneton
52 */
53public abstract class AbstractTest extends TestCase {
54
55    protected String n;
56
57    protected InputStream is;
58
59    public AbstractTest() {
60        super("test");
61    }
62
63    protected void init(final String n, final InputStream is) {
64        this.n = n;
65        this.is = is;
66    }
67
68    protected TestSuite getSuite() throws Exception {
69        TestSuite suite = new TestSuite(getClass().getName());
70        String files = System.getProperty("asm.test");
71        String clazz = System.getProperty("asm.test.class");
72        if(files==null) {
73            files = System.getProperty("java.home") + File.separator + "lib" + File.separator + "rt.jar";
74            if(clazz==null) {
75                clazz = "java.lang.";
76            }
77        }
78        files += ",";
79
80        while (files.indexOf(',') != -1) {
81            String file = files.substring(0, files.indexOf(','));
82            files = files.substring(files.indexOf(',') + 1);
83            File f = new File(file);
84            if (f.isDirectory()) {
85                File[] fs = f.listFiles();
86                for (int i = 0; i < fs.length; ++i) {
87                    String n = fs[i].getName();
88                    if (n.endsWith(".class")) {
89                        n = n.substring(0, n.length() - 6).replace('/', '.');
90                        if (clazz == null || n.indexOf(clazz) != -1) {
91                            InputStream is = new FileInputStream(fs[i]);
92                            AbstractTest t = (AbstractTest) getClass().newInstance();
93                            t.init(n, is);
94                            suite.addTest(t);
95                        }
96                    }
97                }
98            } else {
99                ZipFile zip = new ZipFile(file);
100                Enumeration entries = zip.entries();
101                while (entries.hasMoreElements()) {
102                    ZipEntry e = (ZipEntry) entries.nextElement();
103                    String n = e.getName();
104                    if (n.endsWith(".class")) {
105                        n = n.substring(0, n.length() - 6).replace('/', '.');
106                        if (clazz == null || n.indexOf(clazz) != -1) {
107                            InputStream is = zip.getInputStream(e);
108                            AbstractTest t = (AbstractTest) getClass().newInstance();
109                            t.init(n, is);
110                            suite.addTest(t);
111                        }
112                    }
113                }
114            }
115        }
116        return suite;
117    }
118
119    public abstract void test() throws Exception;
120
121    public void assertEquals(final ClassReader cr1, final ClassReader cr2)
122            throws Exception
123    {
124        if (!Arrays.equals(cr1.b, cr2.b)) {
125            StringWriter sw1 = new StringWriter();
126            StringWriter sw2 = new StringWriter();
127            ClassVisitor cv1 = new TraceClassVisitor(new PrintWriter(sw1));
128            ClassVisitor cv2 = new TraceClassVisitor(new PrintWriter(sw2));
129            cr1.accept(new ClassFilter(cv1), false);
130            cr2.accept(new ClassFilter(cv2), false);
131            String s1 = sw1.toString();
132            String s2 = sw2.toString();
133            assertEquals("different data", s1, s2);
134        }
135    }
136
137    public String getName() {
138        return super.getName() + ": " + n;
139    }
140
141    // -------------------------------------------------------------------------
142
143    static class ClassFilter extends ClassAdapter {
144
145        public ClassFilter(final ClassVisitor cv) {
146            super(cv);
147        }
148
149        public void visitAttribute(final Attribute attr) {
150            // remove unknown attributes
151        }
152
153        public FieldVisitor visitField(
154            final int access,
155            final String name,
156            final String desc,
157            final String signature,
158            final Object value)
159        {
160            return new FieldFilter(cv.visitField(access,
161                    name,
162                    desc,
163                    signature,
164                    value));
165        }
166
167        public MethodVisitor visitMethod(
168            final int access,
169            final String name,
170            final String desc,
171            final String signature,
172            final String[] exceptions)
173        {
174            return new MethodFilter(cv.visitMethod(access,
175                    name,
176                    desc,
177                    signature,
178                    exceptions));
179        }
180    }
181
182    static class MethodFilter extends MethodAdapter {
183
184        public MethodFilter(final MethodVisitor mv) {
185            super(mv);
186        }
187
188        public void visitAttribute(final Attribute attr) {
189            // remove unknown attributes
190        }
191    }
192
193    static class FieldFilter implements FieldVisitor {
194
195        FieldVisitor fv;
196
197        public FieldFilter(final FieldVisitor fv) {
198            this.fv = fv;
199        }
200
201        public AnnotationVisitor visitAnnotation(
202            final String desc,
203            final boolean visible)
204        {
205            return fv.visitAnnotation(desc, visible);
206        }
207
208        public TypeAnnotationVisitor visitTypeAnnotation(
209            final String desc,
210            final boolean visible)
211        {
212            return fv.visitTypeAnnotation(desc, visible);
213        }
214
215        public void visitAttribute(final Attribute attr) {
216            // remove unknown attributes
217        }
218
219        public void visitEnd() {
220            fv.visitEnd();
221        }
222    }
223}
224