package net.piemaster.kuta.algorithms.sorting;

import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

import static com.google.common.truth.Truth.assertThat;

/**
 * Abstract tests for Sorter classes.
 */
public abstract class SorterTest {

    /**
     * The Sorter under test, created by {@link #buildSorter()}.
     */
    protected Sorter<Integer> sorter;

    // Input arrays
    protected static final Integer[] EMPTY_ARRAY = new Integer[0];
    protected static final Integer[] SINGLE_ARRAY = new Integer[]{1};
    protected static final Integer[] MULTIPLE_ARRAY = new Integer[]{5, 2, 4, 1, 3, 10, 9, 8, 7, 6};
    protected static final Integer[] MULTIPLE_ARRAY_SORTED = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // Input collections
    protected static final List<Integer> EMPTY_COLL = ImmutableList.of();
    protected static final List<Integer> SINGLE_COLL = ImmutableList.of(1);
    protected static final List<Integer> MULTIPLE_COLL = ImmutableList.of(5, 2, 4, 1, 3, 10, 9, 8, 7, 6);
    protected static final List<Integer> MULTIPLE_COLL_SORTED = ImmutableList.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    /**
     * Abstract method to build a Sorter of a specific type to test.
     *
     * @return A new Sorter instance.
     */
    protected abstract Sorter<Integer> buildSorter();

    @Before
    public void setup() {
        sorter = buildSorter();
    }

    @After
    public void tearDown() {
        sorter = null;
    }

    @Test
    public void testSortArray_single() {
        Integer[] items = SINGLE_ARRAY.clone();
        sorter.sort(items);
        assertThat(items).isEqualTo(SINGLE_ARRAY);
    }

    @Test
    public void testSortArray_multiple() {
        Integer[] items = MULTIPLE_ARRAY.clone();
        sorter.sort(items);
        assertThat(items).isEqualTo(MULTIPLE_ARRAY_SORTED);
    }

    @Test
    public void testSortArray_empty() {
        Integer[] items = EMPTY_ARRAY.clone();
        sorter.sort(items);
        assertThat(items).isEqualTo(EMPTY_ARRAY);
    }


    @Test
    public void testSortList_single() {
        List<Integer> items = new ArrayList<>(SINGLE_COLL);
        sorter.sort(items);
        assertThat(items).isEqualTo(SINGLE_COLL);
    }

    @Test
    public void testSortList_multiple() {
        List<Integer> items = new ArrayList<>(MULTIPLE_COLL);
        sorter.sort(items);
        assertThat(items).isEqualTo(MULTIPLE_COLL_SORTED);
    }

    @Test
    public void testSortList_empty() {
        List<Integer> items = new ArrayList<>(EMPTY_COLL);
        sorter.sort(items);
        assertThat(items).isEqualTo(EMPTY_COLL);
    }


}

@@ -186,24 +186,54 @@
 .ArrayList;%0A
+import java.util.Collections;%0A
 import java.
@@ -299,16 +299,79 @@
 ertThat;
+%0Aimport static com.google.common.truth.Truth.assertWithMessage;
 %0A%0A/**%0A *
@@ -2223,16 +2223,903 @@
 %0A    %7D%0A%0A
+    @Test%0A    public void testSortArray_random() %7B%0A        // One more than a perfect square to hit some edge cases.%0A        final int size = 65;%0A        Integer%5B%5D items = new Integer%5Bsize%5D;%0A        for (int i = 0; i %3C size; i++) %7B%0A            // Choose a random number from MIN_INT to MAX_INT.%0A            double value = (Math.random() - 0.5) * 2 * Integer.MAX_VALUE;%0A            items%5Bi%5D = Integer.valueOf(%22%22 + Math.round(value));%0A        %7D%0A        sorter.sort(items);%0A%0A        int numWrong = 0;%0A        // Each element should be equal to or greater than the element before it.%0A        for (int i = 1; i %3C items.length; i++) %7B%0A            if (items%5Bi%5D.compareTo(items%5Bi - 1%5D) %3C 0) %7B%0A                numWrong++;%0A            %7D%0A        %7D%0A        assertWithMessage(%22Output should be sorted, but %25s elements are out of order%22, numWrong)%0A                .that(numWrong).isEqualTo(0);%0A    %7D%0A%0A
 %0A    @Te

Add larger random test case for sorting