package com.google.job.data;

import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.*;
import com.google.firestore.FireStoreUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

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

public final class JobsDatabaseTest {

    private static final String TEST_JOB_COLLECTION = "Jobs_Test";
    private static final int BATCH_SIZE = 10;

    Firestore firestore;
    JobsDatabase jobsDatabase;

    @Before
    public void setUp() 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);
        Future<DocumentReference> addedJobFuture = jobsDatabase.addJob(job);

        DocumentReference documentReference = addedJobFuture.get();
        // Asynchronously retrieve the document.
        ApiFuture<DocumentSnapshot> future = documentReference.get();

        // future.get() blocks on response.
        DocumentSnapshot document = future.get();

        Job actualJob = document.toObject(Job.class);
        String actualJobName = actualJob.getJobName();

        Assert.assertEquals(expectedJobName, actualJobName);
    }

    @Test
    public void editJob_NormalInput_success() throws ExecutionException, InterruptedException {
        Future<DocumentReference> addedJobFuture = firestore.collection(TEST_JOB_COLLECTION)
                .add(new Job("Noogler"));

        String expectedJobName = "Googler";
        Job job = new Job(expectedJobName);

        DocumentReference documentReference = addedJobFuture.get();
        // Asynchronously retrieve the document.
        ApiFuture<DocumentSnapshot> future = documentReference.get();

        // future.get() blocks on response.
        DocumentSnapshot document = future.get();
        String jobId = document.getId();

        jobsDatabase.editJob(jobId, job);

        ApiFuture<DocumentSnapshot> documentSnapshotApiFuture = firestore.collection(TEST_JOB_COLLECTION).document(jobId).get();
        DocumentSnapshot documentSnapshot = documentSnapshotApiFuture.get();
        Job actualJob = documentSnapshot.toObject(Job.class);

        String actualJobName = actualJob.getJobName();

        Assert.assertEquals(expectedJobName, actualJobName);
    }

    @Test
    public void fetchJob_NormalInput_success() throws ExecutionException, InterruptedException {
        Future<DocumentReference> addedJobFuture = firestore.collection(TEST_JOB_COLLECTION)
                .add(new Job("Noogler"));

        DocumentReference documentReference = addedJobFuture.get();
        // Asynchronously retrieve the document.
        ApiFuture<DocumentSnapshot> future = documentReference.get();

        // future.get() blocks on response.
        DocumentSnapshot document = future.get();
        String jobId = document.getId();

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

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

        Assert.assertEquals(expectedJobName, actualJobName);
    }

    @After
    public void clearCollection() {
        deleteCollection(firestore.collection(TEST_JOB_COLLECTION), BATCH_SIZE);
    }

    /** Delete a collection in batches to avoid out-of-memory errors.
     * Batch size may be tuned based on document size (atmost 1MB) and application requirements.
     */
    private void deleteCollection(CollectionReference collection, int batchSize) {
        try {
            // retrieve a small batch of documents to avoid out-of-memory errors
            ApiFuture<QuerySnapshot> future = collection.limit(batchSize).get();
            int deleted = 0;
            // future.get() blocks on document retrieval
            List<QueryDocumentSnapshot> documents = future.get().getDocuments();
            for (QueryDocumentSnapshot document : documents) {
                document.getReference().delete();
                ++deleted;
            }
            if (deleted >= batchSize) {
                // retrieve and delete another batch
                deleteCollection(collection, batchSize);
            }
        } catch (Exception e) {
            System.err.println("Error deleting collection : " + e.getMessage());
        }
    }
}
@@ -146,32 +146,8 @@
 ls;%0A
-import org.junit.After;%0A
 impo
@@ -248,31 +248,8 @@
 on;%0A
-import java.util.List;%0A
 impo
@@ -431,13 +431,8 @@
 Jobs
-_Test
 %22;%0A 
@@ -836,29 +836,39 @@
 dJobName = %22
-Noogl
+Software Engine
 er%22;%0A       
@@ -1255,32 +1255,73 @@
  = future.get();
+%0A        String jobId = document.getId();
 %0A%0A        Job ac
@@ -1468,32 +1468,109 @@
  actualJobName);
+%0A%0A        firestore.collection(TEST_JOB_COLLECTION).document(jobId).delete();
 %0A    %7D%0A%0A    @Tes
@@ -1807,97 +1807,8 @@
 );%0A%0A
-        String expectedJobName = %22Googler%22;%0A        Job job = new Job(expectedJobName);%0A%0A
     
@@ -2139,39 +2139,236 @@
     
-jobsDatabase.editJob(jobId, job
+String expectedJobName = %22Googler%22;%0A        Job job = new Job(expectedJobName);%0A        Future%3CWriteResult%3E edittedDocRef = jobsDatabase.editJob(jobId, job);%0A        // future.get() blocks on response.%0A        edittedDocRef.get(
 );%0A%0A
@@ -2744,32 +2744,109 @@
  actualJobName);
+%0A%0A        firestore.collection(TEST_JOB_COLLECTION).document(jobId).delete();
 %0A    %7D%0A%0A    @Tes
@@ -3059,37 +3059,40 @@
   .add(new Job(%22
-Noogl
+Programm
 er%22));%0A%0A        
@@ -3545,21 +3545,24 @@
 Name = %22
-Noogl
+Programm
 er%22;%0A%0A  
@@ -3624,1191 +3624,84 @@
 e);%0A
-    %7D%0A%0A    @After%0A    public void clearCollection() %7B%0A        deleteCollection(firestore.collection(TEST_JOB_COLLECTION), BATCH_SIZE);%0A    %7D%0A%0A    /** 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        firestore.collection(TEST_JOB_COLLECTION).document(jobId).delete();
 %0A   

Make the test synchronous