| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.servicecomb.it.junit; |
| |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Stack; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import org.apache.commons.lang3.reflect.FieldUtils; |
| import org.apache.commons.lang3.reflect.MethodUtils; |
| import org.apache.servicecomb.core.Const; |
| import org.apache.servicecomb.foundation.common.utils.BeanUtils; |
| import org.apache.servicecomb.foundation.common.utils.JvmUtils; |
| import org.apache.servicecomb.it.Consumers; |
| import org.apache.servicecomb.it.extend.engine.GateRestTemplate; |
| import org.apache.servicecomb.it.extend.engine.ITSCBRestTemplate; |
| import org.junit.runner.JUnitCore; |
| import org.junit.runner.Result; |
| import org.junit.runner.notification.Failure; |
| import org.junit.runner.notification.RunListener; |
| |
| import com.google.common.reflect.ClassPath; |
| |
| public final class ITJUnitUtils { |
| private static ClassLoader classLoader = JvmUtils.findClassLoader(); |
| |
| private static JUnitCore jUnitCore = new JUnitCore(); |
| |
| private static Stack<String> parents = new Stack<>(); |
| |
| private static List<SCBFailure> failures = new ArrayList<>(); |
| |
| private static AtomicInteger runCount = new AtomicInteger(); |
| |
| private static String transport; |
| |
| private static String producerName; |
| |
| public static String getProducerName() { |
| return producerName; |
| } |
| |
| public static void setProducerName(String producerName) { |
| ITJUnitUtils.producerName = producerName; |
| } |
| |
| static { |
| jUnitCore.addListener(new RunListener() { |
| @Override |
| public void testFailure(Failure failure) { |
| SCBFailure scbFailure = new SCBFailure(failure.getDescription(), failure.getException()); |
| failures.add(scbFailure); |
| System.out.println(scbFailure.toString()); |
| } |
| }); |
| } |
| |
| private ITJUnitUtils() { |
| } |
| |
| public static int getRunCount() { |
| return runCount.get(); |
| } |
| |
| public static Stack<String> getParents() { |
| return parents; |
| } |
| |
| public static void pushTransport(String transport) { |
| ITJUnitUtils.transport = transport; |
| addParent(transport); |
| } |
| |
| public static String getTransport() { |
| return transport; |
| } |
| |
| public static void popTransport() { |
| ITJUnitUtils.transport = null; |
| popParent(); |
| } |
| |
| public static void addProducer(String producerName) { |
| ITJUnitUtils.setProducerName(producerName); |
| parents.add(producerName); |
| } |
| |
| public static void popProducer() { |
| ITJUnitUtils.setProducerName(null); |
| parents.pop(); |
| } |
| |
| public static void addParent(String name) { |
| parents.add(name); |
| } |
| |
| public static void popParent() { |
| parents.pop(); |
| } |
| |
| public static List<String> cloneParents() { |
| return new ArrayList<>(parents); |
| } |
| |
| public static List<SCBFailure> getFailures() { |
| return failures; |
| } |
| |
| public static void runFromPackage(String packageName) throws Throwable { |
| Class<?>[] classes = findAllClassInPackage(packageName); |
| run(classes); |
| } |
| |
| public static void run(Class<?>... classes) throws Throwable { |
| initClasses(classes); |
| Result result = jUnitCore.run(classes); |
| runCount.addAndGet(result.getRunCount()); |
| } |
| |
| public static void initClasses(Class<?>... classes) throws Throwable { |
| for (Class<?> cls : classes) { |
| for (Field field : FieldUtils.getAllFieldsList(cls)) { |
| if (Consumers.class.isAssignableFrom(field.getType()) |
| || GateRestTemplate.class.isAssignableFrom(field.getType()) |
| || ITSCBRestTemplate.class.isAssignableFrom(field.getType())) { |
| Object target = FieldUtils.readStaticField(field, true); |
| MethodUtils.invokeMethod(target, "init"); |
| } |
| } |
| } |
| } |
| |
| public static Class<?>[] findAllClassInPackage(String packageName) { |
| try { |
| return ClassPath.from(classLoader) |
| .getTopLevelClassesRecursive(packageName).stream() |
| .map(clsInfo -> clsInfo.load()) |
| .toArray(Class[]::new); |
| } catch (IOException e) { |
| throw new IllegalStateException("failed to find all classes in package " + packageName, e); |
| } |
| } |
| |
| public static void runWithHighwayAndRest(Class<?>... classes) throws Throwable { |
| runWithTransports(Arrays.asList(Const.HIGHWAY, Const.RESTFUL), classes); |
| } |
| |
| public static void runWithRest(Class<?>... classes) throws Throwable { |
| runWithTransports(Arrays.asList(Const.RESTFUL), classes); |
| } |
| |
| public static void runWithTransports(List<String> transports, Class<?>... classes) throws Throwable { |
| for (String transport : transports) { |
| ITJUnitUtils.pushTransport(transport); |
| |
| ITJUnitUtils.run(classes); |
| |
| ITJUnitUtils.popTransport(); |
| } |
| } |
| |
| /** |
| * <pre> |
| * make easier to debug only one test case |
| * normal test case: |
| * @Test |
| * public void test() { |
| * ... |
| * } |
| * |
| * when need to test one this case: |
| * 1.start SC/it-edge and your test target manually |
| * 2. change the code to |
| * @Test |
| * public void test() { |
| * ITJUnitUtils.initForDebug("it-producer", "rest"); |
| * ... |
| * } |
| * 3.run the case |
| * 4.after finished the debug, remove code of ITJUnitUtils.initForDebug |
| * </pre> |
| * @param producerName |
| * @param transport |
| */ |
| public static void initForDebug(String producerName, String transport) { |
| BeanUtils.init(); |
| ITJUnitUtils.addProducer(producerName); |
| ITJUnitUtils.pushTransport(transport); |
| try { |
| Class<?> testClass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); |
| ITJUnitUtils.initClasses(testClass); |
| } catch (Throwable e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| } |