blob: ccaf6040ac974845fe937309908a096734ed2270 [file] [log] [blame]
/*
* 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 test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import javax.crypto.Cipher;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.shell.DMCommand;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class DMCommandTest {
/** System output just used to debug **/
private final static PrintStream OUT =
new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out), 128));
/** Setup a ByteArrayOutputStream to capture the system out printlines */
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
private DependencyManager dm;
@Spy @InjectMocks private DMCommand dme;
@Mock private BundleContext m_bundleContext;
@Before
public void setUp() throws Exception {
m_bundleContext = mock(BundleContext.class);
Bundle bundle = mock(Bundle.class);
when(m_bundleContext.getBundle()).thenReturn(bundle);
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
dm = new DependencyManager(m_bundleContext);
dme = new DMCommand(m_bundleContext);
}
@After
public void cleanUp() {
System.setOut(null);
System.setErr(null);
}
@Test
public void testWithoutAnyDependcyManagersShouldNotCrash() {
OUT.println("testWithoutAnyDependcyManagersShouldNotCrash");
setupEmptyBundles();
dme.wtf();
assertEquals("No unregistered components found\n", outContent.toString());
}
@Test
public void testASingleComponentShouldNotRegisterAsFailure() {
OUT.println("testASingleComponentShouldNotRegisterAsFailure");
setupEmptyBundles();
dm.add(dm.createComponent()
.setImplementation(Object.class)
.setInterface(Object.class.getName(), null)
);
dme.wtf();
assertEquals("No unregistered components found\n", outContent.toString());
}
@Test
public void testComponentThatDependsOnAOtheComponentShouldRegisterAsFailure() {
OUT.println("testComponentThatDependsOnAOtheComponentShouldRegisterAsFailure");
setupEmptyBundles();
DependencyManager dm = new DependencyManager(m_bundleContext);
DependencyManager.getDependencyManagers().add(dm);
Component component = dm.createComponent()
.setImplementation(Object.class)
.setInterface(Object.class.getName(), null)
.add(dm.createServiceDependency().setService(Math.class).setRequired(true));
dm.add(component);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("1 unregistered"));
assertTrue(output.contains("java.lang.Math"));
// remove the mess
dm.remove(component);
}
@Test
public void testComponentThatHaveCycliclyDependencyOnAOtheComponentShouldRegisterAsFailure() {
OUT.println("testComponentThatHaveCycliclyDependencyOnAOtheComponentShouldRegisterAsFailure");
setupEmptyBundles();
DependencyManager dm = new DependencyManager(m_bundleContext);
DependencyManager.getDependencyManagers().add(dm);
Component component1 = dm.createComponent()
.setImplementation(Cipher.class)
.setInterface(Cipher.class.getName(), null)
.add(dm.createServiceDependency().setService(Math.class).setRequired(true));
dm.add(component1);
Component component2 = dm.createComponent()
.setImplementation(Math.class)
.setInterface(Math.class.getName(), null)
.add(dm.createServiceDependency().setService(Cipher.class).setRequired(true));
dm.add(component2);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("-> java.lang.Math -> javax.crypto.Cipher -> java.lang.Math") ||
output.contains("-> javax.crypto.Cipher -> java.lang.Math -> javax.crypto.Cipher"));
// remove the mess
dm.remove(component1);
dm.remove(component2);
}
@Test
public void testCanFindRootFailure() {
OUT.println("testCanFindRootFailure");
setupEmptyBundles();
Component component1 = dm.createComponent()
.setImplementation(Object.class)
.setInterface(Object.class.getName(), null)
.add(dm.createServiceDependency().setService(Math.class).setRequired(true));
dm.add(component1);
Component component2 = dm.createComponent()
.setImplementation(Math.class)
.setInterface(Math.class.getName(), null)
.add(dm.createServiceDependency().setService(String.class).setRequired(true));
dm.add(component2);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("2 unregistered"));
assertTrue(output.contains("java.lang.String"));
// remove the mess
dm.remove(component1);
dm.remove(component2);
}
@Test
public void testCanFindRootFailureWithSecondair() {
OUT.println("testCanFindRootFailureWithSecondair");
setupEmptyBundles();
Component component1 = dm.createComponent()
.setImplementation(Object.class)
.setInterface(Object.class.getName(), null)
.add(dm.createServiceDependency().setService(Math.class).setRequired(true));
dm.add(component1);
Component component2 = dm.createComponent()
.setImplementation(Math.class)
.setInterface(Math.class.getName(), null)
.add(dm.createServiceDependency().setService(Float.class).setRequired(true));
dm.add(component2);
Component component3 = dm.createComponent()
.setImplementation(Object.class)
.setInterface(new String[] {Object.class.getName(), Float.class.getName()}, null)
.add(dm.createServiceDependency().setService(String.class).setRequired(true));
dm.add(component3);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("3 unregistered"));
assertTrue(output.contains("java.lang.String"));
assertFalse(output.contains("java.lang.Float"));
// remove the mess
dm.remove(component1);
dm.remove(component2);
dm.remove(component3);
}
@Test
public void testCanFindRootFailureWithTwoFailures() {
OUT.println("testCanFindRootFailureWithTwoFailures");
setupEmptyBundles();
Component component1 = dm.createComponent()
.setImplementation(Object.class)
.setInterface(Object.class.getName(), null)
.add(dm.createServiceDependency().setService(Math.class).setRequired(true))
.add(dm.createServiceDependency().setService(Long.class).setRequired(true));
dm.add(component1);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("1 unregistered"));
assertTrue(output.contains("java.lang.Math"));
assertTrue(output.contains("java.lang.Long"));
// remove the mess
dm.remove(component1);
}
@Test
public void testInstalledBundleListing() {
OUT.println("testInstalledBundleListing");
Bundle bundle1 = mock(Bundle.class);
when(bundle1.getState()).thenReturn(Bundle.INSTALLED);
when(bundle1.getSymbolicName()).thenReturn("BadBundle");
setupBundles(bundle1);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("following bundles are in the INSTALLED"));
assertTrue(output.contains("[0] BadBundle"));
// Will print null if it gets bundle 2, that should not happen
assertFalse(output.contains("null"));
}
@Test
public void testResolvedBundleListing() {
OUT.println("testResolvedBundleListing");
Bundle bundle1 = mock(Bundle.class);
when(bundle1.getState()).thenReturn(Bundle.RESOLVED);
when(bundle1.getSymbolicName()).thenReturn("BadBundle");
Hashtable<String, String> headers = new Hashtable<>();
when(bundle1.getHeaders()).thenReturn(headers);
setupBundles(bundle1);
dme.wtf();
String output = outContent.toString();
assertTrue(output.contains("following bundles are in the RESOLVED"));
assertTrue(output.contains("[0] BadBundle"));
assertFalse(output.contains("null"));
}
@Test
public void testResolvedBundleListingButNoFragements() {
OUT.println("testResolvedBundleListingButNoFragements");
Bundle bundle1 = mock(Bundle.class);
when(bundle1.getState()).thenReturn(Bundle.RESOLVED);
when(bundle1.getSymbolicName()).thenReturn("BadBundle");
Hashtable<String, String> headers = new Hashtable<>();
headers.put("Fragment-Host", "some value");
when(bundle1.getHeaders()).thenReturn(headers);
setupBundles(bundle1);
dme.wtf();
String output = outContent.toString();
assertFalse(output.contains("following bundles are in the RESOLVED"));
// Will print null if it gets bundle 2, that should not happen
assertFalse(output.contains("null"));
}
private void setupBundles( Bundle bundle1) {
Bundle bundle2 = mock(Bundle.class);
when(bundle2.getState()).thenReturn(Bundle.ACTIVE);
when(m_bundleContext.getBundles()).thenReturn(new Bundle[] { bundle1, bundle2});
}
/** Sets up the bundle context without any bundles */
private void setupEmptyBundles() {
when(m_bundleContext.getBundles()).thenReturn(new Bundle[] {});
}
}