1 package org.wikimedia.search.extra.superdetectnoop;
2
3 import static java.util.stream.Collectors.toList;
4 import static org.assertj.core.api.Assertions.assertThat;
5 import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
6
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.stream.IntStream;
10 import java.util.stream.Stream;
11
12 import javax.annotation.Nullable;
13
14 import org.junit.Test;
15
16 import com.google.common.collect.ImmutableList;
17
18 public class MultiListHandlerTest {
19 private static final List<String> A = ImmutableList.of(
20 "A/foo", "A/bar");
21 private static final List<String> B1 = ImmutableList.of(
22 "B/something");
23 private static final List<String> B2 = ImmutableList.of(
24 "B/otherthing");
25 private static final List<String> U = ImmutableList.of(
26 "unnamed", "also.unnamed");
27
28 @Test
29 public void testSingleClassNullable() {
30 testCase(null, A, A);
31 testCase(A, null, null);
32 testCase(B1, B2, B2);
33 testCaseCloseEnough(A, A);
34 testCaseCloseEnough(B1, B1);
35 testCaseCloseEnough(U, U);
36 testCase(Collections.emptyList(), A, A);
37 }
38
39 @Test
40 public void testMultiClass() {
41 testCase(null, concat(A, B1), concat(A, B1));
42 testCase(concat(A, B1), null, null);
43 testCase(A, B1, concat(A, B1));
44 testCaseCloseEnough(concat(A, B1), A);
45 testCaseCloseEnough(concat(A, B1), B1);
46 testCase(concat(A, B1), B2, concat(A, B2));
47 testCase(concat(A, B2), B1, concat(A, B1));
48 }
49
50 @Test
51 public void testUnnamedGroups() {
52 testCase(A, U, concat(A, U));
53 testCase(U, A, concat(A, U));
54 testCase(A, concat(A, U), concat(A, U));
55 testCase(U, concat(A, U), concat(A, U));
56
57 testCaseCloseEnough(concat(A, U), U);
58 testCaseCloseEnough(concat(A, B1, U), A);
59 testCaseCloseEnough(concat(A, B1, U), B1);
60 testCaseCloseEnough(concat(A, B1, U), U);
61 testCaseCloseEnough(concat(A, B1, U), concat(A, U));
62
63 testCase(concat(B1, U), B2, concat(B2, U));
64 testCase(concat(A, B2, U), B1, concat(A, B1, U));
65 }
66
67 private List<String> deleteList(String group) {
68
69
70 return ImmutableList.of(group + MultiListHandler.DELETE);
71 }
72
73 @Test
74 public void testDelete() {
75 testCaseCloseEnough(A, deleteList("B/"));
76 testCase(A, deleteList("A/"), Collections.emptyList());
77 testCase(concat(A, U), deleteList(""), A);
78 testCase(concat(A, U), deleteList("A/"), U);
79 testCase(concat(A, B1, U), concat(B2, deleteList("A/")), concat(B2, U));
80 }
81
82 @Test
83 public void testAwkwardInputs() {
84 testFailureCase(0, 1);
85 testFailureCase(A, 4);
86 testFailureCase(A, ImmutableList.of(5));
87 testFailureCase(U, ImmutableList.of("Something", 5, "Otherthing"));
88 testFailureCase(77, A);
89 testFailureCase(ImmutableList.of("Words", 5), B1);
90 testFailureCase(A, Collections.emptyList());
91 }
92
93
94 @Test(timeout = 1000)
95 public void testOversizedInputs() {
96 List<String> c = IntStream.range(0, 100000)
97 .mapToObj(i -> "B/" + i)
98 .collect(toList());
99
100
101 testCaseCloseEnough(c, c);
102 }
103
104 private void testCaseCloseEnough(@Nullable List<String> oldValue, @Nullable List<String> newValue) {
105 testCase(oldValue, newValue, null, true);
106 }
107
108 private void testCase(@Nullable List<String> oldValue, @Nullable List<String> newValue, @Nullable List<String> expected) {
109 testCase(oldValue, newValue, expected, false);
110 }
111
112 @SuppressWarnings("unchecked")
113 private void testCase(
114 @Nullable List<String> oldValue, @Nullable List<String> newValue,
115 @Nullable List<String> expected, boolean isCloseEnough
116 ) {
117 ChangeHandler.Result result = MultiListHandler.INSTANCE.handle(oldValue, newValue);
118 assertThat(result.isCloseEnough()).isEqualTo(isCloseEnough);
119 if (expected != null && result.newValue() instanceof List) {
120 List<Object> resultList = (List<Object>)result.newValue();
121 assertThat(resultList).containsExactlyInAnyOrder(expected.toArray());
122 } else {
123 assertThat(result.newValue()).isEqualTo(expected);
124 }
125 assertThat(result.isDocumentNooped()).isEqualTo(false);
126 }
127
128 private void testFailureCase(@Nullable Object oldValue, @Nullable Object newValue) {
129 try {
130 MultiListHandler.INSTANCE.handle(oldValue, newValue);
131 } catch (IllegalArgumentException e) {
132 return;
133 }
134 failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
135 }
136
137 @SafeVarargs
138 private final <T> List<T> concat(List<T>... lists) {
139 return Stream.of(lists).flatMap(List::stream).collect(toList());
140 }
141 }