1use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};
7use anyhow::Result;
8use std::collections::HashMap;
9
10#[cfg(feature = "terraphim")]
12use terraphim_automata::find_matches as terraphim_find_matches;
13#[cfg(feature = "terraphim")]
14use terraphim_types::{NormalizedTerm, NormalizedTermValue, Thesaurus};
15
16use super::loader::ToolPattern;
17
18pub trait PatternMatcher: Send + Sync {
20 fn initialize(&mut self, patterns: &[ToolPattern]) -> Result<()>;
26
27 fn find_matches<'a>(&self, text: &'a str) -> Vec<ToolMatch<'a>>;
31
32 #[allow(dead_code)] fn matcher_type(&self) -> &'static str;
35}
36
37#[derive(Debug, Clone, PartialEq)]
39pub struct ToolMatch<'a> {
40 pub tool_name: String,
42
43 pub start: usize,
45
46 pub end: usize,
48
49 pub text: &'a str,
51
52 pub category: String,
54
55 pub confidence: f32,
57}
58
59pub struct AhoCorasickMatcher {
64 automaton: Option<AhoCorasick>,
66
67 pattern_to_tool: HashMap<usize, ToolInfo>,
69}
70
71#[derive(Debug, Clone)]
72struct ToolInfo {
73 name: String,
74 category: String,
75 confidence: f32,
76}
77
78impl Default for AhoCorasickMatcher {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84impl AhoCorasickMatcher {
85 #[must_use]
87 pub fn new() -> Self {
88 Self {
89 automaton: None,
90 pattern_to_tool: HashMap::new(),
91 }
92 }
93
94 fn build_automaton(&mut self, patterns: &[ToolPattern]) -> Result<()> {
96 let mut all_patterns = Vec::new();
97 self.pattern_to_tool.clear();
98
99 for tool in patterns.iter() {
100 for pattern in &tool.patterns {
101 let pattern_idx = all_patterns.len();
102 all_patterns.push(pattern.clone());
103
104 self.pattern_to_tool.insert(
105 pattern_idx,
106 ToolInfo {
107 name: tool.name.clone(),
108 category: tool.metadata.category.clone(),
109 confidence: tool.metadata.confidence,
110 },
111 );
112 }
113 }
114
115 let automaton = AhoCorasickBuilder::new()
116 .ascii_case_insensitive(true)
117 .match_kind(MatchKind::LeftmostLongest)
118 .build(&all_patterns)
119 .map_err(|e| anyhow::anyhow!("Failed to build Aho-Corasick automaton: {e}"))?;
120
121 self.automaton = Some(automaton);
122 Ok(())
123 }
124}
125
126impl PatternMatcher for AhoCorasickMatcher {
127 fn initialize(&mut self, patterns: &[ToolPattern]) -> Result<()> {
128 self.build_automaton(patterns)
129 }
130
131 fn find_matches<'a>(&self, text: &'a str) -> Vec<ToolMatch<'a>> {
132 let Some(ref automaton) = self.automaton else {
133 return Vec::new();
134 };
135
136 let mut matches = Vec::new();
137
138 for mat in automaton.find_iter(text) {
139 if let Some(tool_info) = self.pattern_to_tool.get(&mat.pattern().as_usize()) {
140 matches.push(ToolMatch {
141 tool_name: tool_info.name.clone(),
142 start: mat.start(),
143 end: mat.end(),
144 text: &text[mat.start()..mat.end()],
145 category: tool_info.category.clone(),
146 confidence: tool_info.confidence,
147 });
148 }
149 }
150
151 matches
152 }
153
154 fn matcher_type(&self) -> &'static str {
155 "aho-corasick"
156 }
157}
158
159#[cfg(feature = "terraphim")]
164pub struct TerraphimMatcher {
165 thesaurus: Option<Thesaurus>,
167
168 tool_metadata: HashMap<String, (String, f32)>, fallback: AhoCorasickMatcher,
173}
174
175#[cfg(feature = "terraphim")]
176impl Default for TerraphimMatcher {
177 fn default() -> Self {
178 Self::new()
179 }
180}
181
182#[cfg(feature = "terraphim")]
183impl TerraphimMatcher {
184 #[must_use]
186 pub fn new() -> Self {
187 Self {
188 thesaurus: None,
189 tool_metadata: HashMap::new(),
190 fallback: AhoCorasickMatcher::new(),
191 }
192 }
193
194 fn build_thesaurus(&mut self, patterns: &[ToolPattern]) -> Result<()> {
196 let mut thesaurus = Thesaurus::new("Tool Patterns".to_string());
197 let mut pattern_id = 0u64;
198
199 self.tool_metadata.clear();
201
202 for tool in patterns {
203 self.tool_metadata.insert(
205 tool.name.clone(),
206 (tool.metadata.category.clone(), tool.metadata.confidence),
207 );
208
209 for pattern in &tool.patterns {
210 pattern_id += 1;
211
212 let normalized_term = NormalizedTerm {
214 id: pattern_id,
215 value: NormalizedTermValue::from(tool.name.as_str()),
216 display_value: None,
217 url: tool.metadata.description.as_ref().map(|d| d.to_string()),
218 };
219
220 thesaurus.insert(NormalizedTermValue::from(pattern.as_str()), normalized_term);
222 }
223 }
224
225 self.thesaurus = Some(thesaurus);
226 Ok(())
227 }
228}
229
230#[cfg(feature = "terraphim")]
231impl PatternMatcher for TerraphimMatcher {
232 fn initialize(&mut self, patterns: &[ToolPattern]) -> Result<()> {
233 self.build_thesaurus(patterns)?;
235
236 self.fallback.initialize(patterns)?;
238
239 Ok(())
240 }
241
242 fn find_matches<'a>(&self, text: &'a str) -> Vec<ToolMatch<'a>> {
243 let Some(ref thesaurus) = self.thesaurus else {
245 return self.fallback.find_matches(text);
247 };
248
249 match terraphim_find_matches(text, thesaurus.clone(), true) {
251 Ok(matches) => {
252 matches
254 .into_iter()
255 .filter_map(|m| {
256 let tool_name = m.normalized_term.value.to_string();
257
258 let (category, confidence) = self
260 .tool_metadata
261 .get(&tool_name)
262 .map(|(cat, conf)| (cat.clone(), *conf))
263 .unwrap_or_else(|| ("unknown".to_string(), 0.5));
264
265 m.pos.map(|(start, end)| ToolMatch {
267 tool_name,
268 start,
269 end,
270 text: &text[start..end],
271 category,
272 confidence,
273 })
274 })
275 .collect()
276 }
277 Err(_) => {
278 self.fallback.find_matches(text)
280 }
281 }
282 }
283
284 fn matcher_type(&self) -> &'static str {
285 if self.thesaurus.is_some() {
286 "terraphim-automata"
287 } else {
288 "terraphim-automata (uninitialized)"
289 }
290 }
291}
292
293#[must_use]
298#[allow(dead_code)] pub fn create_matcher() -> Box<dyn PatternMatcher> {
300 #[cfg(feature = "terraphim")]
301 {
302 Box::new(TerraphimMatcher::new())
303 }
304
305 #[cfg(not(feature = "terraphim"))]
306 {
307 Box::new(AhoCorasickMatcher::new())
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314 use crate::patterns::loader::ToolMetadata;
315
316 fn create_test_patterns() -> Vec<ToolPattern> {
317 vec![
318 ToolPattern {
319 name: "wrangler".to_string(),
320 patterns: vec!["npx wrangler".to_string(), "bunx wrangler".to_string()],
321 metadata: ToolMetadata {
322 category: "cloudflare".to_string(),
323 description: Some("Cloudflare Workers CLI".to_string()),
324 confidence: 0.95,
325 },
326 },
327 ToolPattern {
328 name: "npm".to_string(),
329 patterns: vec!["npm ".to_string()],
330 metadata: ToolMetadata {
331 category: "package-manager".to_string(),
332 description: Some("Node package manager".to_string()),
333 confidence: 0.9,
334 },
335 },
336 ]
337 }
338
339 #[test]
340 fn test_matcher_initialization() {
341 let patterns = create_test_patterns();
342 let mut matcher = AhoCorasickMatcher::new();
343
344 let result = matcher.initialize(&patterns);
345 assert!(result.is_ok());
346 assert!(matcher.automaton.is_some());
347 }
348
349 #[test]
350 fn test_find_matches_basic() {
351 let patterns = create_test_patterns();
352 let mut matcher = AhoCorasickMatcher::new();
353 matcher.initialize(&patterns).unwrap();
354
355 let text = "npx wrangler deploy --env production";
356 let matches = matcher.find_matches(text);
357
358 assert_eq!(matches.len(), 1);
359 assert_eq!(matches[0].tool_name, "wrangler");
360 assert_eq!(matches[0].text, "npx wrangler");
361 assert_eq!(matches[0].category, "cloudflare");
362 }
363
364 #[test]
365 fn test_find_matches_case_insensitive() {
366 let patterns = create_test_patterns();
367 let mut matcher = AhoCorasickMatcher::new();
368 matcher.initialize(&patterns).unwrap();
369
370 let text = "NPX WRANGLER deploy";
371 let matches = matcher.find_matches(text);
372
373 assert_eq!(matches.len(), 1);
374 assert_eq!(matches[0].tool_name, "wrangler");
375 }
376
377 #[test]
378 fn test_find_matches_multiple_tools() {
379 let patterns = create_test_patterns();
380 let mut matcher = AhoCorasickMatcher::new();
381 matcher.initialize(&patterns).unwrap();
382
383 let text = "npm install && npx wrangler deploy";
384 let matches = matcher.find_matches(text);
385
386 assert_eq!(matches.len(), 2);
387 assert_eq!(matches[0].tool_name, "npm");
388 assert_eq!(matches[1].tool_name, "wrangler");
389 }
390
391 #[test]
392 fn test_find_matches_alternative_pattern() {
393 let patterns = create_test_patterns();
394 let mut matcher = AhoCorasickMatcher::new();
395 matcher.initialize(&patterns).unwrap();
396
397 let text = "bunx wrangler dev";
398 let matches = matcher.find_matches(text);
399
400 assert_eq!(matches.len(), 1);
401 assert_eq!(matches[0].tool_name, "wrangler");
402 assert_eq!(matches[0].text, "bunx wrangler");
403 }
404
405 #[test]
406 fn test_find_matches_no_matches() {
407 let patterns = create_test_patterns();
408 let mut matcher = AhoCorasickMatcher::new();
409 matcher.initialize(&patterns).unwrap();
410
411 let text = "echo hello world";
412 let matches = matcher.find_matches(text);
413
414 assert_eq!(matches.len(), 0);
415 }
416
417 #[test]
418 fn test_matcher_type() {
419 let matcher = AhoCorasickMatcher::new();
420 assert_eq!(matcher.matcher_type(), "aho-corasick");
421 }
422
423 #[test]
424 fn test_create_matcher_factory() {
425 let matcher = create_matcher();
426
427 #[cfg(feature = "terraphim")]
429 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
430
431 #[cfg(not(feature = "terraphim"))]
432 assert_eq!(matcher.matcher_type(), "aho-corasick");
433 }
434
435 #[test]
436 fn test_uninitialized_matcher() {
437 let matcher = AhoCorasickMatcher::new();
438 let matches = matcher.find_matches("npx wrangler deploy");
439 assert_eq!(matches.len(), 0);
440 }
441}
442
443#[cfg(test)]
444mod wrangler_tests {
445 use super::*;
446 use crate::patterns::loader::ToolMetadata;
447
448 fn create_wrangler_patterns() -> Vec<ToolPattern> {
450 vec![ToolPattern {
451 name: "wrangler".to_string(),
452 patterns: vec![
453 "npx wrangler".to_string(),
454 "bunx wrangler".to_string(),
455 "pnpm wrangler".to_string(),
456 "yarn wrangler".to_string(),
457 ],
458 metadata: ToolMetadata {
459 category: "cloudflare".to_string(),
460 description: Some("Cloudflare Workers CLI".to_string()),
461 confidence: 0.95,
462 },
463 }]
464 }
465
466 #[test]
467 fn test_wrangler_login_npx() {
468 let patterns = create_wrangler_patterns();
469 let mut matcher = AhoCorasickMatcher::new();
470 matcher.initialize(&patterns).unwrap();
471
472 let text = "npx wrangler login";
473 let matches = matcher.find_matches(text);
474
475 assert_eq!(matches.len(), 1);
476 assert_eq!(matches[0].tool_name, "wrangler");
477 assert_eq!(matches[0].text, "npx wrangler");
478 assert_eq!(matches[0].category, "cloudflare");
479 assert_eq!(matches[0].confidence, 0.95);
480 }
481
482 #[test]
483 fn test_wrangler_login_bunx() {
484 let patterns = create_wrangler_patterns();
485 let mut matcher = AhoCorasickMatcher::new();
486 matcher.initialize(&patterns).unwrap();
487
488 let text = "bunx wrangler login";
489 let matches = matcher.find_matches(text);
490
491 assert_eq!(matches.len(), 1);
492 assert_eq!(matches[0].tool_name, "wrangler");
493 assert_eq!(matches[0].text, "bunx wrangler");
494 assert_eq!(matches[0].category, "cloudflare");
495 }
496
497 #[test]
498 fn test_wrangler_deploy_basic() {
499 let patterns = create_wrangler_patterns();
500 let mut matcher = AhoCorasickMatcher::new();
501 matcher.initialize(&patterns).unwrap();
502
503 let text = "npx wrangler deploy";
504 let matches = matcher.find_matches(text);
505
506 assert_eq!(matches.len(), 1);
507 assert_eq!(matches[0].tool_name, "wrangler");
508 assert_eq!(matches[0].text, "npx wrangler");
509 }
510
511 #[test]
512 fn test_wrangler_deploy_with_env() {
513 let patterns = create_wrangler_patterns();
514 let mut matcher = AhoCorasickMatcher::new();
515 matcher.initialize(&patterns).unwrap();
516
517 let text = "npx wrangler deploy --env production";
519 let matches = matcher.find_matches(text);
520
521 assert_eq!(matches.len(), 1);
522 assert_eq!(matches[0].tool_name, "wrangler");
523 assert_eq!(matches[0].text, "npx wrangler");
524
525 let text = "bunx wrangler deploy --env staging";
527 let matches = matcher.find_matches(text);
528
529 assert_eq!(matches.len(), 1);
530 assert_eq!(matches[0].tool_name, "wrangler");
531 assert_eq!(matches[0].text, "bunx wrangler");
532 }
533
534 #[test]
535 fn test_wrangler_deploy_with_minify() {
536 let patterns = create_wrangler_patterns();
537 let mut matcher = AhoCorasickMatcher::new();
538 matcher.initialize(&patterns).unwrap();
539
540 let text = "npx wrangler deploy --minify";
541 let matches = matcher.find_matches(text);
542
543 assert_eq!(matches.len(), 1);
544 assert_eq!(matches[0].tool_name, "wrangler");
545 assert_eq!(matches[0].text, "npx wrangler");
546 }
547
548 #[test]
549 fn test_wrangler_deploy_complex_flags() {
550 let patterns = create_wrangler_patterns();
551 let mut matcher = AhoCorasickMatcher::new();
552 matcher.initialize(&patterns).unwrap();
553
554 let text = "npx wrangler deploy --env prod --minify --compatibility-date 2024-01-01";
555 let matches = matcher.find_matches(text);
556
557 assert_eq!(matches.len(), 1);
558 assert_eq!(matches[0].tool_name, "wrangler");
559 assert_eq!(matches[0].text, "npx wrangler");
560 assert_eq!(matches[0].start, 0);
561 assert_eq!(matches[0].end, 12); }
563
564 #[test]
565 fn test_wrangler_all_package_managers() {
566 let patterns = create_wrangler_patterns();
567 let mut matcher = AhoCorasickMatcher::new();
568 matcher.initialize(&patterns).unwrap();
569
570 let test_cases = vec![
572 ("npx wrangler deploy", "npx wrangler"),
573 ("bunx wrangler deploy", "bunx wrangler"),
574 ("pnpm wrangler deploy", "pnpm wrangler"),
575 ("yarn wrangler deploy", "yarn wrangler"),
576 ];
577
578 for (command, expected_text) in test_cases {
579 let matches = matcher.find_matches(command);
580 assert_eq!(matches.len(), 1, "Failed for command: {command}");
581 assert_eq!(matches[0].tool_name, "wrangler");
582 assert_eq!(matches[0].text, expected_text);
583 assert_eq!(matches[0].category, "cloudflare");
584 }
585 }
586
587 #[test]
588 fn test_wrangler_publish() {
589 let patterns = create_wrangler_patterns();
590 let mut matcher = AhoCorasickMatcher::new();
591 matcher.initialize(&patterns).unwrap();
592
593 let text = "npx wrangler publish";
594 let matches = matcher.find_matches(text);
595
596 assert_eq!(matches.len(), 1);
597 assert_eq!(matches[0].tool_name, "wrangler");
598 assert_eq!(matches[0].text, "npx wrangler");
599 }
600
601 #[test]
602 fn test_wrangler_dev() {
603 let patterns = create_wrangler_patterns();
604 let mut matcher = AhoCorasickMatcher::new();
605 matcher.initialize(&patterns).unwrap();
606
607 let text = "bunx wrangler dev";
608 let matches = matcher.find_matches(text);
609
610 assert_eq!(matches.len(), 1);
611 assert_eq!(matches[0].tool_name, "wrangler");
612 assert_eq!(matches[0].text, "bunx wrangler");
613 }
614
615 #[test]
616 fn test_wrangler_tail() {
617 let patterns = create_wrangler_patterns();
618 let mut matcher = AhoCorasickMatcher::new();
619 matcher.initialize(&patterns).unwrap();
620
621 let text = "npx wrangler tail";
622 let matches = matcher.find_matches(text);
623
624 assert_eq!(matches.len(), 1);
625 assert_eq!(matches[0].tool_name, "wrangler");
626 assert_eq!(matches[0].text, "npx wrangler");
627 }
628
629 #[test]
630 fn test_wrangler_case_insensitive() {
631 let patterns = create_wrangler_patterns();
632 let mut matcher = AhoCorasickMatcher::new();
633 matcher.initialize(&patterns).unwrap();
634
635 let text = "NPX WRANGLER DEPLOY";
636 let matches = matcher.find_matches(text);
637
638 assert_eq!(matches.len(), 1);
639 assert_eq!(matches[0].tool_name, "wrangler");
640 }
641
642 #[test]
643 fn test_wrangler_in_pipeline() {
644 let patterns = create_wrangler_patterns();
645 let mut matcher = AhoCorasickMatcher::new();
646 matcher.initialize(&patterns).unwrap();
647
648 let text = "npm install && npx wrangler deploy && npm test";
649 let matches = matcher.find_matches(text);
650
651 let wrangler_matches: Vec<_> = matches
653 .iter()
654 .filter(|m| m.tool_name == "wrangler")
655 .collect();
656 assert_eq!(wrangler_matches.len(), 1);
657 assert_eq!(wrangler_matches[0].text, "npx wrangler");
658 }
659
660 #[test]
661 fn test_wrangler_multiple_commands() {
662 let patterns = create_wrangler_patterns();
663 let mut matcher = AhoCorasickMatcher::new();
664 matcher.initialize(&patterns).unwrap();
665
666 let text = "npx wrangler login && bunx wrangler deploy";
667 let matches = matcher.find_matches(text);
668
669 assert_eq!(matches.len(), 2);
671 assert_eq!(matches[0].tool_name, "wrangler");
672 assert_eq!(matches[0].text, "npx wrangler");
673 assert_eq!(matches[1].tool_name, "wrangler");
674 assert_eq!(matches[1].text, "bunx wrangler");
675 }
676
677 #[test]
678 fn test_wrangler_with_output_redirection() {
679 let patterns = create_wrangler_patterns();
680 let mut matcher = AhoCorasickMatcher::new();
681 matcher.initialize(&patterns).unwrap();
682
683 let text = "npx wrangler deploy > deploy.log 2>&1";
684 let matches = matcher.find_matches(text);
685
686 assert_eq!(matches.len(), 1);
687 assert_eq!(matches[0].tool_name, "wrangler");
688 assert_eq!(matches[0].text, "npx wrangler");
689 }
690
691 #[test]
692 fn test_wrangler_subcommands() {
693 let patterns = create_wrangler_patterns();
694 let mut matcher = AhoCorasickMatcher::new();
695 matcher.initialize(&patterns).unwrap();
696
697 let subcommands = vec![
698 "login",
699 "deploy",
700 "publish",
701 "dev",
702 "tail",
703 "whoami",
704 "init",
705 "secret",
706 "kv:namespace",
707 "pages",
708 ];
709
710 for subcommand in subcommands {
711 let text = format!("npx wrangler {subcommand}");
712 let matches = matcher.find_matches(&text);
713
714 assert_eq!(matches.len(), 1, "Failed for subcommand: {subcommand}");
715 assert_eq!(matches[0].tool_name, "wrangler");
716 assert_eq!(matches[0].text, "npx wrangler");
717 }
718 }
719}
720
721#[cfg(all(test, feature = "terraphim"))]
722mod terraphim_tests {
723 use super::*;
724 use crate::patterns::loader::ToolMetadata;
725
726 fn create_test_patterns() -> Vec<ToolPattern> {
727 vec![
728 ToolPattern {
729 name: "wrangler".to_string(),
730 patterns: vec!["npx wrangler".to_string(), "bunx wrangler".to_string()],
731 metadata: ToolMetadata {
732 category: "cloudflare".to_string(),
733 description: Some("Cloudflare Workers CLI".to_string()),
734 confidence: 0.95,
735 },
736 },
737 ToolPattern {
738 name: "npm".to_string(),
739 patterns: vec!["npm ".to_string()],
740 metadata: ToolMetadata {
741 category: "package-manager".to_string(),
742 description: Some("Node package manager".to_string()),
743 confidence: 0.9,
744 },
745 },
746 ]
747 }
748
749 #[test]
750 fn test_terraphim_matcher_initialization() {
751 let patterns = create_test_patterns();
752 let mut matcher = TerraphimMatcher::new();
753
754 let result = matcher.initialize(&patterns);
755 assert!(result.is_ok());
756 }
757
758 #[test]
759 fn test_terraphim_find_matches_basic() {
760 let patterns = create_test_patterns();
761 let mut matcher = TerraphimMatcher::new();
762 matcher.initialize(&patterns).unwrap();
763
764 let text = "npx wrangler deploy --env production";
765 let matches = matcher.find_matches(text);
766
767 assert_eq!(matches.len(), 1);
768 assert_eq!(matches[0].tool_name, "wrangler");
769 assert_eq!(matches[0].category, "cloudflare");
770 }
771
772 #[test]
773 fn test_terraphim_find_matches_case_insensitive() {
774 let patterns = create_test_patterns();
775 let mut matcher = TerraphimMatcher::new();
776 matcher.initialize(&patterns).unwrap();
777
778 let text = "NPX WRANGLER deploy";
779 let matches = matcher.find_matches(text);
780
781 assert_eq!(matches.len(), 1);
782 assert_eq!(matches[0].tool_name, "wrangler");
783 }
784
785 #[test]
786 fn test_terraphim_find_matches_multiple_tools() {
787 let patterns = create_test_patterns();
788 let mut matcher = TerraphimMatcher::new();
789 matcher.initialize(&patterns).unwrap();
790
791 let text = "npm install && npx wrangler deploy";
792 let matches = matcher.find_matches(text);
793
794 assert_eq!(matches.len(), 2);
795 assert_eq!(matches[0].tool_name, "npm");
796 assert_eq!(matches[1].tool_name, "wrangler");
797 }
798
799 #[test]
800 fn test_terraphim_find_matches_alternative_pattern() {
801 let patterns = create_test_patterns();
802 let mut matcher = TerraphimMatcher::new();
803 matcher.initialize(&patterns).unwrap();
804
805 let text = "bunx wrangler dev";
806 let matches = matcher.find_matches(text);
807
808 assert_eq!(matches.len(), 1);
809 assert_eq!(matches[0].tool_name, "wrangler");
810 }
811
812 #[test]
813 fn test_terraphim_find_matches_no_matches() {
814 let patterns = create_test_patterns();
815 let mut matcher = TerraphimMatcher::new();
816 matcher.initialize(&patterns).unwrap();
817
818 let text = "echo hello world";
819 let matches = matcher.find_matches(text);
820
821 assert_eq!(matches.len(), 0);
822 }
823
824 #[test]
825 fn test_terraphim_matcher_type() {
826 let matcher = TerraphimMatcher::new();
827 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
828
829 let patterns = create_test_patterns();
831 let mut matcher = TerraphimMatcher::new();
832 matcher.initialize(&patterns).unwrap();
833 assert_eq!(matcher.matcher_type(), "terraphim-automata");
834 }
835
836 #[test]
837 fn test_terraphim_create_matcher_factory() {
838 let matcher = create_matcher();
839 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
841 }
842
843 #[test]
844 fn test_terraphim_uninitialized_matcher() {
845 let matcher = TerraphimMatcher::new();
846 let matches = matcher.find_matches("npx wrangler deploy");
847 assert_eq!(matches.len(), 0);
848 }
849}