Search in sources :

Example 1 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class PersistentMutationOutboxTest method existingCreationIncomingCreationYieldsError.

/**
 * When there is an existing creation for a model, and a new creation for that
 * model comes in, an error should be returned. In other words, it is illegal to
 * create a mutation twice.
 * @throws DataStoreException On failure to query storage to assert post-action value of mutation
 * @throws InterruptedException If interrupted while awaiting terminal result in test observer
 */
@Test
public void existingCreationIncomingCreationYieldsError() throws DataStoreException, InterruptedException {
    // Arrange an existing creation mutation
    BlogOwner modelInExistingMutation = BlogOwner.builder().name("The Real Papa Tony").build();
    PendingMutation<BlogOwner> existingCreation = PendingMutation.creation(modelInExistingMutation, schema);
    String existingCreationId = existingCreation.getMutationId().toString();
    mutationOutbox.enqueue(existingCreation).blockingAwait(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    // Act: try to create the blog owner again -- but there's already a pending creation
    BlogOwner modelInIncomingMutation = modelInExistingMutation.copyOfBuilder().name("Someone Posing as Papa Tony Who isn't \uD83D\uDCAF legit.").build();
    PendingMutation<BlogOwner> incomingCreation = PendingMutation.creation(modelInIncomingMutation, schema);
    String incomingCreationId = incomingCreation.getMutationId().toString();
    TestObserver<Void> enqueueObserver = mutationOutbox.enqueue(incomingCreation).test();
    // Assert: caused a failure.
    enqueueObserver.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    enqueueObserver.assertError(throwable -> throwable instanceof DataStoreException);
    // Assert: original mutation is present, but the new one isn't.
    PendingMutation.PersistentRecord storedMutation = storage.query(PersistentRecord.class, Where.id(existingCreationId)).get(0);
    assertEquals(modelInExistingMutation, converter.fromRecord(storedMutation).getMutatedItem());
    assertTrue(storage.query(PersistentRecord.class, Where.id(incomingCreationId)).isEmpty());
    // Existing mutation still attainable as next mutation (right now, its the ONLY mutation in outbox)
    assertTrue(mutationOutbox.hasPendingMutation(modelInExistingMutation.getId()));
    assertEquals(existingCreation, mutationOutbox.peek());
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) PersistentRecord(com.amplifyframework.datastore.syncengine.PendingMutation.PersistentRecord) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) RandomString(com.amplifyframework.testutils.random.RandomString) PersistentRecord(com.amplifyframework.datastore.syncengine.PendingMutation.PersistentRecord) Test(org.junit.Test)

Example 2 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class PersistentMutationOutboxTest method enqueueIsSynchronized.

/**
 * When two creations for the same model are enqueued, the second should fail.  This is similar to
 * {@link #existingCreationIncomingCreationYieldsError}, except that the Completable's from the two enqueue calls
 * are concatenated into the same stream.   The second enqueue should not check if an item exists in the queue
 * until the first enqueue is completed.
 * @throws InterruptedException If interrupted while awaiting terminal result in test observer
 */
@Test
public void enqueueIsSynchronized() throws InterruptedException {
    // Arrange an existing creation mutation
    BlogOwner modelInExistingMutation = BlogOwner.builder().name("The Real Papa Tony").build();
    PendingMutation<BlogOwner> firstCreation = PendingMutation.creation(modelInExistingMutation, schema);
    PendingMutation<BlogOwner> secondCreation = PendingMutation.creation(modelInExistingMutation, schema);
    TestObserver<Void> enqueueObserver = mutationOutbox.enqueue(firstCreation).andThen(mutationOutbox.enqueue(secondCreation)).test();
    // Assert: caused a failure.
    enqueueObserver.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    enqueueObserver.assertError(throwable -> throwable instanceof DataStoreException);
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) Test(org.junit.Test)

Example 3 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class PersistentMutationOutboxTest method existingUpdateIncomingCreationYieldsError.

/**
 * When there is an existing update for a model, and a new creation for that
 * model comes in, an error should be returned. In other words, you can't create
 * something that already exists and is being updated.
 * @throws DataStoreException On failure to to query which mutations are in storage
 * @throws InterruptedException If interrupted while awaiting terminal result in test observer
 */
@Test
public void existingUpdateIncomingCreationYieldsError() throws DataStoreException, InterruptedException {
    // Arrange an existing update mutation
    BlogOwner modelInExistingMutation = BlogOwner.builder().name("Tony with improvements applied").build();
    PendingMutation<BlogOwner> existingUpdate = PendingMutation.update(modelInExistingMutation, schema);
    String exitingUpdateId = existingUpdate.getMutationId().toString();
    mutationOutbox.enqueue(existingUpdate).blockingAwait(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    // Act: try to CREATE tony again -- but isn't he already created, if there's an update?
    BlogOwner modelInIncomingMutation = modelInExistingMutation.copyOfBuilder().name("Brand new tony").build();
    PendingMutation<BlogOwner> incomingCreation = PendingMutation.creation(modelInIncomingMutation, schema);
    String incomingCreationId = incomingCreation.getMutationId().toString();
    TestObserver<Void> enqueueObserver = mutationOutbox.enqueue(incomingCreation).test();
    // Assert: caused a failure.
    enqueueObserver.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
    enqueueObserver.assertError(throwable -> throwable instanceof DataStoreException);
    // Assert: original mutation is present, but the new one isn't.
    PendingMutation.PersistentRecord storedMutation = storage.query(PersistentRecord.class, Where.id(exitingUpdateId)).get(0);
    assertEquals(modelInExistingMutation, converter.fromRecord(storedMutation).getMutatedItem());
    assertTrue(storage.query(PersistentRecord.class, Where.id(incomingCreationId)).isEmpty());
    // Existing mutation still attainable as next mutation (right now, its the ONLY mutation in outbox)
    assertTrue(mutationOutbox.hasPendingMutation(modelInExistingMutation.getId()));
    assertEquals(existingUpdate, mutationOutbox.peek());
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) PersistentRecord(com.amplifyframework.datastore.syncengine.PendingMutation.PersistentRecord) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) RandomString(com.amplifyframework.testutils.random.RandomString) PersistentRecord(com.amplifyframework.datastore.syncengine.PendingMutation.PersistentRecord) Test(org.junit.Test)

Example 4 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SubscriptionProcessorTest method appSyncInvokedWhenSubscriptionsStarted.

/**
 * When {@link SubscriptionProcessor#startSubscriptions()} is invoked,
 * the {@link AppSync} client receives subscription requests.
 */
@Test
public void appSyncInvokedWhenSubscriptionsStarted() {
    // For every Class-SubscriptionType pairing, use a CountDownLatch
    // to tell whether or not we've "seen" a subscription event for it.
    Map<Pair<ModelSchema, SubscriptionType>, CountDownLatch> seen = new HashMap<>();
    // Build a stream of such pairs.
    Observable.fromIterable(modelSchemas).flatMap(modelSchema -> Observable.fromArray(SubscriptionType.values()).map(value -> Pair.create(modelSchema, value))).blockingForEach(pair -> {
        // For each one, store a latch. Add a mocking behavior to count down
        // the latch when the subscription API is hit, for that class and subscription type.
        CountDownLatch latch = new CountDownLatch(1);
        seen.put(Pair.create(pair.first, pair.second), latch);
        Answer<Cancelable> answer = invocation -> {
            latch.countDown();
            return new NoOpCancelable();
        };
        arrangeSubscription(appSync, answer, pair.first, pair.second);
    });
    // Act: start some subscriptions.
    try {
        subscriptionProcessor.startSubscriptions();
    } catch (DataStoreException exception) {
    // startSubscriptions throws this exception if it doesn't receive the start_ack messages after a time out.
    // This test doesn't mock those start_ack messages, so this expection is expected.  That's okay though -
    // we just want to verify that the subscriptions were requested.
    }
    // Make sure that all of the subscriptions have been
    Observable.fromIterable(seen.entrySet()).blockingForEach(entry -> {
        CountDownLatch latch = entry.getValue();
        assertTrue(latch.await(OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
    });
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) ModelProvider(com.amplifyframework.core.model.ModelProvider) Pair(android.util.Pair) RunWith(org.junit.runner.RunWith) AppSync(com.amplifyframework.datastore.appsync.AppSync) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) SchemaRegistry(com.amplifyframework.core.model.SchemaRegistry) Answer(org.mockito.stubbing.Answer) Consumer(com.amplifyframework.core.Consumer) SubscriptionType(com.amplifyframework.api.graphql.SubscriptionType) Observable(io.reactivex.rxjava3.core.Observable) Map(java.util.Map) Mockito.doAnswer(org.mockito.Mockito.doAnswer) NoOpCancelable(com.amplifyframework.core.async.NoOpCancelable) ModelSchema(com.amplifyframework.core.model.ModelSchema) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Before(org.junit.Before) DataStoreConfiguration(com.amplifyframework.datastore.DataStoreConfiguration) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) Model(com.amplifyframework.core.model.Model) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Completable(io.reactivex.rxjava3.core.Completable) Action(com.amplifyframework.core.Action) RobolectricTestRunner(org.robolectric.RobolectricTestRunner) TimeUnit(java.util.concurrent.TimeUnit) DataStoreException(com.amplifyframework.datastore.DataStoreException) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Cancelable(com.amplifyframework.core.async.Cancelable) Assert.assertFalse(org.junit.Assert.assertFalse) RandomString(com.amplifyframework.testutils.random.RandomString) Temporal(com.amplifyframework.core.model.temporal.Temporal) AmplifyModelProvider(com.amplifyframework.testmodels.commentsblog.AmplifyModelProvider) Collections(java.util.Collections) Mockito.mock(org.mockito.Mockito.mock) DataStoreException(com.amplifyframework.datastore.DataStoreException) HashMap(java.util.HashMap) NoOpCancelable(com.amplifyframework.core.async.NoOpCancelable) CountDownLatch(java.util.concurrent.CountDownLatch) NoOpCancelable(com.amplifyframework.core.async.NoOpCancelable) Cancelable(com.amplifyframework.core.async.Cancelable) Pair(android.util.Pair) Test(org.junit.Test)

Example 5 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SyncProcessorTest method retriedOnAppSyncFailure.

/**
 * Verify that retry is called on appsync failure when syncRetry is set to true.
 *
 * @throws AmplifyException On failure to build GraphQLRequest for sync query.
 */
@Test
public void retriedOnAppSyncFailure() throws AmplifyException {
    // Arrange: mock failure when invoking hydrate on the mock object.
    requestRetry = mock(RetryHandler.class);
    when(requestRetry.retry(any(), any())).thenReturn(Single.error(new DataStoreException("PaginatedResult<ModelWithMetadata<BlogOwner>>", "")));
    initSyncProcessor(10_000);
    AppSyncMocking.sync(appSync).mockFailure(new DataStoreException("Something timed out during sync.", ""));
    // Act: call hydrate.
    syncProcessor.hydrate().test(false).assertNotComplete();
    verify(requestRetry, times(1)).retry(any(), any());
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) Test(org.junit.Test)

Aggregations

DataStoreException (com.amplifyframework.datastore.DataStoreException)89 Test (org.junit.Test)52 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)36 Consumer (com.amplifyframework.core.Consumer)32 List (java.util.List)32 Cancelable (com.amplifyframework.core.async.Cancelable)31 Model (com.amplifyframework.core.model.Model)31 ArrayList (java.util.ArrayList)31 AmplifyException (com.amplifyframework.AmplifyException)29 ModelSchema (com.amplifyframework.core.model.ModelSchema)28 Collections (java.util.Collections)28 Action (com.amplifyframework.core.Action)27 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)27 TimeUnit (java.util.concurrent.TimeUnit)25 Post (com.amplifyframework.testmodels.commentsblog.Post)23 PostStatus (com.amplifyframework.testmodels.commentsblog.PostStatus)23 Arrays (java.util.Arrays)23 Assert.assertEquals (org.junit.Assert.assertEquals)23 ObserveQueryOptions (com.amplifyframework.core.model.query.ObserveQueryOptions)22 DataStoreQuerySnapshot (com.amplifyframework.datastore.DataStoreQuerySnapshot)21