package ru.pdguard; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Set; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; 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.detect.Validators; import ru.pdguard.mask.MaskMode; import ru.pdguard.mask.Masker; /** Виды замены: звёздочки, токены, правдоподобные значения. */ class MaskModeTest { private final Pipeline pipeline = new Pipeline(new RuleRegistry(), new Masker(), new PayloadStore(30)); private SystemPolicy policy(MaskMode mode) { return new SystemPolicy( SystemPolicy.DEFAULT_NAME, true, true, mode, Set.of(SystemPolicy.ALL), SystemPolicy.DEFAULT.requireCompanion(), null); } private String mask(MaskMode mode, String text) { return pipeline.process(text, UUID.randomUUID().toString(), policy(mode)); } @Test void strictModeHidesEverythingIncludingFio() { String masked = mask(MaskMode.STRICT, "Клиент Иванов Иван Иванович, паспорт 4509 123456"); assertFalse(masked.contains("Иванов"), masked); assertFalse( masked.contains("И. И. И."), "STRICT не должен превращать ФИО в инициалы: " + masked); assertTrue( masked.contains("****** **** ********"), "ожидались звёздочки по длине каждого слова: " + masked); assertTrue(masked.contains("**** ******"), "край паспорта не должен открываться: " + masked); } @Test void tokenModeNumbersEachType() { String masked = mask(MaskMode.TOKEN, "Клиент Иванов Иван Иванович, почта ivan@mail.ru"); assertTrue(masked.contains("[FIO_1]"), masked); assertTrue(masked.contains("[EMAIL_1]"), masked); } @Test void sameValueGetsSameTokenWithinRequest() { String masked = mask(MaskMode.TOKEN, "ivan@mail.ru и ещё раз ivan@mail.ru, а также petr@mail.ru"); assertEquals(2, count(masked, "[EMAIL_1]"), masked); assertEquals(1, count(masked, "[EMAIL_2]"), masked); } @Test void syntheticModeProducesPlausibleValues() { String masked = mask(MaskMode.SYNTHETIC, "Карта 4111 1111 1111 1111 клиента Иванова Ивана"); assertFalse(masked.contains("4111 1111 1111 1111"), masked); assertFalse(masked.contains("*"), "подстановка должна выглядеть настоящей: " + masked); Matcher card = Pattern.compile("\\d{4} \\d{4} \\d{4} \\d{4}").matcher(masked); assertTrue(card.find(), masked); assertTrue( Validators.luhn(card.group()), "подставленный номер карты обязан проходить проверку Луна"); } @Test void syntheticValuesAreStable() { String text = "Почта ivan@mail.ru, паспорт 4509 123456"; assertEquals(mask(MaskMode.SYNTHETIC, text), mask(MaskMode.SYNTHETIC, text)); } @Test void unmaskingWorksInEveryMode() { String original = "Клиент Иванов Иван Иванович, карта 4111 1111 1111 1111, почта ivan@mail.ru"; for (MaskMode mode : MaskMode.values()) { String id = "mode-" + mode; String masked = pipeline.process(original, id, policy(mode)); assertFalse(masked.contains("Иванов Иван Иванович"), mode + ": " + masked); assertEquals(original, pipeline.process(masked, id, policy(mode)), mode.name()); } } private static int count(String text, String fragment) { int n = 0; for (int i = text.indexOf(fragment); i >= 0; i = text.indexOf(fragment, i + fragment.length())) { n++; } return n; } }