Merged revisions 1784-1824 via svnmerge from
[scons.git] / src / engine / SCons / Tool / JavaCommonTests.py
1 #
2 # __COPYRIGHT__
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #
23
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25
26 import os.path
27 import sys
28 import unittest
29
30 import SCons.Tool.JavaCommon
31
32
33 # Adding this trace to any of the calls below to the parse_java() method
34 # will cause the parser to spit out trace messages of the tokens it sees
35 # and state transitions.
36
37 def trace(token, newstate):
38     from SCons.Debug import Trace
39     statename = newstate.__class__.__name__
40     Trace('token = %s, state = %s\n' % (repr(token), statename))
41
42 class parse_javaTestCase(unittest.TestCase):
43
44     def test_bare_bones(self):
45         """Test a bare-bones class"""
46
47         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
48 package com.sub.bar;
49
50 public class Foo
51 {
52
53      public static void main(String[] args)
54      {
55
56         /* This tests a former bug where strings would eat later code. */
57         String hello1 = new String("Hello, world!");
58
59      }
60
61 }
62 """)
63         assert pkg_dir == os.path.join('com', 'sub', 'bar'), pkg_dir
64         assert classes == ['Foo'], classes
65
66
67     def test_inner_classes(self):
68         """Test parsing various forms of inner classes"""
69
70         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
71 class Empty {
72 }
73
74 interface Listener {
75   public void execute();
76 }
77
78 public
79 class
80 Test implements Listener {
81   class Inner {
82     void go() {
83       use(new Listener() {
84         public void execute() {
85           System.out.println("In Inner");
86         }
87       });
88     }
89     String s1 = "class A";
90     String s2 = "new Listener() { }";
91     /* class B */
92     /* new Listener() { } */
93   }
94
95   class Inner2 {
96      Inner2() { Listener l = new Listener(); }
97   }
98
99   /* Make sure this class doesn't get interpreted as an inner class of the previous one, when "new" is used in the previous class. */
100   class Inner3 {
101
102   }
103
104   public static void main(String[] args) {
105     new Test().run();
106   }
107
108   void run() {
109     use(new Listener() {
110       public void execute() {
111         use(new Listener( ) {
112           public void execute() {
113             System.out.println("Inside execute()");
114           }
115         });
116       }
117     });
118
119     new Inner().go();
120   }
121
122   void use(Listener l) {
123     l.execute();
124   }
125 }
126
127 class Private {
128   void run() {
129     new Listener() {
130       public void execute() {
131       }
132     };
133   }
134 }
135 """)
136     
137         assert pkg_dir is None, pkg_dir
138         expect = [
139                    'Empty',
140                    'Listener',
141                    'Test$1',
142                    'Test$Inner',
143                    'Test$Inner2',
144                    'Test$Inner3',
145                    'Test$2',
146                    'Test$3',
147                    'Test',
148                    'Private$1',
149                    'Private',
150                  ]
151         assert classes == expect, classes
152
153
154     def test_comments(self):
155         """Test a class with comments"""
156
157         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
158 package com.sub.foo;
159
160 import java.rmi.Naming;
161 import java.rmi.RemoteException;
162 import java.rmi.RMISecurityManager;
163 import java.rmi.server.UnicastRemoteObject;
164
165 public class Example1 extends UnicastRemoteObject implements Hello {
166
167     public Example1() throws RemoteException {
168         super();
169     }
170
171     public String sayHello() {
172         return "Hello World!";
173     }
174
175     public static void main(String args[]) {
176         if (System.getSecurityManager() == null) {
177             System.setSecurityManager(new RMISecurityManager());
178         }
179         // a comment
180         try {
181             Example1 obj = new Example1();
182
183             Naming.rebind("//myhost/HelloServer", obj);
184
185             System.out.println("HelloServer bound in registry");
186         } catch (Exception e) {
187             System.out.println("Example1 err: " + e.getMessage());
188             e.printStackTrace();
189         }
190     }
191 }
192 """)
193
194         assert pkg_dir == os.path.join('com', 'sub', 'foo'), pkg_dir
195         assert classes == ['Example1'], classes
196
197
198     def test_arrays(self):
199         """Test arrays of class instances"""
200
201         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
202 public class Test {
203     MyClass abc = new MyClass();
204     MyClass xyz = new MyClass();
205     MyClass _array[] = new MyClass[] {
206         abc,
207         xyz
208     }
209 }
210 """)
211         assert pkg_dir == None, pkg_dir
212         assert classes == ['Test'], classes
213
214
215 # This test comes from bug report #1197470:
216 #
217 #    http://sourceforge.net/tracker/index.php?func=detail&aid=1194740&group_id=30337&atid=398971
218 #
219 # I've captured it here so that someone with a better grasp of Java syntax
220 # and the parse_java() state machine can uncomment it and fix it some day.
221 #
222 #    def test_arrays_in_decls(self):
223 #        """Test how arrays in method declarations affect class detection"""
224 #
225 #        pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
226 #public class A {
227 #    public class B{
228 #        public void F(Object[] o) {
229 #            F(new Object[] {Object[].class});
230 #        }
231 #        public void G(Object[] o) {
232 #            F(new Object[] {});
233 #        }
234 #    }
235 #}
236 #""")
237 #        assert pkg_dir == None, pkg_dir
238 #        assert classes == ['A$B', 'A'], classes
239
240
241     def test_backslash(self):
242         """Test backslash handling"""
243
244         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
245 public class MyTabs
246 {
247         private class MyInternal
248         {
249         }
250         private final static String PATH = "images\\\\";
251 }
252 """)
253         assert pkg_dir == None, pkg_dir
254         assert classes == ['MyTabs$MyInternal', 'MyTabs'], classes
255
256
257     def test_enum(self):
258         """Test the Java 1.5 enum keyword"""
259
260         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
261 package p;
262 public enum a {}
263 """)
264         assert pkg_dir == 'p', pkg_dir
265         assert classes == ['a'], classes
266
267
268     def test_anon_classes(self):
269         """Test anonymous classes"""
270         pkg_dir, classes = SCons.Tool.JavaCommon.parse_java("""\
271 public abstract class TestClass
272 {
273     public void completed()
274     {
275         new Thread()
276         {
277         }.start();
278
279         new Thread()
280         {
281         }.start();
282     }
283 }
284 """)
285         assert pkg_dir == None, pkg_dir
286         assert classes == ['TestClass$1', 'TestClass$2', 'TestClass'], classes
287
288
289
290 if __name__ == "__main__":
291     suite = unittest.TestSuite()
292     tclasses = [ parse_javaTestCase ]
293     for tclass in tclasses:
294         names = unittest.getTestCaseNames(tclass, 'test_')
295         suite.addTests(map(tclass, names))
296     if not unittest.TextTestRunner().run(suite).wasSuccessful():
297         sys.exit(1)