package ru.pdguard.detect; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; /** Денилист известных людей: встроенный список и дозагрузка сверху без пересборки. */ class NameDictionaryTest { /** Возвращает состояние словаря к встроенному списку — не течёт в остальные тесты. */ @AfterEach void resetToBundledList() { NameDictionary.useExternalFile(Path.of("config/well-known.txt")); } @Test void bundledListCoversClassicFigures() { // Сравнение по началу слова покрывает обычную русскую флексию («Пушкин» → // «Пушкина»), но не прилагательное склонение («Толстой» → «Толстого», где // «-ой» меняется на «-ого» целиком, а не дописывается) — известное // ограничение самого приёма, не завязанное на список имён. assertTrue(NameDictionary.isWellKnown("Стихи Пушкина")); assertTrue(NameDictionary.isWellKnown("Портрет Толстой")); } @Test void bundledListCoversCurrentPublicFigures() { assertTrue(NameDictionary.isWellKnown("Заявление Набиуллиной")); assertTrue(NameDictionary.isWellKnown("Интервью Путина")); } @Test void unknownSurnameIsNotWellKnown() { assertFalse(NameDictionary.isWellKnown("Заявление Смирнова")); } /** * Фамилии, в честь которых чаще всего называют улицы в России (Росреестр). * Само по себе «улица Ленина» никогда не попало бы под ФИО — для этого * правила нужны два слова, — но денилист должен покрывать и составные * названия («Феликса Дзержинского»), и вариации написания («Будённый»/ * «Буденный»). */ @Test void bundledListCoversCommemorativeStreetNames() { assertTrue(NameDictionary.isWellKnown("улица Кирова")); // «-ский» склоняется целиком («Дзержинский» → «Дзержинского»), для таких // основа обрезается сразу до «ск» — см. Declension. assertTrue(NameDictionary.isWellKnown("проспект Дзержинского")); assertTrue(NameDictionary.isWellKnown("улица Донского")); // «Будённый» — чистое прилагательное без «-ский» (как «Толстой»): та же // известная граница приёма, родительный падеж («Будённого») им не ловится. assertTrue(NameDictionary.isWellKnown("улица Будённый")); assertTrue(NameDictionary.isWellKnown("улица Буденный"), "написание без «ё» тоже должно ловиться"); assertTrue(NameDictionary.isWellKnown("улица Жукова")); assertTrue(NameDictionary.isWellKnown("улица Островского")); } @Test void externalFileAddsNamesWithoutRebuild(@TempDir Path dir) throws IOException { Path file = dir.resolve("well-known.txt"); Files.writeString(file, "Кастомов\n", StandardCharsets.UTF_8); NameDictionary.useExternalFile(file); assertTrue(NameDictionary.isWellKnown("Интервью Кастомова"), "дописанное сверху имя должно распознаваться наравне со встроенными"); assertTrue(NameDictionary.isWellKnown("Стихи Пушкина"), "встроенный список не должен теряться при дозагрузке"); } @Test void missingExternalFileFallsBackToBundledListOnly(@TempDir Path dir) { NameDictionary.useExternalFile(dir.resolve("нет-такого-файла.txt")); assertTrue(NameDictionary.isWellKnown("Стихи Пушкина")); assertFalse(NameDictionary.isWellKnown("Заявление Смирнова")); } }