BackupRulesCoverageTest.kt

1.9 KB · raw

1package com.peachpasswords.backup23import java.io.File4import javax.xml.parsers.DocumentBuilderFactory5import org.junit.Assert.assertTrue6import org.junit.Test78/** Every declared SharedPreferences file must be excluded from both transfer paths. */9class BackupRulesCoverageTest {10    @Test11    fun every_shared_preferences_filename_is_excluded_from_both_rule_files() {12        val sourceRoot = projectFile("app/src/main/java")13        val preferences = sourceRoot.walkTopDown()14            .filter { it.isFile && it.extension == "kt" }15            .flatMap { file -> PREFERENCE_DECLARATION.findAll(file.readText()).map { it.groupValues[1] } }16            .map { "$it.xml" }17            .toSet()18        assertTrue("no SharedPreferences declarations were found", preferences.isNotEmpty())1920        val backup = excludedPaths(projectFile("app/src/main/res/xml/backup_rules.xml"))21        val extraction = excludedPaths(projectFile("app/src/main/res/xml/data_extraction_rules.xml"))22        preferences.forEach { filename ->23            assertTrue("$filename is missing from backup_rules.xml", filename in backup)24            assertTrue("$filename is missing from data_extraction_rules.xml", filename in extraction)25        }26    }2728    private fun excludedPaths(file: File): Set<String> {29        val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file)30        return (0 until document.getElementsByTagName("exclude").length)31            .map { index -> document.getElementsByTagName("exclude").item(index).attributes.getNamedItem("path").nodeValue }32            .toSet()33    }3435    private fun projectFile(relativePath: String): File =36        File(relativePath).takeIf { it.exists() } ?: File("../$relativePath")3738    private companion object {39        val PREFERENCE_DECLARATION = Regex(40            "(?m)^\\s*(?:private\\s+|internal\\s+|public\\s+)?(?:const\\s+)?val\\s+\\w*PREFS\\w*\\s*=\\s*\"([^\"]+)\"",41        )42    }43}