Skip to main content

bcore_mutation/
project.rs

1use clap::ValueEnum;
2
3/// A project that this tool can generate and analyze mutants for.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
5pub enum Project {
6    /// Bitcoin Core (https://github.com/bitcoin/bitcoin)
7    #[value(name = "bitcoin-core")]
8    BitcoinCore,
9    /// libsecp256k1 (https://github.com/bitcoin-core/secp256k1)
10    #[value(name = "secp256k1")]
11    Secp256k1,
12}
13
14impl Default for Project {
15    fn default() -> Self {
16        Project::BitcoinCore
17    }
18}
19
20impl Project {
21    /// The upstream repository URL for this project.
22    pub fn repository_url(&self) -> &'static str {
23        match self {
24            Project::BitcoinCore => "https://github.com/bitcoin/bitcoin",
25            Project::Secp256k1 => "https://github.com/bitcoin-core/secp256k1",
26        }
27    }
28
29    /// The name used for this project in the SQLite `projects` table.
30    pub fn db_name(&self) -> &'static str {
31        match self {
32            Project::BitcoinCore => "Bitcoin Core",
33            Project::Secp256k1 => "secp256k1",
34        }
35    }
36
37    /// Returns true if the given changed-file path should be excluded from
38    /// mutation. Documentation, tooling, benchmarks and other non-source
39    /// files are not worth mutating, and the exact set differs per project
40    /// because each repository has its own layout and auxiliary files.
41    pub fn should_skip_file(&self, path: &str) -> bool {
42        self.skip_substrings().iter().any(|s| path.contains(s))
43            || self.skip_suffixes().iter().any(|s| path.ends_with(s))
44    }
45
46    /// Path substrings that mark a file as non-source for this project.
47    fn skip_substrings(&self) -> &'static [&'static str] {
48        match self {
49            Project::BitcoinCore => &[
50                "doc",
51                "contrib",
52                "fuzz",
53                "bench",
54                "util",
55                "sanitizer_supressions",
56                "test_framework.py",
57            ],
58            Project::Secp256k1 => &[
59                // e.g. tests_impl and bench_impl
60                "tests_",
61                "bench_",
62                "doc",
63                "contrib",
64                "examples",
65                "ci",
66                "tools",
67                "bench",
68            ],
69        }
70    }
71
72    /// File suffixes that mark a file as non-source for this project.
73    fn skip_suffixes(&self) -> &'static [&'static str] {
74        match self {
75            Project::BitcoinCore => &[".txt"],
76            // CMakeLists.txt, *.md, configure.ac, Makefile.am, etc.
77            Project::Secp256k1 => &[".txt", ".md", ".ac", ".am"],
78        }
79    }
80}