001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 *****************************************************************************/ 008 package org.picocontainer.lifecycle; 009 010 import static org.junit.Assert.assertEquals; 011 import static org.junit.Assert.assertTrue; 012 import static org.junit.Assert.fail; 013 import static org.picocontainer.Characteristics.CACHE; 014 import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme; 015 016 import java.io.Serializable; 017 018 import org.jmock.Expectations; 019 import org.jmock.Mockery; 020 import org.jmock.integration.junit4.JMock; 021 import org.junit.Before; 022 import org.junit.Test; 023 import org.junit.runner.RunWith; 024 import org.picocontainer.DefaultPicoContainer; 025 import org.picocontainer.Disposable; 026 import org.picocontainer.PicoLifecycleException; 027 import org.picocontainer.Startable; 028 import org.picocontainer.containers.EmptyPicoContainer; 029 import org.picocontainer.monitors.NullComponentMonitor; 030 031 /** 032 * 033 * @author Mauro Talevi 034 */ 035 @SuppressWarnings("serial") 036 @RunWith(JMock.class) 037 public class StartableLifecycleStrategyTestCase { 038 039 private Mockery mockery = mockeryWithCountingNamingScheme(); 040 041 private StartableLifecycleStrategy strategy; 042 043 @Before 044 public void setUp(){ 045 strategy = new StartableLifecycleStrategy(new NullComponentMonitor()); 046 } 047 048 @Test public void testStartable(){ 049 Object startable = mockComponent(true, false); 050 strategy.start(startable); 051 strategy.stop(startable); 052 } 053 054 @Test public void testDisposable(){ 055 Object startable = mockComponent(false, true); 056 strategy.dispose(startable); 057 } 058 059 @Test public void testSerializable(){ 060 Object serializable = mockComponent(false, false); 061 strategy.start(serializable); 062 strategy.stop(serializable); 063 strategy.dispose(serializable); 064 } 065 066 private Object mockComponent(boolean startable, boolean disposeable) { 067 if ( startable ) { 068 final Startable mock = mockery.mock(Startable.class); 069 mockery.checking(new Expectations() {{ 070 one(mock).start(); 071 one(mock).stop(); 072 }}); 073 return mock; 074 } 075 if ( disposeable ) { 076 final Disposable mock = mockery.mock(Disposable.class); 077 mockery.checking(new Expectations() {{ 078 one(mock).dispose(); 079 }}); 080 return mock; 081 } 082 return mockery.mock(Serializable.class); 083 } 084 085 interface ThirdPartyStartable { 086 void sstart() throws Exception; 087 void sstop(); 088 void ddispose(); 089 } 090 public static class ThirdPartyStartableComponent implements ThirdPartyStartable { 091 StringBuilder sb; 092 public ThirdPartyStartableComponent(StringBuilder sb) { 093 this.sb = sb; 094 } 095 096 public void sstart() { 097 sb.append("<"); 098 } 099 100 public void sstop() { 101 sb.append(">"); 102 } 103 104 public void ddispose() { 105 sb.append("!"); 106 } 107 } 108 109 public static class ThirdPartyStartableComponent2 implements ThirdPartyStartable { 110 public void sstart() { 111 throw new UnsupportedOperationException(); 112 } 113 public void sstop() { 114 } 115 116 public void ddispose() { 117 } 118 } 119 120 public static class ThirdPartyStartableComponent3 implements ThirdPartyStartable { 121 public void sstart() throws Exception { 122 throw new Exception("whoaa!"); 123 } 124 public void sstop() { 125 } 126 127 public void ddispose() { 128 } 129 } 130 131 @Test public void testThirdPartyStartableAndDisposable() { 132 DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer()); 133 StringBuilder sb = new StringBuilder(); 134 pico.addComponent(sb); 135 pico.as(CACHE).addComponent(ThirdPartyStartableComponent.class); 136 pico.start(); 137 pico.stop(); 138 pico.dispose(); 139 assertEquals("<>!", sb.toString()); 140 141 } 142 143 @Test public void testThirdPartyStartableCanNoteLifecycleRuntimeException() { 144 DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer()); 145 pico.as(CACHE).addComponent(ThirdPartyStartableComponent2.class); 146 try { 147 pico.start(); 148 fail("should have barfed"); 149 } catch (PicoLifecycleException e) { 150 assertTrue(e.getCause() instanceof UnsupportedOperationException); 151 assertTrue(e.getInstance() instanceof ThirdPartyStartableComponent2); 152 assertEquals("sstart", e.getMethod().getName()); 153 // expected 154 } 155 156 } 157 158 @Test public void testThirdPartyStartableCanNoteLifecycleException() { 159 DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer()); 160 pico.as(CACHE).addComponent(ThirdPartyStartableComponent3.class); 161 try { 162 pico.start(); 163 fail("should have barfed"); 164 } catch (PicoLifecycleException e) { 165 Throwable throwable = e.getCause(); 166 assertTrue(throwable instanceof Exception); 167 String s = throwable.getMessage(); 168 assertEquals("whoaa!", s); 169 assertTrue(e.getInstance() instanceof ThirdPartyStartableComponent3); 170 assertEquals("sstart", e.getMethod().getName()); 171 // expected 172 } 173 174 } 175 176 private static class MyStartableLifecycleStrategy extends StartableLifecycleStrategy { 177 public MyStartableLifecycleStrategy() { 178 super(new NullComponentMonitor()); 179 } 180 181 protected String getStopMethodName() { 182 return "sstop"; 183 } 184 185 protected String getStartMethodName() { 186 return "sstart"; 187 } 188 189 protected String getDisposeMethodName() { 190 return "ddispose"; 191 } 192 193 194 protected Class getStartableInterface() { 195 return ThirdPartyStartable.class; 196 } 197 198 protected Class getDisposableInterface() { 199 return ThirdPartyStartable.class; 200 } 201 } 202 }