PageRenderTime 75ms CodeModel.GetById 42ms RepoModel.GetById 0ms app.codeStats 1ms

/app/src/test/java/info/blockchain/wallet/datamanagers/AuthDataManagerTest.java

https://gitlab.com/github-cloud-corporation/My-Wallet-V3-Android
Java | 472 lines | 338 code | 56 blank | 78 comment | 0 complexity | 9ea550a19bbee59c6c337f745ded59d9 MD5 | raw file
  1. package info.blockchain.wallet.datamanagers;
  2. import android.app.Application;
  3. import info.blockchain.api.Access;
  4. import info.blockchain.wallet.access.AccessState;
  5. import info.blockchain.wallet.payload.Payload;
  6. import info.blockchain.wallet.payload.PayloadManager;
  7. import info.blockchain.wallet.util.AESUtilWrapper;
  8. import info.blockchain.wallet.util.AppUtil;
  9. import info.blockchain.wallet.util.CharSequenceX;
  10. import info.blockchain.wallet.util.PrefsUtil;
  11. import org.junit.Before;
  12. import org.junit.Test;
  13. import org.junit.runner.RunWith;
  14. import org.mockito.Mock;
  15. import org.mockito.MockitoAnnotations;
  16. import org.robolectric.RobolectricGradleTestRunner;
  17. import org.robolectric.RuntimeEnvironment;
  18. import org.robolectric.annotation.Config;
  19. import java.util.concurrent.TimeUnit;
  20. import piuk.blockchain.android.BlockchainTestApplication;
  21. import piuk.blockchain.android.BuildConfig;
  22. import piuk.blockchain.android.RxTest;
  23. import piuk.blockchain.android.di.ApiModule;
  24. import piuk.blockchain.android.di.ApplicationModule;
  25. import piuk.blockchain.android.di.DataManagerModule;
  26. import piuk.blockchain.android.di.Injector;
  27. import piuk.blockchain.android.di.InjectorTestUtils;
  28. import rx.observers.TestSubscriber;
  29. import static org.mockito.Matchers.any;
  30. import static org.mockito.Matchers.anyInt;
  31. import static org.mockito.Matchers.anyString;
  32. import static org.mockito.Mockito.doAnswer;
  33. import static org.mockito.Mockito.doThrow;
  34. import static org.mockito.Mockito.mock;
  35. import static org.mockito.Mockito.verify;
  36. import static org.mockito.Mockito.when;
  37. /**
  38. * Created by adambennett on 15/08/2016.
  39. */
  40. @Config(sdk = 23, constants = BuildConfig.class, application = BlockchainTestApplication.class)
  41. @RunWith(RobolectricGradleTestRunner.class)
  42. public class AuthDataManagerTest extends RxTest {
  43. private static final String STRING_TO_RETURN = "string_to_return";
  44. private AuthDataManager mSubject;
  45. @Mock private PayloadManager mPayloadManager;
  46. @Mock private PrefsUtil mPrefsUtil;
  47. @Mock private Access mAccess;
  48. @Mock private AppUtil mAppUtil;
  49. @Mock private AESUtilWrapper mAesUtils;
  50. @Mock private AccessState mAccessState;
  51. @Before
  52. public void setUp() throws Exception {
  53. super.setUp();
  54. MockitoAnnotations.initMocks(this);
  55. InjectorTestUtils.initApplicationComponent(
  56. Injector.getInstance(),
  57. new MockApplicationModule(RuntimeEnvironment.application),
  58. new MockApiModule(),
  59. new DataManagerModule());
  60. mSubject = new AuthDataManager();
  61. }
  62. @Test
  63. public void getEncryptedPayload() throws Exception {
  64. // Arrange
  65. TestSubscriber<String> subscriber = new TestSubscriber<>();
  66. when(mAccess.getEncryptedPayload(anyString(), anyString())).thenReturn(STRING_TO_RETURN);
  67. // Act
  68. mSubject.getEncryptedPayload("1234567890", "1234567890").toBlocking().subscribe(subscriber);
  69. // Assert
  70. verify(mAccess).getEncryptedPayload(anyString(), anyString());
  71. subscriber.assertCompleted();
  72. subscriber.onNext(STRING_TO_RETURN);
  73. subscriber.assertNoErrors();
  74. }
  75. @Test
  76. public void getSessionId() throws Exception {
  77. // Arrange
  78. TestSubscriber<String> subscriber = new TestSubscriber<>();
  79. when(mAccess.getEncryptedPayload(anyString(), anyString())).thenReturn(STRING_TO_RETURN);
  80. // Act
  81. mSubject.getSessionId("1234567890").toBlocking().subscribe(subscriber);
  82. // Assert
  83. verify(mAccess).getSessionId(anyString());
  84. subscriber.assertCompleted();
  85. subscriber.onNext(STRING_TO_RETURN);
  86. subscriber.assertNoErrors();
  87. }
  88. @Test
  89. public void validatePin() throws Exception {
  90. // Arrange
  91. TestSubscriber<CharSequenceX> subscriber = new TestSubscriber<>();
  92. CharSequenceX charSequenceX = new CharSequenceX("1234567890");
  93. when(mAccessState.validatePIN(anyString())).thenReturn(charSequenceX);
  94. // Act
  95. mSubject.validatePin(anyString()).toBlocking().subscribe(subscriber);
  96. // Assert
  97. verify(mAccessState).validatePIN(anyString());
  98. subscriber.assertCompleted();
  99. subscriber.onNext(charSequenceX);
  100. subscriber.assertNoErrors();
  101. }
  102. @Test
  103. public void createPin() throws Exception {
  104. // Arrange
  105. TestSubscriber<Boolean> subscriber = new TestSubscriber<>();
  106. when(mAccessState.createPIN(any(CharSequenceX.class), anyString())).thenReturn(true);
  107. // Act
  108. mSubject.createPin(any(CharSequenceX.class), anyString()).toBlocking().subscribe(subscriber);
  109. // Assert
  110. verify(mAccessState).createPIN(any(CharSequenceX.class), anyString());
  111. subscriber.assertCompleted();
  112. subscriber.onNext(true);
  113. subscriber.assertNoErrors();
  114. }
  115. @Test
  116. public void createHdWallet() throws Exception {
  117. // Arrange
  118. TestSubscriber<Payload> subscriber = new TestSubscriber<>();
  119. Payload payload = new Payload();
  120. when(mPayloadManager.createHDWallet(anyString(), anyString())).thenReturn(payload);
  121. // Act
  122. mSubject.createHdWallet(anyString(), anyString()).toBlocking().subscribe(subscriber);
  123. // Assert
  124. verify(mPayloadManager).createHDWallet(anyString(), anyString());
  125. subscriber.assertCompleted();
  126. subscriber.onNext(payload);
  127. subscriber.assertNoErrors();
  128. }
  129. /**
  130. * Access returns a valid payload, Observable should complete successfully
  131. */
  132. @Test
  133. public void startPollingAuthStatusSuccess() throws Exception {
  134. // Arrange
  135. TestSubscriber<String> subscriber = new TestSubscriber<>();
  136. when(mAccess.getSessionId(anyString())).thenReturn(STRING_TO_RETURN);
  137. when(mAccess.getEncryptedPayload(anyString(), anyString())).thenReturn(STRING_TO_RETURN);
  138. // Act
  139. mSubject.startPollingAuthStatus("1234567890").toBlocking().subscribe(subscriber);
  140. // Assert
  141. verify(mAccess).getSessionId(anyString());
  142. verify(mAccess).getEncryptedPayload(anyString(), anyString());
  143. subscriber.assertCompleted();
  144. subscriber.onNext(STRING_TO_RETURN);
  145. subscriber.assertNoErrors();
  146. }
  147. /**
  148. * Getting encrypted payload returns error, should be caught by Observable and transformed into
  149. * {@link Access#KEY_AUTH_REQUIRED}
  150. */
  151. @Test
  152. public void startPollingAuthStatusError() throws Exception {
  153. // Arrange
  154. TestSubscriber<String> subscriber = new TestSubscriber<>();
  155. when(mAccess.getSessionId(anyString())).thenReturn(STRING_TO_RETURN);
  156. when(mAccess.getEncryptedPayload(anyString(), anyString())).thenThrow(mock(RuntimeException.class));
  157. // Act
  158. mSubject.startPollingAuthStatus("1234567890").toBlocking().subscribe(subscriber);
  159. // Assert
  160. verify(mAccess).getSessionId(anyString());
  161. verify(mAccess).getEncryptedPayload(anyString(), anyString());
  162. subscriber.assertCompleted();
  163. subscriber.onNext(Access.KEY_AUTH_REQUIRED);
  164. subscriber.assertNoErrors();
  165. }
  166. /**
  167. * Getting encrypted payload returns Auth Required, should be filtered out and emit no values.
  168. */
  169. @Test
  170. public void startPollingAuthStatusAccessRequired() throws Exception {
  171. // Arrange
  172. TestSubscriber<String> subscriber = new TestSubscriber<>();
  173. when(mAccess.getSessionId(anyString())).thenReturn(STRING_TO_RETURN);
  174. when(mAccess.getEncryptedPayload(anyString(), anyString())).thenReturn(Access.KEY_AUTH_REQUIRED);
  175. // Act
  176. mSubject.startPollingAuthStatus("1234567890").take(1, TimeUnit.SECONDS).toBlocking().subscribe(subscriber);
  177. // Assert
  178. subscriber.assertCompleted();
  179. subscriber.assertNoValues();
  180. subscriber.assertNoErrors();
  181. }
  182. /**
  183. * Update payload completes successfully, should set temp password and complete with no errors
  184. */
  185. @Test
  186. public void initiatePayloadSuccess() throws Exception {
  187. // Arrange
  188. TestSubscriber<Void> subscriber = new TestSubscriber<>();
  189. doAnswer(invocation -> {
  190. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitSuccess();
  191. return null;
  192. }).when(mPayloadManager).initiatePayload(
  193. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  194. // Act
  195. mSubject.updatePayload("1234567890", "1234567890", new CharSequenceX("1234567890")).toBlocking().subscribe(subscriber);
  196. // Assert
  197. verify(mPayloadManager).setTempPassword(any(CharSequenceX.class));
  198. subscriber.assertCompleted();
  199. subscriber.assertNoErrors();
  200. }
  201. /**
  202. * Update payload returns a pairing failure, Observable should throw {@link AuthDataManager.PairFailThrowable}
  203. */
  204. @Test
  205. public void initiatePayloadPairFail() throws Exception {
  206. // Arrange
  207. TestSubscriber<Void> subscriber = new TestSubscriber<>();
  208. doAnswer(invocation -> {
  209. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitPairFail();
  210. return null;
  211. }).when(mPayloadManager).initiatePayload(
  212. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  213. // Act
  214. mSubject.updatePayload("1234567890", "1234567890", new CharSequenceX("1234567890")).toBlocking().subscribe(subscriber);
  215. // Assert
  216. subscriber.assertNotCompleted();
  217. subscriber.assertError(AuthDataManager.PairFailThrowable.class);
  218. }
  219. /**
  220. * Update payload returns a create failure, Observable should throw {@link AuthDataManager.CreateFailThrowable}
  221. */
  222. @Test
  223. public void initiatePayloadCreateFail() throws Exception {
  224. // Arrange
  225. TestSubscriber<Void> subscriber = new TestSubscriber<>();
  226. doAnswer(invocation -> {
  227. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitCreateFail("1234567890");
  228. return null;
  229. }).when(mPayloadManager).initiatePayload(
  230. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  231. // Act
  232. mSubject.updatePayload("1234567890", "1234567890", new CharSequenceX("1234567890")).toBlocking().subscribe(subscriber);
  233. // Assert
  234. subscriber.assertNotCompleted();
  235. subscriber.assertError(AuthDataManager.CreateFailThrowable.class);
  236. }
  237. /**
  238. * PayloadManager throws exception, should trigger onError
  239. */
  240. @Test
  241. public void initiatePayloadException() throws Exception {
  242. // Arrange
  243. TestSubscriber<Void> subscriber = new TestSubscriber<>();
  244. doThrow(new RuntimeException()).when(mPayloadManager).initiatePayload(
  245. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  246. // Act
  247. mSubject.updatePayload("1234567890", "1234567890", new CharSequenceX("1234567890")).toBlocking().subscribe(subscriber);
  248. // Assert
  249. subscriber.assertNotCompleted();
  250. subscriber.assertError(Throwable.class);
  251. }
  252. @Test
  253. public void createCheckEmailTimer() throws Exception {
  254. // Arrange
  255. TestSubscriber<Integer> subscriber = new TestSubscriber<>();
  256. // Act
  257. mSubject.createCheckEmailTimer().take(1).toBlocking().subscribe(subscriber);
  258. mSubject.timer = 1;
  259. // Assert
  260. subscriber.assertCompleted();
  261. subscriber.assertNoErrors();
  262. }
  263. @Test
  264. public void attemptDecryptPayloadInvalidPayload() throws Exception {
  265. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  266. // Act
  267. mSubject.attemptDecryptPayload(
  268. new CharSequenceX("1234567890"),
  269. "1234567890",
  270. "1234567890",
  271. listener);
  272. // Assert
  273. verify(listener).onFatalError();
  274. }
  275. @Test
  276. public void attemptDecryptPayloadSuccessful() throws Exception {
  277. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  278. doAnswer(invocation -> {
  279. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitSuccess();
  280. return null;
  281. }).when(mPayloadManager).initiatePayload(
  282. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  283. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenReturn(DECRYPTED_PAYLOAD);
  284. // Act
  285. mSubject.attemptDecryptPayload(
  286. new CharSequenceX("1234567890"),
  287. "1234567890",
  288. TEST_PAYLOAD,
  289. listener);
  290. // Assert
  291. verify(mPrefsUtil).setValue(anyString(), anyString());
  292. verify(mAppUtil).setSharedKey(anyString());
  293. verify(listener).onSuccess();
  294. }
  295. @Test
  296. public void attemptDecryptPayloadInitPairFail() throws Exception {
  297. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  298. doAnswer(invocation -> {
  299. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitPairFail();
  300. return null;
  301. }).when(mPayloadManager).initiatePayload(
  302. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  303. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenReturn(DECRYPTED_PAYLOAD);
  304. // Act
  305. mSubject.attemptDecryptPayload(
  306. new CharSequenceX("1234567890"),
  307. "1234567890",
  308. TEST_PAYLOAD,
  309. listener);
  310. // Assert
  311. verify(mPrefsUtil).setValue(anyString(), anyString());
  312. verify(mAppUtil).setSharedKey(anyString());
  313. verify(listener).onPairFail();
  314. }
  315. @Test
  316. public void attemptDecryptPayloadFatalError() throws Exception {
  317. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  318. doThrow(new Exception()).when(mPayloadManager).initiatePayload(
  319. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  320. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenReturn(DECRYPTED_PAYLOAD);
  321. // Act
  322. mSubject.attemptDecryptPayload(
  323. new CharSequenceX("1234567890"),
  324. "1234567890",
  325. TEST_PAYLOAD,
  326. listener);
  327. // Assert
  328. verify(mPrefsUtil).setValue(anyString(), anyString());
  329. verify(mAppUtil).setSharedKey(anyString());
  330. verify(listener).onFatalError();
  331. }
  332. @Test
  333. public void attemptDecryptPayloadCreateFail() throws Exception {
  334. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  335. doAnswer(invocation -> {
  336. ((PayloadManager.InitiatePayloadListener) invocation.getArguments()[3]).onInitCreateFail("1234567890");
  337. return null;
  338. }).when(mPayloadManager).initiatePayload(
  339. anyString(), anyString(), any(CharSequenceX.class), any(PayloadManager.InitiatePayloadListener.class));
  340. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenReturn(DECRYPTED_PAYLOAD);
  341. // Act
  342. mSubject.attemptDecryptPayload(
  343. new CharSequenceX("1234567890"),
  344. "1234567890",
  345. TEST_PAYLOAD,
  346. listener);
  347. // Assert
  348. verify(mPrefsUtil).setValue(anyString(), anyString());
  349. verify(mAppUtil).setSharedKey(anyString());
  350. verify(listener).onCreateFail();
  351. }
  352. @Test
  353. public void attemptDecryptPayloadDecryptionFailed() throws Exception {
  354. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  355. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenReturn(null);
  356. // Act
  357. mSubject.attemptDecryptPayload(
  358. new CharSequenceX("1234567890"),
  359. "1234567890",
  360. TEST_PAYLOAD,
  361. listener);
  362. // Assert
  363. verify(listener).onAuthFail();
  364. }
  365. @Test
  366. public void attemptDecryptPayloadDecryptionThrowsException() throws Exception {
  367. AuthDataManager.DecryptPayloadListener listener = mock(AuthDataManager.DecryptPayloadListener.class);
  368. when(mAesUtils.decrypt(anyString(), any(CharSequenceX.class), anyInt())).thenThrow(mock(RuntimeException.class));
  369. // Act
  370. mSubject.attemptDecryptPayload(
  371. new CharSequenceX("1234567890"),
  372. "1234567890",
  373. TEST_PAYLOAD,
  374. listener);
  375. // Assert
  376. verify(listener).onFatalError();
  377. }
  378. private class MockApplicationModule extends ApplicationModule {
  379. MockApplicationModule(Application application) {
  380. super(application);
  381. }
  382. @Override
  383. protected AppUtil provideAppUtil() {
  384. return mAppUtil;
  385. }
  386. @Override
  387. protected PrefsUtil providePrefsUtil() {
  388. return mPrefsUtil;
  389. }
  390. @Override
  391. protected AESUtilWrapper provideAesUtils() {
  392. return mAesUtils;
  393. }
  394. @Override
  395. protected AccessState provideAccessState() {
  396. return mAccessState;
  397. }
  398. }
  399. private class MockApiModule extends ApiModule {
  400. @Override
  401. protected Access provideAccess() {
  402. return mAccess;
  403. }
  404. @Override
  405. protected PayloadManager providePayloadManager() {
  406. return mPayloadManager;
  407. }
  408. }
  409. private static final String TEST_PAYLOAD = "{\n" +
  410. " \"payload\": \"test payload\",\n" +
  411. " \"pbkdf2_iterations\": 2000\n" +
  412. "}";
  413. private static final String DECRYPTED_PAYLOAD = "{\n" +
  414. "\t\"sharedKey\": \"1234567890\"\n" +
  415. "}";
  416. }