package com.peachpasswords.backup import java.io.File import javax.xml.parsers.DocumentBuilderFactory import org.junit.Assert.assertTrue import org.junit.Test /** Every declared SharedPreferences file must be excluded from both transfer paths. */ class BackupRulesCoverageTest { @Test fun every_shared_preferences_filename_is_excluded_from_both_rule_files() { val sourceRoot = projectFile("app/src/main/java") val preferences = sourceRoot.walkTopDown() .filter { it.isFile && it.extension == "kt" } .flatMap { file -> PREFERENCE_DECLARATION.findAll(file.readText()).map { it.groupValues[1] } } .map { "$it.xml" } .toSet() assertTrue("no SharedPreferences declarations were found", preferences.isNotEmpty()) val backup = excludedPaths(projectFile("app/src/main/res/xml/backup_rules.xml")) val extraction = excludedPaths(projectFile("app/src/main/res/xml/data_extraction_rules.xml")) preferences.forEach { filename -> assertTrue("$filename is missing from backup_rules.xml", filename in backup) assertTrue("$filename is missing from data_extraction_rules.xml", filename in extraction) } } private fun excludedPaths(file: File): Set { val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file) return (0 until document.getElementsByTagName("exclude").length) .map { index -> document.getElementsByTagName("exclude").item(index).attributes.getNamedItem("path").nodeValue } .toSet() } private fun projectFile(relativePath: String): File = File(relativePath).takeIf { it.exists() } ?: File("../$relativePath") private companion object { val PREFERENCE_DECLARATION = Regex( "(?m)^\\s*(?:private\\s+|internal\\s+|public\\s+)?(?:const\\s+)?val\\s+\\w*PREFS\\w*\\s*=\\s*\"([^\"]+)\"", ) } }