use super::tests::{lookup, syllables, table, Table};
use super::*;
fn women_you_ju_ru() -> Table {
table(&[
("wo", &[("我", 30_000_000)]),
("men", &[("们", 3_000_000)]),
("wo'men", &[("我们", 13_696_325)]),
("you", &[("有", 15_615_006), ("又", 2_794_198)]),
("wo'men'you", &[("我们有", 83_600)]),
("ju", &[("据", 323_831), ("具", 58_121)]),
("ru", &[("如", 2_514_076), ("乳", 26_706)]),
("ju'ru", &[("巨乳", 3_174)]),
("you'ju", &[("邮局", 22_016), ("有句", 15_824)]),
])
}
fn sentences(text: &str, rows: &Table) -> Vec<SentencePath> {
let options = LatticeOptions {
nbest: 6,
..LatticeOptions::default()
};
decode_sentences(&syllables(text), &mut lookup(rows), &options)
}
#[test]
fn an_offensive_word_is_not_assembled_into_a_sentence() {
let rows = women_you_ju_ru();
let paths = sentences("wo'men'you'ju'ru", &rows);
assert!(!paths.is_empty());
for path in &paths {
assert!(
!path.words.iter().any(|word| word == "巨乳"),
"{}",
path.sentence
);
}
assert_eq!(paths[0].sentence, "我们邮局如");
}
#[test]
fn an_offensive_word_spanning_the_whole_input_is_still_its_own_sentence() {
let rows = women_you_ju_ru();
let paths = sentences("ju'ru", &rows);
assert_eq!(paths[0].sentence, "巨乳");
}
#[test]
fn a_blocked_word_is_filtered_before_the_span_limit_is_taken() {
let rows = table(&[
("wo", &[("我", 30_000_000)]),
("ju", &[("据", 323_831)]),
("ru", &[("如", 2_514_076)]),
("ju'ru", &[("巨乳", 3_174), ("句如", 100)]),
]);
let options = LatticeOptions {
span_limit: 1,
..LatticeOptions::default()
};
let paths = decode_sentences(&syllables("wo'ju'ru"), &mut lookup(&rows), &options);
assert_eq!(paths[0].sentence, "我句如");
}
fn assert_clean(paths: &[SentencePath]) {
assert!(!paths.is_empty());
for path in paths {
assert!(
!path.words.iter().any(|word| offensive::is_offensive(word)),
"{}",
path.sentence
);
}
}
#[test]
fn a_longer_word_containing_an_offensive_word_is_not_assembled() {
let rows = table(&[
("xiao", &[("小", 2_876_209)]),
("gou", &[("狗", 28_740)]),
("xiao'gou", &[("小狗", 39_026)]),
("chi", &[("吃", 1_402_977)]),
("shi", &[("食", 10_192), ("屎", 5_709)]),
("le", &[("了", 52_009_647)]),
("gou'chi", &[("狗吃", 1_067)]),
("chi'shi", &[("吃屎", 18_952), ("吃食", 9_706)]),
("chi'shi'le", &[("吃屎了", 837)]),
]);
let paths = sentences("xiao'gou'chi'shi'le", &rows);
assert_clean(&paths);
assert_eq!(paths[0].sentence, "小狗吃食了");
}
#[test]
fn sexual_slang_is_not_assembled_into_everyday_sentences() {
let rows = table(&[
("wo", &[("我", 26_297_004)]),
("men", &[("们", 544_382)]),
("wo'men", &[("我们", 13_696_325)]),
("de", &[("的", 454_876_841)]),
("wo'de", &[("我的", 4_559_189)]),
("yue", &[("约", 444_511)]),
("pao", &[("跑", 660_436), ("炮", 25_754)]),
("bu", &[("不", 4_807_412), ("步", 57_481)]),
("ba", &[("吧", 8_469_475), ("把", 8_805_251)]),
("you", &[("友", 19_462)]),
("hen", &[("很", 2_544_248)]),
("duo", &[("多", 4_347_697)]),
("yue'pao", &[("约炮", 17_710)]),
("pao'bu", &[("跑步", 335_220)]),
("bu'ba", &[("不把", 61_125)]),
("pao'you", &[("炮友", 7_075)]),
("hen'duo", &[("很多", 8_495_676)]),
]);
let paths = sentences("wo'men'yue'pao'bu'ba", &rows);
assert_clean(&paths);
assert_eq!(paths[0].sentence, "我们约跑步吧");
let paths = sentences("wo'de'pao'you'hen'duo", &rows);
assert_clean(&paths);
assert_eq!(paths[0].sentence, "我的跑友很多");
}
#[test]
fn an_exempt_word_is_still_assembled() {
let rows = table(&[
("ta", &[("他", 13_506_151)]),
("men", &[("们", 544_382)]),
("ta'men", &[("他们", 8_697_542)]),
("shui", &[("水", 125_437)]),
("ru", &[("乳", 26_706)]),
("jiao", &[("交", 392_654)]),
("rong", &[("融", 24_888)]),
("ru'jiao", &[("乳交", 1_196)]),
("jiao'rong", &[("交融", 18_980)]),
("shui'ru'jiao'rong", &[("水乳交融", 3_008)]),
]);
let paths = sentences("ta'men'shui'ru'jiao'rong", &rows);
assert_clean(&paths);
assert_eq!(paths[0].sentence, "他们水乳交融");
}
#[test]
fn a_typo_edge_never_substitutes_an_offensive_word() {
let rows = table(&[
("wo", &[("我", 30_000_000)]),
("ju", &[("据", 323_831)]),
("lu", &[("路", 476_190)]),
]);
let text = "wo'ju'lu";
let options = LatticeOptions::default();
let literal = decode_sentences(&syllables(text), &mut lookup(&rows), &options);
let edge = |value: &str| TypoEdge {
start: 1,
end: 3,
key: "ju'ru".into(),
value: value.into(),
weight: 3_174,
penalty: 0.5,
};
assert!(decode_typo_sentence(
&syllables(text),
&mut lookup(&rows),
&options,
&literal[0],
&[edge("巨乳")],
)
.is_none());
let typo = decode_typo_sentence(
&syllables(text),
&mut lookup(&rows),
&options,
&literal[0],
&[edge("句如")],
)
.expect("an ordinary typo word is used");
assert_eq!(typo.sentence, "我句如");
}
#[test]
fn a_typo_edge_spanning_the_whole_input_never_substitutes_an_offensive_word() {
let rows = table(&[
("chi", &[("吃", 1_402_977)]),
("si", &[("四", 1_011_573)]),
("le", &[("了", 52_009_647)]),
]);
let text = "chi'si'le";
let options = LatticeOptions::default();
let literal = decode_sentences(&syllables(text), &mut lookup(&rows), &options);
let edge = |value: &str| TypoEdge {
start: 0,
end: 3,
key: "chi'shi'le".into(),
value: value.into(),
weight: 837,
penalty: 0.5,
};
assert!(decode_typo_sentence(
&syllables(text),
&mut lookup(&rows),
&options,
&literal[0],
&[edge("吃屎了")],
)
.is_none());
let typo = decode_typo_sentence(
&syllables(text),
&mut lookup(&rows),
&options,
&literal[0],
&[edge("吃食了")],
)
.expect("an ordinary typo word is used");
assert_eq!(typo.sentence, "吃食了");
}