package aud.exam.prep; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ArgumentsSource; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assumptions.assumeTrue; public abstract class SequenceProcessorTest { protected final Comparator cmp = Integer::compareTo; protected final SequenceProcessor processor; protected SequenceProcessorTest(SequenceProcessor processor) { this.processor = processor; } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_createAndIterateWork(List list) { S s = processor.create(list); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_findOfNonExistsIsFalse(List list) { S s = processor.create(list); assertFalse(processor.find(s, -1)); assertFalse(processor.find(s, 999)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_findOfExistsIsTrue(List list) { S s = processor.create(list); for (var n : list) { assertTrue(processor.find(s, n)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_findBinaryOfNonExistsIsFalse(List list) { list.sort(cmp); S s = processor.create(list); assertFalse(processor.findBinary(s, -1, cmp)); assertFalse(processor.findBinary(s, 999, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_findBinaryOfExistsIsTrue(List list) { list.sort(Comparable::compareTo); S s = processor.create(list); for (var n : list) { assertTrue(processor.findBinary(s, n, cmp)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideOfNotExistsIsFalseAndDoesNotModify(List list) { S s = processor.create(list); assertFalse(processor.override(s, -1, -5)); assertFalse(processor.override(s, 999, -5)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideOfExistsIsTrueAndDoesModify(List list) { S s = processor.create(list); for (int i = 0; i < list.size(); i++) { var to = -(i*i) - 5; assertTrue(processor.override(s, list.get(i), to)); list.set(i, to); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideAllOfNotExistsIsFalseAndDoesNotModify(List list) { S s = processor.create(list); assertFalse(processor.overrideAll(s, -1, -5)); assertFalse(processor.overrideAll(s, 999, -5)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideAllOfExistsIsTrueAndDoesModify(List list) { S s = processor.create(list); for (int i = 0; i < list.size(); i++) { var from = list.get(i); var to = -(i*i) - 5; assertTrue(processor.overrideAll(s, from, to)); list.replaceAll(k -> Objects.equals(k, from) ? to : k); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideAtOfBadIndexIsFalseAndDoesNotModify(List list) { S s = processor.create(list); assertFalse(processor.overrideAt(s, -5, -1)); assertFalse(processor.overrideAt(s, -5, 999)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_overrideAtOfExistsIsTrueAndDoesModify(List list) { S s = processor.create(list); for (int i = 0; i < list.size(); i++) { var to = -(i*i) - 5; assertTrue(processor.overrideAt(s, to, i)); list.set(i, to); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_insertInOrderWorks(List list) { list.sort(cmp); S s = processor.create(list); for (int i = -1; i < 110; i++) { processor.insertInOrder(s, i, cmp); list.add(i); list.sort(cmp); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_removeOfNonExistsIsFalseAndDoesNotModify(List list) { S s = processor.create(list); assertFalse(processor.remove(s, -1)); assertFalse(processor.remove(s, 999)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_removeOfExistsIsTrueAndDoesModify(List list) { S s = processor.create(list); while (!list.isEmpty()) { var toRemove = list.get(list.size()/2); list.remove(toRemove); assertTrue(processor.remove(s, toRemove)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_removeAllOfNonExistsIsFalseAndDoesNotModify(List list) { S s = processor.create(list); assertFalse(processor.removeAll(s, -1)); assertFalse(processor.removeAll(s, 999)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_removeAllOfExistsIsTrueAndDoesModify(List list) { S s = processor.create(list); while (!list.isEmpty()) { var toRemove = list.get(list.size()/2); list.removeAll(Collections.singleton(toRemove)); assertTrue(processor.removeAll(s, toRemove)); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_ifAscendingOfUnsortedIsFalse(List list) { assumeTrue(list.size() > 2, "The list is to small"); list.add(list.size()/2, -1); S s = processor.create(list); assertFalse(processor.isAscending(s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_ifAscendingOfSortedIsTrue(List list) { list.sort(cmp); S s = processor.create(list); assertTrue(processor.isAscending(s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_maxWorks(List list) { list.add(-1); S s = processor.create(list); var max = list .stream() .max(cmp) .orElseThrow(); assertEquals(max, processor.max(s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_secondMaxWorks(List list) { list.add(-1); list.add(-2); S s = processor.create(list); var max = list .stream() .sorted(cmp.reversed()) .skip(1) .findFirst() .orElseThrow(); assertEquals(max, processor.secondMax(s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessOrEqualOfSameIsTrue(List list) { S s = processor.create(list); assertTrue(processor.isItemWiseLessOrEqual(s, s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessOrEqualWithPlus5Works(List list) { S a = processor.create(list); for (int i = 0; i < list.size(); i++) { if (i % 2 == 0) { list.set(i, list.get(i)+5); } } S b = processor.create(list); assertTrue(processor.isItemWiseLessOrEqual(a, b, cmp)); assumeTrue(!list.isEmpty(), "List must not be empty to be less then"); assertFalse(processor.isItemWiseLessOrEqual(b, a, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessOrEqualWithMoreElementsWorks(List list) { S a = processor.create(list); for (int i = 1; i < 4; i++) { list.add(-i); } S b = processor.create(list); assertTrue(processor.isItemWiseLessOrEqual(a, b, cmp)); assertFalse(processor.isItemWiseLessOrEqual(b, a, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessOfSameIsFalse(List list) { S s = processor.create(list); assertFalse(processor.isItemWiseLess(s, s, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessWithAlmostSameIsTrue(List list) { S a = processor.create(list); var index = list.size()/2; if (list.isEmpty()) { list.add(1); } else { list.set(index, list.get(index)+1); } S b = processor.create(list); assertTrue(processor.isItemWiseLess(a, b, cmp)); assertFalse(processor.isItemWiseLess(b, a, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isItemWiseLessWithPlus5Works(List list) { S a = processor.create(list); for (int i = 0; i < list.size(); i++) { if (i % 2 == 0) { list.set(i, list.get(i)+5); } } if (list.isEmpty()) { list.add(1); } S b = processor.create(list); assertTrue(processor.isItemWiseLess(a, b, cmp)); assertFalse(processor.isItemWiseLess(b, a, cmp)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_isLexSmallerOfSameIfFalse(List list) { S s = processor.create(list); assertFalse(processor.isLexSmaller(s, s, cmp)); } @ParameterizedTest @ArgumentsSource(DoubleLatinProvider.class) void testThat_isLexSmallerWithWorksLikeStrings(String stringA, String stringB) { S a = toSequenceByAscii(stringA); S b = toSequenceByAscii(stringB); assertEquals( stringA.compareTo(stringB) < 0, processor.isLexSmaller(a, b, cmp)); assertEquals( stringB.compareTo(stringA) < 0, processor.isLexSmaller(b, a, cmp)); } protected S toSequenceByAscii(String string) { var list = string .chars() .boxed() .collect(Collectors.toList()); return processor.create(list); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_exchangePairsWorks(List list) { S s = processor.create(list); for (int i = 1; i < list.size()-1; i += 2) { Collections.swap(list, i, i+1); } processor.exchangePairs(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_rotateTriplesWorks(List list) { S s = processor.create(list); for (int i = 1; i < list.size()-2; i += 3) { Collections.swap(list, i+1, i+2); Collections.swap(list, i, i+1); } processor.rotateTriples(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_removeEverySecondWorks(List list) { S s = processor.create(list); var everyFirst = IntStream .iterate(0, i -> i < list.size(), i -> i+2) .mapToObj(list::get) .collect(Collectors.toList()); processor.removeEverySecond(s); assertTrue(processor.check(s)); assertIterableEquals(everyFirst, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_doubleAllKeysWorks(List list) { S s = processor.create(list); list = list .stream() .flatMap(n -> Stream.of(n, n)) .collect(Collectors.toList()); processor.doubleAllKeys(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_rotateRightWorks(List list) { S s = processor.create(list); if (list.size() > 1) { var right = list.remove(list.size()-1); list.add(0, right); } s = processor.rotateRight(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_rotateLeftWorks(List list) { S s = processor.create(list); if (list.size() > 1) { var left = list.remove(0); list.add(left); } s = processor.rotateLeft(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(DuplicateListProvider.class) void testThat_removeDuplicatesWorks(List list) { S s = processor.create(list); var noDuplicatesList = new ArrayList(); for (var n : list) { if (noDuplicatesList.isEmpty() || !Objects.equals(n, noDuplicatesList.get(noDuplicatesList.size()-1))) { noDuplicatesList.add(n); } } processor.removeDuplicates(s); assertTrue(processor.check(s)); assertIterableEquals(noDuplicatesList, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_invertWorks(List list) { S s = processor.create(list); Collections.reverse(list); s = processor.invert(s); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_cloneWorks(List list) { S a = processor.create(list); S b = processor.clone(a); assertNotSame(a, b); assertTrue(processor.check(b)); assertIterableEquals(list, processor.iterate(b)); } @ParameterizedTest @ArgumentsSource(DoubleListProvider.class) void testThat_cloneWorks(List listA, List listB) { S a = processor.create(listA); S b = processor.create(listB); var list = new ArrayList(); while(!listA.isEmpty() || !listB.isEmpty()) { if (!listA.isEmpty()) { list.add(listA.remove(0)); } if (!listB.isEmpty()) { list.add(listB.remove(0)); } } S s = processor.alternate(a, b); assertTrue(processor.check(s)); assertIterableEquals(list, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(DoubleListProvider.class) void testThat_mergeWorks(List listA, List listB) { listA.sort(cmp); S a = processor.create(listA); listB.sort(cmp); S b = processor.create(listB); listA.addAll(listB); listA.sort(cmp); S s = processor.merge(a, b, cmp); assertTrue(processor.check(s)); assertIterableEquals(listA, processor.iterate(s)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_divideAlternatingWorks(List list) { S s = processor.create(list); var div = List.of(new ArrayList(), new ArrayList()); for (int i = 0; i < list.size(); i++) { div.get(i % 2).add(list.get(i)); } var p = processor.divideAlternating(s); assertTrue(processor.check(p.fst)); assertIterableEquals(div.get(0), processor.iterate(p.fst)); assertTrue(processor.check(p.snd)); assertIterableEquals(div.get(1), processor.iterate(p.snd)); } @ParameterizedTest @ArgumentsSource(ListOfRunsProvider.class) void testThat_divideAlternatingByRunsWorks(List> runs) { var list = runs .stream() .flatMap(List::stream) .collect(Collectors.toList()); S s = processor.create(list); var div = List.of(new ArrayList(), new ArrayList()); for (int i = 0; i < runs.size(); i++) { div.get(i % 2).addAll(runs.get(i)); } var p = processor.divideAlternatingByRuns(s, cmp); assertTrue(processor.check(p.fst)); assertIterableEquals(div.get(0), processor.iterate(p.fst)); assertTrue(processor.check(p.snd)); assertIterableEquals(div.get(1), processor.iterate(p.snd)); } @ParameterizedTest @ArgumentsSource(ListProvider.class) void testThat_divideByPivotWorks(List list) { S s = processor.create(list); var pivot = list.isEmpty() ? 50 : list.get(0); var div = list .stream() .collect(Collectors.groupingBy(n -> (int) Math.signum(cmp.compare(n, pivot)))); div.putIfAbsent(-1, List.of()); div.putIfAbsent(+1, List.of()); var p = processor.divideByPivot(s, pivot, cmp); assertTrue(processor.check(p.fst)); assertIterableEquals(div.get(-1), processor.iterate(p.fst)); assertTrue(processor.check(p.snd)); assertIterableEquals(div.get(+1), processor.iterate(p.snd)); } }