package ru.pdguard; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; 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 ContextDetectionTest { 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 + "»"); } @Test void masksPassportInEveryNotation() { assertHidden("Паспорт 4509 123456 выдан давно", "4509 123456"); assertHidden("паспорт гражданина РФ 45 09 123456", "45 09 123456"); assertHidden("ПАСПОРТ 4509123456", "4509123456"); assertHidden("Серия 4509 номер 123456", "4509"); assertHidden("серии 45 09 № 123456", "123456"); } @Test void masksPassportSeriesAndNumberSplitByWords() { String masked = mask("Документ: серия 4509 номер 123456, выдан отделом"); assertTrue(masked.contains("серия "), masked); assertTrue(masked.contains("номер "), masked); assertFalse(masked.contains("4509"), masked); assertFalse(masked.contains("123456"), masked); } @Test void masksDepartmentCode() { assertHidden("Код подразделения 770-001", "770-001"); assertHidden("к/п 770001", "770001"); } @Test void masksIssuingAuthorityButNotTheDateAfterIt() { String masked = mask("Паспорт выдан ОУФМС России по г. Москве 12.05.2015"); assertFalse(masked.contains("ОУФМС"), masked); assertFalse(masked.contains("12.05.2015"), masked); assertTrue(masked.contains("**.**.****"), "дата маскируется отдельно от органа выдачи: " + masked); } @Test void masksDriverLicense() { assertHidden("Водительское удостоверение 9902 123456", "9902 123456"); assertHidden("в/у 99 02 123456", "99 02 123456"); } @Test void masksCitizenship() { assertHidden("Гражданство: РФ", "РФ"); assertHidden("гражданство Республики Беларусь", "Беларусь"); assertHidden("Гражданин России обратился", "России"); } @Test void masksBirthPlace() { // Место рождения — тип из requireCompanion: без другого ПД рядом не маскируется // («Нижний Новгород» в рассказе о городе не должен теряться), поэтому в тесте // на распознавание якоря рядом добавлен телефон. assertHidden("Место рождения: город Тверь, проживает в Москве, тел. +7 916 123-45-67", "город Тверь"); assertHidden("Родился в Нижнем Новгороде, тел. +7 916 123-45-67", "Нижнем Новгороде"); } @Test void doesNotMaskBirthPlaceWithoutAnyOtherPersonalData() { String text = "Экскурсия в Нижний Новгород перенесена на май"; assertEquals(text, mask(text), "место рождения без другого ПД рядом не маскируется"); } @Test void masksBirthPlaceWhenOtherPersonalDataIsAlsoPresent() { assertHidden("Место рождения: город Тверь, ИНН 770301234550", "город Тверь"); } @Test void doesNotMaskCountryWithoutAnyOtherPersonalData() { String text = "Цены на нефть выросли в Казахстане в этом квартале"; assertEquals(text, mask(text), "страна без другого ПД рядом не маскируется"); } @Test void masksCountryWhenOtherPersonalDataIsAlsoPresent() { assertHidden("Страна проживания Казахстан, ИНН 770301234550", "Казахстан"); } @Test void masksCardholderName() { assertHidden("Держатель карты IVAN PETROV", "IVAN PETROV"); assertHidden("cardholder: PETR SIDOROV", "PETR SIDOROV"); } @Test void masksSecurityCodeAndPinCompletely() { String masked = mask("Карта 4111 1111 1111 1111, CVV 123, пин-код 4321"); assertFalse(masked.contains("123,"), masked); assertFalse(masked.contains("4321"), masked); assertTrue(masked.contains("***"), masked); } @Test void doesNotMaskPinWithoutAnyOtherPersonalData() { String text = "Пин-код 1234 введён неверно"; assertEquals(text, mask(text), "одиночный пин-код персональными данными не является"); } @Test void masksPinWhenCardNumberIsAlsoPresent() { assertHidden("Пин-код 1234 от карты 4111 1111 1111 1111", "1234 от"); } @Test void anchorWordsAreCaseInsensitive() { assertHidden("ПАСПОРТ СЕРИЯ 4509 НОМЕР 123456", "123456"); assertHidden("гРаЖдАнСтВо РФ, паспорт 4509 123456", "4509 123456"); } @Test void complexSentenceKeepsSurroundingWords() { String original = "Клиент, паспорт 4509 123456 выдан ОУФМС по г. Москве, " + "код подразделения 770-001, ИНН 770301234550, телефон +7 916 123-45-67"; String masked = mask(original); assertTrue(masked.startsWith("Клиент, паспорт "), masked); assertTrue(masked.contains("код подразделения"), masked); assertTrue(masked.contains("телефон"), masked); assertFalse(masked.contains("4509 123456"), masked); assertFalse(masked.contains("770301234550"), masked); } @Test void unmaskingRestoresComplexSentence() { String original = "Паспорт 4509 123456, выдан ОУФМС России по г. Москве, " + "код подразделения 770-001, гражданство РФ, CVV 123, карта 4111 1111 1111 1111"; String id = "complex-1"; String masked = pipeline.process(original, id, SystemPolicy.DEFAULT); assertFalse(masked.contains("4509 123456"), masked); assertEquals(original, pipeline.process(masked, id, SystemPolicy.DEFAULT)); } }