package com.braintreepayments.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;

import androidx.test.core.app.ApplicationProvider;

import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.concurrent.TimeUnit;

@RunWith(RobolectricTestRunner.class)
public class ConfigurationCacheUnitTest {

    BraintreeSharedPreferences braintreeSharedPreferences;
    Context context;

    @Before
    public void beforeEach() throws GeneralSecurityException, IOException {
        context = ApplicationProvider.getApplicationContext();
        braintreeSharedPreferences = mock(BraintreeSharedPreferences.class);
    }

    @Test
    public void saveConfiguration_savesConfigurationInSharedPrefs() throws JSONException, UnexpectedException {
        Configuration configuration = Configuration.fromJson(Fixtures.CONFIGURATION_WITHOUT_ACCESS_TOKEN);

        ConfigurationCache sut = new ConfigurationCache(braintreeSharedPreferences);
        sut.saveConfiguration(context, configuration, "cacheKey", 123);
        verify(braintreeSharedPreferences).putStringAndLong(context, "cacheKey", configuration.toJson(), "cacheKey_timestamp", 123L);
    }

    @Test
    public void getConfiguration_returnsConfigurationFromSharedPrefs() throws JSONException, UnexpectedException {
        Configuration configuration = Configuration.fromJson(Fixtures.CONFIGURATION_WITHOUT_ACCESS_TOKEN);
        when(braintreeSharedPreferences.containsKey(context, "cacheKey_timestamp")).thenReturn(true);
        when(braintreeSharedPreferences.getLong(context, "cacheKey_timestamp")).thenReturn(0L);
        when(braintreeSharedPreferences.getString(context, "cacheKey", "")).thenReturn(configuration.toJson());

        ConfigurationCache sut = new ConfigurationCache(braintreeSharedPreferences);
        sut.saveConfiguration(context, configuration, "cacheKey", 0);

        assertEquals(configuration.toJson(), sut.getConfiguration(context, "cacheKey", TimeUnit.MINUTES.toMillis(5)-1));
    }

    @Test
    public void getConfiguration_whenCacheEntryExpires_returnsNull() throws JSONException, UnexpectedException {
        Configuration configuration = Configuration.fromJson(Fixtures.CONFIGURATION_WITHOUT_ACCESS_TOKEN);
        when(braintreeSharedPreferences.containsKey(context, "cacheKey_timestamp")).thenReturn(true);
        when(braintreeSharedPreferences.getLong(context, "cacheKey_timestamp")).thenReturn(TimeUnit.MINUTES.toMillis(5));
        when(braintreeSharedPreferences.getString(context, "cacheKey","")).thenReturn(configuration.toJson());

        ConfigurationCache sut = new ConfigurationCache(braintreeSharedPreferences);
        sut.saveConfiguration(context, configuration, "cacheKey", 0);

        assertNull(sut.getConfiguration(context, "cacheKey", TimeUnit.MINUTES.toMillis(20)));
    }

    @Test
    public void getConfiguration_whenEncryptedSharedPrefsFails_returnsNull() throws JSONException, UnexpectedException {
        UnexpectedException unexpectedException = new UnexpectedException("unexpected exception");
        when(braintreeSharedPreferences.containsKey(context, "cacheKey_timestamp")).thenThrow(unexpectedException);
        when(braintreeSharedPreferences.getLong(context, "cacheKey_timestamp")).thenThrow(unexpectedException);
        when(braintreeSharedPreferences.getString(context, "cacheKey","")).thenThrow(unexpectedException);

        ConfigurationCache sut = new ConfigurationCache(braintreeSharedPreferences);
        assertNull(sut.getConfiguration(context, "cacheKey", TimeUnit.MINUTES.toMillis(5)-1));
    }
}
@@ -139,70 +139,262 @@
 org.
-mockito.Mockito.mock;%0Aimport static org.mockito.Mockito.verify
+junit.Assert.fail;%0Aimport static org.mockito.ArgumentMatchers.any;%0Aimport static org.mockito.ArgumentMatchers.anyLong;%0Aimport static org.mockito.ArgumentMatchers.anyString;%0Aimport static org.mockito.Mockito.doThrow;%0Aimport static org.mockito.Mockito.mock
 ;%0Aim
@@ -1498,32 +1498,33 @@
 eferences);%0A
+%0A
         
 sut.saveConf
@@ -1515,86 +1515,157 @@
     
-sut.saveConfiguration(context, configuration, %22cacheKey%22, 123);%0A        verify
+UnexpectedException unexpectedException = new UnexpectedException(%22unexpected exception%22);%0A        doThrow(unexpectedException)%0A                .when
 (bra
@@ -1688,16 +1688,33 @@
 erences)
+%0A                
 .putStri
@@ -1727,81 +1727,262 @@
 ong(
-c
+any(C
 ontext
-, %22cacheKey%22, configuration.toJson(), %22cacheKey_timestamp%22, 123L);
+.class), anyString(), anyString(), anyString(), anyLong());%0A%0A        try %7B%0A            sut.saveConfiguration(context, configuration, %22cacheKey%22, 123);%0A        %7D catch (Exception e) %7B%0A            fail(%22This method should not throw.%22);%0A        %7D
 %0A   
@@ -3724,39 +3724,24 @@
 ull() throws
- JSONException,
  UnexpectedE
@@ -3906,37 +3906,39 @@
 Key(
-c
+any(C
 ontext
-, %22cacheKey_timestamp%22
+.class), anyString()
 )).t
@@ -4020,37 +4020,39 @@
 ong(
-c
+any(C
 ontext
-, %22cacheKey_timestamp%22
+.class), anyString()
 )).t
@@ -4132,38 +4132,59 @@
 tString(
-c
+any(C
 ontext
-, %22cacheKey%22,%22%22
+.class), anyString(),anyString()
 )).thenT

Update Configuration Cache unit test.