package mock.model;

import mock.exceptions.SourceIDAllocationException;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;


/**
 * Tests if allocating source IDs works.
 */
public class SourceIdAllocatorTest {

    /**
     * This is the list of source IDs that we start with.
     */
    private List<Integer> originalSourceIDs;

    /**
     * Used to allocate source IDs.
     */
    private SourceIdAllocator sourceIdAllocator;


    @Before
    public void setUp() throws Exception {

        originalSourceIDs = new ArrayList<>();
        originalSourceIDs.add(120);
        originalSourceIDs.add(121);
        originalSourceIDs.add(122);
        originalSourceIDs.add(123);
        originalSourceIDs.add(124);
        originalSourceIDs.add(125);


        sourceIdAllocator = new SourceIdAllocator(originalSourceIDs);

    }


    /**
     * Tests that allocation fails when we don't have any source IDs to allocate.
     */
    @Test
    public void emptyAllocationTest() {

        SourceIdAllocator allocator = new SourceIdAllocator(new ArrayList<>());


        try {
            int sourceID = allocator.allocateSourceID();

            fail("Exception should have been thrown, but wasn't.");

        } catch (SourceIDAllocationException e) {

            //We expect this exception to be thrown - success.

        }

    }


    /**
     * Tests that we can allocate a source ID.
     * @throws Exception Thrown in case of error.
     */
    @Test
    public void allocationTest() throws Exception {


        int sourceID = sourceIdAllocator.allocateSourceID();

    }


    /**
     * Tests that we can allocate source IDs, but it will eventually be unable to allocate source IDs.
     */
    @Test
    public void allocationEventuallyFailsTest() {

        while (true) {

            try {
                int sourceID = sourceIdAllocator.allocateSourceID();

            } catch (SourceIDAllocationException e) {
                //We expect to encounter this exception after enough allocations - success.
                break;

            }

        }

    }


    /**
     * Tests if we can allocate a source ID, return it, and reallocate it.
     * @throws Exception Thrown in case of error.
     */
    @Test
    public void reallocationTest() throws Exception {

        List<Integer> sourceIDList = new ArrayList<>();
        sourceIDList.add(123);

        SourceIdAllocator sourceIdAllocator = new SourceIdAllocator(sourceIDList);

        //Allocate.
        int sourceID = sourceIdAllocator.allocateSourceID();

        //Return.
        sourceIdAllocator.returnSourceID(sourceID);

        //Reallocate.
        int sourceID2 = sourceIdAllocator.allocateSourceID();

    }
}
