1use std::fmt::{self, Debug};
10use std::iter;
11use std::slice;
12
13use git_workarea::{CommitId, GitContext, GitError, Identity, WorkAreaError};
14use log::{debug, error};
15use rayon::prelude::*;
16use thiserror::Error;
17
18use crate::check::{BranchCheck, Check, CheckResult, TopicCheck};
19use crate::commit::{Commit, CommitError, Topic};
20use crate::context::CheckGitContext;
21
22#[derive(Debug, Error)]
24#[non_exhaustive]
25pub enum RunError {
26 #[error("git error: {}", source)]
28 Git {
29 #[from]
31 source: GitError,
32 },
33 #[error("git workarea error: {}", source)]
35 WorkArea {
36 #[from]
38 source: WorkAreaError,
39 },
40 #[error("commit error: {}", source)]
42 Commit {
43 #[from]
45 source: CommitError,
46 },
47 #[error("run check error: failed to update the {} ref: {}", base_ref, output)]
49 UpdateRef {
50 base_ref: CommitId,
52 output: String,
54 },
55 #[error(
57 "run check error: failed to list refs from {} to {}",
58 base_ref,
59 new_ref
60 )]
61 RevList {
62 base_ref: CommitId,
64 new_ref: CommitId,
66 output: String,
68 },
69}
70
71impl RunError {
72 fn update_ref(base_ref: CommitId, output: &[u8]) -> Self {
73 RunError::UpdateRef {
74 base_ref,
75 output: String::from_utf8_lossy(output).into(),
76 }
77 }
78
79 fn rev_list(base_ref: CommitId, new_ref: CommitId, output: &[u8]) -> Self {
80 RunError::RevList {
81 base_ref,
82 new_ref,
83 output: String::from_utf8_lossy(output).into(),
84 }
85 }
86}
87
88#[derive(Default, Clone)]
90pub struct GitCheckConfiguration<'a> {
91 checks: Vec<&'a dyn Check>,
93 checks_branch: Vec<&'a dyn BranchCheck>,
95 checks_topic: Vec<&'a dyn TopicCheck>,
97}
98
99#[derive(Debug)]
101pub struct TopicCheckResult {
102 commit_results: Vec<(CommitId, CheckResult)>,
104 topic_result: CheckResult,
106}
107
108impl TopicCheckResult {
109 pub fn commit_results(&self) -> slice::Iter<(CommitId, CheckResult)> {
111 self.commit_results.iter()
112 }
113
114 pub fn topic_result(&self) -> &CheckResult {
116 &self.topic_result
117 }
118}
119
120impl From<TopicCheckResult> for CheckResult {
121 fn from(res: TopicCheckResult) -> Self {
122 res.commit_results
123 .into_iter()
124 .map(|(_, result)| result)
125 .chain(iter::once(res.topic_result))
126 .fold(Self::new(), Self::combine)
127 }
128}
129
130impl<'a> GitCheckConfiguration<'a> {
131 pub fn new() -> Self {
133 GitCheckConfiguration {
134 checks: Vec::new(),
135 checks_branch: Vec::new(),
136 checks_topic: Vec::new(),
137 }
138 }
139
140 pub fn add_check(&mut self, check: &'a dyn Check) -> &mut Self {
142 self.checks.push(check);
143
144 self
145 }
146
147 pub fn add_branch_check(&mut self, check: &'a dyn BranchCheck) -> &mut Self {
149 self.checks_branch.push(check);
150
151 self
152 }
153
154 pub fn add_topic_check(&mut self, check: &'a dyn TopicCheck) -> &mut Self {
156 self.checks_topic.push(check);
157
158 self
159 }
160
161 fn list<'b, B>(
163 &self,
164 ctx: &GitContext,
165 reason: &str,
166 target_branch: &CommitId,
167 bases: B,
168 topic: &CommitId,
169 ) -> Result<Vec<CommitId>, RunError>
170 where
171 B: IntoIterator<Item = &'b CommitId>,
172 {
173 let (new_ref, base_ref) = ctx.reserve_refs(format!("check/{}", reason), topic)?;
174 let update_ref = ctx
175 .git()
176 .arg("update-ref")
177 .args(["-m", reason])
178 .arg(&base_ref)
179 .arg(target_branch.as_str())
180 .output()
181 .map_err(|err| GitError::subcommand("update-ref", err))?;
182 if !update_ref.status.success() {
183 return Err(RunError::update_ref(
184 CommitId::new(base_ref),
185 &update_ref.stderr,
186 ));
187 }
188
189 let rev_list = ctx
190 .git()
191 .arg("rev-list")
192 .arg("--reverse")
193 .arg("--topo-order")
194 .arg(&new_ref)
195 .arg(format!("^{}", base_ref))
196 .args(bases.into_iter().map(|base| format!("^{}", base)))
197 .output()
198 .map_err(|err| GitError::subcommand("rev-list", err))?;
199 if !rev_list.status.success() {
200 return Err(RunError::rev_list(
201 CommitId::new(base_ref),
202 CommitId::new(new_ref),
203 &rev_list.stderr,
204 ));
205 }
206 let refs = String::from_utf8_lossy(&rev_list.stdout);
207
208 Ok(refs.lines().map(CommitId::new).collect())
209 }
210
211 fn run_check(ctx: &CheckGitContext, check: &dyn Check, commit: &Commit) -> CheckResult {
213 debug!(
214 target: "git-checks",
215 "running check {} on commit {}",
216 check.name(),
217 commit.sha1,
218 );
219
220 check.check(ctx, commit).unwrap_or_else(|err| {
221 error!(
222 target: "git-checks",
223 "check {} failed on commit {}: {:?}",
224 check.name(),
225 commit.sha1,
226 err,
227 );
228
229 let mut res = CheckResult::new();
230 res.add_alert(
231 format!(
232 "failed to run the {} check on commit {}",
233 check.name(),
234 commit.sha1,
235 ),
236 true,
237 );
238 res
239 })
240 }
241
242 fn run_branch_check(
244 ctx: &CheckGitContext,
245 check: &dyn BranchCheck,
246 commit: &CommitId,
247 ) -> CheckResult {
248 debug!(target: "git-checks", "running check {}", check.name());
249
250 check.check(ctx, commit).unwrap_or_else(|err| {
251 error!(
252 target: "git-checks",
253 "branch check {}: {:?}",
254 check.name(),
255 err,
256 );
257
258 let mut res = CheckResult::new();
259 res.add_alert(
260 format!("failed to run the {} branch check", check.name()),
261 true,
262 );
263 res
264 })
265 }
266
267 fn run_topic_check(
269 ctx: &CheckGitContext,
270 check: &dyn TopicCheck,
271 topic: &Topic,
272 ) -> CheckResult {
273 debug!(target: "git-checks", "running check {}", check.name());
274
275 check.check(ctx, topic).unwrap_or_else(|err| {
276 error!(
277 target: "git-checks",
278 "topic check {}: {:?}",
279 check.name(),
280 err,
281 );
282
283 let mut res = CheckResult::new();
284 res.add_alert(
285 format!("failed to run the {} topic check", check.name()),
286 true,
287 );
288 res
289 })
290 }
291
292 fn run_topic_impl(
294 &self,
295 ctx: &GitContext,
296 base: &CommitId,
297 refs: Vec<CommitId>,
298 owner: &Identity,
299 ) -> Result<TopicCheckResult, RunError> {
300 let topic_result = refs.last().map_or_else(
301 || Ok(CheckResult::new()) as Result<_, RunError>,
302 |head_commit| {
303 if self.checks_branch.is_empty() && self.checks_topic.is_empty() {
305 return Ok(CheckResult::new());
306 }
307
308 let workarea = ctx.prepare(head_commit)?;
309 let check_ctx = CheckGitContext::new(workarea, owner.clone());
310 let topic = Topic::new(ctx, base, head_commit)?;
311
312 Ok(self
313 .checks_branch
314 .par_iter()
315 .map(|&check| Self::run_branch_check(&check_ctx, check, head_commit))
316 .chain(
317 self.checks_topic
318 .par_iter()
319 .map(|&check| Self::run_topic_check(&check_ctx, check, &topic)),
320 )
321 .reduce(CheckResult::new, CheckResult::combine))
322 },
323 )?;
324 let commit_results = refs
325 .into_par_iter()
326 .map(|sha1| {
327 self.run_commit(ctx, &sha1, owner)
328 .map(|result| (sha1, result))
329 })
330 .collect::<Vec<Result<_, RunError>>>()
331 .into_iter()
332 .collect::<Result<Vec<_>, RunError>>()?;
333
334 Ok(TopicCheckResult {
335 commit_results,
336 topic_result,
337 })
338 }
339
340 pub fn run_commit(
342 &self,
343 ctx: &GitContext,
344 commit: &CommitId,
345 owner: &Identity,
346 ) -> Result<CheckResult, RunError> {
347 if self.checks.is_empty() {
349 return Ok(CheckResult::new());
350 }
351
352 let workarea = ctx.prepare(commit)?;
353 let check_ctx = CheckGitContext::new(workarea, owner.clone());
354
355 let commit = Commit::new(ctx, commit)?;
356
357 Ok(self
358 .checks
359 .par_iter()
360 .map(|&check| Self::run_check(&check_ctx, check, &commit))
361 .reduce(CheckResult::new, CheckResult::combine))
362 }
363
364 pub fn run_topic<R>(
366 &self,
367 ctx: &GitContext,
368 reason: R,
369 target_branch: &CommitId,
370 topic: &CommitId,
371 owner: &Identity,
372 ) -> Result<TopicCheckResult, RunError>
373 where
374 R: AsRef<str>,
375 {
376 let refs = self.list(ctx, reason.as_ref(), target_branch, &[], topic)?;
377 self.run_topic_impl(ctx, target_branch, refs, owner)
378 }
379
380 pub fn run_topic_multi_base<'b, R, B>(
382 &self,
383 ctx: &GitContext,
384 reason: R,
385 target_branch: &CommitId,
386 bases: B,
387 topic: &CommitId,
388 owner: &Identity,
389 ) -> Result<TopicCheckResult, RunError>
390 where
391 R: AsRef<str>,
392 B: IntoIterator<Item = &'b CommitId>,
393 {
394 let refs = self.list(ctx, reason.as_ref(), target_branch, bases, topic)?;
395 self.run_topic_impl(ctx, target_branch, refs, owner)
396 }
397}
398
399impl Debug for GitCheckConfiguration<'_> {
400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401 write!(
402 f,
403 "GitCheckConfiguration {{ {} commit checks, {} branch checks, {} topic checks }}",
404 self.checks.len(),
405 self.checks_branch.len(),
406 self.checks_topic.len(),
407 )
408 }
409}
410
411#[cfg(test)]
412mod test {
413 use std::iter;
414 use std::path::Path;
415
416 use git_workarea::{CommitId, GitContext, Identity};
417
418 use crate::run::{CheckResult, GitCheckConfiguration, TopicCheckResult};
419
420 mod checks {
421 use thiserror::Error;
422
423 use crate::impl_prelude::*;
424
425 #[derive(Debug)]
426 pub struct FailingCheck {}
427
428 #[derive(Debug, Error)]
429 #[error("the failing check did its thing")]
430 struct FailingCheckError;
431
432 impl Check for FailingCheck {
433 fn name(&self) -> &str {
434 "test-failing-check-commit"
435 }
436
437 fn check(
438 &self,
439 _: &CheckGitContext,
440 _: &Commit,
441 ) -> Result<CheckResult, Box<dyn Error>> {
442 Err(FailingCheckError.into())
443 }
444 }
445
446 impl BranchCheck for FailingCheck {
447 fn name(&self) -> &str {
448 "test-failing-check-branch"
449 }
450
451 fn check(
452 &self,
453 _: &CheckGitContext,
454 _: &CommitId,
455 ) -> Result<CheckResult, Box<dyn Error>> {
456 Err(FailingCheckError.into())
457 }
458 }
459
460 impl TopicCheck for FailingCheck {
461 fn name(&self) -> &str {
462 "test-failing-check-topic"
463 }
464
465 fn check(&self, _: &CheckGitContext, _: &Topic) -> Result<CheckResult, Box<dyn Error>> {
466 Err(FailingCheckError.into())
467 }
468 }
469 }
470
471 #[test]
472 fn test_configuration_debug() {
473 let config = GitCheckConfiguration::new();
474 assert_eq!(
475 format!("{:?}", config),
476 "GitCheckConfiguration { 0 commit checks, 0 branch checks, 0 topic checks }",
477 );
478 }
479
480 const TARGET_COMMIT: &str = "27ff3ef5532d76afa046f76f4dd8f588dc3e83c3";
481 const TOPIC_COMMIT: &str = "a61fd3759b61a4a1f740f3fe656bc42151cefbdd";
482 const TOPIC2_COMMIT: &str = "112e9b34401724bff57f68cf47c5065d4342b263";
483
484 fn git_context() -> GitContext {
485 let gitdir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../.git"));
486 if !gitdir.exists() {
487 panic!("The tests must be run from a git checkout.");
488 }
489
490 GitContext::new(gitdir)
491 }
492
493 fn run_commit(config: &GitCheckConfiguration) -> CheckResult {
494 let ctx = git_context();
495 config
496 .run_commit(
497 &ctx,
498 &CommitId::new(TOPIC_COMMIT),
499 &Identity::new(
500 "Rust Git Checks Core Tests",
501 "rust-git-checks@example.invalid",
502 ),
503 )
504 .unwrap()
505 }
506
507 fn run_topic(
508 test_name: &str,
509 config: &GitCheckConfiguration,
510 commit: &str,
511 ) -> TopicCheckResult {
512 let ctx = git_context();
513 config
514 .run_topic(
515 &ctx,
516 test_name,
517 &CommitId::new(TARGET_COMMIT),
518 &CommitId::new(commit),
519 &Identity::new(
520 "Rust Git Checks Core Tests",
521 "rust-git-checks@example.invalid",
522 ),
523 )
524 .unwrap()
525 }
526
527 fn run_topic_bases(
528 test_name: &str,
529 config: &GitCheckConfiguration,
530 commit: &str,
531 bases: &[&str],
532 ) -> TopicCheckResult {
533 let ctx = git_context();
534 let bases: Vec<_> = bases.iter().copied().map(CommitId::new).collect();
535 config
536 .run_topic_multi_base(
537 &ctx,
538 test_name,
539 &CommitId::new(TARGET_COMMIT),
540 bases.iter(),
541 &CommitId::new(commit),
542 &Identity::new(
543 "Rust Git Checks Core Tests",
544 "rust-git-checks@example.invalid",
545 ),
546 )
547 .unwrap()
548 }
549
550 fn no_strings<'a>() -> iter::Empty<&'a String> {
551 iter::empty()
552 }
553
554 fn check_result(result: &CheckResult, errors: &[&str]) {
555 itertools::assert_equal(result.warnings(), no_strings());
556 itertools::assert_equal(result.alerts(), errors);
557 itertools::assert_equal(result.errors(), no_strings());
558 assert!(!result.temporary());
559 assert!(!result.allowed());
560 assert!(!result.pass());
561 }
562
563 fn check_result_ok(result: &CheckResult) {
564 itertools::assert_equal(result.warnings(), no_strings());
565 itertools::assert_equal(result.alerts(), no_strings());
566 itertools::assert_equal(result.errors(), no_strings());
567 assert!(!result.temporary());
568 assert!(!result.allowed());
569 assert!(result.pass());
570 }
571
572 #[test]
573 fn test_commit_check_errors_commit() {
574 let check = self::checks::FailingCheck {};
575 let mut config = GitCheckConfiguration::new();
576 config.add_check(&check);
577
578 let result = run_commit(&config);
579
580 check_result(
581 &result,
582 &[
583 "failed to run the test-failing-check-commit check on commit \
584 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
585 ],
586 );
587 }
588
589 #[test]
590 fn test_branch_check_errors_commit() {
591 let check = self::checks::FailingCheck {};
592 let mut config = GitCheckConfiguration::new();
593 config.add_branch_check(&check);
594
595 let result = run_commit(&config);
596
597 check_result_ok(&result);
598 }
599
600 #[test]
601 fn test_topic_check_errors_commit() {
602 let check = self::checks::FailingCheck {};
603 let mut config = GitCheckConfiguration::new();
604 config.add_topic_check(&check);
605
606 let result = run_commit(&config);
607
608 check_result_ok(&result);
609 }
610
611 #[test]
612 fn test_commit_check_errors_topic() {
613 let check = self::checks::FailingCheck {};
614 let mut config = GitCheckConfiguration::new();
615 config.add_check(&check);
616
617 let result = run_topic("test_commit_check_errors_topic", &config, TOPIC_COMMIT);
618
619 let mut commit_results = result.commit_results();
620 let (commit, commit_result) = commit_results.next().unwrap();
621 assert_eq!(commit.as_str(), "a61fd3759b61a4a1f740f3fe656bc42151cefbdd");
622 check_result(
623 commit_result,
624 &[
625 "failed to run the test-failing-check-commit check on commit \
626 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
627 ],
628 );
629 if let Some(res) = commit_results.next() {
630 panic!(
631 "multiple commits returned from a single-commit topic: {:?}",
632 res,
633 );
634 }
635 check_result_ok(result.topic_result());
636 check_result(
637 &result.into(),
638 &[
639 "failed to run the test-failing-check-commit check on commit \
640 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
641 ],
642 );
643 }
644
645 #[test]
646 fn test_commit_check_errors_topic_bases() {
647 let check = self::checks::FailingCheck {};
648 let mut config = GitCheckConfiguration::new();
649 config.add_check(&check);
650
651 let result = run_topic_bases(
652 "test_commit_check_errors_topic_bases",
653 &config,
654 TOPIC2_COMMIT,
655 &[TOPIC_COMMIT],
656 );
657
658 let mut commit_results = result.commit_results();
659 let (commit, commit_result) = commit_results.next().unwrap();
660 assert_eq!(commit.as_str(), "112e9b34401724bff57f68cf47c5065d4342b263");
661 check_result(
662 commit_result,
663 &[
664 "failed to run the test-failing-check-commit check on commit \
665 112e9b34401724bff57f68cf47c5065d4342b263",
666 ],
667 );
668 if let Some(res) = commit_results.next() {
669 panic!(
670 "multiple commits returned from a single-commit topic: {:?}",
671 res,
672 );
673 }
674 check_result_ok(result.topic_result());
675 check_result(
676 &result.into(),
677 &[
678 "failed to run the test-failing-check-commit check on commit \
679 112e9b34401724bff57f68cf47c5065d4342b263",
680 ],
681 );
682 }
683
684 #[test]
685 fn test_branch_check_errors_topic() {
686 let check = self::checks::FailingCheck {};
687 let mut config = GitCheckConfiguration::new();
688 config.add_branch_check(&check);
689
690 let result = run_topic("test_branch_check_errors_topic", &config, TOPIC_COMMIT);
691
692 let mut commit_results = result.commit_results();
693 let (commit, commit_result) = commit_results.next().unwrap();
694 assert_eq!(commit.as_str(), "a61fd3759b61a4a1f740f3fe656bc42151cefbdd");
695 check_result_ok(commit_result);
696 if let Some(res) = commit_results.next() {
697 panic!(
698 "multiple commits returned from a single-commit topic: {:?}",
699 res,
700 );
701 }
702 check_result(
703 result.topic_result(),
704 &["failed to run the test-failing-check-branch branch check"],
705 );
706 check_result(
707 &result.into(),
708 &["failed to run the test-failing-check-branch branch check"],
709 );
710 }
711
712 #[test]
713 fn test_branch_check_errors_topic_bases() {
714 let check = self::checks::FailingCheck {};
715 let mut config = GitCheckConfiguration::new();
716 config.add_branch_check(&check);
717
718 let result = run_topic_bases(
719 "test_branch_check_errors_topic_bases",
720 &config,
721 TOPIC2_COMMIT,
722 &[TOPIC_COMMIT],
723 );
724
725 let mut commit_results = result.commit_results();
726 let (commit, commit_result) = commit_results.next().unwrap();
727 assert_eq!(commit.as_str(), "112e9b34401724bff57f68cf47c5065d4342b263");
728 check_result_ok(commit_result);
729 if let Some(res) = commit_results.next() {
730 panic!(
731 "multiple commits returned from a single-commit topic: {:?}",
732 res,
733 );
734 }
735 check_result(
736 result.topic_result(),
737 &["failed to run the test-failing-check-branch branch check"],
738 );
739 check_result(
740 &result.into(),
741 &["failed to run the test-failing-check-branch branch check"],
742 );
743 }
744
745 #[test]
746 fn test_topic_check_errors_topic() {
747 let check = self::checks::FailingCheck {};
748 let mut config = GitCheckConfiguration::new();
749 config.add_topic_check(&check);
750
751 let result = run_topic("test_topic_check_errors_topic", &config, TOPIC_COMMIT);
752
753 let mut commit_results = result.commit_results();
754 let (commit, commit_result) = commit_results.next().unwrap();
755 assert_eq!(commit.as_str(), "a61fd3759b61a4a1f740f3fe656bc42151cefbdd");
756 check_result_ok(commit_result);
757 if let Some(res) = commit_results.next() {
758 panic!(
759 "multiple commits returned from a single-commit topic: {:?}",
760 res,
761 );
762 }
763 check_result(
764 result.topic_result(),
765 &["failed to run the test-failing-check-topic topic check"],
766 );
767 check_result(
768 &result.into(),
769 &["failed to run the test-failing-check-topic topic check"],
770 );
771 }
772
773 #[test]
774 fn test_topic_check_errors_topic_bases() {
775 let check = self::checks::FailingCheck {};
776 let mut config = GitCheckConfiguration::new();
777 config.add_topic_check(&check);
778
779 let result = run_topic_bases(
780 "test_topic_check_errors_topic_bases",
781 &config,
782 TOPIC2_COMMIT,
783 &[TOPIC_COMMIT],
784 );
785
786 let mut commit_results = result.commit_results();
787 let (commit, commit_result) = commit_results.next().unwrap();
788 assert_eq!(commit.as_str(), "112e9b34401724bff57f68cf47c5065d4342b263");
789 check_result_ok(commit_result);
790 if let Some(res) = commit_results.next() {
791 panic!(
792 "multiple commits returned from a single-commit topic: {:?}",
793 res,
794 );
795 }
796 check_result(
797 result.topic_result(),
798 &["failed to run the test-failing-check-topic topic check"],
799 );
800 check_result(
801 &result.into(),
802 &["failed to run the test-failing-check-topic topic check"],
803 );
804 }
805
806 #[test]
807 fn test_multiple_check_commit() {
808 let check = self::checks::FailingCheck {};
809 let mut config = GitCheckConfiguration::new();
810 config.add_check(&check);
811 config.add_check(&check);
812 config.add_branch_check(&check);
813 config.add_branch_check(&check);
814 config.add_topic_check(&check);
815 config.add_topic_check(&check);
816
817 let result = run_commit(&config);
818
819 check_result(
820 &result,
821 &[
822 "failed to run the test-failing-check-commit check on commit \
823 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
824 "failed to run the test-failing-check-commit check on commit \
825 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
826 ],
827 );
828 }
829
830 #[test]
831 fn test_multiple_check_topic() {
832 let check = self::checks::FailingCheck {};
833 let mut config = GitCheckConfiguration::new();
834 config.add_check(&check);
835 config.add_check(&check);
836 config.add_branch_check(&check);
837 config.add_branch_check(&check);
838 config.add_topic_check(&check);
839 config.add_topic_check(&check);
840
841 let result = run_topic("test_multiple_check_topic", &config, TOPIC_COMMIT);
842
843 let mut commit_results = result.commit_results();
844 let (commit, commit_result) = commit_results.next().unwrap();
845 assert_eq!(commit.as_str(), "a61fd3759b61a4a1f740f3fe656bc42151cefbdd");
846 check_result(
847 commit_result,
848 &[
849 "failed to run the test-failing-check-commit check on commit \
850 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
851 "failed to run the test-failing-check-commit check on commit \
852 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
853 ],
854 );
855 if let Some(res) = commit_results.next() {
856 panic!(
857 "multiple commits returned from a single-commit topic: {:?}",
858 res,
859 );
860 }
861 check_result(
862 result.topic_result(),
863 &[
864 "failed to run the test-failing-check-branch branch check",
865 "failed to run the test-failing-check-branch branch check",
866 "failed to run the test-failing-check-topic topic check",
867 "failed to run the test-failing-check-topic topic check",
868 ],
869 );
870 check_result(
871 &result.into(),
872 &[
873 "failed to run the test-failing-check-commit check on commit \
874 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
875 "failed to run the test-failing-check-commit check on commit \
876 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
877 "failed to run the test-failing-check-branch branch check",
878 "failed to run the test-failing-check-branch branch check",
879 "failed to run the test-failing-check-topic topic check",
880 "failed to run the test-failing-check-topic topic check",
881 ],
882 );
883 }
884
885 #[test]
886 fn test_check_multiple_topic() {
887 let check = self::checks::FailingCheck {};
888 let mut config = GitCheckConfiguration::new();
889 config.add_check(&check);
890 config.add_branch_check(&check);
891 config.add_topic_check(&check);
892
893 let result = run_topic("test_check_multiple_topic", &config, TOPIC2_COMMIT);
894
895 let mut commit_results = result.commit_results();
896 let (commit, commit_result) = commit_results.next().unwrap();
897 assert_eq!(commit.as_str(), "a61fd3759b61a4a1f740f3fe656bc42151cefbdd");
898 check_result(
899 commit_result,
900 &[
901 "failed to run the test-failing-check-commit check on commit \
902 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
903 ],
904 );
905 let (commit, commit_result) = commit_results.next().unwrap();
906 assert_eq!(commit.as_str(), "112e9b34401724bff57f68cf47c5065d4342b263");
907 check_result(
908 commit_result,
909 &[
910 "failed to run the test-failing-check-commit check on commit \
911 112e9b34401724bff57f68cf47c5065d4342b263",
912 ],
913 );
914 if let Some(res) = commit_results.next() {
915 panic!(
916 "multiple commits returned from a single-commit topic: {:?}",
917 res,
918 );
919 }
920 check_result(
921 result.topic_result(),
922 &[
923 "failed to run the test-failing-check-branch branch check",
924 "failed to run the test-failing-check-topic topic check",
925 ],
926 );
927 check_result(
928 &result.into(),
929 &[
930 "failed to run the test-failing-check-commit check on commit \
931 a61fd3759b61a4a1f740f3fe656bc42151cefbdd",
932 "failed to run the test-failing-check-commit check on commit \
933 112e9b34401724bff57f68cf47c5065d4342b263",
934 "failed to run the test-failing-check-branch branch check",
935 "failed to run the test-failing-check-topic topic check",
936 ],
937 );
938 }
939}