package com.here.account.auth;

import static org.junit.Assert.assertTrue;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

import org.junit.Before;
import org.junit.Test;

import com.here.account.http.HttpProvider.HttpRequest;
import com.here.account.util.Clock;

public class OAuth1SignerTest {

    private String clientId = "clientId";
    private String clientSecret = "clientSecret";
    
    private OAuth1Signer oauth1Signer;
    
    MyHttpRequest httpRequest;
    
    private static class MyHttpRequest implements HttpRequest {
        
        private String authorizationHeader;
        
        public MyHttpRequest() {
            super();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void addAuthorizationHeader(String value) {
            this.authorizationHeader = value;
        }

        public String getAuthorizationHeader() {
            return this.authorizationHeader;
        }
        
    }
    
    private String method;
    private String url;
    private Clock clock;
    
    @Before
    public void setUp() {
        this.clock = new Clock() {

            @Override
            public long currentTimeMillis() {
                // TODO Auto-generated method stub
                return 0;
            }

            @Override
            public void schedule(ScheduledExecutorService scheduledExecutorService, Runnable runnable,
                    long millisecondsInTheFutureToSchedule) {
                // TODO Auto-generated method stub
                
            }
            
        };
        this.oauth1Signer = new MyOAuth1Signer(clock, clientId, clientSecret);
        this.httpRequest = new MyHttpRequest();
        this.method = "GET";
        this.url = "http://localhost:8080/whatever";
    }
    
    protected static class MyOAuth1Signer extends OAuth1Signer {
        public MyOAuth1Signer(Clock clock, String clientId, String clientSecret) {
            super(clock, clientId, clientSecret);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        protected void nextBytes(byte[] bytes) {
            byte a = 0x00;
            for (int i = 0; i < bytes.length; i++) {
                bytes[i] = a;
                a += 0x01;
            }
        }
    }
    
    @Test
    public void test_sign_formParams_impactsSignature() {
        Map<String, List<String>> formParams = null;
        
        oauth1Signer.authorize(httpRequest, method, url, formParams);
        String signatureNull = httpRequest.getAuthorizationHeader();
        
        formParams = new HashMap<String, List<String>>();
        oauth1Signer.authorize(httpRequest, method, url, formParams);
        String signatureEmpty = httpRequest.getAuthorizationHeader();
        
        formParams.put("foo", Collections.singletonList("bar"));
        oauth1Signer.authorize(httpRequest, method, url, formParams);
        String signatureFooBar = httpRequest.getAuthorizationHeader();

        formParams.put("foo", Collections.singletonList("none"));
        oauth1Signer.authorize(httpRequest, method, url, formParams);
        String signatureFooNone = httpRequest.getAuthorizationHeader();

        assertTrue("signatureNull was null, but shouldn't be", null != signatureNull);
        assertTrue("signatureEmpty was null, but shouldn't be", null != signatureEmpty);
        assertTrue("signatureFooBar was null, but shouldn't be", null != signatureFooBar);
        assertTrue("signatureFooNone was null, but shouldn't be", null != signatureFooNone);
        
        assertTrue("signatureNull "+signatureNull+" doesn't match signatureEmpty "+signatureEmpty,
                signatureNull.equals(signatureEmpty));
        assertTrue("signatureNull "+signatureNull+" matches signatureFooBar "+signatureFooBar+", but shouldn't",
                !signatureNull.equals(signatureFooBar));
        assertTrue("signatureFooBar "+signatureFooBar+" matches signatureFooNone "+signatureFooNone+", but shouldn't",
                !signatureFooBar.equals(signatureFooNone));
    }
}

@@ -65,24 +65,139 @@
 ssertTrue;%0A%0A
+import java.security.InvalidKeyException;%0Aimport java.security.Key;%0Aimport java.security.NoSuchAlgorithmException;%0A
 import java.
@@ -214,16 +214,16 @@
 ctions;%0A
-
 import j
@@ -281,24 +281,47 @@
 a.util.Map;%0A
+import java.util.UUID;%0A
 import java.
@@ -359,24 +359,137 @@
 orService;%0A%0A
+import javax.crypto.Mac;%0Aimport javax.crypto.spec.SecretKeySpec;%0A%0Aimport org.apache.commons.codec.binary.Base64;%0A
 import org.j
@@ -4429,10 +4429,1322 @@
 ;%0A    %7D%0A
+    %0A    /**%0A     * Demonstrate the tradeoffs between HmacSHA1 and HmacSHA256 signature methods.%0A     * %0A     * @throws NoSuchAlgorithmException%0A     * @throws InvalidKeyException%0A     */%0A    @Test%0A    public void test_HmacSHA1_HmacSHA256() throws NoSuchAlgorithmException, InvalidKeyException %7B%0A        String key = UUID.randomUUID().toString();%0A        %0A        String input = %22my dog has fleas%22;%0A        %0A        String sig1 = HmacSHAN(key, %22HmacSHA1%22, input);%0A        assertTrue(%22sig1 was null for HmacSHA1%22, null != sig1);%0A        %0A        String sig256 = HmacSHAN(key, %22HmacSHA256%22, input);%0A        assertTrue(%22sig256 was null for HmacSHA256%22, null != sig256);%0A        %0A        assertTrue(%22sig1 %22+sig1+%22 wasn't smaller than sig256 %22+sig256, sig1.length() %3C sig256.length());%0A%0A    %7D%0A    %0A    protected String HmacSHAN(String keyString, String algorithm, String baseString) throws NoSuchAlgorithmException, InvalidKeyException %7B%0A        Key signingKey = new SecretKeySpec(keyString.getBytes(), algorithm);%0A        Mac mac = Mac.getInstance(algorithm);%0A        mac.init(signingKey);%0A    %0A        //generate signature bytes%0A        byte%5B%5D signatureBytes = mac.doFinal(baseString.toString().getBytes());%0A    %0A        // base64-encode the hmac%0A        return new Base64().encodeAsString(signatureBytes);%0A    %7D%0A%0A%0A
 %7D%0A

add a test showing diff between hmac-sha1 and hmac-sha256.