1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.proxy.invoker;
19  
20  import junit.framework.TestCase;
21  import org.apache.commons.proxy.ObjectProvider;
22  import org.apache.commons.proxy.ProxyFactory;
23  import org.apache.commons.proxy.provider.ConstantProvider;
24  
25  import java.io.Serializable;
26  
27  /**
28   *
29   */
30  public class TestDuckTypingInvoker extends TestCase
31  {
32  //----------------------------------------------------------------------------------------------------------------------
33  // Other Methods
34  //----------------------------------------------------------------------------------------------------------------------
35  
36      public void testExactSignatureMatch()
37      {
38          final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
39          final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
40          final Duck duck = ( Duck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Duck.class } );
41          assertEquals( "Quack!", duck.sayQuack() );
42      }
43  
44      public void testNoMatchingMethod()
45      {
46          final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
47          final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
48          final Goose goose = ( Goose ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{ Goose.class } );
49          try
50          {
51              goose.sayHonk();
52              fail( "No matching method should be found." );
53          }
54          catch ( UnsupportedOperationException e )
55          {
56              // Do nothing, expected behavior!
57          }
58      }
59  
60      public void testMismatchingParameterType()
61      {
62          final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
63          final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
64          final ParameterizedDuck parameterizedDuck = ( ParameterizedDuck ) new ProxyFactory()
65                  .createInvokerProxy( invoker, new Class[]{ ParameterizedDuck.class } );
66          try
67          {
68              parameterizedDuck.sayQuack("Elmer");
69              fail( "No matching method should be found." );
70          }
71          catch ( UnsupportedOperationException e )
72          {
73              // Do nothing, expected behavior!
74          }
75      }
76  
77      public void testTargetHasCompatibleReturnType()
78      {
79          final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
80          final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
81          final SerializableDuck duck = ( SerializableDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
82                  SerializableDuck.class } );
83          assertEquals("Quack!", duck.sayQuack() );
84  
85      }
86  
87      public void testMismatchingReturnType()
88      {
89          final ObjectProvider targetProvider = new ConstantProvider( new LegacyDuck() );
90          final DuckTypingInvoker invoker = new DuckTypingInvoker( targetProvider );
91          final VoidReturnDuck voidDuck = ( VoidReturnDuck ) new ProxyFactory().createInvokerProxy( invoker, new Class[]{
92                  VoidReturnDuck.class } );
93          try
94          {
95              voidDuck.sayQuack();
96              fail( "No matching method should be found." );
97          }
98          catch ( UnsupportedOperationException e )
99          {
100             // Do nothing, expected behavior!
101         }
102     }
103 
104 //----------------------------------------------------------------------------------------------------------------------
105 // Inner Classes
106 //----------------------------------------------------------------------------------------------------------------------
107 
108     public static class LegacyDuck
109     {
110         public String sayQuack()
111         {
112             return "Quack!";
113         }
114     }
115 
116     public interface Duck
117     {
118         public String sayQuack();
119     }
120 
121     public interface SerializableDuck
122     {
123         public Serializable sayQuack();
124     }
125     
126     public interface ParameterizedDuck
127     {
128         public String sayQuack( String recipient );
129     }
130 
131     public interface VoidReturnDuck
132     {
133         public void sayQuack();
134     }
135 
136     public interface Goose
137     {
138         public void sayHonk();
139     }
140 }