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 =
214 NormalizedTerm::new(pattern_id, NormalizedTermValue::from(tool.name.as_str()));
215 let normalized_term =
216 if let Some(url) = tool.metadata.description.as_ref().map(|d| d.to_string()) {
217 normalized_term.with_url(url)
218 } else {
219 normalized_term
220 };
221
222 thesaurus.insert(NormalizedTermValue::from(pattern.as_str()), normalized_term);
224 }
225 }
226
227 self.thesaurus = Some(thesaurus);
228 Ok(())
229 }
230}
231
232#[cfg(feature = "terraphim")]
233impl PatternMatcher for TerraphimMatcher {
234 fn initialize(&mut self, patterns: &[ToolPattern]) -> Result<()> {
235 self.build_thesaurus(patterns)?;
237
238 self.fallback.initialize(patterns)?;
240
241 Ok(())
242 }
243
244 fn find_matches<'a>(&self, text: &'a str) -> Vec<ToolMatch<'a>> {
245 let Some(ref thesaurus) = self.thesaurus else {
247 return self.fallback.find_matches(text);
249 };
250
251 match terraphim_find_matches(text, thesaurus.clone(), true) {
253 Ok(matches) => {
254 matches
256 .into_iter()
257 .filter_map(|m| {
258 let tool_name = m.normalized_term.value.to_string();
259
260 let (category, confidence) = self
262 .tool_metadata
263 .get(&tool_name)
264 .map(|(cat, conf)| (cat.clone(), *conf))
265 .unwrap_or_else(|| ("unknown".to_string(), 0.5));
266
267 m.pos.map(|(start, end)| ToolMatch {
269 tool_name,
270 start,
271 end,
272 text: &text[start..end],
273 category,
274 confidence,
275 })
276 })
277 .collect()
278 }
279 Err(_) => {
280 self.fallback.find_matches(text)
282 }
283 }
284 }
285
286 fn matcher_type(&self) -> &'static str {
287 if self.thesaurus.is_some() {
288 "terraphim-automata"
289 } else {
290 "terraphim-automata (uninitialized)"
291 }
292 }
293}
294
295#[must_use]
300#[allow(dead_code)] pub fn create_matcher() -> Box<dyn PatternMatcher> {
302 #[cfg(feature = "terraphim")]
303 {
304 Box::new(TerraphimMatcher::new())
305 }
306
307 #[cfg(not(feature = "terraphim"))]
308 {
309 Box::new(AhoCorasickMatcher::new())
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316 use crate::patterns::loader::ToolMetadata;
317
318 fn create_test_patterns() -> Vec<ToolPattern> {
319 vec![
320 ToolPattern {
321 name: "wrangler".to_string(),
322 patterns: vec!["npx wrangler".to_string(), "bunx wrangler".to_string()],
323 metadata: ToolMetadata {
324 category: "cloudflare".to_string(),
325 description: Some("Cloudflare Workers CLI".to_string()),
326 confidence: 0.95,
327 },
328 },
329 ToolPattern {
330 name: "npm".to_string(),
331 patterns: vec!["npm ".to_string()],
332 metadata: ToolMetadata {
333 category: "package-manager".to_string(),
334 description: Some("Node package manager".to_string()),
335 confidence: 0.9,
336 },
337 },
338 ]
339 }
340
341 #[test]
342 fn test_matcher_initialization() {
343 let patterns = create_test_patterns();
344 let mut matcher = AhoCorasickMatcher::new();
345
346 let result = matcher.initialize(&patterns);
347 assert!(result.is_ok());
348 assert!(matcher.automaton.is_some());
349 }
350
351 #[test]
352 fn test_find_matches_basic() {
353 let patterns = create_test_patterns();
354 let mut matcher = AhoCorasickMatcher::new();
355 matcher.initialize(&patterns).unwrap();
356
357 let text = "npx wrangler deploy --env production";
358 let matches = matcher.find_matches(text);
359
360 assert_eq!(matches.len(), 1);
361 assert_eq!(matches[0].tool_name, "wrangler");
362 assert_eq!(matches[0].text, "npx wrangler");
363 assert_eq!(matches[0].category, "cloudflare");
364 }
365
366 #[test]
367 fn test_find_matches_case_insensitive() {
368 let patterns = create_test_patterns();
369 let mut matcher = AhoCorasickMatcher::new();
370 matcher.initialize(&patterns).unwrap();
371
372 let text = "NPX WRANGLER deploy";
373 let matches = matcher.find_matches(text);
374
375 assert_eq!(matches.len(), 1);
376 assert_eq!(matches[0].tool_name, "wrangler");
377 }
378
379 #[test]
380 fn test_find_matches_multiple_tools() {
381 let patterns = create_test_patterns();
382 let mut matcher = AhoCorasickMatcher::new();
383 matcher.initialize(&patterns).unwrap();
384
385 let text = "npm install && npx wrangler deploy";
386 let matches = matcher.find_matches(text);
387
388 assert_eq!(matches.len(), 2);
389 assert_eq!(matches[0].tool_name, "npm");
390 assert_eq!(matches[1].tool_name, "wrangler");
391 }
392
393 #[test]
394 fn test_find_matches_alternative_pattern() {
395 let patterns = create_test_patterns();
396 let mut matcher = AhoCorasickMatcher::new();
397 matcher.initialize(&patterns).unwrap();
398
399 let text = "bunx wrangler dev";
400 let matches = matcher.find_matches(text);
401
402 assert_eq!(matches.len(), 1);
403 assert_eq!(matches[0].tool_name, "wrangler");
404 assert_eq!(matches[0].text, "bunx wrangler");
405 }
406
407 #[test]
408 fn test_find_matches_no_matches() {
409 let patterns = create_test_patterns();
410 let mut matcher = AhoCorasickMatcher::new();
411 matcher.initialize(&patterns).unwrap();
412
413 let text = "echo hello world";
414 let matches = matcher.find_matches(text);
415
416 assert_eq!(matches.len(), 0);
417 }
418
419 #[test]
420 fn test_matcher_type() {
421 let matcher = AhoCorasickMatcher::new();
422 assert_eq!(matcher.matcher_type(), "aho-corasick");
423 }
424
425 #[test]
426 fn test_create_matcher_factory() {
427 let matcher = create_matcher();
428
429 #[cfg(feature = "terraphim")]
431 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
432
433 #[cfg(not(feature = "terraphim"))]
434 assert_eq!(matcher.matcher_type(), "aho-corasick");
435 }
436
437 #[test]
438 fn test_uninitialized_matcher() {
439 let matcher = AhoCorasickMatcher::new();
440 let matches = matcher.find_matches("npx wrangler deploy");
441 assert_eq!(matches.len(), 0);
442 }
443}
444
445#[cfg(test)]
446mod wrangler_tests {
447 use super::*;
448 use crate::patterns::loader::ToolMetadata;
449
450 fn create_wrangler_patterns() -> Vec<ToolPattern> {
452 vec![ToolPattern {
453 name: "wrangler".to_string(),
454 patterns: vec![
455 "npx wrangler".to_string(),
456 "bunx wrangler".to_string(),
457 "pnpm wrangler".to_string(),
458 "yarn wrangler".to_string(),
459 ],
460 metadata: ToolMetadata {
461 category: "cloudflare".to_string(),
462 description: Some("Cloudflare Workers CLI".to_string()),
463 confidence: 0.95,
464 },
465 }]
466 }
467
468 #[test]
469 fn test_wrangler_login_npx() {
470 let patterns = create_wrangler_patterns();
471 let mut matcher = AhoCorasickMatcher::new();
472 matcher.initialize(&patterns).unwrap();
473
474 let text = "npx wrangler login";
475 let matches = matcher.find_matches(text);
476
477 assert_eq!(matches.len(), 1);
478 assert_eq!(matches[0].tool_name, "wrangler");
479 assert_eq!(matches[0].text, "npx wrangler");
480 assert_eq!(matches[0].category, "cloudflare");
481 assert_eq!(matches[0].confidence, 0.95);
482 }
483
484 #[test]
485 fn test_wrangler_login_bunx() {
486 let patterns = create_wrangler_patterns();
487 let mut matcher = AhoCorasickMatcher::new();
488 matcher.initialize(&patterns).unwrap();
489
490 let text = "bunx wrangler login";
491 let matches = matcher.find_matches(text);
492
493 assert_eq!(matches.len(), 1);
494 assert_eq!(matches[0].tool_name, "wrangler");
495 assert_eq!(matches[0].text, "bunx wrangler");
496 assert_eq!(matches[0].category, "cloudflare");
497 }
498
499 #[test]
500 fn test_wrangler_deploy_basic() {
501 let patterns = create_wrangler_patterns();
502 let mut matcher = AhoCorasickMatcher::new();
503 matcher.initialize(&patterns).unwrap();
504
505 let text = "npx wrangler deploy";
506 let matches = matcher.find_matches(text);
507
508 assert_eq!(matches.len(), 1);
509 assert_eq!(matches[0].tool_name, "wrangler");
510 assert_eq!(matches[0].text, "npx wrangler");
511 }
512
513 #[test]
514 fn test_wrangler_deploy_with_env() {
515 let patterns = create_wrangler_patterns();
516 let mut matcher = AhoCorasickMatcher::new();
517 matcher.initialize(&patterns).unwrap();
518
519 let text = "npx wrangler deploy --env production";
521 let matches = matcher.find_matches(text);
522
523 assert_eq!(matches.len(), 1);
524 assert_eq!(matches[0].tool_name, "wrangler");
525 assert_eq!(matches[0].text, "npx wrangler");
526
527 let text = "bunx wrangler deploy --env staging";
529 let matches = matcher.find_matches(text);
530
531 assert_eq!(matches.len(), 1);
532 assert_eq!(matches[0].tool_name, "wrangler");
533 assert_eq!(matches[0].text, "bunx wrangler");
534 }
535
536 #[test]
537 fn test_wrangler_deploy_with_minify() {
538 let patterns = create_wrangler_patterns();
539 let mut matcher = AhoCorasickMatcher::new();
540 matcher.initialize(&patterns).unwrap();
541
542 let text = "npx wrangler deploy --minify";
543 let matches = matcher.find_matches(text);
544
545 assert_eq!(matches.len(), 1);
546 assert_eq!(matches[0].tool_name, "wrangler");
547 assert_eq!(matches[0].text, "npx wrangler");
548 }
549
550 #[test]
551 fn test_wrangler_deploy_complex_flags() {
552 let patterns = create_wrangler_patterns();
553 let mut matcher = AhoCorasickMatcher::new();
554 matcher.initialize(&patterns).unwrap();
555
556 let text = "npx wrangler deploy --env prod --minify --compatibility-date 2024-01-01";
557 let matches = matcher.find_matches(text);
558
559 assert_eq!(matches.len(), 1);
560 assert_eq!(matches[0].tool_name, "wrangler");
561 assert_eq!(matches[0].text, "npx wrangler");
562 assert_eq!(matches[0].start, 0);
563 assert_eq!(matches[0].end, 12); }
565
566 #[test]
567 fn test_wrangler_all_package_managers() {
568 let patterns = create_wrangler_patterns();
569 let mut matcher = AhoCorasickMatcher::new();
570 matcher.initialize(&patterns).unwrap();
571
572 let test_cases = vec![
574 ("npx wrangler deploy", "npx wrangler"),
575 ("bunx wrangler deploy", "bunx wrangler"),
576 ("pnpm wrangler deploy", "pnpm wrangler"),
577 ("yarn wrangler deploy", "yarn wrangler"),
578 ];
579
580 for (command, expected_text) in test_cases {
581 let matches = matcher.find_matches(command);
582 assert_eq!(matches.len(), 1, "Failed for command: {command}");
583 assert_eq!(matches[0].tool_name, "wrangler");
584 assert_eq!(matches[0].text, expected_text);
585 assert_eq!(matches[0].category, "cloudflare");
586 }
587 }
588
589 #[test]
590 fn test_wrangler_publish() {
591 let patterns = create_wrangler_patterns();
592 let mut matcher = AhoCorasickMatcher::new();
593 matcher.initialize(&patterns).unwrap();
594
595 let text = "npx wrangler publish";
596 let matches = matcher.find_matches(text);
597
598 assert_eq!(matches.len(), 1);
599 assert_eq!(matches[0].tool_name, "wrangler");
600 assert_eq!(matches[0].text, "npx wrangler");
601 }
602
603 #[test]
604 fn test_wrangler_dev() {
605 let patterns = create_wrangler_patterns();
606 let mut matcher = AhoCorasickMatcher::new();
607 matcher.initialize(&patterns).unwrap();
608
609 let text = "bunx wrangler dev";
610 let matches = matcher.find_matches(text);
611
612 assert_eq!(matches.len(), 1);
613 assert_eq!(matches[0].tool_name, "wrangler");
614 assert_eq!(matches[0].text, "bunx wrangler");
615 }
616
617 #[test]
618 fn test_wrangler_tail() {
619 let patterns = create_wrangler_patterns();
620 let mut matcher = AhoCorasickMatcher::new();
621 matcher.initialize(&patterns).unwrap();
622
623 let text = "npx wrangler tail";
624 let matches = matcher.find_matches(text);
625
626 assert_eq!(matches.len(), 1);
627 assert_eq!(matches[0].tool_name, "wrangler");
628 assert_eq!(matches[0].text, "npx wrangler");
629 }
630
631 #[test]
632 fn test_wrangler_case_insensitive() {
633 let patterns = create_wrangler_patterns();
634 let mut matcher = AhoCorasickMatcher::new();
635 matcher.initialize(&patterns).unwrap();
636
637 let text = "NPX WRANGLER DEPLOY";
638 let matches = matcher.find_matches(text);
639
640 assert_eq!(matches.len(), 1);
641 assert_eq!(matches[0].tool_name, "wrangler");
642 }
643
644 #[test]
645 fn test_wrangler_in_pipeline() {
646 let patterns = create_wrangler_patterns();
647 let mut matcher = AhoCorasickMatcher::new();
648 matcher.initialize(&patterns).unwrap();
649
650 let text = "npm install && npx wrangler deploy && npm test";
651 let matches = matcher.find_matches(text);
652
653 let wrangler_matches: Vec<_> = matches
655 .iter()
656 .filter(|m| m.tool_name == "wrangler")
657 .collect();
658 assert_eq!(wrangler_matches.len(), 1);
659 assert_eq!(wrangler_matches[0].text, "npx wrangler");
660 }
661
662 #[test]
663 fn test_wrangler_multiple_commands() {
664 let patterns = create_wrangler_patterns();
665 let mut matcher = AhoCorasickMatcher::new();
666 matcher.initialize(&patterns).unwrap();
667
668 let text = "npx wrangler login && bunx wrangler deploy";
669 let matches = matcher.find_matches(text);
670
671 assert_eq!(matches.len(), 2);
673 assert_eq!(matches[0].tool_name, "wrangler");
674 assert_eq!(matches[0].text, "npx wrangler");
675 assert_eq!(matches[1].tool_name, "wrangler");
676 assert_eq!(matches[1].text, "bunx wrangler");
677 }
678
679 #[test]
680 fn test_wrangler_with_output_redirection() {
681 let patterns = create_wrangler_patterns();
682 let mut matcher = AhoCorasickMatcher::new();
683 matcher.initialize(&patterns).unwrap();
684
685 let text = "npx wrangler deploy > deploy.log 2>&1";
686 let matches = matcher.find_matches(text);
687
688 assert_eq!(matches.len(), 1);
689 assert_eq!(matches[0].tool_name, "wrangler");
690 assert_eq!(matches[0].text, "npx wrangler");
691 }
692
693 #[test]
694 fn test_wrangler_subcommands() {
695 let patterns = create_wrangler_patterns();
696 let mut matcher = AhoCorasickMatcher::new();
697 matcher.initialize(&patterns).unwrap();
698
699 let subcommands = vec![
700 "login",
701 "deploy",
702 "publish",
703 "dev",
704 "tail",
705 "whoami",
706 "init",
707 "secret",
708 "kv:namespace",
709 "pages",
710 ];
711
712 for subcommand in subcommands {
713 let text = format!("npx wrangler {subcommand}");
714 let matches = matcher.find_matches(&text);
715
716 assert_eq!(matches.len(), 1, "Failed for subcommand: {subcommand}");
717 assert_eq!(matches[0].tool_name, "wrangler");
718 assert_eq!(matches[0].text, "npx wrangler");
719 }
720 }
721}
722
723#[cfg(all(test, feature = "terraphim"))]
724mod terraphim_tests {
725 use super::*;
726 use crate::patterns::loader::ToolMetadata;
727
728 fn create_test_patterns() -> Vec<ToolPattern> {
729 vec![
730 ToolPattern {
731 name: "wrangler".to_string(),
732 patterns: vec!["npx wrangler".to_string(), "bunx wrangler".to_string()],
733 metadata: ToolMetadata {
734 category: "cloudflare".to_string(),
735 description: Some("Cloudflare Workers CLI".to_string()),
736 confidence: 0.95,
737 },
738 },
739 ToolPattern {
740 name: "npm".to_string(),
741 patterns: vec!["npm ".to_string()],
742 metadata: ToolMetadata {
743 category: "package-manager".to_string(),
744 description: Some("Node package manager".to_string()),
745 confidence: 0.9,
746 },
747 },
748 ]
749 }
750
751 #[test]
752 fn test_terraphim_matcher_initialization() {
753 let patterns = create_test_patterns();
754 let mut matcher = TerraphimMatcher::new();
755
756 let result = matcher.initialize(&patterns);
757 assert!(result.is_ok());
758 }
759
760 #[test]
761 fn test_terraphim_find_matches_basic() {
762 let patterns = create_test_patterns();
763 let mut matcher = TerraphimMatcher::new();
764 matcher.initialize(&patterns).unwrap();
765
766 let text = "npx wrangler deploy --env production";
767 let matches = matcher.find_matches(text);
768
769 assert_eq!(matches.len(), 1);
770 assert_eq!(matches[0].tool_name, "wrangler");
771 assert_eq!(matches[0].category, "cloudflare");
772 }
773
774 #[test]
775 fn test_terraphim_find_matches_case_insensitive() {
776 let patterns = create_test_patterns();
777 let mut matcher = TerraphimMatcher::new();
778 matcher.initialize(&patterns).unwrap();
779
780 let text = "NPX WRANGLER deploy";
781 let matches = matcher.find_matches(text);
782
783 assert_eq!(matches.len(), 1);
784 assert_eq!(matches[0].tool_name, "wrangler");
785 }
786
787 #[test]
788 fn test_terraphim_find_matches_multiple_tools() {
789 let patterns = create_test_patterns();
790 let mut matcher = TerraphimMatcher::new();
791 matcher.initialize(&patterns).unwrap();
792
793 let text = "npm install && npx wrangler deploy";
794 let matches = matcher.find_matches(text);
795
796 assert_eq!(matches.len(), 2);
797 assert_eq!(matches[0].tool_name, "npm");
798 assert_eq!(matches[1].tool_name, "wrangler");
799 }
800
801 #[test]
802 fn test_terraphim_find_matches_alternative_pattern() {
803 let patterns = create_test_patterns();
804 let mut matcher = TerraphimMatcher::new();
805 matcher.initialize(&patterns).unwrap();
806
807 let text = "bunx wrangler dev";
808 let matches = matcher.find_matches(text);
809
810 assert_eq!(matches.len(), 1);
811 assert_eq!(matches[0].tool_name, "wrangler");
812 }
813
814 #[test]
815 fn test_terraphim_find_matches_no_matches() {
816 let patterns = create_test_patterns();
817 let mut matcher = TerraphimMatcher::new();
818 matcher.initialize(&patterns).unwrap();
819
820 let text = "echo hello world";
821 let matches = matcher.find_matches(text);
822
823 assert_eq!(matches.len(), 0);
824 }
825
826 #[test]
827 fn test_terraphim_matcher_type() {
828 let matcher = TerraphimMatcher::new();
829 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
830
831 let patterns = create_test_patterns();
833 let mut matcher = TerraphimMatcher::new();
834 matcher.initialize(&patterns).unwrap();
835 assert_eq!(matcher.matcher_type(), "terraphim-automata");
836 }
837
838 #[test]
839 fn test_terraphim_create_matcher_factory() {
840 let matcher = create_matcher();
841 assert_eq!(matcher.matcher_type(), "terraphim-automata (uninitialized)");
843 }
844
845 #[test]
846 fn test_terraphim_uninitialized_matcher() {
847 let matcher = TerraphimMatcher::new();
848 let matches = matcher.find_matches("npx wrangler deploy");
849 assert_eq!(matches.len(), 0);
850 }
851}