Initial commit
This commit is contained in:
91
tests/analyzer_tests.rs
Normal file
91
tests/analyzer_tests.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use anagram_generator::{
|
||||
analyzer::PronounceabilityAnalyzer,
|
||||
scorer::{CharacterClassifier, ConsonantClusterRules, PronounceabilityScorer},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_empty_string_scores_zero() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert_eq!(analyzer.score("").value(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_good_pronounceable_words() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert!(analyzer.score("hello").value() > 60);
|
||||
assert!(analyzer.score("world").value() > 50);
|
||||
assert!(analyzer.score("create").value() > 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poor_pronounceable_words() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert!(analyzer.score("bcdfg").value() < 50);
|
||||
assert!(analyzer.score("xzqwk").value() < 50);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_many_consecutive_consonants() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert!(analyzer.score("strngth").value() < 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_character_classification() {
|
||||
let classifier = CharacterClassifier::default_french();
|
||||
assert!(classifier.is_vowel('a'));
|
||||
assert!(classifier.is_vowel('e'));
|
||||
assert!(classifier.is_vowel('A'));
|
||||
assert!(!classifier.is_vowel('b'));
|
||||
assert!(classifier.is_consonant('b'));
|
||||
assert!(classifier.is_consonant('B'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_common_clusters() {
|
||||
let rules = ConsonantClusterRules::default_french();
|
||||
assert!(rules.is_common_cluster("th"));
|
||||
assert!(rules.is_common_cluster("st"));
|
||||
assert!(rules.is_common_cluster("TH"));
|
||||
assert!(!rules.is_common_cluster("xz"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_alternating_patterns_get_bonus() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
// "banana" has good alternation (b-a-n-a-n-a)
|
||||
let score_good_alternation = analyzer.score("banana").value();
|
||||
// "strength" has poor alternation
|
||||
let score_poor_alternation = analyzer.score("strength").value();
|
||||
assert!(score_good_alternation > score_poor_alternation);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_words_starting_with_consonants() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
let score_consonant = analyzer.score("banana").value();
|
||||
let score_vowel = analyzer.score("ananas").value();
|
||||
// Words starting with consonants should get a small bonus
|
||||
assert!(score_consonant >= score_vowel);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_only_vowels_penalized() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert!(analyzer.score("aeiou").value() < 80);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_vowels_heavily_penalized() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
assert!(analyzer.score("bcdfg").value() < 50);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_common_consonant_clusters_not_penalized() {
|
||||
let analyzer = PronounceabilityAnalyzer::with_defaults();
|
||||
// "three" has "th" which is a common cluster
|
||||
let score_with_common = analyzer.score("three").value();
|
||||
// Should have a decent score despite consecutive consonants
|
||||
assert!(score_with_common > 60);
|
||||
}
|
||||
150
tests/generator_tests.rs
Normal file
150
tests/generator_tests.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use anagram_generator::{
|
||||
analyzer::PronounceabilityAnalyzer, generator::AnagramGenerator, generator::GenerationConfig,
|
||||
};
|
||||
use rand::SeedableRng;
|
||||
use rand::rngs::StdRng;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn test_generation_produces_valid_anagrams() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 100);
|
||||
let anagrams = generator.generate("test", 5, &config);
|
||||
|
||||
assert!(!anagrams.is_empty());
|
||||
|
||||
// Verify all anagrams have the same letters as source
|
||||
for anagram in &anagrams {
|
||||
let mut source_chars: Vec<char> = "test".chars().collect();
|
||||
let mut anagram_chars: Vec<char> = anagram.text().chars().collect();
|
||||
source_chars.sort();
|
||||
anagram_chars.sort();
|
||||
assert_eq!(source_chars, anagram_chars);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_respects_min_score() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let min_score = 70;
|
||||
let config = GenerationConfig::new(min_score, 10000);
|
||||
let anagrams = generator.generate("example", 10, &config);
|
||||
|
||||
for anagram in &anagrams {
|
||||
assert!(anagram.score().value() >= min_score);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_produces_unique_anagrams() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 10000);
|
||||
let anagrams = generator.generate("hello", 5, &config);
|
||||
|
||||
let unique_texts: HashSet<&str> = anagrams.iter().map(|a| a.text()).collect();
|
||||
assert_eq!(unique_texts.len(), anagrams.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anagrams_sorted_by_score() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 10000);
|
||||
let anagrams = generator.generate("world", 10, &config);
|
||||
|
||||
for i in 1..anagrams.len() {
|
||||
assert!(anagrams[i - 1].score() >= anagrams[i].score());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_config_builder() {
|
||||
let config = GenerationConfig::default()
|
||||
.with_min_score(60)
|
||||
.with_max_attempts(5000);
|
||||
|
||||
assert_eq!(config.min_score.value(), 60);
|
||||
assert_eq!(config.max_attempts_per_anagram, 5000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_excludes_original_word() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "test";
|
||||
let config = GenerationConfig::new(0, 10000);
|
||||
let anagrams = generator.generate(source, 20, &config);
|
||||
|
||||
// None of the anagrams should be the original word
|
||||
assert!(anagrams.iter().all(|a| a.text() != source));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_normalizes_input() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 100);
|
||||
let anagrams = generator.generate("TeSt", 5, &config);
|
||||
|
||||
// All anagrams should be lowercase
|
||||
for anagram in &anagrams {
|
||||
assert_eq!(anagram.text(), anagram.text().to_lowercase());
|
||||
|
||||
// Verify the anagram contains the same letters as the normalized input
|
||||
let mut source_chars: Vec<char> = "test".chars().collect();
|
||||
let mut anagram_chars: Vec<char> = anagram.text().chars().collect();
|
||||
source_chars.sort();
|
||||
anagram_chars.sort();
|
||||
assert_eq!(source_chars, anagram_chars);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_with_long_word() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(50, 5000);
|
||||
let anagrams = generator.generate("complexity", 10, &config);
|
||||
|
||||
assert!(!anagrams.is_empty());
|
||||
for anagram in &anagrams {
|
||||
assert_eq!(anagram.text().len(), "complexity".len());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_with_repeated_letters() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 1000);
|
||||
let anagrams = generator.generate("balloon", 5, &config);
|
||||
|
||||
assert!(!anagrams.is_empty());
|
||||
// Verify the letter counts are preserved
|
||||
for anagram in &anagrams {
|
||||
let mut source_chars: Vec<char> = "balloon".chars().collect();
|
||||
let mut anagram_chars: Vec<char> = anagram.text().chars().collect();
|
||||
source_chars.sort();
|
||||
anagram_chars.sort();
|
||||
assert_eq!(source_chars, anagram_chars);
|
||||
}
|
||||
}
|
||||
113
tests/integration_tests.rs
Normal file
113
tests/integration_tests.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
use anagram_generator::{
|
||||
analyzer::PronounceabilityAnalyzer, generator::AnagramGenerator, generator::GenerationConfig,
|
||||
scorer::PronounceabilityScorer,
|
||||
};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn test_end_to_end_anagram_generation() {
|
||||
let rng = thread_rng();
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(50, 1000);
|
||||
let anagrams = generator.generate("example", 5, &config);
|
||||
|
||||
assert!(!anagrams.is_empty());
|
||||
assert!(anagrams.len() <= 5);
|
||||
|
||||
for anagram in &anagrams {
|
||||
assert!(anagram.score().value() >= 50);
|
||||
assert_eq!(anagram.text().len(), "example".len());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_high_quality_anagrams_only() {
|
||||
let rng = thread_rng();
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(80, 5000);
|
||||
let anagrams = generator.generate("lawrence", 10, &config);
|
||||
|
||||
for anagram in &anagrams {
|
||||
assert!(anagram.score().value() >= 80);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_with_difficult_word() {
|
||||
let rng = thread_rng();
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
// A word with few vowels is harder to generate pronounceable anagrams from
|
||||
let config = GenerationConfig::new(30, 5000);
|
||||
let anagrams = generator.generate("rhythm", 3, &config);
|
||||
|
||||
// Should still be able to generate some anagrams
|
||||
assert!(!anagrams.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_customizable_scoring_via_trait() {
|
||||
// Test that we can use the trait abstraction
|
||||
struct SimpleScorer;
|
||||
|
||||
impl PronounceabilityScorer for SimpleScorer {
|
||||
fn score(&self, text: &str) -> anagram_generator::PronouncabilityScore {
|
||||
// Simple scorer: just count vowels
|
||||
let vowel_count = text
|
||||
.chars()
|
||||
.filter(|c| matches!(c, 'a' | 'e' | 'i' | 'o' | 'u'))
|
||||
.count();
|
||||
anagram_generator::PronouncabilityScore::new((vowel_count * 20) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
let rng = thread_rng();
|
||||
let scorer = SimpleScorer;
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let config = GenerationConfig::new(0, 100);
|
||||
let anagrams = generator.generate("aeiou", 5, &config);
|
||||
|
||||
assert!(!anagrams.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_analyzer_with_custom_configuration() {
|
||||
use anagram_generator::scorer::{
|
||||
CharacterClassifier, ConsonantClusterRules, PatternAnalysisConfig, ScoringPenalties,
|
||||
};
|
||||
|
||||
let classifier = CharacterClassifier::default_french();
|
||||
let cluster_rules = ConsonantClusterRules::default_french();
|
||||
let penalties = ScoringPenalties::default();
|
||||
let config = PatternAnalysisConfig::default();
|
||||
|
||||
let analyzer = PronounceabilityAnalyzer::new(classifier, cluster_rules, penalties, config);
|
||||
|
||||
let score = analyzer.score("hello");
|
||||
assert!(score.value() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_config_builder_pattern() {
|
||||
let config = GenerationConfig::default()
|
||||
.with_min_score(70)
|
||||
.with_max_attempts(3000);
|
||||
|
||||
assert_eq!(config.min_score.value(), 70);
|
||||
assert_eq!(config.max_attempts_per_anagram, 3000);
|
||||
|
||||
let rng = thread_rng();
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let anagrams = generator.generate("test", 5, &config);
|
||||
for anagram in &anagrams {
|
||||
assert!(anagram.score().value() >= 70);
|
||||
}
|
||||
}
|
||||
177
tests/letter_removal_tests.rs
Normal file
177
tests/letter_removal_tests.rs
Normal file
@@ -0,0 +1,177 @@
|
||||
use anagram_generator::{
|
||||
analyzer::PronounceabilityAnalyzer, generator::AnagramGenerator, generator::GenerationConfig,
|
||||
generator::LetterRemovalStrategy,
|
||||
};
|
||||
use rand::SeedableRng;
|
||||
use rand::rngs::StdRng;
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_disabled_by_default() {
|
||||
let config = GenerationConfig::default();
|
||||
assert_eq!(config.letter_removal, LetterRemovalStrategy::None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_can_be_enabled() {
|
||||
let config = GenerationConfig::default().allow_removing_letters(3);
|
||||
assert_eq!(
|
||||
config.letter_removal,
|
||||
LetterRemovalStrategy::Adaptive { max_removals: 3 }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_without_removal_produces_same_length() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "difficult";
|
||||
let config = GenerationConfig::new(0, 1000);
|
||||
let anagrams = generator.generate(source, 5, &config);
|
||||
|
||||
for anagram in &anagrams {
|
||||
assert_eq!(anagram.text().len(), source.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation_with_removal_may_produce_shorter_words() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "xyzqwbcdfg"; // Very hard to pronounce word
|
||||
let config = GenerationConfig::new(60, 5000).allow_removing_letters(4);
|
||||
let anagrams = generator.generate(source, 5, &config);
|
||||
|
||||
// With letter removal enabled, some results might be shorter
|
||||
let has_shorter = anagrams.iter().any(|a| a.text().len() < source.len());
|
||||
// Due to randomness and the difficult source word, we expect some shorter results
|
||||
assert!(has_shorter || anagrams.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_improves_pronounceability() {
|
||||
let rng1 = StdRng::seed_from_u64(42);
|
||||
let rng2 = StdRng::seed_from_u64(42);
|
||||
let scorer1 = PronounceabilityAnalyzer::with_defaults();
|
||||
let scorer2 = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator_without = AnagramGenerator::new(rng1, scorer1);
|
||||
let mut generator_with = AnagramGenerator::new(rng2, scorer2);
|
||||
|
||||
let source = "bcdfghjklm"; // No vowels, very hard to pronounce
|
||||
let config_without = GenerationConfig::new(40, 10000);
|
||||
let config_with = GenerationConfig::new(40, 10000).allow_removing_letters(5);
|
||||
|
||||
let anagrams_without = generator_without.generate(source, 10, &config_without);
|
||||
let anagrams_with = generator_with.generate(source, 10, &config_with);
|
||||
|
||||
// With letter removal, we should be able to generate more anagrams
|
||||
// or achieve higher scores on average
|
||||
if !anagrams_with.is_empty() && !anagrams_without.is_empty() {
|
||||
let avg_score_without: f32 = anagrams_without
|
||||
.iter()
|
||||
.map(|a| a.score().value() as f32)
|
||||
.sum::<f32>()
|
||||
/ anagrams_without.len() as f32;
|
||||
|
||||
let avg_score_with: f32 = anagrams_with
|
||||
.iter()
|
||||
.map(|a| a.score().value() as f32)
|
||||
.sum::<f32>()
|
||||
/ anagrams_with.len() as f32;
|
||||
|
||||
// Letter removal should help achieve better or equal scores
|
||||
assert!(
|
||||
avg_score_with >= avg_score_without || anagrams_with.len() > anagrams_without.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_respects_max_removals() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "testing";
|
||||
let max_removals = 2;
|
||||
let config = GenerationConfig::new(0, 1000).allow_removing_letters(max_removals);
|
||||
let anagrams = generator.generate(source, 20, &config);
|
||||
|
||||
// All anagrams should have at least (source.len() - max_removals) letters
|
||||
let min_length = source.len() - max_removals;
|
||||
for anagram in &anagrams {
|
||||
assert!(
|
||||
anagram.text().len() >= min_length,
|
||||
"Anagram '{}' is too short (min: {})",
|
||||
anagram.text(),
|
||||
min_length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_maintains_min_word_length() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "abc";
|
||||
let config = GenerationConfig::new(0, 1000).allow_removing_letters(10); // More than word length
|
||||
let anagrams = generator.generate(source, 10, &config);
|
||||
|
||||
// Should maintain at least 2 characters (word length - 1)
|
||||
for anagram in &anagrams {
|
||||
assert!(
|
||||
anagram.text().len() >= 1,
|
||||
"Anagram '{}' is too short",
|
||||
anagram.text()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_with_good_word() {
|
||||
let rng = StdRng::seed_from_u64(42);
|
||||
let scorer = PronounceabilityAnalyzer::with_defaults();
|
||||
let mut generator = AnagramGenerator::new(rng, scorer);
|
||||
|
||||
let source = "example"; // Already pronounceable
|
||||
let config = GenerationConfig::new(70, 1000).allow_removing_letters(2);
|
||||
let anagrams = generator.generate(source, 10, &config);
|
||||
|
||||
// With an already good word, letter removal might not be necessary
|
||||
// But it should still work and produce results
|
||||
assert!(!anagrams.is_empty());
|
||||
for anagram in &anagrams {
|
||||
assert!(anagram.score().value() >= 70);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_builder_with_letter_removal() {
|
||||
let config = GenerationConfig::default()
|
||||
.with_min_score(60)
|
||||
.with_max_attempts(5000)
|
||||
.allow_removing_letters(3);
|
||||
|
||||
assert_eq!(config.min_score.value(), 60);
|
||||
assert_eq!(config.max_attempts_per_anagram, 5000);
|
||||
assert_eq!(
|
||||
config.letter_removal,
|
||||
LetterRemovalStrategy::Adaptive { max_removals: 3 }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_letter_removal_strategy_with_method() {
|
||||
let config = GenerationConfig::default()
|
||||
.with_letter_removal(LetterRemovalStrategy::Adaptive { max_removals: 5 });
|
||||
|
||||
assert_eq!(
|
||||
config.letter_removal,
|
||||
LetterRemovalStrategy::Adaptive { max_removals: 5 }
|
||||
);
|
||||
}
|
||||
93
tests/types_tests.rs
Normal file
93
tests/types_tests.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
use anagram_generator::types::{Anagram, PronouncabilityScore};
|
||||
|
||||
#[test]
|
||||
fn test_score_value_clamped_to_range() {
|
||||
let score1 = PronouncabilityScore::new(150);
|
||||
assert_eq!(score1.value(), 100); // Should clamp to max
|
||||
|
||||
let score2 = PronouncabilityScore::new(50);
|
||||
assert_eq!(score2.value(), 50); // Should stay as is
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_saturating_operations() {
|
||||
let score = PronouncabilityScore::new(80);
|
||||
|
||||
let increased = score.saturating_add(30);
|
||||
assert_eq!(increased.value(), 100); // Should clamp at max
|
||||
|
||||
let decreased = score.saturating_sub(90);
|
||||
assert_eq!(decreased.value(), 0); // Should clamp at min
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_default_is_max() {
|
||||
let score = PronouncabilityScore::default();
|
||||
assert_eq!(score.value(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_from_u32() {
|
||||
let score: PronouncabilityScore = 75u32.into();
|
||||
assert_eq!(score.value(), 75);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_ordering() {
|
||||
let score1 = PronouncabilityScore::new(50);
|
||||
let score2 = PronouncabilityScore::new(80);
|
||||
|
||||
assert!(score2 > score1);
|
||||
assert!(score1 < score2);
|
||||
assert_eq!(score1, PronouncabilityScore::new(50));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anagram_creation() {
|
||||
let score = PronouncabilityScore::new(75);
|
||||
let anagram = Anagram::new("hello".to_string(), score);
|
||||
|
||||
assert_eq!(anagram.text(), "hello");
|
||||
assert_eq!(anagram.score(), score);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anagram_ordering() {
|
||||
let anagram1 = Anagram::new("hello".to_string(), PronouncabilityScore::new(50));
|
||||
let anagram2 = Anagram::new("world".to_string(), PronouncabilityScore::new(80));
|
||||
|
||||
// Anagrams with higher scores should come first
|
||||
assert!(anagram2 < anagram1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anagram_equality() {
|
||||
let anagram1 = Anagram::new("hello".to_string(), PronouncabilityScore::new(75));
|
||||
let anagram2 = Anagram::new("hello".to_string(), PronouncabilityScore::new(75));
|
||||
let anagram3 = Anagram::new("world".to_string(), PronouncabilityScore::new(75));
|
||||
|
||||
assert_eq!(anagram1, anagram2);
|
||||
assert_ne!(anagram1, anagram3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anagram_sorting() {
|
||||
let mut anagrams = vec![
|
||||
Anagram::new("a".to_string(), PronouncabilityScore::new(50)),
|
||||
Anagram::new("b".to_string(), PronouncabilityScore::new(80)),
|
||||
Anagram::new("c".to_string(), PronouncabilityScore::new(65)),
|
||||
];
|
||||
|
||||
anagrams.sort();
|
||||
|
||||
// Should be sorted by score descending
|
||||
assert_eq!(anagrams[0].score().value(), 80);
|
||||
assert_eq!(anagrams[1].score().value(), 65);
|
||||
assert_eq!(anagrams[2].score().value(), 50);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_score_display() {
|
||||
let score = PronouncabilityScore::new(75);
|
||||
assert_eq!(format!("{}", score), "75");
|
||||
}
|
||||
Reference in New Issue
Block a user