/******************************************************************************* * Copyright (c) 2010 Oak Ridge National Laboratory. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html ******************************************************************************/ package org.eclipse.nebula.visualization.widgets.figures; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.LightweightSystem; import org.eclipse.draw2d.StackLayout; import org.eclipse.nebula.visualization.internal.widgets.introspection.Introspectable; import org.eclipse.nebula.visualization.xygraph.util.XYGraphMediaFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.junit.Test; /** * The basement test class for all widgets to simplify the widget test. * * @author Xihui Chen * */ public abstract class AbstractWidgetTest { private int pdIndex = 0; private int runIndex = 1; private Figure testWidget; private Shell shell; private Text text; @Test public void testAll() throws Exception { shell = new Shell(); shell.open(); shell.setLayout(new GridLayout(1, false)); final Canvas canvas = new Canvas(shell, SWT.None); canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); text = new Text(shell, SWT.READ_ONLY); text.setFont(XYGraphMediaFactory.getInstance().getFont("default", 18, SWT.BOLD)); text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); final LightweightSystem lws = new LightweightSystem(canvas); lws.setContents(getTestBench()); shell.setSize(800, 500); testGetBeanInfo(); testWidget(); } public void testGetBeanInfo() throws Exception { if (getWidgetInstance() instanceof Introspectable) { final PropertyDescriptor[] pds = ((Introspectable) getWidgetInstance()) .getBeanInfo().getPropertyDescriptors(); final List<String> propNameList = new ArrayList<String>(); for (final PropertyDescriptor pd : pds) { System.out.println(pd.getName()); propNameList.add(pd.getName()); } final String[] predefinedPropNames = getPropertyNames(); for (final String p : predefinedPropNames) { if (!propNameList.contains(p)) { throw new Exception( "The widget doesn't have the property: " + p); } } final List<String> prePropList = Arrays.asList(predefinedPropNames); for (final String p : propNameList) { if (!prePropList.contains(p)) { System.err.println(p + " is not predefined in test."); } } } else { throw new Exception("The widget under test is not introspectable"); } } /** * Graphically test widget. * * @throws Exception */ public void testWidget() throws Exception { final Figure widget = getWidgetInstance(); shell.setText("Widget Figure Test"); final Display display = Display.getCurrent(); if (widget instanceof Introspectable) { final BeanInfo bi = ((Introspectable) widget).getBeanInfo(); final PropertyDescriptor[] pds = bi.getPropertyDescriptors(); final Runnable propertyTestTask = new Runnable() { public void run() { int nextRunTime = 10; if ((getTestRepeatCount() > 0) && (pdIndex > getTestRepeatCount() * pds.length)) { shell.close(); shell.dispose(); display.dispose(); return; } final PropertyDescriptor pd = pds[(pdIndex) % pds.length]; if (runIndex % getRepeatCountOnEachProperty() == 0) { pdIndex++; } final Method writeMethod = pd.getWriteMethod(); if (writeMethod != null) { final Object testData = generateTestData(pd, runIndex); if (testData != null) { try { text.setText(pd.getName() + " : " + testData); System.out.println(pd.getName() + " : " + testData); writeMethod.invoke(widget, testData); nextRunTime = getAutoTestSpeedInterval(); } catch (final Exception e) { e.printStackTrace(); } } } runIndex++; display.timerExec(nextRunTime, this); } }; if (isAutoTest()) { display.asyncExec(propertyTestTask); } } else { throw new Exception("The widget under test is not introspectable"); } while (!shell.isDisposed()) { try { if (!display.readAndDispatch()) { display.sleep(); } } catch (Exception e) { e.printStackTrace(); } } } /** * @return the count of the tests need to be repeated. -1 for infinite test. * Test can be terminated at any time by closing the shell. */ public int getTestRepeatCount() { return 2; } /** * @return the predefined properties of the widget. */ public String[] getPropertyNames() { return new String[] { "backgroundColor", "border", "bounds", "cursor", "enabled", "font", "foregroundColor", "location", "opaque", "size", "visible"}; } /** * @return the widget under test. */ public Figure getWidgetInstance() { if (testWidget == null) { testWidget = createTestWidget(); } return testWidget; } /** * @return create the widget to be tested. */ public abstract Figure createTestWidget(); /** * Generate test data. * * @param pd * the property descriptor of the property under test. * @param seed * the seed that could be used as a reference in generating test * data. It is the runIndex integer number by default. * @return */ public Object generateTestData(final PropertyDescriptor pd, final Object seed) { final int REPEAT_COUNT = getRepeatCountOnEachProperty(); final Class<?> propType = pd.getPropertyType(); if (propType == boolean.class) { if ((seed != null) && (seed instanceof Integer)) { return ((Integer) seed) % 2 == 0; } return Math.random() > 0.5; } else if (propType == Color.class) { return XYGraphMediaFactory.getInstance().getColor( new RGB((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255))); } else if (propType == double.class) { if ((seed != null) && (seed instanceof Integer)) { if (((Integer) seed) % REPEAT_COUNT == 1) { return Double.NaN; } else if (((Integer) seed) % REPEAT_COUNT == 2) { return Double.NEGATIVE_INFINITY; } else if (((Integer) seed) % REPEAT_COUNT == 3) { return Double.POSITIVE_INFINITY; } else if (((Integer) seed) % REPEAT_COUNT == 4) { return Double.MAX_VALUE; } else if (((Integer) seed) % REPEAT_COUNT == 5) { return Double.MIN_VALUE; } else if (((Integer) seed) % REPEAT_COUNT == 5) { return 0; } else { return Math.random() * 100; } } return Math.random() * 100; } else if (propType == int.class) { if (seed != null && seed instanceof Integer) { if (((Integer) seed) % REPEAT_COUNT == 1) return Integer.MAX_VALUE; else if (((Integer) seed) % REPEAT_COUNT == 2) return Integer.MIN_VALUE; else if (((Integer) seed) % REPEAT_COUNT == 3) return 0; else return (int) (Math.random() * 100); } return (int) (Math.random() * 100); } else if (propType == String.class) { return "Hello, I'm " + seed; } else if (propType == Font.class) { if (seed != null && seed instanceof Integer) { return XYGraphMediaFactory.getInstance().getFont("Arial", (Integer) seed % 100, (Integer) seed % 3); } } return null; } protected int getRepeatCountOnEachProperty() { return 8; } protected int getAutoTestSpeedInterval() { return 50; } /** * @return the test bench figure on which the widget will placed on. */ private Figure getTestBench() { final Figure result = new TestBench(); result.setLayoutManager(new StackLayout()); return result; } /** * @return true if the test will automatically poll on every property. */ public boolean isAutoTest() { return true; } public String[] concatenateStringArrays(final String[] A, final String[] B) { final String[] C = new String[A.length + B.length]; System.arraycopy(A, 0, C, 0, A.length); System.arraycopy(B, 0, C, A.length, B.length); return C; } class TestBench extends Figure { public TestBench() { add(getWidgetInstance()); } } }