Search in sources :

Example 21 with HubAccumulator

use of com.amplifyframework.testutils.HubAccumulator in project amplify-android by aws-amplify.

the class MutationProcessorTest method canDrainMutationOutboxOnPublicationError.

/**
 * If error is caused by AppSync response, then the mutation outbox continues to
 * drain without getting blocked.
 * @throws DataStoreException On failure to save models
 */
@Test
public void canDrainMutationOutboxOnPublicationError() throws DataStoreException {
    ModelSchema schema = schemaRegistry.getModelSchemaForModelClass(BlogOwner.class);
    // We will attempt to "sync" 10 models.
    final int maxAttempts = 10;
    for (int attempt = 0; attempt < maxAttempts; attempt++) {
        BlogOwner model = BlogOwner.builder().name("Blogger #" + attempt).build();
        synchronousStorageAdapter.save(model);
        // Every other model triggers an AppSync error response.
        if (attempt % 2 == 0) {
            AppSyncMocking.create(appSync).mockErrorResponse(model);
        } else {
            AppSyncMocking.create(appSync).mockSuccessResponse(model);
        }
        // Enqueue a creation in the mutation outbox
        assertTrue(mutationOutbox.enqueue(PendingMutation.creation(model, schema)).blockingAwait(TIMEOUT_SECONDS, TimeUnit.SECONDS));
    }
    // Start listening for Mutation Outbox Empty event.
    HubAccumulator accumulator = HubAccumulator.create(HubChannel.DATASTORE, isOutboxEmpty(true), 1).start();
    // Start draining the outbox.
    mutationProcessor.startDrainingMutationOutbox();
    accumulator.await();
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) HubAccumulator(com.amplifyframework.testutils.HubAccumulator) Test(org.junit.Test)

Example 22 with HubAccumulator

use of com.amplifyframework.testutils.HubAccumulator in project amplify-android by aws-amplify.

the class HybridOfflineInstrumentationTest method setupPlugin.

/**
 * Configures an AWSDataStorePlugin which only operates offline (not connected to any remote backend),
 * and is able to warehouse the commentsblog family of models.
 * @throws AmplifyException In a variety of scenarios where setup fails
 */
@Before
public void setupPlugin() throws AmplifyException {
    blogOwnerSchema = schemaFrom("schemas/commentsblog/blog-owner.json");
    blogSchema = schemaFrom("schemas/commentsblog/blog.json");
    SchemaProvider schemaProvider = SchemaProvider.of(blogOwnerSchema, blogSchema);
    getApplicationContext().deleteDatabase("AmplifyDatastore.db");
    StrictMode.enable();
    Amplify.addPlugin(new AndroidLoggingPlugin(LogLevel.VERBOSE));
    HubAccumulator initializationObserver = HubAccumulator.create(HubChannel.DATASTORE, InitializationStatus.SUCCEEDED, 1).start();
    AWSDataStorePlugin plugin = AWSDataStorePlugin.builder().modelProvider(schemaProvider).build();
    DataStoreCategory dataStoreCategory = new DataStoreCategory();
    dataStoreCategory.addPlugin(plugin);
    dataStoreCategory.configure(new DataStoreCategoryConfiguration(), getApplicationContext());
    dataStoreCategory.initialize(getApplicationContext());
    initializationObserver.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    hybridBehaviors = SynchronousHybridBehaviors.delegatingTo(plugin);
    normalBehaviors = SynchronousDataStore.delegatingTo(plugin);
}
Also used : HubAccumulator(com.amplifyframework.testutils.HubAccumulator) AndroidLoggingPlugin(com.amplifyframework.logging.AndroidLoggingPlugin) Before(org.junit.Before)

Example 23 with HubAccumulator

use of com.amplifyframework.testutils.HubAccumulator in project amplify-android by aws-amplify.

the class HybridTemporalSyncInstrumentationTest method temporalTypesAreSyncedUpToCloud.

/**
 * It is possible to dispatch a model that contain temporal types. After publishing
 * such a model to the cloud, we can query AppSync and find it there.
 * @throws ApiException on failure to communicate with AppSync API in verification phase of test
 */
@Ignore("It passes. Not automating due to operational concerns as noted in class-level @Ignore.")
@Test
public void temporalTypesAreSyncedUpToCloud() throws ApiException {
    // Prepare a SerializedModel that we will save to DataStore.
    Meeting meeting = createMeeting();
    Map<String, Object> sentData = toMap(meeting);
    SerializedModel sentModel = SerializedModel.builder().serializedData(sentData).modelSchema(modelSchema).build();
    HubAccumulator publicationAccumulator = HubAccumulator.create(HubChannel.DATASTORE, publicationOf(modelSchema.getName(), sentModel.getId()), 1).start();
    hybridBehaviors.save(sentModel);
    publicationAccumulator.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    // Retrieve the model from AppSync.
    Meeting remoteMeeting = api.get(Meeting.class, sentModel.getId());
    // Inspect the fields of the data in AppSync, and prepare it into a map
    // that we can compare with what we sent. Are they the same? They should be.
    assertEquals(sentData, toMap(remoteMeeting));
}
Also used : Meeting(com.amplifyframework.testmodels.meeting.Meeting) HubAccumulator(com.amplifyframework.testutils.HubAccumulator) SerializedModel(com.amplifyframework.core.model.SerializedModel) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 24 with HubAccumulator

use of com.amplifyframework.testutils.HubAccumulator in project amplify-android by aws-amplify.

the class AWSDataStorePluginTest method clearStopsSyncAndDeletesDatabase.

/**
 * Verify that when the clear method is called, the following happens
 * - All remote synchronization processes are stopped
 * - The database is deleted.
 * - On the next interaction with the DataStore, the synchronization processes are restarted.
 * @throws JSONException on failure to arrange plugin config
 * @throws AmplifyException on failure to arrange API plugin via Amplify facade
 */
@Test
public void clearStopsSyncAndDeletesDatabase() throws AmplifyException, JSONException {
    ApiCategory mockApiCategory = mockApiCategoryWithGraphQlApi();
    ApiPlugin<?> mockApiPlugin = mockApiCategory.getPlugin(MOCK_API_PLUGIN_NAME);
    JSONObject dataStorePluginJson = new JSONObject().put("syncIntervalInMinutes", 60);
    AWSDataStorePlugin awsDataStorePlugin = AWSDataStorePlugin.builder().modelProvider(modelProvider).apiCategory(mockApiCategory).build();
    SynchronousDataStore synchronousDataStore = SynchronousDataStore.delegatingTo(awsDataStorePlugin);
    awsDataStorePlugin.configure(dataStorePluginJson, context);
    awsDataStorePlugin.initialize(context);
    // Trick the DataStore since it's not getting initialized as part of the Amplify.initialize call chain
    Amplify.Hub.publish(HubChannel.DATASTORE, HubEvent.create(InitializationStatus.SUCCEEDED));
    // Setup objects
    Person person1 = createPerson("Test", "Dummy I");
    Person person2 = createPerson("Test", "Dummy II");
    // Mock responses for person 1
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        ModelMetadata modelMetadata = new ModelMetadata(person1.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person1, modelMetadata);
        onResponse.accept(new GraphQLResponse<>(modelWithMetadata, Collections.emptyList()));
        return mock(GraphQLOperation.class);
    }).when(mockApiPlugin).mutate(any(), any(), any());
    HubAccumulator apiInteractionObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.OUTBOX_MUTATION_PROCESSED, 1).start();
    // Save person 1
    synchronousDataStore.save(person1);
    Person result1 = synchronousDataStore.get(Person.class, person1.getId());
    assertEquals(person1, result1);
    apiInteractionObserver.await();
    verify(mockApiCategory).mutate(argThat(getMatcherFor(person1)), any(), any());
    // Mock responses for person 2
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        ModelMetadata modelMetadata = new ModelMetadata(person2.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person2, modelMetadata);
        onResponse.accept(new GraphQLResponse<>(modelWithMetadata, Collections.emptyList()));
        return mock(GraphQLOperation.class);
    }).when(mockApiPlugin).mutate(any(), any(), any());
    // Do the thing!
    synchronousDataStore.clear();
    assertRemoteSubscriptionsCancelled();
    apiInteractionObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.OUTBOX_MUTATION_PROCESSED, 1).start();
    HubAccumulator orchestratorInitObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.READY, 1).start();
    // Interact with the DataStore after the clear
    synchronousDataStore.save(person2);
    // Verify person 2 was published to the cloud
    apiInteractionObserver.await();
    // Verify the orchestrator started back up and subscriptions are active.
    orchestratorInitObserver.await();
    assertRemoteSubscriptionsStarted();
    Person result2 = synchronousDataStore.get(Person.class, person2.getId());
    assertEquals(person2, result2);
    verify(mockApiCategory, atLeastOnce()).mutate(argThat(getMatcherFor(person2)), any(), any());
}
Also used : ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) JSONObject(org.json.JSONObject) SynchronousDataStore(com.amplifyframework.testutils.sync.SynchronousDataStore) ApiCategory(com.amplifyframework.api.ApiCategory) HubAccumulator(com.amplifyframework.testutils.HubAccumulator) Person(com.amplifyframework.testmodels.personcar.Person) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata) Test(org.junit.Test)

Example 25 with HubAccumulator

use of com.amplifyframework.testutils.HubAccumulator in project amplify-android by aws-amplify.

the class AWSDataStorePluginTest method stopStopsSyncUntilNextInteraction.

/**
 * Verify that when the stop method is called, the following happens
 * - All remote synchronization processes are stopped
 * - On the next interaction with the DataStore, the synchronization processes are restarted.
 * @throws JSONException on failure to arrange plugin config
 * @throws AmplifyException on failure to arrange API plugin via Amplify facade
 */
@Test
public void stopStopsSyncUntilNextInteraction() throws AmplifyException, JSONException {
    ApiCategory mockApiCategory = mockApiCategoryWithGraphQlApi();
    ApiPlugin<?> mockApiPlugin = mockApiCategory.getPlugin(MOCK_API_PLUGIN_NAME);
    JSONObject dataStorePluginJson = new JSONObject().put("syncIntervalInMinutes", 60);
    AWSDataStorePlugin awsDataStorePlugin = AWSDataStorePlugin.builder().modelProvider(modelProvider).apiCategory(mockApiCategory).build();
    SynchronousDataStore synchronousDataStore = SynchronousDataStore.delegatingTo(awsDataStorePlugin);
    awsDataStorePlugin.configure(dataStorePluginJson, context);
    awsDataStorePlugin.initialize(context);
    // Trick the DataStore since it's not getting initialized as part of the Amplify.initialize call chain
    Amplify.Hub.publish(HubChannel.DATASTORE, HubEvent.create(InitializationStatus.SUCCEEDED));
    // Setup objects
    Person person1 = createPerson("Test", "Dummy I");
    Person person2 = createPerson("Test", "Dummy II");
    // Mock responses for person 1
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        ModelMetadata modelMetadata = new ModelMetadata(person1.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person1, modelMetadata);
        onResponse.accept(new GraphQLResponse<>(modelWithMetadata, Collections.emptyList()));
        return mock(GraphQLOperation.class);
    }).when(mockApiPlugin).mutate(any(), any(), any());
    HubAccumulator apiInteractionObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.OUTBOX_MUTATION_PROCESSED, 1).start();
    // Save person 1
    synchronousDataStore.save(person1);
    Person result1 = synchronousDataStore.get(Person.class, person1.getId());
    assertEquals(person1, result1);
    apiInteractionObserver.await();
    verify(mockApiCategory).mutate(argThat(getMatcherFor(person1)), any(), any());
    // Mock responses for person 2
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        ModelMetadata modelMetadata = new ModelMetadata(person2.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person2, modelMetadata);
        onResponse.accept(new GraphQLResponse<>(modelWithMetadata, Collections.emptyList()));
        return mock(GraphQLOperation.class);
    }).when(mockApiPlugin).mutate(any(), any(), any());
    // Do the thing!
    synchronousDataStore.stop();
    assertRemoteSubscriptionsCancelled();
    apiInteractionObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.OUTBOX_MUTATION_PROCESSED, 1).start();
    HubAccumulator orchestratorInitObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.READY, 1).start();
    // Interact with the DataStore after the stop
    synchronousDataStore.save(person2);
    // Verify person 2 was published to the cloud
    apiInteractionObserver.await();
    // Verify the orchestrator started back up and subscriptions are active.
    orchestratorInitObserver.await();
    assertRemoteSubscriptionsStarted();
    // Verify person 1 and 2 are in the DataStore
    List<Person> results = synchronousDataStore.list(Person.class);
    assertEquals(Arrays.asList(person1, person2), results);
    verify(mockApiCategory, atLeastOnce()).mutate(argThat(getMatcherFor(person2)), any(), any());
}
Also used : ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) JSONObject(org.json.JSONObject) SynchronousDataStore(com.amplifyframework.testutils.sync.SynchronousDataStore) ApiCategory(com.amplifyframework.api.ApiCategory) HubAccumulator(com.amplifyframework.testutils.HubAccumulator) Person(com.amplifyframework.testmodels.personcar.Person) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata) Test(org.junit.Test)

Aggregations

HubAccumulator (com.amplifyframework.testutils.HubAccumulator)30 Test (org.junit.Test)27 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)21 ModelSchema (com.amplifyframework.core.model.ModelSchema)7 SerializedModel (com.amplifyframework.core.model.SerializedModel)5 ModelMetadata (com.amplifyframework.datastore.appsync.ModelMetadata)5 ModelWithMetadata (com.amplifyframework.datastore.appsync.ModelWithMetadata)5 JSONObject (org.json.JSONObject)5 Ignore (org.junit.Ignore)5 ApiCategory (com.amplifyframework.api.ApiCategory)4 SynchronousDataStore (com.amplifyframework.testutils.sync.SynchronousDataStore)4 GraphQLResponse (com.amplifyframework.api.graphql.GraphQLResponse)3 HubEvent (com.amplifyframework.hub.HubEvent)3 Blog (com.amplifyframework.testmodels.commentsblog.Blog)3 RandomString (com.amplifyframework.testutils.random.RandomString)3 Before (org.junit.Before)3 AmplifyException (com.amplifyframework.AmplifyException)2 Model (com.amplifyframework.core.model.Model)2 HubChannel (com.amplifyframework.hub.HubChannel)2 Person (com.amplifyframework.testmodels.personcar.Person)2