Skip to content

Commit 1df5b19

Browse files
authored
Merge pull request #23 from adam-rhebo/remove-lifetime-marker
Remove explicit lifetime marker from RegexTestCase
2 parents 19a3091 + be4fdb3 commit 1df5b19

File tree

1 file changed

+77
-114
lines changed

1 file changed

+77
-114
lines changed

src/lib.rs

+77-114
Original file line numberDiff line numberDiff line change
@@ -64,52 +64,33 @@ impl Deref for HashableRegex {
6464
type TestFn<T> = fn(&mut T, &Step) -> ();
6565
type TestRegexFn<T> = fn(&mut T, &[String], &Step) -> ();
6666

67-
pub struct TestCase<T: Default> {
68-
pub test: TestFn<T>,
69-
}
70-
71-
impl<T: Default> TestCase<T> {
72-
pub fn new(test: TestFn<T>) -> TestCase<T> {
73-
TestCase { test }
74-
}
75-
}
67+
pub struct TestCase<T: Default>(pub TestFn<T>);
68+
pub struct RegexTestCase<T: Default>(pub TestRegexFn<T>);
7669

77-
pub struct RegexTestCase<'a, T: 'a + Default> {
78-
pub test: TestRegexFn<T>,
79-
_marker: std::marker::PhantomData<&'a T>,
80-
}
81-
82-
impl<'a, T: Default> RegexTestCase<'a, T> {
83-
pub fn new(test: TestRegexFn<T>) -> RegexTestCase<'a, T> {
84-
RegexTestCase {
85-
test,
86-
_marker: std::marker::PhantomData,
87-
}
88-
}
89-
}
70+
type TestBag<T> = HashMap<&'static str, TestCase<T>>;
71+
type RegexBag<T> = HashMap<HashableRegex, RegexTestCase<T>>;
9072

9173
#[derive(Default)]
92-
pub struct Steps<'s, T: 's + Default> {
93-
pub given: HashMap<&'static str, TestCase<T>>,
94-
pub when: HashMap<&'static str, TestCase<T>>,
95-
pub then: HashMap<&'static str, TestCase<T>>,
96-
pub regex: RegexSteps<'s, T>,
74+
pub struct Steps<T: Default> {
75+
pub given: TestBag<T>,
76+
pub when: TestBag<T>,
77+
pub then: TestBag<T>,
78+
pub regex: RegexSteps<T>,
9779
}
9880

9981
#[derive(Default)]
100-
pub struct RegexSteps<'s, T: 's + Default> {
101-
pub given: HashMap<HashableRegex, RegexTestCase<'s, T>>,
102-
pub when: HashMap<HashableRegex, RegexTestCase<'s, T>>,
103-
pub then: HashMap<HashableRegex, RegexTestCase<'s, T>>,
82+
pub struct RegexSteps<T: Default> {
83+
pub given: RegexBag<T>,
84+
pub when: RegexBag<T>,
85+
pub then: RegexBag<T>,
10486
}
10587

10688
pub enum TestCaseType<'a, T>
10789
where
108-
T: 'a,
109-
T: Default,
90+
T: 'a + Default,
11091
{
11192
Normal(&'a TestCase<T>),
112-
Regex(&'a RegexTestCase<'a, T>, Vec<String>),
93+
Regex(&'a RegexTestCase<T>, Vec<String>),
11394
}
11495

11596
pub enum TestResult {
@@ -120,74 +101,61 @@ pub enum TestResult {
120101
Fail(PanicDetails, Vec<u8>),
121102
}
122103

123-
impl<'s, T: Default> Steps<'s, T> {
124-
fn test_bag_for(&self, ty: StepType) -> &HashMap<&'static str, TestCase<T>> {
104+
impl<T: Default> Steps<T> {
105+
fn test_bag_for(&self, ty: StepType) -> &TestBag<T> {
125106
match ty {
126107
StepType::Given => &self.given,
127108
StepType::When => &self.when,
128109
StepType::Then => &self.then,
129110
}
130111
}
131112

132-
fn regex_bag_for<'a>(&'a self, ty: StepType) -> &HashMap<HashableRegex, RegexTestCase<'a, T>> {
113+
fn regex_bag_for(&self, ty: StepType) -> &RegexBag<T> {
133114
match ty {
134115
StepType::Given => &self.regex.given,
135116
StepType::When => &self.regex.when,
136117
StepType::Then => &self.regex.then,
137118
}
138119
}
139120

140-
fn test_type(&'s self, step: &Step) -> Option<TestCaseType<'s, T>> {
141-
let test_bag = self.test_bag_for(step.ty);
142-
143-
match test_bag.get(&*step.value) {
144-
Some(v) => Some(TestCaseType::Normal(v)),
145-
None => {
146-
let regex_bag = self.regex_bag_for(step.ty);
147-
148-
let result = regex_bag
149-
.iter()
150-
.find(|(regex, _)| regex.is_match(&step.value));
121+
fn test_type<'a>(&'a self, step: &Step) -> Option<TestCaseType<'a, T>> {
122+
if let Some(t) = self.test_bag_for(step.ty).get(&*step.value) {
123+
return Some(TestCaseType::Normal(t));
124+
}
151125

152-
match result {
153-
Some((regex, tc)) => {
154-
let matches = regex.0.captures(&step.value).unwrap();
155-
let matches: Vec<String> = matches
156-
.iter()
157-
.map(|x| {
158-
x.map(|s| s.as_str().to_string())
159-
.unwrap_or_else(String::new)
160-
})
161-
.collect();
162-
Some(TestCaseType::Regex(tc, matches))
163-
}
164-
None => None,
165-
}
166-
}
126+
if let Some((regex, t)) = self
127+
.regex_bag_for(step.ty)
128+
.iter()
129+
.find(|(regex, _)| regex.is_match(&step.value))
130+
{
131+
let matches = regex
132+
.0
133+
.captures(&step.value)
134+
.unwrap()
135+
.iter()
136+
.map(|match_| {
137+
match_
138+
.map(|match_| match_.as_str().to_owned())
139+
.unwrap_or_default()
140+
})
141+
.collect();
142+
143+
return Some(TestCaseType::Regex(t, matches));
167144
}
168-
}
169145

170-
fn run_test_inner<'a>(
171-
&'s self,
172-
world: &mut T,
173-
test_type: TestCaseType<'s, T>,
174-
step: &'a gherkin::Step,
175-
) {
176-
match test_type {
177-
TestCaseType::Normal(t) => (t.test)(world, &step),
178-
TestCaseType::Regex(t, ref c) => (t.test)(world, c, &step),
179-
};
146+
None
180147
}
181148

182-
fn run_test<'a>(
183-
&'s self,
149+
fn run_test(
150+
&self,
184151
world: &mut T,
185-
test_type: TestCaseType<'s, T>,
186-
step: &'a Step,
152+
test_type: TestCaseType<'_, T>,
153+
step: &Step,
187154
suppress_output: bool,
188155
) -> TestResult {
189-
let test_result = PanicTrap::run(suppress_output, move || {
190-
self.run_test_inner(world, test_type, &step)
156+
let test_result = PanicTrap::run(suppress_output, move || match test_type {
157+
TestCaseType::Normal(t) => (t.0)(world, &step),
158+
TestCaseType::Regex(t, ref c) => (t.0)(world, c, &step),
191159
});
192160

193161
match test_result.result {
@@ -203,13 +171,13 @@ impl<'s, T: Default> Steps<'s, T> {
203171
}
204172

205173
#[allow(clippy::too_many_arguments)]
206-
fn run_scenario<'a>(
207-
&'s self,
208-
feature: &'a gherkin::Feature,
209-
rule: Option<&'a gherkin::Rule>,
210-
scenario: &'a gherkin::Scenario,
211-
before_fns: &'a Option<&[HelperFn]>,
212-
after_fns: &'a Option<&[HelperFn]>,
174+
fn run_scenario(
175+
&self,
176+
feature: &gherkin::Feature,
177+
rule: Option<&gherkin::Rule>,
178+
scenario: &gherkin::Scenario,
179+
before_fns: &Option<&[HelperFn]>,
180+
after_fns: &Option<&[HelperFn]>,
213181
suppress_output: bool,
214182
output: &mut impl OutputVisitor,
215183
) -> bool {
@@ -221,8 +189,6 @@ impl<'s, T: Default> Steps<'s, T> {
221189
}
222190
}
223191

224-
let mut is_success = true;
225-
226192
let mut world = {
227193
let panic_trap = PanicTrap::run(suppress_output, T::default);
228194
match panic_trap.result {
@@ -241,20 +207,17 @@ impl<'s, T: Default> Steps<'s, T> {
241207
}
242208
};
243209

244-
let mut steps: Vec<&'a Step> = vec![];
245-
if let Some(ref bg) = &feature.background {
246-
for s in &bg.steps {
247-
steps.push(&s);
248-
}
249-
}
250-
251-
for s in &scenario.steps {
252-
steps.push(&s);
253-
}
254-
210+
let mut is_success = true;
255211
let mut is_skipping = false;
256212

257-
for step in steps.iter() {
213+
let steps = feature
214+
.background
215+
.iter()
216+
.map(|bg| bg.steps.iter())
217+
.flatten()
218+
.chain(scenario.steps.iter());
219+
220+
for step in steps {
258221
output.visit_step(rule, &scenario, &step);
259222

260223
let test_type = match self.test_type(&step) {
@@ -300,10 +263,10 @@ impl<'s, T: Default> Steps<'s, T> {
300263
}
301264

302265
#[allow(clippy::too_many_arguments)]
303-
fn run_scenarios<'a>(
304-
&'s self,
305-
feature: &'a gherkin::Feature,
306-
rule: Option<&'a gherkin::Rule>,
266+
fn run_scenarios(
267+
&self,
268+
feature: &gherkin::Feature,
269+
rule: Option<&gherkin::Rule>,
307270
scenarios: &[gherkin::Scenario],
308271
before_fns: Option<&[HelperFn]>,
309272
after_fns: Option<&[HelperFn]>,
@@ -347,7 +310,7 @@ impl<'s, T: Default> Steps<'s, T> {
347310
}
348311

349312
pub fn run(
350-
&'s self,
313+
&self,
351314
feature_files: Vec<PathBuf>,
352315
before_fns: Option<&[HelperFn]>,
353316
after_fns: Option<&[HelperFn]>,
@@ -639,7 +602,7 @@ macro_rules! steps {
639602
) => {
640603
$tests.regex.$ty.insert(
641604
$crate::HashableRegex($crate::regex::Regex::new($name).expect(&format!("{} is a valid regex", $name))),
642-
$crate::RegexTestCase::new($body));
605+
$crate::RegexTestCase($body));
643606
};
644607

645608
(
@@ -648,7 +611,7 @@ macro_rules! steps {
648611
) => {
649612
$tests.regex.$ty.insert(
650613
$crate::HashableRegex($crate::regex::Regex::new($name).expect(&format!("{} is a valid regex", $name))),
651-
$crate::RegexTestCase::new($body));
614+
$crate::RegexTestCase($body));
652615

653616
steps!(@gather_steps, $worldtype, $tests, $( $items )*);
654617
};
@@ -659,7 +622,7 @@ macro_rules! steps {
659622
) => {
660623
$tests.regex.$ty.insert(
661624
$crate::HashableRegex($crate::regex::Regex::new($name).expect(&format!("{} is a valid regex", $name))),
662-
$crate::RegexTestCase::new(|world: &mut $worldtype, matches, step| {
625+
$crate::RegexTestCase(|world: &mut $worldtype, matches, step| {
663626
let closure: Box<Fn(&mut $worldtype, $($arg_type,)* &$crate::gherkin::Step) -> ()> = Box::new($body);
664627
let mut matches = matches.into_iter().enumerate();
665628

@@ -680,7 +643,7 @@ macro_rules! steps {
680643
) => {
681644
$tests.regex.$ty.insert(
682645
$crate::HashableRegex($crate::regex::Regex::new($name).expect(&format!("{} is a valid regex", $name))),
683-
$crate::RegexTestCase::new(|world: &mut $worldtype, matches, step| {
646+
$crate::RegexTestCase(|world: &mut $worldtype, matches, step| {
684647
let closure: Box<Fn(&mut $worldtype, $($arg_type,)* &$crate::gherkin::Step) -> ()> = Box::new($body);
685648
let mut matches = matches.into_iter().enumerate().skip(1);
686649

@@ -701,14 +664,14 @@ macro_rules! steps {
701664
@gather_steps, $worldtype:path, $tests:tt,
702665
$ty:ident $name:tt $body:expr;
703666
) => {
704-
$tests.$ty.insert($name, $crate::TestCase::new($body));
667+
$tests.$ty.insert($name, $crate::TestCase($body));
705668
};
706669

707670
(
708671
@gather_steps, $worldtype:path, $tests:tt,
709672
$ty:ident $name:tt $body:expr; $( $items:tt )*
710673
) => {
711-
$tests.$ty.insert($name, $crate::TestCase::new($body));
674+
$tests.$ty.insert($name, $crate::TestCase($body));
712675

713676
steps!(@gather_steps, $worldtype, $tests, $( $items )*);
714677
};
@@ -717,11 +680,11 @@ macro_rules! steps {
717680
$worldtype:path => { $( $items:tt )* }
718681
) => {
719682
#[allow(unused_imports)]
720-
pub fn steps<'a>() -> $crate::Steps<'a, $worldtype> {
683+
pub fn steps() -> $crate::Steps<$worldtype> {
721684
use std::path::Path;
722685
use std::process;
723686

724-
let mut tests: $crate::Steps<'a, $worldtype> = $crate::Steps::default();
687+
let mut tests: $crate::Steps<$worldtype> = Default::default();
725688
steps!(@gather_steps, $worldtype, tests, $( $items )*);
726689
tests
727690
}

0 commit comments

Comments
 (0)