package ru.pdguard; import org.junit.jupiter.api.Test; import ru.pdguard.config.SystemPolicy; import ru.pdguard.core.PayloadStore; import ru.pdguard.core.Pipeline; import ru.pdguard.detect.RuleRegistry; import ru.pdguard.mask.Masker; import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; /** ФИО и защита от ложных срабатываний. */ class FioTest { private final Pipeline pipeline = new Pipeline(new RuleRegistry(), new Masker(), new PayloadStore(1_000_000L, 30)); private String mask(String text) { return pipeline.process(text, UUID.randomUUID().toString(), SystemPolicy.DEFAULT); } private void assertHidden(String text, String secret) { String masked = mask(text); assertFalse(masked.contains(secret), "не замаскировано: «" + secret + "» в ответе «" + masked + "»"); } private void assertUnchanged(String text) { assertEquals(text, mask(text), "ложное срабатывание"); } @Test void masksFullNameAsInitials() { assertEquals("Клиент И. И. И. обратился", mask("Клиент Иванов Иван Иванович обратился")); } @Test void masksNameAndPatronymicWithoutSurname() { assertHidden("Пригласите Ивана Сергеевича на встречу", "Ивана Сергеевича"); } @Test void masksFemalePatronymic() { assertHidden("Петрова Анна Ивановна подписала", "Петрова Анна Ивановна"); assertHidden("Мария Никитична ждёт ответа", "Мария Никитична"); } @Test void masksSurnameWithInitialsInBothOrders() { assertHidden("Заявление от Иванов И.И. принято", "Иванов И.И."); assertHidden("Подписал И.И. Иванов", "И.И. Иванов"); } @Test void masksSurnameNextToKnownGivenName() { assertHidden("Петров Сергей подтвердил заявку", "Петров Сергей"); assertHidden("Сергей Петров подтвердил заявку", "Сергей Петров"); assertHidden("Обращение Ольги Ковалёвой рассмотрено", "Ольги Ковалёвой"); } @Test void masksLowercaseNameAfterExplicitAnchor() { assertHidden("ФИО: иванов иван иванович", "иванов иван иванович"); assertHidden("Карта оформлена на имя петров сергей", "петров сергей"); } @Test void masksNameAfterRoleAnchor() { assertHidden("Клиент Петров Сергей, заявка одобрена", "Петров Сергей"); assertHidden("Плательщик Ковалёва подтвердила перевод", "Ковалёва"); } @Test void doesNotMaskWellKnownPerson() { assertUnchanged("Напиши стихотворение в духе Александра Пушкина про осень"); assertUnchanged("Сравни Толстого и Достоевского как прозаиков"); assertUnchanged("Когда Гагарин полетел в космос"); } @Test void masksWellKnownSurnameWhenOtherPersonalDataIsPresent() { assertHidden("Клиент Александр Пушкин, паспорт 4509 123456", "Александр Пушкин"); } @Test void doesNotMaskPlaceNamesThatLookLikeSurnames() { assertUnchanged("Московский Кремль открыт для посещения"); assertUnchanged("Экскурсия в Нижний Новгород перенесена"); assertUnchanged("Смоленская площадь закрыта на ремонт"); } @Test void doesNotMaskOrdinaryCapitalisedWords() { assertUnchanged("Банк Открытие подтвердил лимит"); assertUnchanged("В Понедельник Отдел Согласует Договор"); } @Test void identificationIgnoresCase() { assertHidden("ИВАНОВ ИВАН ИВАНОВИЧ", "ИВАНОВ ИВАН ИВАНОВИЧ"); assertHidden("фио: петрова анна ивановна", "петрова анна ивановна"); } @Test void unmaskingRestoresNames() { String original = "Клиент Иванов Иван Иванович, паспорт 4509 123456, " + "дата рождения 12.05.1985, телефон +7 916 123-45-67"; String id = "fio-1"; String masked = pipeline.process(original, id, SystemPolicy.DEFAULT); assertFalse(masked.contains("Иванов Иван Иванович"), masked); assertTrue(masked.contains("И. И. И."), masked); assertEquals(original, pipeline.process(masked, id, SystemPolicy.DEFAULT)); } @Test void namesStayFastOnLargeText() { String block = "Клиент Иванов Иван Иванович, паспорт 4509 123456, город Москва. "; String large = block.repeat(4000); long started = System.nanoTime(); String masked = pipeline.process(large, "fio-large", SystemPolicy.DEFAULT); long millis = (System.nanoTime() - started) / 1_000_000; assertFalse(masked.contains("Иванов Иван Иванович")); assertTrue(millis < 1000, "обработка заняла " + millis + " мс"); } }