Author: lfryc(a)redhat.com
Date: 2010-07-28 09:38:50 -0400 (Wed, 28 Jul 2010)
New Revision: 18254
Added:
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/MatrixConfigurator.java
Modified:
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/AbstractMetamerTest.java
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/internal/NamedType.java
Log:
listener configuring underlying test instance parameters using @Inject and @Use (replacing
of @Factory method approach)
Modified:
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/AbstractMetamerTest.java
===================================================================
---
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/AbstractMetamerTest.java 2010-07-28
12:32:53 UTC (rev 18253)
+++
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/AbstractMetamerTest.java 2010-07-28
13:38:50 UTC (rev 18254)
@@ -25,31 +25,17 @@
import static org.jboss.test.selenium.utils.URLUtils.buildUrl;
import static org.testng.Assert.assertEquals;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
import java.net.URL;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.lang.StringUtils;
import org.jboss.test.selenium.AbstractTestCase;
import org.jboss.test.selenium.dom.Event;
import org.jboss.test.selenium.encapsulated.JavaScript;
import org.jboss.test.selenium.locator.ElementLocator;
import org.jboss.test.selenium.locator.JQueryLocator;
-import org.richfaces.tests.metamer.ftest.annotations.Inject;
-import org.richfaces.tests.metamer.ftest.annotations.Use;
-import org.richfaces.tests.metamer.ftest.internal.NamedType;
import org.testng.SkipException;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
-import org.testng.annotations.Factory;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
@@ -203,154 +189,4 @@
protected void showControls() {
selenium.getEval(new JavaScript("window.showControls()"));
}
-
- @Factory
- public Object[] createTests() {
- // obtain parametrized constructor
- Constructor<?> constructor = null;
- for (Constructor<?> c : this.getClass().getConstructors()) {
- if (c.getParameterTypes().length > 0) {
- if (constructor == null) {
- constructor = c;
- } else {
- throw new IllegalStateException("there cannot be more than one
parametrized constructor");
- }
- }
- }
-
- if (constructor == null) {
- try {
- return new Object[] { this.getClass().newInstance() };
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- Map<NamedType, List<? extends Object>> parameters = new
LinkedHashMap<NamedType, List<? extends Object>>();
-
- // fill all parameters with null values to sorted map
- for (int i = 0; i < constructor.getParameterTypes().length; i++) {
- NamedType namedType = new NamedType(constructor.getParameterTypes()[i],
- constructor.getParameterAnnotations()[i]);
-
- if (parameters.containsKey(namedType)) {
- throw new IllegalStateException("there are ambiguous
parameters");
- } else {
- parameters.put(namedType, null);
- }
- }
-
- List<Field> injections = new LinkedList<Field>();
-
- for (Field field : this.getClass().getDeclaredFields()) {
- if (field.getAnnotation(Inject.class) != null) {
- if (field.getAnnotation(Use.class) != null) {
- NamedType namedType = new NamedType(field.getType(), (String) null);
- if (!parameters.containsKey(namedType)) {
- namedType = new NamedType(field.getType(), field.getName());
- }
- if (!parameters.containsKey(namedType)) {
- throw new IllegalStateException("cannot find equivalent
constructor parameter");
- }
-
- parameters.put(namedType, getUseParameter(field.getType(),
field.getAnnotation(Use.class)));
- } else {
- injections.add(field);
- }
- }
- }
-
- if (!injections.isEmpty()) {
- throw new IllegalStateException("all injections weren't
satisfied");
- }
-
- Object[][] parameterArray = new Object[parameters.size()][];
- int parameterPosition = 0;
- for (List<? extends Object> parameter : parameters.values()) {
- parameterArray[parameterPosition++] = parameter.toArray();
- }
-
- Object[][] combinations = generateCombinations(parameterArray);
-
- Object[] result = new Object[combinations.length];
- try {
- for (int i = 0; i < combinations.length; i++) {
- result[i] = constructor.newInstance(combinations[i]);
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- return result;
- }
-
- private Object[][] generateCombinations(Object[][] toCombine) {
- int count = 1;
- for (int outter = 0; outter < toCombine.length; outter++) {
- count *= toCombine[outter].length;
- }
-
- Object[][] result = new Object[count][toCombine.length];
-
- int[] position = new int[toCombine.length];
- Arrays.fill(position, 0);
- // int iterate = 0;
-
- for (int i = 0; i < count; i++) {
- result[i] = new Object[toCombine.length];
-
- for (int j = 0; j < toCombine.length; j++) {
- result[i][j] = toCombine[j][position[j]];
- }
-
- // iterate
- if (i + 1 < count) {
- for (int j = 0; j < toCombine.length; j++) {
- position[j] += 1;
- if (position[j] < toCombine[j].length) {
- break;
- } else {
- position[j] = 0;
- }
- }
- }
- }
-
- return result;
- }
-
- private List<? extends Object> getUseParameter(Class<?> parameterType,
Use use) {
- if (parameterType == int.class || parameterType == Integer.class) {
- return Arrays.asList(ArrayUtils.toObject(use.ints()));
- }
-
- // tries satisfy parameter from fields
- List<Object> result = new LinkedList<Object>();
- for (int i = 0; i < use.value().length; i++) {
- boolean satisfied = false;
- for (Field field : this.getClass().getDeclaredFields()) {
- String name = use.value()[i];
- name = StringUtils.replace(name, "*", ".+");
- name = StringUtils.replace(name, "?", ".");
- Pattern pattern = Pattern.compile(name);
- if (pattern.matcher(field.getName()).matches()) {
- if (parameterType.isAssignableFrom(field.getType())) {
- try {
- field.setAccessible(true);
- result.add(field.get(this));
- satisfied = true;
- } catch (Exception e) {
- throw new IllegalStateException("the field cannot be
obtained");
- }
- }
- }
- }
- if (satisfied) {
- continue;
- }
- throw new IllegalStateException("cannot find the field satysfying
injection point");
- }
- return result;
- }
-
}
Added:
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/MatrixConfigurator.java
===================================================================
---
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/MatrixConfigurator.java
(rev 0)
+++
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/MatrixConfigurator.java 2010-07-28
13:38:50 UTC (rev 18254)
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ *******************************************************************************/
+package org.richfaces.tests.metamer.ftest;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.richfaces.tests.metamer.ftest.annotations.Inject;
+import org.richfaces.tests.metamer.ftest.annotations.Use;
+import org.richfaces.tests.metamer.ftest.internal.NamedType;
+import org.testng.IAnnotationTransformer;
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.IMethodInstance;
+import org.testng.IMethodInterceptor;
+import org.testng.ITestContext;
+import org.testng.ITestResult;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.ITestAnnotation;
+
+/**
+ * @author <a href="mailto:ppitonak@redhat.com">Pavol Pitonak</a>
+ * @version $Revision$
+ */
+public class MatrixConfigurator implements IAnnotationTransformer,
IInvokedMethodListener, IMethodInterceptor {
+
+ private static final Class<? extends Annotation>[] AFTER_ANNOTATION = new
Class[] { AfterMethod.class,
+ AfterClass.class, AfterTest.class, AfterSuite.class };
+
+ Map<Class<?>, Map<Method, Configuration>> configurations = new
HashMap<Class<?>, Map<Method, Configuration>>();
+ LinkedList<Method> methods = new LinkedList<Method>();
+ boolean methodConfigured = false;
+
+ public List<IMethodInstance> intercept(List<IMethodInstance>
methodInstances, ITestContext context) {
+ for (IMethodInstance methodInstance : methodInstances) {
+ for (int i = 0; i < methodInstance.getMethod().getInvocationCount(); i++)
{
+ methods.add(methodInstance.getMethod().getMethod());
+ }
+ }
+ return methodInstances;
+ }
+
+ public void beforeInvocation(IInvokedMethod invokedMethod, ITestResult testResult) {
+ if (!methodConfigured) {
+ Method method = invokedMethod.getTestMethod().getMethod();
+ for (Class<? extends Annotation> annotationClass : AFTER_ANNOTATION) {
+ if (method.getAnnotation(annotationClass) != null) {
+ return;
+ }
+ }
+
+ configureMethod(testResult);
+
+ methodConfigured = true;
+ }
+ }
+
+ private void configureMethod(ITestResult testResult) {
+ Method realMethod = ((Queue<Method>) methods).poll();
+ Class<?> realClass;
+ try {
+ realClass = realMethod.getDeclaringClass();
+ } catch (NullPointerException e) {
+ System.out.println(e);
+ return;
+ }
+
+ final Object testInstance = testResult.getInstance();
+ Map<NamedType, Object> configuration =
configurations.get(realClass).get(realMethod).next();
+
+ try {
+ for (Entry<NamedType, Object> entry : configuration.entrySet()) {
+ final NamedType namedType = entry.getKey();
+ final Object parameter = entry.getValue();
+
+ Field field = realClass.getDeclaredField(namedType.getName());
+ Object assignment;
+ if (parameter instanceof String &&
!parameter.getClass().isAssignableFrom(field.getType())) {
+ Field parameterField = realClass.getDeclaredField((String)
parameter);
+ boolean isAccessible = parameterField.isAccessible();
+ if (!isAccessible) {
+ parameterField.setAccessible(true);
+ }
+ assignment = parameterField.get(testInstance);
+ parameterField.setAccessible(isAccessible);
+ } else {
+ assignment = parameter;
+ }
+
+ boolean isAccessible = field.isAccessible();
+ if (!isAccessible) {
+ field.setAccessible(true);
+ }
+ field.set(testInstance, assignment);
+ field.setAccessible(isAccessible);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot configure method", e);
+ }
+ }
+
+ public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
+ if (method.isTestMethod()) {
+ methodConfigured = false;
+ }
+ }
+
+ public void transform(ITestAnnotation annotation, Class testClass, Constructor
testConstructor, Method testMethod) {
+ int invocationCount = createConfiguration(testMethod.getDeclaringClass(),
testMethod);
+ annotation.setInvocationCount(invocationCount);
+ }
+
+ // public List<IMethodInstance> intercept(List<IMethodInstance> methods,
ITestContext context) {
+ // for (IMethodInstance methodInstance : methods) {
+ // int count = createConfiguration(methodInstance);
+ // for (int i = 0; i < count; i++) {
+ // methodInstances.add(methodInstance);
+ // }
+ // }
+ //
+ // return methodInstances;
+ // }
+
+ public int createConfiguration(Class<?> realClass, Method realMethod) {
+
+ // Class<?> realClass = method.getRealClass();
+ // String methodName = method.getName();
+
+ Map<NamedType, List<? extends Object>> parameters = new
LinkedHashMap<NamedType, List<? extends Object>>();
+
+ List<NamedType> unsatisfied = new LinkedList<NamedType>();
+
+ // get a list of satisfied and unsatisfied parameters/injections
+ for (Field field : realClass.getDeclaredFields()) {
+ if (field.getAnnotation(Inject.class) != null) {
+ final NamedType namedType = new NamedType(field.getType(),
field.getName());
+ if (field.getAnnotation(Use.class) != null ||
field.getAnnotation(Use.class) != null) {
+ parameters.put(namedType,
+ getUseParameter(realClass, field.getType(),
field.getAnnotation(Use.class)));
+ } else {
+ parameters.put(namedType, null);
+ unsatisfied.add(namedType);
+ }
+ }
+ }
+
+ // get a injections from method level
+ // Method realMethod;
+ // try {
+ // realMethod = realClass.getMethod(methodName);
+ // } catch (Exception e) {
+ // throw new IllegalStateException(e);
+ // }
+ for (Annotation annotation : realMethod.getAnnotations()) {
+ if (annotation.annotationType() == Use.class) {
+ Use use = (Use) annotation;
+ for (NamedType namedType : parameters.keySet()) {
+ if (namedType.getName().equals(use.field())) {
+ parameters.put(namedType, getUseParameter(realClass,
namedType.getParameterType(), use));
+ unsatisfied.remove(namedType);
+ }
+ }
+ }
+ }
+
+ if (!unsatisfied.isEmpty()) {
+ throw new IllegalStateException("cannot satisfy following injection
points: " + unsatisfied.toString());
+ }
+
+ Configuration configuration = new Configuration(parameters);
+
+ int count = 0;
+ while (configuration.hasNext()) {
+ configuration.next();
+ count += 1;
+ }
+ configuration.reset();
+
+ getClassConfigurations(realClass).put(realMethod, configuration);
+
+ return count;
+ }
+
+ private Map<Method, Configuration> getClassConfigurations(Class<?>
realClass) {
+ if (!configurations.containsKey(realClass)) {
+ configurations.put(realClass, new HashMap<Method, Configuration>());
+ }
+ return configurations.get(realClass);
+ }
+
+ private List<? extends Object> getUseParameter(Class<?> testClass,
Class<?> parameterType, Use use) {
+ if (parameterType == int.class || parameterType == Integer.class) {
+ return Arrays.asList(ArrayUtils.toObject(use.ints()));
+ }
+
+ // tries satisfy parameter from fields
+ List<Object> result = new LinkedList<Object>();
+ for (int i = 0; i < use.value().length; i++) {
+ boolean satisfied = false;
+ for (Field field : testClass.getDeclaredFields()) {
+ String name = use.value()[i];
+ name = StringUtils.replace(name, "*", ".+");
+ name = StringUtils.replace(name, "?", ".");
+ Pattern pattern = Pattern.compile(name);
+ if (pattern.matcher(field.getName()).matches()) {
+ if (parameterType.isAssignableFrom(field.getType())) {
+ result.add(field.getName());
+ satisfied = true;
+ }
+ }
+ }
+ if (satisfied) {
+ continue;
+ }
+ throw new IllegalStateException("cannot find the field satysfying
injection point");
+ }
+ return result;
+ }
+
+ private class Configuration implements Iterator<Map<NamedType, Object>>
{
+ Map<NamedType, List<? extends Object>> parameters;
+ Map<NamedType, Queue<? extends Object>> queues;
+ Queue<? extends Object> lastQueue;
+
+ public Configuration(Map<NamedType, List<? extends Object>>
parameters) {
+ this.parameters = parameters;
+ reset();
+ }
+
+ public void reset() {
+ queues = new LinkedHashMap<NamedType, Queue<? extends
Object>>();
+ for (Entry<NamedType, List<? extends Object>> entry :
parameters.entrySet()) {
+ final NamedType namedType = entry.getKey();
+ List<? extends Object> parameter = entry.getValue();
+
+ lastQueue = new LinkedList<Object>(parameter);
+ queues.put(namedType, lastQueue);
+ }
+ }
+
+ public Map<NamedType, Object> next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ Map<NamedType, Object> pass = new HashMap<NamedType, Object>();
+
+ for (Entry<NamedType, Queue<? extends Object>> entry :
queues.entrySet()) {
+ final NamedType namedType = entry.getKey();
+ final Queue<? extends Object> queue = entry.getValue();
+
+ pass.put(namedType, queue.peek());
+ }
+
+ for (Entry<NamedType, Queue<? extends Object>> entry :
queues.entrySet()) {
+ final NamedType namedType = entry.getKey();
+ final Queue<? extends Object> queue = entry.getValue();
+
+ queue.poll();
+
+ if (queue.isEmpty() && hasNext()) {
+ List<? extends Object> parameter = parameters.get(namedType);
+ queues.put(namedType, new LinkedList<Object>(parameter));
+ } else {
+ break;
+ }
+ }
+
+ return pass;
+ }
+
+ public boolean hasNext() {
+ return !lastQueue.isEmpty();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
Modified:
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/internal/NamedType.java
===================================================================
---
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/internal/NamedType.java 2010-07-28
12:32:53 UTC (rev 18253)
+++
root/tests/metamer/trunk/ftest-source/src/main/java/org/richfaces/tests/metamer/ftest/internal/NamedType.java 2010-07-28
13:38:50 UTC (rev 18254)
@@ -37,7 +37,7 @@
this.parameterType = parameterType;
this.name = name;
}
-
+
public NamedType(Class<?> parameterType, Annotation[] annotations) {
this.parameterType = parameterType;
for (Annotation annotation : annotations) {
@@ -46,6 +46,14 @@
}
}
}
+
+ public Class<?> getParameterType() {
+ return parameterType;
+ }
+
+ public String getName() {
+ return name;
+ }
@Override
public String toString() {