use of com.amplifyframework.datastore.appsync.ModelWithMetadata in project amplify-android by aws-amplify.
the class MergerTest method mergeDeletionForNotExistingItem.
/**
* Assume there is NOT an item in the store. Then, we try to
* merge a mutation to delete item A. This should succeed, since
* there was no work to be performed (it was already deleted.) After
* the merge, there should STILL be no matching item in the store.
* @throws DataStoreException On failure to query results for assertions
* @throws InterruptedException If interrupted while awaiting terminal result in test observer
*/
@Test
public void mergeDeletionForNotExistingItem() throws DataStoreException, InterruptedException {
// Arrange, to start, there are no items matching the incoming deletion request.
BlogOwner blogOwner = BlogOwner.builder().name("Jameson").build();
// Note that storageAdapter.save(...) does NOT happen!
// storageAdapter.save(blogOwner, new ModelMetadata(blogOwner.getId(), false, 1, Time.now()));
// Act: try to merge a deletion that refers to an item not in the store
ModelMetadata deletionMetadata = new ModelMetadata(blogOwner.getId(), true, 1, Temporal.Timestamp.now());
TestObserver<Void> observer = merger.merge(new ModelWithMetadata<>(blogOwner, deletionMetadata)).test();
assertTrue(observer.await(REASONABLE_WAIT_TIME, TimeUnit.MILLISECONDS));
observer.assertNoErrors().assertComplete();
// Assert: there is still nothing in the store.
assertEquals(0, storageAdapter.query(BlogOwner.class).size());
}
use of com.amplifyframework.datastore.appsync.ModelWithMetadata in project amplify-android by aws-amplify.
the class MergerTest method itemWithoutVersionIsNotMerged.
/**
* Gray-box, we know that "no version" evaluates to a version of 0.
* So, this test should always behave like {@link #itemWithLowerVersionIsNotMerged()}.
* But, it the inputs to the system are technically different, so it is
* a distinct test in terms of system input/output.
* @throws DataStoreException On failure to interact with storage during arrange/verification
* @throws InterruptedException If interrupted while awaiting terminal result in test observer
*/
@Test
public void itemWithoutVersionIsNotMerged() throws DataStoreException, InterruptedException {
// Arrange a model and metadata into storage.
BlogOwner existingModel = BlogOwner.builder().name("Cornelius Daniels").build();
ModelMetadata existingMetadata = new ModelMetadata(existingModel.getId(), false, 1, Temporal.Timestamp.now());
storageAdapter.save(existingModel, existingMetadata);
// Act: try to merge, but don't specify a version in the metadata being used to merge.
BlogOwner incomingModel = existingModel.copyOfBuilder().name("Cornelius Daniels, but woke af, now.").build();
ModelMetadata metadataWithoutVersion = new ModelMetadata(incomingModel.getId(), null, null, null);
ModelWithMetadata<BlogOwner> incomingModelWithMetadata = new ModelWithMetadata<>(existingModel, metadataWithoutVersion);
TestObserver<Void> mergeObserver = merger.merge(incomingModelWithMetadata).test();
mergeObserver.await(REASONABLE_WAIT_TIME, TimeUnit.MILLISECONDS);
mergeObserver.assertNoErrors().assertComplete();
// Assert: Joey is still the same old Joey.
assertEquals(Collections.singletonList(existingModel), storageAdapter.query(BlogOwner.class));
// And his metadata is the still the same.
assertEquals(Collections.singletonList(existingMetadata), storageAdapter.query(ModelMetadata.class, Where.id(existingModel.getId())));
}
use of com.amplifyframework.datastore.appsync.ModelWithMetadata in project amplify-android by aws-amplify.
the class MergerTest method itemIsNotMergedWhenOutboxHasPendingMutation.
/**
* When an item comes into the merger to be merged,
* if there is a pending mutation in the outbox, for a model of the same ID,
* then that item shall NOT be merged.
* @throws DataStoreException On failure to arrange data into store
* @throws InterruptedException If interrupted while awaiting terminal result in test observer
* @throws AmplifyException On failure to arrange model schema
*/
@Test
public void itemIsNotMergedWhenOutboxHasPendingMutation() throws AmplifyException, InterruptedException {
// Arrange: some model with a well known ID exists on the system.
// We pretend that the user has recently updated it via the DataStore update() API.
String knownId = RandomString.string();
BlogOwner blogOwner = BlogOwner.builder().name("Jameson").id(knownId).build();
ModelMetadata localMetadata = new ModelMetadata(blogOwner.getId(), false, 1, Temporal.Timestamp.now());
storageAdapter.save(blogOwner, localMetadata);
ModelSchema schema = ModelSchema.fromModelClass(BlogOwner.class);
PendingMutation<BlogOwner> pendingMutation = PendingMutation.instance(blogOwner, schema, PendingMutation.Type.CREATE, QueryPredicates.all());
TestObserver<Void> enqueueObserver = mutationOutbox.enqueue(pendingMutation).test();
enqueueObserver.await(REASONABLE_WAIT_TIME, TimeUnit.MILLISECONDS);
enqueueObserver.assertNoErrors().assertComplete();
// Act: now, cloud sync happens, and the sync engine tries to apply an update
// for the same model ID, into the store. According to the cloud, this same
// item should be DELETED.
ModelMetadata cloudMetadata = new ModelMetadata(knownId, true, 2, Temporal.Timestamp.now());
TestObserver<Void> mergeObserver = merger.merge(new ModelWithMetadata<>(blogOwner, cloudMetadata)).test();
mergeObserver.await(REASONABLE_WAIT_TIME, TimeUnit.MILLISECONDS);
mergeObserver.assertNoErrors().assertComplete();
// Assert: the item is NOT deleted from the local store.
// The original is still there.
// Or in other words, the cloud data was NOT merged.
final List<BlogOwner> blogOwnersInStorage = storageAdapter.query(BlogOwner.class);
assertEquals(1, blogOwnersInStorage.size());
assertEquals(blogOwner, blogOwnersInStorage.get(0));
}
use of com.amplifyframework.datastore.appsync.ModelWithMetadata in project amplify-android by aws-amplify.
the class MergerTest method orphanedItemIsNotMerged.
/**
* Assume item A is dependent on item B, but the remote store has an
* orphaned item A without item B. Then, we try to merge a save for a
* item A. This should gracefully fail, with A not being in the local
* store, at the end.
* @throws DataStoreException On failure to query results for assertions
* @throws InterruptedException If interrupted while awaiting terminal result in test observer
*/
@Test
public void orphanedItemIsNotMerged() throws DataStoreException, InterruptedException {
// Arrange: an item and its parent are not in the local store
BlogOwner badOwner = BlogOwner.builder().name("Raphael").build();
Blog orphanedBlog = Blog.builder().name("How Not To Save Blogs").owner(badOwner).build();
ModelMetadata metadata = new ModelMetadata(orphanedBlog.getId(), false, 1, Temporal.Timestamp.now());
// Enforce foreign key constraint on in-memory storage adapter
doThrow(SQLiteConstraintException.class).when(inMemoryStorageAdapter).save(eq(orphanedBlog), any(), any(), any(), any());
// Act: merge a creation for an item
TestObserver<Void> observer = merger.merge(new ModelWithMetadata<>(orphanedBlog, metadata)).test();
assertTrue(observer.await(REASONABLE_WAIT_TIME, TimeUnit.MILLISECONDS));
observer.assertNoErrors().assertComplete();
// Assert: orphaned model was not merged locally
final List<Blog> blogsInStorage = storageAdapter.query(Blog.class);
assertTrue(blogsInStorage.isEmpty());
}
use of com.amplifyframework.datastore.appsync.ModelWithMetadata in project amplify-android by aws-amplify.
the class OrchestratorTest method setup.
/**
* Setup mocks and other common elements.
* @throws AmplifyException Not expected.
*/
@SuppressWarnings("unchecked")
@Before
public void setup() throws AmplifyException {
ShadowLog.stream = System.out;
// Arrange: create a BlogOwner
susan = BlogOwner.builder().name("Susan Quimby").build();
// SYNC_QUERIES_READY indicates that the sync queries have completed.
orchestratorInitObserver = HubAccumulator.create(HubChannel.DATASTORE, DataStoreChannelEventName.SYNC_QUERIES_READY, 1).start();
ModelMetadata metadata = new ModelMetadata(susan.getId(), false, 1, Temporal.Timestamp.now());
ModelWithMetadata<BlogOwner> modelWithMetadata = new ModelWithMetadata<>(susan, metadata);
// Mock behaviors from for the API category
mockApi = mock(GraphQLBehavior.class);
ApiMocking.mockSubscriptionStart(mockApi);
ApiMocking.mockSuccessfulMutation(mockApi, susan.getId(), modelWithMetadata);
ApiMocking.mockSuccessfulQuery(mockApi, modelWithMetadata);
AppSyncClient appSync = AppSyncClient.via(mockApi);
localStorageAdapter = InMemoryStorageAdapter.create();
ModelProvider modelProvider = SimpleModelProvider.withRandomVersion(BlogOwner.class);
SchemaRegistry schemaRegistry = SchemaRegistry.instance();
schemaRegistry.clear();
schemaRegistry.register(modelProvider.models());
orchestrator = new Orchestrator(modelProvider, schemaRegistry, localStorageAdapter, appSync, DataStoreConfiguration::defaults, () -> Orchestrator.State.SYNC_VIA_API, true);
}
Aggregations