001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.proxy.invoker;
019    
020    import org.apache.commons.proxy.ObjectProvider;
021    import org.apache.commons.proxy.ProxyFactory;
022    import org.apache.commons.proxy.provider.ConstantProvider;
023    import org.apache.commons.proxy.util.AbstractTestCase;
024    
025    import java.io.Serializable;
026    
027    /**
028     *
029     */
030    public class TestDuckTypingInvoker extends AbstractTestCase
031    {
032    //**********************************************************************************************************************
033    // Other Methods
034    //**********************************************************************************************************************
035    
036        public void testExactSignatureMatch()
037        {
038            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
039            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
040            final Duck duck = ( Duck ) new ProxyFactory().createInvokerProxy(invoker, new Class[] {Duck.class});
041            assertEquals("Quack!", duck.sayQuack());
042        }
043    
044        public void testMismatchingParameterType()
045        {
046            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
047            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
048            final ParameterizedDuck parameterizedDuck = ( ParameterizedDuck ) new ProxyFactory()
049                    .createInvokerProxy(invoker, new Class[] {ParameterizedDuck.class});
050            try
051            {
052                parameterizedDuck.sayQuack("Elmer");
053                fail("No matching method should be found.");
054            }
055            catch( UnsupportedOperationException e )
056            {
057                // Do nothing, expected behavior!
058            }
059        }
060    
061        public void testMismatchingReturnType()
062        {
063            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
064            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
065            final VoidReturnDuck voidDuck = ( VoidReturnDuck ) new ProxyFactory().createInvokerProxy(invoker, new Class[] {
066                    VoidReturnDuck.class});
067            try
068            {
069                voidDuck.sayQuack();
070                fail("No matching method should be found.");
071            }
072            catch( UnsupportedOperationException e )
073            {
074                // Do nothing, expected behavior!
075            }
076        }
077    
078        public void testNoMatchingMethod()
079        {
080            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
081            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
082            final Goose goose = ( Goose ) new ProxyFactory().createInvokerProxy(invoker, new Class[] {Goose.class});
083            try
084            {
085                goose.sayHonk();
086                fail("No matching method should be found.");
087            }
088            catch( UnsupportedOperationException e )
089            {
090                // Do nothing, expected behavior!
091            }
092        }
093    
094        public void testSerialization()
095        {
096            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
097            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
098            assertSerializable(invoker);
099        }
100    
101        public void testTargetHasCompatibleReturnType()
102        {
103            final ObjectProvider targetProvider = new ConstantProvider(new LegacyDuck());
104            final DuckTypingInvoker invoker = new DuckTypingInvoker(targetProvider);
105            final SerializableDuck duck = ( SerializableDuck ) new ProxyFactory().createInvokerProxy(invoker, new Class[] {
106                    SerializableDuck.class});
107            assertEquals("Quack!", duck.sayQuack());
108        }
109    
110    //**********************************************************************************************************************
111    // Inner Classes
112    //**********************************************************************************************************************
113    
114        public interface Duck
115        {
116            public String sayQuack();
117        }
118    
119        public interface Goose
120        {
121            public void sayHonk();
122        }
123    
124        public static class LegacyDuck implements Serializable
125        {
126            public String sayQuack()
127            {
128                return "Quack!";
129            }
130        }
131    
132        public interface ParameterizedDuck
133        {
134            public String sayQuack( String recipient );
135        }
136    
137        public interface SerializableDuck
138        {
139            public Serializable sayQuack();
140        }
141    
142        public interface VoidReturnDuck
143        {
144            public void sayQuack();
145        }
146    }