| /******************************************************************************* |
| s |
| s This |
| * program and the accompanying materials are made available under the terms of |
| * the Eclipse Public License 2.0 which accompanies this distribution, and is |
| * available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.log.test; |
| |
| import java.io.File; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.atomic.AtomicReference; |
| import org.eclipse.equinox.log.ExtendedLogEntry; |
| import org.eclipse.equinox.log.SynchronousLogListener; |
| import org.eclipse.osgi.container.Module; |
| import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent; |
| import org.eclipse.osgi.internal.framework.EquinoxConfiguration; |
| import org.eclipse.osgi.launch.Equinox; |
| import org.eclipse.osgi.tests.OSGiTestsActivator; |
| import org.eclipse.osgi.tests.bundles.AbstractBundleTests; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleEvent; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.FrameworkEvent; |
| import org.osgi.framework.ServiceEvent; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.log.LogEntry; |
| import org.osgi.service.log.LogLevel; |
| import org.osgi.service.log.LogListener; |
| import org.osgi.service.log.LogReaderService; |
| import org.osgi.service.log.LogService; |
| import org.osgi.service.log.Logger; |
| import org.osgi.service.log.admin.LoggerAdmin; |
| import org.osgi.service.log.admin.LoggerContext; |
| |
| public class LogReaderServiceTest extends AbstractBundleTests { |
| |
| private LogService log; |
| private ServiceReference logReference; |
| private LogReaderService reader; |
| private ServiceReference readerReference; |
| private ServiceReference<LoggerAdmin> loggerAdminReference; |
| private LoggerAdmin loggerAdmin; |
| LoggerContext rootLoggerContext; |
| Map<String, LogLevel> rootLogLevels; |
| |
| public LogReaderServiceTest(String name) { |
| setName(name); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| logReference = OSGiTestsActivator.getContext().getServiceReference(LogService.class.getName()); |
| readerReference = OSGiTestsActivator.getContext().getServiceReference(LogReaderService.class.getName()); |
| loggerAdminReference = OSGiTestsActivator.getContext().getServiceReference(LoggerAdmin.class); |
| |
| log = (LogService) OSGiTestsActivator.getContext().getService(logReference); |
| reader = (LogReaderService) OSGiTestsActivator.getContext().getService(readerReference); |
| loggerAdmin = OSGiTestsActivator.getContext().getService(loggerAdminReference); |
| |
| rootLoggerContext = loggerAdmin.getLoggerContext(null); |
| rootLogLevels = rootLoggerContext.getLogLevels(); |
| |
| Map<String, LogLevel> copyLogLevels = new HashMap<>(rootLogLevels); |
| copyLogLevels.put(Logger.ROOT_LOGGER_NAME, LogLevel.TRACE); |
| rootLoggerContext.setLogLevels(copyLogLevels); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| rootLoggerContext.setLogLevels(rootLogLevels); |
| OSGiTestsActivator.getContext().ungetService(loggerAdminReference); |
| OSGiTestsActivator.getContext().ungetService(logReference); |
| OSGiTestsActivator.getContext().ungetService(readerReference); |
| super.tearDown(); |
| } |
| |
| public void testaddListener() throws Exception { |
| TestListener listener = new TestListener(); |
| reader.addLogListener(listener); |
| log.log(LogService.LOG_INFO, "info"); //$NON-NLS-1$ |
| assertTrue(listener.getEntryX().getLevel() == LogService.LOG_INFO); |
| } |
| |
| public void testaddListenerTwice() throws Exception { |
| TestListener listener = new TestListener(); |
| reader.addLogListener(listener); |
| reader.addLogListener(listener); |
| log.log(LogService.LOG_INFO, "info"); //$NON-NLS-1$ |
| assertTrue(listener.getEntryX().getLevel() == LogService.LOG_INFO); |
| } |
| |
| public void testaddNullListener() throws Exception { |
| try { |
| reader.addLogListener(null); |
| } catch (IllegalArgumentException t) { |
| return; |
| } |
| fail(); |
| } |
| |
| public void testBadListener() throws Exception { |
| LogListener listener = new LogListener() { |
| public synchronized void logged(LogEntry entry) { |
| notifyAll(); |
| throw new RuntimeException("Expected error for testBadListener."); //$NON-NLS-1$ |
| } |
| }; |
| reader.addLogListener(listener); |
| |
| synchronized (listener) { |
| log.log(LogService.LOG_INFO, "info"); //$NON-NLS-1$ |
| listener.wait(); |
| } |
| } |
| |
| public void testLogEntry() throws Exception { |
| TestListener listener = new TestListener(); |
| reader.addLogListener(listener); |
| long timeBeforeLog = System.currentTimeMillis(); |
| log.log(logReference, LogService.LOG_INFO, "info", new Throwable("test")); //$NON-NLS-1$ //$NON-NLS-2$ |
| LogEntry entry = listener.getEntryX(); |
| assertTrue(entry.getBundle() == OSGiTestsActivator.getContext().getBundle()); |
| assertTrue(entry.getMessage().equals("info")); //$NON-NLS-1$ |
| assertTrue(entry.getException().getMessage().equals("test")); //$NON-NLS-1$ |
| assertTrue(entry.getServiceReference() == logReference); |
| assertTrue(entry.getTime() >= timeBeforeLog); |
| assertTrue(entry.getLevel() == LogService.LOG_INFO); |
| } |
| |
| public void testLogBundleEventInfo() throws Exception { |
| // this is just a bundle that is harmless to start/stop |
| Bundle testBundle = installer.installBundle("test.logging.a"); //$NON-NLS-1$ |
| TestListener listener = new TestListener(testBundle.getLocation()); |
| reader.addLogListener(listener); |
| |
| testBundle.start(); |
| |
| ExtendedLogEntry entry = listener.getEntryX(); |
| assertTrue(entry.getLevel() == LogService.LOG_INFO); |
| assertEquals("Wrong level.", LogLevel.INFO, entry.getLogLevel()); |
| assertTrue("Wrong context: " + entry.getContext(), entry.getContext() instanceof BundleEvent); |
| } |
| |
| public void testLogBundleEventSynchronous() throws Exception { |
| // this is just a bundle that is harmless to start/stop |
| final Bundle testBundle = installer.installBundle("test.logging.a"); //$NON-NLS-1$ |
| final AtomicReference<Thread> logThread = new AtomicReference<>(); |
| LogListener listener = new SynchronousLogListener() { |
| @Override |
| public void logged(LogEntry entry) { |
| if (entry.getBundle() == testBundle) { |
| logThread.compareAndSet(null, Thread.currentThread()); |
| } |
| } |
| }; |
| reader.addLogListener(listener); |
| testBundle.start(); |
| |
| assertEquals("Wrong thread for synchronous bundle event logs.", Thread.currentThread(), logThread.get()); |
| |
| } |
| |
| public void testLogServiceEventInfo() throws Exception { |
| TestListener listener = new TestListener(); |
| reader.addLogListener(listener); |
| OSGiTestsActivator.getContext().registerService(Object.class.getName(), new Object(), null); |
| ExtendedLogEntry entry = listener.getEntryX(); |
| assertTrue(entry.getLevel() == LogService.LOG_INFO); |
| assertEquals("Wrong level.", LogLevel.INFO, entry.getLogLevel()); |
| assertTrue("Wrong context: " + entry.getContext(), entry.getContext() instanceof ServiceEvent); |
| } |
| |
| public void testLogServiceEventDebug() throws Exception { |
| ServiceRegistration registration = OSGiTestsActivator.getContext().registerService(Object.class.getName(), new Object(), null); |
| |
| TestListener listener = new TestListener(); |
| reader.addLogListener(listener); |
| registration.setProperties(new Hashtable()); |
| ExtendedLogEntry entry = listener.getEntryX(); |
| assertTrue(entry.getLevel() == LogService.LOG_DEBUG); |
| assertEquals("Wrong level.", LogLevel.DEBUG, entry.getLogLevel()); |
| assertTrue("Wrong context: " + entry.getContext(), entry.getContext() instanceof ServiceEvent); |
| } |
| |
| public void testLogFrameworkEvent() throws Exception { |
| Bundle testBundle = installer.installBundle("test.logging.a"); //$NON-NLS-1$ |
| final AtomicReference<LogEntry> logEntry = new AtomicReference<>(); |
| final CountDownLatch countDown = new CountDownLatch(1); |
| LogListener listener = new LogListener() { |
| @Override |
| public void logged(LogEntry entry) { |
| if ((entry.getLoggerName()).startsWith("Events.Framework.")) { |
| logEntry.set(entry); |
| countDown.countDown(); |
| } |
| } |
| }; |
| reader.addLogListener(listener); |
| installer.refreshPackages(new Bundle[] {testBundle}); |
| |
| countDown.await(5, TimeUnit.SECONDS); |
| |
| ExtendedLogEntry entry = (ExtendedLogEntry) logEntry.get(); |
| assertNotNull("Framework event not logged", entry); |
| assertTrue(entry.getLevel() == LogService.LOG_INFO); |
| assertEquals("Wrong level.", LogLevel.INFO, entry.getLogLevel()); |
| assertTrue("Wrong context: " + entry.getContext(), entry.getContext() instanceof FrameworkEvent); |
| assertEquals("Wrong bundle.", getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION), entry.getBundle()); |
| assertEquals("Wrong logger name.", "Events.Framework." + entry.getBundle().getSymbolicName(), entry.getLoggerName()); |
| } |
| |
| public void testLogFrameworkEventType() throws Exception { |
| final List<LogEntry> events = new CopyOnWriteArrayList<>(); |
| final CountDownLatch countDown = new CountDownLatch(3); |
| final Bundle b = getContext().getBundle(); |
| LogListener listener = new LogListener() { |
| @Override |
| public void logged(LogEntry entry) { |
| if (b.equals(entry.getBundle())) { |
| events.add(entry); |
| countDown.countDown(); |
| } |
| } |
| }; |
| reader.addLogListener(listener); |
| |
| //publishing an event with ERROR |
| b.adapt(Module.class).getContainer().getAdaptor().publishContainerEvent(ContainerEvent.ERROR, b.adapt(Module.class), new Exception()); |
| //publishing an event with WARNING |
| b.adapt(Module.class).getContainer().getAdaptor().publishContainerEvent(ContainerEvent.WARNING, b.adapt(Module.class), new Exception()); |
| //publishing an event with INFO |
| b.adapt(Module.class).getContainer().getAdaptor().publishContainerEvent(ContainerEvent.INFO, b.adapt(Module.class), new Exception()); |
| |
| countDown.await(2, TimeUnit.SECONDS); |
| assertEquals("Wrong number of events", 3, events.size()); |
| assertEquals("Wrong type.", LogLevel.ERROR, events.get(0).getLogLevel()); |
| assertEquals("Wrong type.", LogLevel.WARN, events.get(1).getLogLevel()); |
| assertEquals("Wrong type.", LogLevel.INFO, events.get(2).getLogLevel()); |
| |
| } |
| |
| public void testLogHistory1() throws BundleException { |
| File config = OSGiTestsActivator.getContext().getDataFile(getName()); |
| Map<String, Object> configuration = new HashMap<>(); |
| configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath()); |
| configuration.put(EquinoxConfiguration.PROP_LOG_HISTORY_MAX, "10"); |
| Equinox equinox = new Equinox(configuration); |
| equinox.start(); |
| |
| try { |
| LogService testLog = equinox.getBundleContext().getService(equinox.getBundleContext().getServiceReference(LogService.class)); |
| LogReaderService testReader = equinox.getBundleContext().getService(equinox.getBundleContext().getServiceReference(LogReaderService.class)); |
| assertEquals("Expecting no logs.", 0, countLogEntries(testReader.getLog(), 0)); |
| // log 9 things |
| for (int i = 0; i < 9; i++) { |
| testLog.log(LogService.LOG_WARNING, String.valueOf(i)); |
| } |
| assertEquals("Wrong number of logs.", 9, countLogEntries(testReader.getLog(), 8)); |
| |
| // log 9 more things |
| for (int i = 9; i < 18; i++) { |
| testLog.log(LogService.LOG_WARNING, String.valueOf(i)); |
| } |
| |
| // should only be the last 10 logs (17-8) |
| assertEquals("Wrong number of logs.", 10, countLogEntries(testReader.getLog(), 17)); |
| } finally { |
| try { |
| equinox.stop(); |
| } catch (BundleException e) { |
| // ignore |
| } |
| } |
| } |
| |
| public void testLogHistory2() throws BundleException { |
| File config = OSGiTestsActivator.getContext().getDataFile(getName()); |
| Map<String, Object> configuration = new HashMap<>(); |
| configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath()); |
| Equinox equinox = new Equinox(configuration); |
| equinox.start(); |
| |
| try { |
| LogService testLog = equinox.getBundleContext().getService(equinox.getBundleContext().getServiceReference(LogService.class)); |
| LogReaderService testReader = equinox.getBundleContext().getService(equinox.getBundleContext().getServiceReference(LogReaderService.class)); |
| assertEquals("Expecting no logs.", 0, countLogEntries(testReader.getLog(), 0)); |
| // log 9 things |
| for (int i = 0; i < 9; i++) { |
| testLog.log(LogService.LOG_WARNING, String.valueOf(i)); |
| } |
| assertEquals("Wrong number of logs.", 0, countLogEntries(testReader.getLog(), 0)); |
| } finally { |
| try { |
| equinox.stop(); |
| } catch (BundleException e) { |
| // ignore |
| } |
| } |
| } |
| |
| private int countLogEntries(Enumeration logEntries, int startingMessage) { |
| int count = 0; |
| while (logEntries.hasMoreElements()) { |
| LogEntry entry = (LogEntry) logEntries.nextElement(); |
| assertEquals("Wrong log message.", String.valueOf(startingMessage), entry.getMessage()); |
| startingMessage--; |
| count++; |
| } |
| return count; |
| } |
| |
| public void testLoggerContextSetLogLevelsWithBundleInstalledAndLogger() throws Exception { |
| Bundle bundle = null; |
| String loggerName = "test.logger"; |
| try { |
| bundle = installer.installBundle("test.logging.a"); |
| bundle.start(); |
| Logger logger = log.getLogger(bundle, loggerName, Logger.class); |
| assertNotNull("Logger cannot be null", logger); |
| //Bundle is installed and a logger is associated with that bundle before setting the log level |
| setAndAssertLogLevel(bundle.getSymbolicName(), loggerName); |
| |
| TestListener listener = new TestListener(bundle.getLocation()); |
| reader.addLogListener(listener); |
| for (LogLevel logLevel : LogLevel.values()) { |
| String message = logLevel.name() + " MESSAGE"; |
| doLogging(bundle, logger, listener, logLevel, message); |
| } |
| } finally { |
| if (bundle != null) { |
| bundle.stop(); |
| bundle.uninstall(); |
| } |
| } |
| } |
| |
| public void testLoggerContextSetLogLevelsWithBundleInstalledAndNoLogger() throws Exception { |
| Bundle bundle = null; |
| String loggerName = "test.logger"; |
| try { |
| bundle = installer.installBundle("test.logging.a"); |
| bundle.start(); |
| //Bundle is installed but a logger is not associated with the bundle before setting the log level |
| setAndAssertLogLevel(bundle.getSymbolicName(), loggerName); |
| Logger logger = log.getLogger(bundle, loggerName, Logger.class); |
| assertNotNull("Logger cannot be null", logger); |
| TestListener listener = new TestListener(bundle.getLocation()); |
| reader.addLogListener(listener); |
| for (LogLevel logLevel : LogLevel.values()) { |
| String message = logLevel.name() + " MESSAGE"; |
| doLogging(bundle, logger, listener, logLevel, message); |
| } |
| } finally { |
| if (bundle != null) { |
| bundle.stop(); |
| bundle.uninstall(); |
| } |
| } |
| } |
| |
| public void testLoggerContextSetLogLevelsWithoutBundleAndLogger() throws Exception { |
| Bundle bundle = null; |
| String loggerName = "test.logger"; |
| //Bundle is not installed and also the logger is not associated with the bundle before setting the log level |
| setAndAssertLogLevel("test.logging.a", loggerName); |
| try { |
| bundle = installer.installBundle("test.logging.a"); |
| bundle.start(); |
| Logger logger = log.getLogger(bundle, loggerName, Logger.class); |
| assertNotNull("Logger cannot be null", logger); |
| TestListener listener = new TestListener(bundle.getLocation()); |
| reader.addLogListener(listener); |
| for (LogLevel logLevel : LogLevel.values()) { |
| String message = logLevel.name() + " MESSAGE"; |
| doLogging(bundle, logger, listener, logLevel, message); |
| } |
| } finally { |
| if (bundle != null) { |
| bundle.stop(); |
| bundle.uninstall(); |
| } |
| } |
| } |
| |
| private void setAndAssertLogLevel(String loggerContextName, String loggerName) { |
| LoggerContext loggerContext = loggerAdmin.getLoggerContext(loggerContextName); |
| Map<String, LogLevel> logLevels = loggerContext.getLogLevels(); |
| logLevels.put(loggerName, LogLevel.TRACE); |
| loggerContext.setLogLevels(logLevels); |
| assertEquals("Log levels not set for " + loggerContext.getName(), logLevels, loggerContext.getLogLevels()); |
| assertEquals("Wrong effective level", LogLevel.TRACE, loggerContext.getEffectiveLogLevel(loggerName)); |
| } |
| |
| private void doLogging(Bundle bundle, Logger logger, TestListener listener, LogLevel logLevel, String message) throws Exception { |
| logToLogger(logger, message, logLevel); |
| ExtendedLogEntry logEntry = listener.getEntryX(); |
| assertEquals("Wrong message logged", message, logEntry.getMessage()); |
| assertEquals("Wrong Log level", logLevel, logEntry.getLogLevel()); |
| assertEquals("Wrong Logger name", logger.getName(), logEntry.getLoggerName()); |
| assertEquals("Wrong bundle", bundle.getSymbolicName(), logEntry.getBundle().getSymbolicName()); |
| } |
| |
| private void logToLogger(Logger logger, String message, LogLevel logLevel) { |
| switch (logLevel) { |
| case AUDIT : |
| logger.audit(message); |
| break; |
| case ERROR : |
| logger.error(message); |
| break; |
| case WARN : |
| logger.warn(message); |
| break; |
| case INFO : |
| logger.info(message); |
| break; |
| case DEBUG : |
| logger.debug(message); |
| break; |
| case TRACE : |
| logger.trace(message); |
| break; |
| default : |
| fail("Unknown Log level"); |
| } |
| } |
| |
| public void testBundleEventsLogged() throws Exception { |
| String testBundleLoc = installer.getBundleLocation("test.logging.a"); |
| TestListener listener = new TestListener(testBundleLoc); |
| reader.addLogListener(listener); |
| Bundle bundle = installer.installBundle("test.logging.a"); |
| |
| bundle.start(); |
| bundle.stop(); |
| bundle.update(); |
| bundle.start(); |
| bundle.stop(); |
| bundle.uninstall(); |
| |
| assertBundleEventLog("BundleEvent INSTALLED", bundle, listener); |
| assertBundleEventLog("BundleEvent RESOLVED", bundle, listener); |
| assertBundleEventLog("BundleEvent STARTING", bundle, listener); |
| assertBundleEventLog("BundleEvent STARTED", bundle, listener); |
| assertBundleEventLog("BundleEvent STOPPING", bundle, listener); |
| assertBundleEventLog("BundleEvent STOPPED", bundle, listener); |
| assertBundleEventLog("BundleEvent UNRESOLVED", bundle, listener); |
| assertBundleEventLog("BundleEvent UPDATED", bundle, listener); |
| assertBundleEventLog("BundleEvent RESOLVED", bundle, listener); |
| assertBundleEventLog("BundleEvent STARTING", bundle, listener); |
| assertBundleEventLog("BundleEvent STARTED", bundle, listener); |
| assertBundleEventLog("BundleEvent STOPPING", bundle, listener); |
| assertBundleEventLog("BundleEvent STOPPED", bundle, listener); |
| assertBundleEventLog("BundleEvent UNRESOLVED", bundle, listener); |
| assertBundleEventLog("BundleEvent UNINSTALLED", bundle, listener); |
| |
| } |
| |
| private void assertBundleEventLog(String message, Bundle bundle, TestListener listener) throws InterruptedException { |
| LogEntry logEntry = listener.getEntryX(); |
| assertEquals("Wrong message.", message, logEntry.getMessage()); |
| assertEquals("Wrong bundle.", bundle, logEntry.getBundle()); |
| assertEquals("Wrong logger name.", "Events.Bundle." + bundle.getSymbolicName(), logEntry.getLoggerName()); |
| |
| } |
| |
| } |