pub(crate) fn document(name: &str) -> &'static str {
match name {
"en.json" => include_str!("../fixtures/documents/en.json"),
"es.json" => include_str!("../fixtures/documents/es.json"),
"fr.json" => include_str!("../fixtures/documents/fr.json"),
"de.json" => include_str!("../fixtures/documents/de.json"),
"package.nls.json" => include_str!("../fixtures/documents/package.nls.json"),
"package.nls.de.json" => include_str!("../fixtures/documents/package.nls.de.json"),
"package.nls.ja.json" => include_str!("../fixtures/documents/package.nls.ja.json"),
"package.nls.zh-cn.json" => include_str!("../fixtures/documents/package.nls.zh-cn.json"),
"bundle.l10n.json" => include_str!("../fixtures/documents/bundle.l10n.json"),
"bundle.l10n.pt-br.json" => include_str!("../fixtures/documents/bundle.l10n.pt-br.json"),
"i18n.en.json" => include_str!("../fixtures/documents/i18n.en.json"),
"i18n.pl.json" => include_str!("../fixtures/documents/i18n.pl.json"),
"i18n.ja.json" => include_str!("../fixtures/documents/i18n.ja.json"),
"icu.en.json" => include_str!("../fixtures/documents/icu.en.json"),
"icu.es.json" => include_str!("../fixtures/documents/icu.es.json"),
"arb.en.arb" => include_str!("../fixtures/documents/arb.en.arb"),
"arb.es.arb" => include_str!("../fixtures/documents/arb.es.arb"),
"signals-i18next.json" => include_str!("../fixtures/documents/signals-i18next.json"),
"signals-next-intl.json" => include_str!("../fixtures/documents/signals-next-intl.json"),
"signals-vscode.json" => include_str!("../fixtures/documents/signals-vscode.json"),
"signals-arb.json" => include_str!("../fixtures/documents/signals-arb.json"),
"edge-escaped-braces.json" => {
include_str!("../fixtures/documents/edge-escaped-braces.json")
}
"edge-duplicates.json" => include_str!("../fixtures/documents/edge-duplicates.json"),
"edge-structure.json" => include_str!("../fixtures/documents/edge-structure.json"),
"edge-broken.json" => include_str!("../fixtures/documents/edge-broken.json"),
"edge-bom.json" => include_str!("../fixtures/documents/edge-bom.json"),
"edge-crlf.json" => include_str!("../fixtures/documents/edge-crlf.json"),
other => panic!("the corpus has no document named {other}"),
}
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use serde_json::Value;
use super::document;
use crate::catalogue;
use crate::library::{Id, Mark};
use crate::locale;
use crate::message;
use crate::scan::{self, Document, ScanOptions, System};
const CORPUS: &str = include_str!("../fixtures/detection.json");
#[derive(Debug, Deserialize)]
struct Corpus {
parsing: Vec<ParsingCase>,
locales: Vec<LocaleCase>,
marks: Vec<MarkCase>,
audit: Vec<AuditCase>,
}
#[derive(Debug, Deserialize)]
struct ParsingCase {
file: String,
keys: Option<Vec<String>>,
#[serde(default)]
duplicates: Vec<DuplicateCase>,
refused: Option<bool>,
}
#[derive(Debug, Deserialize)]
struct DuplicateCase {
key: String,
occurrences: usize,
}
#[derive(Debug, Deserialize)]
struct LocaleCase {
names: Vec<String>,
locales: Option<Vec<Option<String>>>,
refused: Option<bool>,
}
#[derive(Debug, Deserialize)]
struct MarkCase {
file: String,
marks: Vec<Mark>,
}
#[derive(Debug, Deserialize)]
struct AuditCase {
name: String,
library: Id,
files: Vec<String>,
#[serde(default)]
options: CaseOptions,
expected: Value,
}
#[derive(Debug, Default, Deserialize)]
struct CaseOptions {
source: Option<String>,
#[serde(rename = "keysAreSource")]
keys_are_source: Option<bool>,
}
fn corpus() -> Corpus {
serde_json::from_str(CORPUS).expect("the corpus is valid JSON")
}
fn documents(names: &[String]) -> Vec<Document> {
let locales = locale::locales_of(names).expect("the corpus names a real set");
names
.iter()
.zip(locales)
.map(|(name, locale)| Document {
name: name.clone(),
locale,
content: document(name).to_string(),
})
.collect()
}
#[test]
fn every_corpus_document_parses_the_same() {
let corpus = corpus();
assert!(!corpus.parsing.is_empty(), "the corpus parses nothing");
for case in corpus.parsing {
let parsed = catalogue::parse(document(&case.file));
if case.refused == Some(true) {
assert!(parsed.is_err(), "{} was not refused", case.file);
continue;
}
let parsed = parsed.expect(&case.file);
let keys: Vec<String> = parsed.entries.into_iter().map(|entry| entry.key).collect();
assert_eq!(
keys,
case.keys.expect("a case pins keys or a refusal"),
"{} keys",
case.file
);
let duplicates: Vec<(String, usize)> = parsed
.duplicates
.into_iter()
.map(|duplicate| (duplicate.key, duplicate.occurrences))
.collect();
let expected: Vec<(String, usize)> = case
.duplicates
.into_iter()
.map(|duplicate| (duplicate.key, duplicate.occurrences))
.collect();
assert_eq!(duplicates, expected, "{} duplicates", case.file);
}
}
#[test]
fn every_corpus_name_yields_the_same_locale() {
let corpus = corpus();
assert!(!corpus.locales.is_empty(), "the corpus names nothing");
for case in corpus.locales {
let actual = locale::locales_of(&case.names);
if case.refused == Some(true) {
assert!(actual.is_err(), "{:?} was not refused", case.names);
continue;
}
assert_eq!(
actual.expect("locales"),
case.locales.expect("a case pins locales or a refusal"),
"{:?}",
case.names
);
}
}
#[test]
fn every_corpus_document_carries_the_same_marks() {
let corpus = corpus();
assert!(!corpus.marks.is_empty(), "the corpus marks nothing");
for case in corpus.marks {
let parsed = catalogue::parse(document(&case.file)).expect("the corpus parses");
let keys: Vec<&str> = parsed
.entries
.iter()
.map(|entry| entry.key.as_str())
.collect();
let mut found = message::key_marks(&keys);
for text in parsed
.entries
.iter()
.filter_map(|entry| entry.text.as_deref())
{
for mark in message::marks(text) {
if !found.contains(&mark) {
found.push(mark);
}
}
}
found.sort_unstable_by_key(|mark| format!("{mark:?}"));
let mut expected = case.marks;
expected.sort_unstable_by_key(|mark| format!("{mark:?}"));
assert_eq!(found, expected, "{}", case.file);
}
}
#[test]
fn every_corpus_audit_reproduces() {
let corpus = corpus();
assert!(!corpus.audit.is_empty(), "the corpus audits nothing");
for case in corpus.audit {
let keys_are_source = case.options.keys_are_source.unwrap_or(false);
let report = scan::report_for(
&documents(&case.files),
System {
library: case.library,
version: None,
layout: None,
keys_are_source,
evidence: Vec::new(),
},
&ScanOptions {
source: case.options.source.clone(),
keys_are_source,
},
)
.expect(&case.name);
let actual = serde_json::to_value(&report).expect("a report serializes");
assert_eq!(actual, case.expected, "{}", case.name);
}
}
#[test]
fn no_corpus_answer_carries_a_translated_value() {
for translated in [
"Bienvenido",
"Bon retour",
"Übersicht",
"Kataloge",
"Verificar",
"Déconnexion",
"Inicio",
"Accueil",
] {
assert!(
!CORPUS.contains(translated),
"the corpus carries {translated}"
);
}
}
#[test]
fn no_corpus_document_carries_a_real_product_name() {
let names = [
"en.json",
"es.json",
"fr.json",
"de.json",
"edge-bom.json",
"edge-crlf.json",
"package.nls.json",
"bundle.l10n.json",
];
for name in names {
let text = document(name);
for leaked in ["SplitWinner", "splitwinner", "OffensiveEdge"] {
assert!(!text.contains(leaked), "{name} carries {leaked}");
}
}
}
}