/******************************************************************************* * Copyright (c) 2011, 2016 Eurotech and/or its affiliates * * 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 * * Contributors: * Eurotech * Red Hat Inc - Fix build warnings *******************************************************************************/ package org.eclipse.kura.test; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.kura.test.annotation.TestTarget; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; import org.osgi.util.tracker.BundleTrackerCustomizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestExtender implements BundleTrackerCustomizer<Object> { private static final Logger s_logger = LoggerFactory.getLogger(TestExtender.class); private static final String KURA_TEST_REPORT_FILENAME = "/tmp/kura_test_report.txt"; private final Map<Long, Bundle> m_bundles; private final BundleContext m_bundleContext; private BufferedWriter m_reportWriter; private final String m_platform; public TestExtender(String platform, BundleContext bundleContext) { this.m_bundles = new HashMap<Long, Bundle>(); this.m_bundleContext = bundleContext; this.m_platform = platform; new File(KURA_TEST_REPORT_FILENAME).delete(); } void addBundle(long bundleId, Bundle bundle) { this.m_bundles.put(bundleId, bundle); } public void testAll() { Set<Map.Entry<Long, Bundle>> entrySet = this.m_bundles.entrySet(); s_logger.debug("Testing all bundles"); for (Entry<Long, Bundle> entry : entrySet) { test(entry.getKey()); } } public void test(long bundleId) { s_logger.debug("Testing bundle: " + bundleId); List<Class<?>> testClazzs = getTestClass(this.m_bundles.get(bundleId)); for (Class<?> clazz : testClazzs) { try { if (!clazz.isInterface()) { s_logger.debug("Testing CLASS in bundle with ID: " + bundleId + " : [" + clazz.getName() + "]"); Test inspectClass = inspectClass(clazz); testClass(clazz.getName(), inspectClass, clazz.newInstance()); } } catch (Exception ex) { ex.printStackTrace(); } } } public Class<?> loadClass(String clazz, Bundle bundleHost) { try { Class<?> loadClass = bundleHost.loadClass(clazz); s_logger.debug("Loaded class: " + loadClass); return loadClass; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } public Bundle getHostBundle(Bundle bundle) { String fragment = bundle.getHeaders().get(org.osgi.framework.Constants.FRAGMENT_HOST) + ""; Bundle[] bundles = this.m_bundleContext.getBundles(); for (Bundle ibundle : bundles) { if (ibundle.getSymbolicName().equals(fragment)) { s_logger.debug("Host bundle is: " + ibundle.getSymbolicName()); return ibundle; } } throw new RuntimeException(); } public List<Class<?>> getTestClass(Bundle bundle) { try { List<Class<?>> clazzs = new ArrayList<Class<?>>(); Enumeration<?> entrs = bundle.findEntries("/", "*Test.class", true); if (entrs == null || !entrs.hasMoreElements()) { return Collections.emptyList(); } Bundle hostBundle = getHostBundle(bundle); while (entrs.hasMoreElements()) { URL e = (URL) entrs.nextElement(); String file = e.getFile(); String className = file.replaceAll("/", ".").replaceAll(".class", "").replaceFirst(".", ""); if (className.startsWith("bin.src.main.java.")) { className = className.substring(18); } else if (className.startsWith("targetes.")) { className = className.substring(9); } s_logger.debug("Trying to load class: " + className); Class<?> clazz = loadClass(className, hostBundle); s_logger.debug("Adding test class: " + clazz); clazzs.add(clazz); } return clazzs; } catch (Exception e) { e.printStackTrace(); return null; } } public Test inspectClass(Class<?> clazz) { Test test = new Test(); Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method method : declaredMethods) { if (method.isAnnotationPresent(org.junit.BeforeClass.class)) { s_logger.debug("Adding before class: " + method); test.setBeforeClass(method); } if (method.isAnnotationPresent(org.junit.AfterClass.class)) { s_logger.debug("Adding after class: " + method); test.setAfterClass(method); } if (method.isAnnotationPresent(org.junit.Before.class)) { s_logger.debug("Adding before: " + method); test.setBefore(method); } if (method.isAnnotationPresent(org.junit.After.class)) { s_logger.debug("Adding after: " + method); test.setAfter(method); } if (method.isAnnotationPresent(org.junit.Test.class)) { if (method.isAnnotationPresent(TestTarget.class)) { TestTarget testTargetAnnotation = method.getAnnotation(TestTarget.class); String[] potentialPlatforms = testTargetAnnotation.targetPlatforms(); for (String potentialPlatform : potentialPlatforms) { if (potentialPlatform.equals(TestTarget.PLATFORM_ALL) || potentialPlatform.equals(this.m_platform)) { s_logger.debug("TestTarget found " + potentialPlatform + " - Adding test: " + method); test.addTest(method); break; } } } else { s_logger.debug("No TestTarget Annotation present - Adding test: " + method); test.addTest(method); } } } return test; } public void testClass(String className, Test testClass, Object object) { try { try { if (testClass.getBeforeClass() != null) { testClass.getBeforeClass().invoke(object, new Object[0]); } this.m_reportWriter = new BufferedWriter(new FileWriter(new File(KURA_TEST_REPORT_FILENAME), true)); List<Method> tests = testClass.getTests(); for (Method method : tests) { try { if (testClass.getBefore() != null) { testClass.getBefore().invoke(object, new Object[0]); } try { method.invoke(object, new Object[0]); s_logger.info("Method : [ " + className + "." + method.getName() + " ] PASS"); this.m_reportWriter.write("Method : [ " + className + "." + method.getName() + " ] PASS\n"); this.m_reportWriter.flush(); } catch (Exception ex) { s_logger.error("Method : [ " + className + "." + method.getName() + " ] FAIL", ex); this.m_reportWriter = new BufferedWriter( new FileWriter(new File(KURA_TEST_REPORT_FILENAME), true)); this.m_reportWriter.write("Method : [ " + className + "." + method.getName() + " ] FAIL\n"); this.m_reportWriter.flush(); } } finally { if (testClass.getAfter() != null) { testClass.getAfter().invoke(object, new Object[0]); } } } } finally { if (testClass.getAfterClass() != null) { testClass.getAfterClass().invoke(object, new Object[0]); } this.m_reportWriter.close(); } } catch (Exception ex) { ex.printStackTrace(); } } @Override public Object addingBundle(Bundle bundle, BundleEvent event) { s_logger.debug("Tracker - Adding Bundle: " + bundle.getSymbolicName()); return bundle; } @Override public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) { s_logger.debug("Tracker - Modified Bundle: " + bundle.getSymbolicName()); } @Override public void removedBundle(Bundle bundle, BundleEvent event, Object object) { s_logger.debug("Tracker - Removed Bundle: " + bundle.getSymbolicName()); } }