Merge "Ensure the SignatureImpl overrides all methods"
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index b11abaa..7a21a46 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -687,16 +687,32 @@
         }
 
         @Override
+        protected int engineSign(byte[] outbuf, int offset, int len) throws SignatureException {
+            return getSpi().engineSign(outbuf, offset, len);
+        }
+
+        @Override
         protected void engineUpdate(byte arg0) throws SignatureException {
             getSpi().engineUpdate(arg0);
         }
 
         @Override
+        protected void engineUpdate(ByteBuffer input) {
+            getSpi().engineUpdate(input);
+        }
+
+        @Override
         protected boolean engineVerify(byte[] arg0) throws SignatureException {
             return getSpi().engineVerify(arg0);
         }
 
         @Override
+        protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+                throws SignatureException {
+            return getSpi().engineVerify(sigBytes, offset, length);
+        }
+
+        @Override
         protected void engineUpdate(byte[] arg0, int arg1, int arg2) throws SignatureException {
             getSpi().engineUpdate(arg0, arg1, arg2);
         }
@@ -707,6 +723,12 @@
         }
 
         @Override
+        protected void engineInitSign(PrivateKey arg0, SecureRandom arg1)
+                throws InvalidKeyException {
+            getSpi(arg0).engineInitSign(arg0, arg1);
+        }
+
+        @Override
         protected void engineInitVerify(PublicKey arg0) throws InvalidKeyException {
             getSpi(arg0).engineInitVerify(arg0);
         }
@@ -717,6 +739,11 @@
         }
 
         @Override
+        protected AlgorithmParameters engineGetParameters() {
+            return getSpi().engineGetParameters();
+        }
+
+        @Override
         protected void engineSetParameter(String arg0, Object arg1)
                 throws InvalidParameterException {
             getSpi().engineSetParameter(arg0, arg1);
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index f6e3a06..79a75c8 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -16,7 +16,9 @@
 
 package libcore.java.security;
 
+import java.lang.reflect.Method;
 import java.math.BigInteger;
+import java.security.AlgorithmParameters;
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
 import java.security.KeyFactory;
@@ -29,6 +31,7 @@
 import java.security.Security;
 import java.security.Signature;
 import java.security.SignatureException;
+import java.security.SignatureSpi;
 import java.security.spec.DSAPrivateKeySpec;
 import java.security.spec.DSAPublicKeySpec;
 import java.security.spec.ECFieldFp;
@@ -41,8 +44,11 @@
 import java.security.spec.RSAPrivateKeySpec;
 import java.security.spec.RSAPublicKeySpec;
 import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -1738,4 +1744,106 @@
         result = ecdsaVerify.verify(SIGNATURE);
         assertEquals(false, result);
     }
+
+    /**
+     * When an instance of a Signature is obtained, it's actually wrapped in an
+     * implementation that makes sure the correct SPI is selected and then calls
+     * through to the underlying SPI. We need to make sure that all methods on
+     * the delegate are wrapped and don't call directly into
+     * {@link SignatureSpi}.
+     */
+    public void testSignatureDelegateOverridesAllMethods() throws Exception {
+        Signature sig = Signature.getInstance("SHA1withRSA");
+
+        /*
+         * Make sure we're dealing with a delegate and not an actual instance of
+         * Signature.
+         */
+        Class<?> sigClass = sig.getClass();
+        assertFalse(sigClass.equals(SignatureSpi.class));
+        assertFalse(sigClass.equals(Signature.class));
+
+        List<String> methodsNotOverridden = new ArrayList<String>();
+
+        for (Method spiMethod : SignatureSpi.class.getDeclaredMethods()) {
+            try {
+                sigClass.getDeclaredMethod(spiMethod.getName(), spiMethod.getParameterTypes());
+            } catch (NoSuchMethodException e) {
+                methodsNotOverridden.add(spiMethod.toString());
+            }
+        }
+
+        assertEquals(Collections.EMPTY_LIST, methodsNotOverridden);
+    }
+
+    public void testGetParameters_IsCalled() throws Exception {
+        Signature sig = Signature.getInstance(FakeProviderForGetParametersTest.ALGORITHM,
+                new FakeProviderForGetParametersTest());
+
+        boolean[] getParametersCalled = new boolean[1];
+        sig.setParameter(FakeProviderForGetParametersTest.CALLBACK_PARAM_NAME, getParametersCalled);
+
+        assertFalse(getParametersCalled[0]);
+        sig.getParameters();
+        assertTrue(getParametersCalled[0]);
+    }
+
+    private static class FakeProviderForGetParametersTest extends Provider {
+        public static final String ALGORITHM = "FAKEFORGETPARAMETERS";
+        public static final String CALLBACK_PARAM_NAME = "callback";
+
+        protected FakeProviderForGetParametersTest() {
+            super("FakeProviderForGetParametersTest", 1.0, "For testing only");
+            put("Signature." + ALGORITHM, FakeSignatureWithGetParameters.class.getName());
+        }
+
+        public static class FakeSignatureWithGetParameters extends SignatureSpi {
+            private boolean[] callback;
+
+            @Override
+            protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+            }
+
+            @Override
+            protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+            }
+
+            @Override
+            protected void engineUpdate(byte b) throws SignatureException {
+            }
+
+            @Override
+            protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+            }
+
+            @Override
+            protected byte[] engineSign() throws SignatureException {
+                return null;
+            }
+
+            @Override
+            protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+                return false;
+            }
+
+            @Override
+            protected void engineSetParameter(String param, Object value)
+                    throws InvalidParameterException {
+                if (CALLBACK_PARAM_NAME.equals(param)) {
+                    callback = (boolean[]) value;
+                }
+            }
+
+            @Override
+            protected Object engineGetParameter(String param) throws InvalidParameterException {
+                return null;
+            }
+
+            @Override
+            protected AlgorithmParameters engineGetParameters() {
+                callback[0] = true;
+                return null;
+            }
+        }
+    }
 }