update copyright
[fedora-idea.git] / plugins / ui-designer / testSrc / com / intellij / uiDesigner / core / AsmCodeGeneratorTest.java
blob43478a25d79d50bd6f207a9cb1bafc121f3afd8f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.uiDesigner.core;
18 import com.intellij.openapi.application.PluginPathManager;
19 import com.intellij.openapi.util.io.FileUtil;
20 import com.intellij.uiDesigner.compiler.AsmCodeGenerator;
21 import com.intellij.uiDesigner.compiler.FormErrorInfo;
22 import com.intellij.uiDesigner.compiler.NestedFormLoader;
23 import com.intellij.uiDesigner.compiler.Utils;
24 import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider;
25 import com.intellij.uiDesigner.lw.LwRootContainer;
26 import junit.framework.TestCase;
27 import org.objectweb.asm.ClassWriter;
29 import javax.swing.*;
30 import javax.swing.border.EtchedBorder;
31 import javax.swing.border.TitledBorder;
32 import java.awt.*;
33 import java.io.ByteArrayInputStream;
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.InputStream;
37 import java.lang.reflect.Field;
38 import java.nio.charset.Charset;
39 import java.util.HashMap;
40 import java.util.Map;
42 /**
43 * @author yole
45 public class AsmCodeGeneratorTest extends TestCase {
46 private MyNestedFormLoader myNestedFormLoader;
47 private MyClassLoader myClassLoader;
49 protected void setUp() throws Exception {
50 super.setUp();
51 myNestedFormLoader = new MyNestedFormLoader();
52 myClassLoader = new MyClassLoader(getClass().getClassLoader());
55 protected void tearDown() throws Exception {
56 myClassLoader = null;
57 myNestedFormLoader = null;
58 super.tearDown();
61 private AsmCodeGenerator initCodeGenerator(final String formFileName, final String className) throws Exception {
62 final String testDataPath = PluginPathManager.getPluginHomePath("ui-designer") + "/testData/";
63 return initCodeGenerator(formFileName, className, testDataPath);
66 private AsmCodeGenerator initCodeGenerator(final String formFileName, final String className, final String testDataPath) throws Exception {
67 String formPath = testDataPath + formFileName;
68 String javaPath = testDataPath + className + ".java";
69 com.sun.tools.javac.Main.compile(new String[] { javaPath } );
70 String classPath = testDataPath + className + ".class";
71 final LwRootContainer rootContainer = loadFormData(formPath);
72 final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, myClassLoader, myNestedFormLoader, false,
73 new ClassWriter(ClassWriter.COMPUTE_FRAMES));
74 final FileInputStream classStream = new FileInputStream(classPath);
75 try {
76 codeGenerator.patchClass(classStream);
78 finally {
79 classStream.close();
80 FileUtil.delete(new File(classPath));
82 return codeGenerator;
85 private LwRootContainer loadFormData(final String formPath) throws Exception {
86 String formData = new String(FileUtil.loadFileText(new File(formPath)));
87 final CompiledClassPropertiesProvider provider = new CompiledClassPropertiesProvider(getClass().getClassLoader());
88 return Utils.getRootContainer(formData, provider);
91 private Class loadAndPatchClass(final String formFileName, final String className) throws Exception {
92 final AsmCodeGenerator codeGenerator = initCodeGenerator(formFileName, className);
94 byte[] patchedData = getVerifiedPatchedData(codeGenerator);
97 FileOutputStream fos = new FileOutputStream("C:\\yole\\FormPreview27447\\MainPatched.class");
98 fos.write(patchedData);
99 fos.close();
102 return myClassLoader.doDefineClass(className, patchedData);
105 private byte[] getVerifiedPatchedData(final AsmCodeGenerator codeGenerator) {
106 byte[] patchedData = codeGenerator.getPatchedData();
107 FormErrorInfo[] errors = codeGenerator.getErrors();
108 FormErrorInfo[] warnings = codeGenerator.getWarnings();
109 if (errors.length == 0 && warnings.length == 0) {
110 assertNotNull("Class patching failed but no errors or warnings were returned", patchedData);
112 else if (errors.length > 0) {
113 assertTrue(errors[0].getErrorMessage(), false);
115 else {
116 assertTrue(warnings[0].getErrorMessage(), false);
118 return patchedData;
121 private JComponent getInstrumentedRootComponent(final String formFileName, final String className) throws Exception {
122 Class cls = loadAndPatchClass(formFileName, className);
123 Field rootComponentField = cls.getField("myRootComponent");
124 rootComponentField.setAccessible(true);
125 Object instance = cls.newInstance();
126 return (JComponent)rootComponentField.get(instance);
129 public void testSimple() throws Exception {
130 JComponent rootComponent = getInstrumentedRootComponent("TestSimple.form", "BindingTest");
131 assertNotNull(rootComponent);
134 public void testNoSuchField() throws Exception {
135 AsmCodeGenerator generator = initCodeGenerator("TestNoSuchField.form", "BindingTest");
136 assertEquals("Cannot bind: field does not exist: BindingTest.myNoSuchField", generator.getErrors() [0].getErrorMessage());
139 public void testStaticField() throws Exception {
140 AsmCodeGenerator generator = initCodeGenerator("TestStaticField.form", "BindingTest");
141 assertEquals("Cannot bind: field is static: BindingTest.myStaticField", generator.getErrors() [0].getErrorMessage());
144 public void testFinalField() throws Exception {
145 AsmCodeGenerator generator = initCodeGenerator("TestFinalField.form", "BindingTest");
146 assertEquals("Cannot bind: field is final: BindingTest.myFinalField", generator.getErrors() [0].getErrorMessage());
149 public void testPrimitiveField() throws Exception {
150 AsmCodeGenerator generator = initCodeGenerator("TestPrimitiveField.form", "BindingTest");
151 assertEquals("Cannot bind: field is of primitive type: BindingTest.myIntField", generator.getErrors() [0].getErrorMessage());
154 public void testIncompatibleTypeField() throws Exception {
155 AsmCodeGenerator generator = initCodeGenerator("TestIncompatibleTypeField.form", "BindingTest");
156 assertEquals("Cannot bind: Incompatible types. Cannot assign javax.swing.JPanel to field BindingTest.myStringField", generator.getErrors() [0].getErrorMessage());
159 public void testGridLayout() throws Exception {
160 JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest");
161 assertTrue(rootComponent.getLayout() instanceof GridLayoutManager);
162 GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout();
163 assertEquals(1, gridLayout.getRowCount());
164 assertEquals(1, gridLayout.getColumnCount());
167 public void testGridConstraints() throws Exception {
168 JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest");
169 assertEquals(1, rootComponent.getComponentCount());
170 GridLayoutManager gridLayout = (GridLayoutManager) rootComponent.getLayout();
171 final GridConstraints constraints = gridLayout.getConstraints(0);
172 assertEquals(1, constraints.getColSpan());
173 assertEquals(1, constraints.getRowSpan());
176 public void testIntProperty() throws Exception {
177 JComponent rootComponent = getInstrumentedRootComponent("TestIntProperty.form", "BindingTest");
178 assertEquals(1, rootComponent.getComponentCount());
179 JTextField textField = (JTextField) rootComponent.getComponent(0);
180 assertEquals(37, textField.getColumns());
181 assertEquals(false, textField.isEnabled());
184 public void testDoubleProperty() throws Exception {
185 JSplitPane splitPane = (JSplitPane)getInstrumentedRootComponent("TestDoubleProperty.form", "BindingTest");
186 assertEquals(0.1f, splitPane.getResizeWeight(), 0.001f);
189 public void testStringProperty() throws Exception {
190 JComponent rootComponent = getInstrumentedRootComponent("TestGridConstraints.form", "BindingTest");
191 JButton btn = (JButton) rootComponent.getComponent(0);
192 assertEquals("MyTestButton", btn.getText());
195 public void testSplitPane() throws Exception {
196 JSplitPane splitPane = (JSplitPane)getInstrumentedRootComponent("TestSplitPane.form", "BindingTest");
197 assertTrue(splitPane.getLeftComponent() instanceof JLabel);
198 assertTrue(splitPane.getRightComponent() instanceof JCheckBox);
201 public void testTabbedPane() throws Exception {
202 JTabbedPane tabbedPane = (JTabbedPane) getInstrumentedRootComponent("TestTabbedPane.form", "BindingTest");
203 assertEquals(2, tabbedPane.getTabCount());
204 assertEquals("First", tabbedPane.getTitleAt(0));
205 assertEquals("Test Value", tabbedPane.getTitleAt(1));
206 assertTrue(tabbedPane.getComponentAt(0) instanceof JLabel);
207 assertTrue(tabbedPane.getComponentAt(1) instanceof JButton);
210 public void testScrollPane() throws Exception {
211 JScrollPane scrollPane = (JScrollPane)getInstrumentedRootComponent("TestScrollPane.form", "BindingTest");
212 assertTrue(scrollPane.getViewport().getView() instanceof JList);
215 public void testBorder() throws Exception {
216 JPanel panel = (JPanel) getInstrumentedRootComponent("TestBorder.form", "BindingTest");
217 assertTrue(panel.getBorder() instanceof TitledBorder);
218 TitledBorder border = (TitledBorder) panel.getBorder();
219 assertEquals("BorderTitle", border.getTitle());
220 assertTrue(border.getBorder() instanceof EtchedBorder);
223 public void testMnemonic() throws Exception {
224 JPanel panel = (JPanel) getInstrumentedRootComponent("TestMnemonics.form", "BindingTest");
225 JLabel label = (JLabel) panel.getComponent(0);
226 assertEquals("Mnemonic", label.getText());
227 assertEquals('M', label.getDisplayedMnemonic());
228 assertEquals(3, label.getDisplayedMnemonicIndex());
231 public void testMnemonicFromProperty() throws Exception {
232 JPanel panel = (JPanel) getInstrumentedRootComponent("TestMnemonicsProperty.form", "BindingTest");
233 JLabel label = (JLabel) panel.getComponent(0);
234 assertEquals("Mnemonic", label.getText());
235 assertEquals('M', label.getDisplayedMnemonic());
236 assertEquals(3, label.getDisplayedMnemonicIndex());
239 public void testGridBagLayout() throws Exception {
240 JPanel panel = (JPanel) getInstrumentedRootComponent("TestGridBag.form", "BindingTest");
241 assertTrue(panel.getLayout() instanceof GridBagLayout);
242 GridBagLayout gridBag = (GridBagLayout) panel.getLayout();
243 JButton btn = (JButton) panel.getComponent(0);
244 GridBagConstraints gbc = gridBag.getConstraints(btn);
245 assertNotNull(gbc);
246 assertEquals(2, gbc.gridheight);
247 assertEquals(2, gbc.gridwidth);
248 assertEquals(1.0, gbc.weightx, 0.01);
249 assertEquals(new Insets(1, 2, 3, 4), gbc.insets);
250 assertEquals(GridBagConstraints.HORIZONTAL, gbc.fill);
251 assertEquals(GridBagConstraints.NORTHWEST, gbc.anchor);
254 public void testGridBagSpacer() throws Exception {
255 JPanel panel = (JPanel) getInstrumentedRootComponent("TestGridBagSpacer.form", "BindingTest");
256 assertTrue(panel.getLayout() instanceof GridBagLayout);
257 assertTrue(panel.getComponent(0) instanceof JLabel);
258 assertTrue(panel.getComponent(1) instanceof JPanel);
260 GridBagLayout gridBag = (GridBagLayout) panel.getLayout();
261 GridBagConstraints gbc = gridBag.getConstraints(panel.getComponent(0));
262 assertEquals(0.0, gbc.weightx, 0.01);
263 assertEquals(0.0, gbc.weighty, 0.01);
264 gbc = gridBag.getConstraints(panel.getComponent(1));
265 assertEquals(0.0, gbc.weightx, 0.01);
266 assertEquals(1.0, gbc.weighty, 0.01);
269 public void testLabelFor() throws Exception {
270 JPanel panel = (JPanel) getInstrumentedRootComponent("TestLabelFor.form", "BindingTest");
271 JTextField textField = (JTextField) panel.getComponent(0);
272 JLabel label = (JLabel) panel.getComponent(1);
273 assertEquals(textField, label.getLabelFor());
276 public void testFieldReference() throws Exception {
277 Class cls = loadAndPatchClass("TestFieldReference.form", "FieldReferenceTest");
278 JPanel instance = (JPanel) cls.newInstance();
279 assertEquals(1, instance.getComponentCount());
282 public void testChainedConstructor() throws Exception {
283 Class cls = loadAndPatchClass("TestChainedConstructor.form", "ChainedConstructorTest");
284 Field scrollPaneField = cls.getField("myScrollPane");
285 Object instance = cls.newInstance();
286 JScrollPane scrollPane = (JScrollPane) scrollPaneField.get(instance);
287 assertNotNull(scrollPane.getViewport().getView());
290 public void testConditionalMethodCall() throws Exception {
291 JPanel panel = (JPanel) getInstrumentedRootComponent("TestConditionalMethodCall.form", "ConditionalMethodCallTest");
292 assertNotNull(panel);
295 public void testMethodCallInSuper() throws Exception {
296 Class cls = loadAndPatchClass("TestMethodCallInSuper.form", "MethodCallInSuperTest");
297 JDialog instance = (JDialog) cls.newInstance();
298 assertEquals(1, instance.getContentPane().getComponentCount());
301 public void testIdeadev14081() throws Exception {
302 // NOTE: That doesn't really reproduce the bug as it's dependent on a particular instrumentation sequence used during form preview
303 // (the nested form is instrumented with a new AsmCodeGenerator instance directly in the middle of instrumentation of the current form)
304 final String testDataPath = PluginPathManager.getPluginHomePath("ui-designer") + File.separatorChar + "testData" + File.separatorChar +
305 File.separatorChar + "formEmbedding" + File.separatorChar + "Ideadev14081" + File.separatorChar;
306 AsmCodeGenerator embeddedClassGenerator = initCodeGenerator("Embedded.form", "Embedded", testDataPath);
307 byte[] embeddedPatchedData = getVerifiedPatchedData(embeddedClassGenerator);
308 myClassLoader.doDefineClass("Embedded", embeddedPatchedData);
309 myNestedFormLoader.registerNestedForm("Embedded.form", testDataPath + "Embedded.form");
310 AsmCodeGenerator mainClassGenerator = initCodeGenerator("Main.form", "Main", testDataPath);
311 byte[] mainPatchedData = getVerifiedPatchedData(mainClassGenerator);
314 FileOutputStream fos = new FileOutputStream("C:\\yole\\FormPreview27447\\MainPatched.class");
315 fos.write(mainPatchedData);
316 fos.close();
319 final Class mainClass = myClassLoader.doDefineClass("Main", mainPatchedData);
320 Object instance = mainClass.newInstance();
323 private static class MyClassLoader extends ClassLoader {
324 private final byte[] myTestProperties = Charset.defaultCharset().encode(TEST_PROPERTY_CONTENT).array();
325 private static final String TEST_PROPERTY_CONTENT = "test=Test Value\nmnemonic=Mne&monic";
327 public MyClassLoader(ClassLoader parent) {
328 super(parent);
331 public Class doDefineClass(String name, byte[] data) {
332 return defineClass(name, data, 0, data.length);
335 public Class<?> loadClass(String name) throws ClassNotFoundException {
336 return super.loadClass(name);
339 public InputStream getResourceAsStream(String name) {
340 if (name.equals("TestProperties.properties")) {
341 return new ByteArrayInputStream(myTestProperties, 0, TEST_PROPERTY_CONTENT.length());
343 return super.getResourceAsStream(name);
347 private class MyNestedFormLoader implements NestedFormLoader {
348 private final Map<String, String> myFormMap = new HashMap<String, String>();
350 public void registerNestedForm(String formName, String fileName) {
351 myFormMap.put(formName, fileName);
354 public LwRootContainer loadForm(String formFileName) throws Exception {
355 final String fileName = myFormMap.get(formFileName);
356 if (fileName != null) {
357 return loadFormData(fileName);
359 throw new UnsupportedOperationException("No nested form found for name " + formFileName);
362 public String getClassToBindName(LwRootContainer container) {
363 return container.getClassToBind();