1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.language.bm;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.lang.reflect.Field;
25 import java.util.Arrays;
26 import java.util.regex.Pattern;
27 import java.util.stream.Stream;
28
29 import org.junit.jupiter.params.ParameterizedTest;
30 import org.junit.jupiter.params.provider.Arguments;
31 import org.junit.jupiter.params.provider.MethodSource;
32 import org.junit.jupiter.params.provider.ValueSource;
33
34
35
36
37 class PhoneticEngineTest {
38
39 private static final Integer TEN = Integer.valueOf(10);
40
41 private static final Pattern PIPE_PATTERN = Pattern.compile("\\|");
42 private static final Pattern MINUS_PATTERN = Pattern.compile("-");
43
44 static Stream<Arguments> data() {
45
46 return Stream.of(
47 Arguments.of("Renault", "rinD|rinDlt|rina|rinalt|rino|rinolt|rinu|rinult", NameType.GENERIC, RuleType.APPROX, Boolean.TRUE, TEN),
48 Arguments.of("Renault", "rYnDlt|rYnalt|rYnult|rinDlt|rinalt|rinolt|rinult", NameType.ASHKENAZI, RuleType.APPROX, Boolean.TRUE, TEN),
49 Arguments.of("Renault", "rinDlt", NameType.ASHKENAZI, RuleType.APPROX, Boolean.TRUE, Integer.valueOf(1)),
50 Arguments.of("Renault", "rinDlt", NameType.SEPHARDIC, RuleType.APPROX, Boolean.TRUE, TEN),
51 Arguments.of("SntJohn-Smith", "sntjonsmit", NameType.GENERIC, RuleType.EXACT, Boolean.TRUE, TEN),
52 Arguments.of("d'ortley", "(ortlaj|ortlej)-(dortlaj|dortlej)", NameType.GENERIC, RuleType.EXACT, Boolean.TRUE, TEN),
53 Arguments.of("van helsing", "(elSink|elsink|helSink|helsink|helzink|xelsink)-(banhelsink|fanhelsink|fanhelzink|vanhelsink|vanhelzink|vanjelsink)", NameType.GENERIC, RuleType.EXACT, Boolean.FALSE, TEN),
54 Arguments.of("Judenburg", "iudnbYrk|iudnbirk|iudnburk|xudnbirk|xudnburk|zudnbirk|zudnburk", NameType.GENERIC, RuleType.APPROX, Boolean.TRUE, TEN),
55 Arguments.of("Judenburg", "iudnbYrk|iudnbirk|iudnburk|xudnbirk|xudnburk|zudnbirk|zudnburk", NameType.GENERIC, RuleType.APPROX, Boolean.TRUE, Integer.MAX_VALUE)
56 );
57
58 }
59
60 static Stream<Arguments> invalidData() {
61
62 return Stream.of(
63 Arguments.of("bar", "bar|bor|var|vor", NameType.ASHKENAZI, RuleType.APPROX, Boolean.FALSE, TEN),
64 Arguments.of("al", "|al", NameType.SEPHARDIC, RuleType.APPROX, Boolean.FALSE, TEN),
65 Arguments.of("da", "da|di", NameType.GENERIC, RuleType.EXACT, Boolean.FALSE, TEN),
66 Arguments.of("'''", "", NameType.SEPHARDIC, RuleType.APPROX, Boolean.FALSE, TEN),
67 Arguments.of("'''", "", NameType.SEPHARDIC, RuleType.APPROX, Boolean.FALSE, Integer.MAX_VALUE)
68 );
69
70 }
71
72
73 @ParameterizedTest
74 @MethodSource("data")
75 void testEncode(final String name, final String phoneticExpected, final NameType nameType,
76 final RuleType ruleType, final boolean concat, final int maxPhonemes) {
77 final PhoneticEngine engine = new PhoneticEngine(nameType, ruleType, concat, maxPhonemes);
78
79 final String phoneticActual = engine.encode(name);
80
81 assertEquals(phoneticExpected, phoneticActual, "phoneme incorrect");
82
83 if (concat) {
84 final String[] split = PIPE_PATTERN.split(phoneticActual);
85 assertTrue(split.length <= maxPhonemes);
86 } else {
87 final String[] words = MINUS_PATTERN.split(phoneticActual);
88 for (final String word : words) {
89 final String[] split = PIPE_PATTERN.split(word);
90 assertTrue(split.length <= maxPhonemes);
91 }
92 }
93 }
94
95 @ParameterizedTest
96 @MethodSource("invalidData")
97 void testInvalidEncode(final String input, final String phoneticExpected, final NameType nameType,
98 final RuleType ruleType, final boolean concat, final int maxPhonemes) {
99 final PhoneticEngine engine = new PhoneticEngine(nameType, ruleType, concat, maxPhonemes);
100
101 assertEquals(engine.encode(input), phoneticExpected);
102 }
103
104 @ParameterizedTest
105 @ValueSource(ints = { -1, 0, 10, 666 })
106 void testRejectsOversizedInputBeforeLanguageGuessing(final int configuredLimit) throws Exception {
107 final PhoneticEngine engine = PhoneticEngine.builder().setMaxInputLength(configuredLimit).get();
108 final int limit = configuredLimit < 0 ? 666 : configuredLimit;
109 final char[] chars = new char[limit + 1];
110 Arrays.fill(chars, 'a');
111 final String input = new String(chars);
112
113
114 final Field langField = PhoneticEngine.class.getDeclaredField("lang");
115 langField.setAccessible(true);
116 langField.set(engine, null);
117 assertThrows(NullPointerException.class, () -> engine.encode(input.substring(1)));
118
119 final String message = "Input is greater than maxInputLength (" + limit + ").";
120 assertEquals(message, assertThrows(IllegalArgumentException.class, () -> engine.encode(input)).getMessage());
121 assertEquals(message, assertThrows(IllegalArgumentException.class, () -> engine.encode(input, Languages.ANY_LANGUAGE)).getMessage());
122 final BeiderMorseEncoder encoder = BeiderMorseEncoder.builder().setPhoneticEngine(engine).get();
123 assertEquals(message, assertThrows(IllegalArgumentException.class, () -> encoder.encode(input)).getMessage());
124 }
125 }