| /* |
| * 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.felix.dm.itest.api; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.PrintStream; |
| |
| import org.junit.Assert; |
| |
| import org.apache.felix.dm.Component; |
| import org.apache.felix.dm.DependencyManager; |
| import org.apache.felix.dm.itest.util.Ensure; |
| import org.apache.felix.dm.itest.util.TestBase; |
| import org.apache.felix.service.command.CommandProcessor; |
| import org.apache.felix.service.command.CommandSession; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class FELIX2955_ShellCommandTest extends TestBase { |
| private long m_myBundleId; |
| private Bundle m_testBundle; |
| |
| public void testShellCommands() throws Throwable { |
| try { |
| m_myBundleId = context.getBundle().getBundleId(); |
| for (Bundle b : context.getBundles()) { |
| if (b.getSymbolicName().equals("org.apache.felix.dependencymanager.itest.bundle")) { |
| m_testBundle = b; |
| b.stop(); |
| break; |
| } |
| } |
| DependencyManager m = getDM(); |
| // helper class that ensures certain steps get executed in sequence |
| Ensure e = new Ensure(); |
| |
| Component shellClient = m.createComponent(); |
| Component missing = m.createComponent(); |
| |
| long shellClientId = shellClient.getComponentDeclaration().getId(); |
| long missingId = missing.getComponentDeclaration().getId(); |
| shellClient.setImplementation(new ShellClient(e, shellClientId, missingId)) |
| .add(m.createServiceDependency() |
| .setService(CommandProcessor.class) |
| .setRequired(true)); |
| |
| m.add(shellClient); |
| e.waitForStep(3, 5000); |
| // now create a component with a missing dependency |
| missing.setImplementation(new Object() { public String toString() { return "Object"; }}) |
| .add(m.createServiceDependency() |
| .setService(Missing.class) // Warning: don't use Object, or Runnable, which are already registered by bndtools ? |
| .setRequired(true)); |
| |
| m.add(missing); |
| e.step(4); |
| e.waitForStep(5, 5000); |
| m.remove(missing); |
| // now start/stop our test bundle, which publishes a service that uses the dependency manager |
| m_testBundle.start(); |
| m_testBundle.stop(); |
| e.step(6); |
| e.waitForStep(7, 5000); |
| e.ensure(); |
| m.remove(shellClient); |
| m_testBundle.start(); // restart the runtime bundle |
| m.clear(); |
| } |
| |
| catch (Throwable t) { |
| error("test failed", t); |
| } |
| } |
| |
| public class ShellClient { |
| volatile CommandProcessor m_commandProcessor; |
| private final Ensure m_ensure; |
| private final long m_shellClientId; |
| private final long m_missingId; |
| |
| public ShellClient(Ensure e, long shellClientId, long missingId) { |
| m_ensure = e; |
| m_shellClientId = shellClientId; |
| m_missingId = missingId; |
| } |
| |
| public void start() throws InterruptedException { |
| Thread t = new Thread("Shell Client") { |
| public void run() { |
| String bsn = context.getBundle().getSymbolicName(); |
| m_ensure.step(1); |
| execute("dm bid " + m_myBundleId, |
| "[" + m_myBundleId + "] " + bsn + "\n" + |
| " [" + m_shellClientId + "] ShellClient registered\n" + |
| " org.apache.felix.service.command.CommandProcessor service required available\n", |
| ""); |
| |
| m_ensure.step(2); |
| // see if there's anything that's not available |
| execute("dm notavail bid " + m_myBundleId, |
| "", |
| ""); |
| m_ensure.step(3); |
| // check again, now there should be something missing |
| m_ensure.waitForStep(4, 5000); |
| execute("dm notavail bid " + m_myBundleId, |
| "[" + m_myBundleId + "] " + bsn + "\n" + |
| " [" + m_missingId + "] Object unregistered\n" + |
| " " + Missing.class.getName() + " service required unavailable\n", |
| ""); |
| m_ensure.step(5); |
| m_ensure.waitForStep(6, 5000); |
| // this next step actually triggers the bug in FELIX-2955 |
| execute("dm notavail bid " + m_myBundleId, |
| "", |
| ""); |
| m_ensure.step(7); |
| } |
| }; |
| t.start(); |
| } |
| |
| @Override |
| public String toString() { |
| return "ShellClient"; |
| } |
| |
| public void execute(String command, String expectedOutput, String expectedError) { |
| try { |
| ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| ByteArrayOutputStream error = new ByteArrayOutputStream(); |
| CommandSession session = m_commandProcessor.createSession(System.in, new PrintStream(output), new PrintStream(error)); |
| session.execute(command); |
| |
| String out = output.toString(); |
| Assert.assertEquals(expectedOutput, out.toString()); |
| Assert.assertEquals(expectedError, error.toString()); |
| } |
| catch (Throwable throwable) { |
| m_ensure.throwable(throwable); |
| } |
| } |
| } |
| |
| public static class Missing { |
| } |
| } |