package com.google.job.data;

import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.QueryDocumentSnapshot;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.firestore.FireStoreUtils;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;

public final class JobsDatabaseTest {

    private static final String JOB_COLLECTION = "Jobs";

    Firestore firestore;
    JobsDatabase jobsDatabase;

    public JobsDatabaseTest() throws IOException {
        firestore = FireStoreUtils.getFireStore();
        jobsDatabase = new JobsDatabase(firestore);
    }

    @Test
    public void addJob_NormalInput_success() throws ExecutionException, InterruptedException {
        String expectedJobName = "Noogler";
        Job job = new Job(expectedJobName);
        jobsDatabase.addJob(job);

        // Asynchronously retrieves all documents.
        ApiFuture<QuerySnapshot> future = firestore.collection(JOB_COLLECTION).get();
        // future.get() blocks on response
        List<QueryDocumentSnapshot> documentSnapshots = future.get().getDocuments();
        Job actualJob = documentSnapshots.get(0).toObject(Job.class);

        String actualJobName = actualJob.getJobName();

        Assert.assertEquals(expectedJobName, actualJobName);
    }

    @Test
    public void editJob_NormalInput_success() throws ExecutionException, InterruptedException {
        String expectedJobName = "Googler";
        Job job = new Job(expectedJobName);

        // Asynchronously retrieves all documents.
        ApiFuture<QuerySnapshot> future = firestore.collection(JOB_COLLECTION).get();
        // future.get() blocks on response
        List<QueryDocumentSnapshot> documentSnapshots = future.get().getDocuments();
        String jobId = documentSnapshots.get(0).getId();

        jobsDatabase.editJob(jobId, job);

        documentSnapshots = firestore.collection(JOB_COLLECTION).get().get().getDocuments();
        Job actualJob = documentSnapshots.get(0).toObject(Job.class);

        String actualJobName = actualJob.getJobName();

        Assert.assertEquals(expectedJobName, actualJobName);
    }

    @Test
    public void fetchJob_NormalInput_success() throws ExecutionException, InterruptedException {
        // Asynchronously retrieves all documents.
        ApiFuture<QuerySnapshot> future = firestore.collection(JOB_COLLECTION).get();
        // future.get() blocks on response
        List<QueryDocumentSnapshot> documentSnapshots = future.get().getDocuments();
        String jobId = documentSnapshots.get(0).getId();

        Job job = jobsDatabase.fetchJob(jobId).get();

        String actualJobName = job.getJobName();
        String expectedJobName = "Googler";

        Assert.assertEquals(expectedJobName, actualJobName);
    }
}
@@ -57,24 +57,79 @@
 .ApiFuture;%0A
+import com.google.cloud.firestore.CollectionReference;%0A
 import com.g
@@ -157,24 +157,24 @@
 .Firestore;%0A
-
 import com.g
@@ -336,16 +336,41 @@
 Assert;%0A
+import org.junit.Before;%0A
 import o
@@ -580,16 +580,62 @@
  %22Jobs%22;
+%0A    private static final int BATCH_SIZE = 10;
 %0A%0A    Fi
@@ -693,31 +693,1086 @@
     
-public JobsDatabaseTest
+/** Delete a collection in batches to avoid out-of-memory errors.%0A     * Batch size may be tuned based on document size (atmost 1MB) and application requirements.%0A     */%0A    private void deleteCollection(CollectionReference collection, int batchSize) %7B%0A        try %7B%0A            // retrieve a small batch of documents to avoid out-of-memory errors%0A            ApiFuture%3CQuerySnapshot%3E future = collection.limit(batchSize).get();%0A            int deleted = 0;%0A            // future.get() blocks on document retrieval%0A            List%3CQueryDocumentSnapshot%3E documents = future.get().getDocuments();%0A            for (QueryDocumentSnapshot document : documents) %7B%0A                document.getReference().delete();%0A                ++deleted;%0A            %7D%0A            if (deleted %3E= batchSize) %7B%0A                // retrieve and delete another batch%0A                deleteCollection(collection, batchSize);%0A            %7D%0A        %7D catch (Exception e) %7B%0A            System.err.println(%22Error deleting collection : %22 + e.getMessage());%0A        %7D%0A    %7D%0A%0A    @Before%0A    public void setUp
 () t
@@ -1998,32 +1998,109 @@
 ptedException %7B%0A
+        deleteCollection(firestore.collection(JOB_COLLECTION), BATCH_SIZE);%0A%0A
         String e
@@ -2764,32 +2764,180 @@
 ptedException %7B%0A
+        deleteCollection(firestore.collection(JOB_COLLECTION), BATCH_SIZE);%0A%0A        firestore.collection(JOB_COLLECTION).add(new Job(%22Noogler%22));%0A%0A
         String e
@@ -3762,32 +3762,180 @@
 ptedException %7B%0A
+        deleteCollection(firestore.collection(JOB_COLLECTION), BATCH_SIZE);%0A%0A        firestore.collection(JOB_COLLECTION).add(new Job(%22Noogler%22));%0A%0A
         // Async
@@ -4371,33 +4371,33 @@
 ectedJobName = %22
-G
+N
 oogler%22;%0A%0A      

Clear the collection for each test