Skip to content

Commit 05d1105

Browse files
hovinenbcopybara-github
authored andcommitted
Remove the dependency of the size matcher on HasSize.
This moves the function `count_elements` from the `unordered_elements_matcher` module to its own module so that it can be used by `SizeMatcher` as well. Now `size` can also be used with slices in addition to all container types over which one can iterate. This includes all standard Rust containers. This change removes the now unused `has_size` module and its contents. One slight API change resulting from this is that one now no longer uses a reference when using the size matcher against slices of arrays: OLD: ``` let value = &[1, 2, 3]; verify_that(&value[0..1], size(eq(1)))?; ``` NEW: ``` let value = &[1, 2, 3]; verify_that(value[0..1], size(eq(1)))?; ``` PiperOrigin-RevId: 515603924
1 parent 3e4015f commit 05d1105

File tree

6 files changed

+86
-114
lines changed

6 files changed

+86
-114
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/// Counts the number of elements in `value`.
16+
///
17+
/// This uses [`Iterator::size_hint`] when that function returns an
18+
/// unambiguous answer, i.e., the upper bound exists and the lower and upper
19+
/// bounds agree. Otherwise it iterates through `value` and counts the
20+
/// elements.
21+
pub(crate) fn count_elements<ContainerT: ?Sized>(value: &ContainerT) -> usize
22+
where
23+
for<'b> &'b ContainerT: IntoIterator,
24+
{
25+
let iterator = value.into_iter();
26+
if let (lower, Some(higher)) = iterator.size_hint() {
27+
if lower == higher {
28+
return lower;
29+
}
30+
}
31+
iterator.count()
32+
}

googletest/src/matchers/has_size.rs

Lines changed: 0 additions & 72 deletions
This file was deleted.

googletest/src/matchers/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub mod contains_matcher;
2525
#[cfg(not(google3))]
2626
pub mod contains_regex_matcher;
2727
#[cfg(not(google3))]
28+
pub mod count_elements;
29+
#[cfg(not(google3))]
2830
pub mod description;
2931
#[cfg(not(google3))]
3032
pub mod disjunction_matcher;
@@ -49,8 +51,6 @@ pub mod gt_matcher;
4951
#[cfg(not(google3))]
5052
pub mod has_entry_matcher;
5153
#[cfg(not(google3))]
52-
pub mod has_size;
53-
#[cfg(not(google3))]
5454
pub mod is_nan_matcher;
5555
#[cfg(not(google3))]
5656
pub mod le_matcher;

googletest/src/matchers/pointwise_matcher.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
/// verify_that!(value, pointwise!(le, [1, 1, 3]))?; // Fails
3030
/// ```
3131
///
32-
/// The actual value must be a container implementing [`IntoIterator`] and
33-
/// [`HasSize`][crate::matchers::has_size::HasSize]. This includes all common
34-
/// containers in the Rust standard library.
32+
/// The actual value must be a container implementing [`IntoIterator`]. This
33+
/// includes standard containers, slices (when dereferenced) and arrays.
3534
///
3635
/// This matcher does not support matching directly against an [`Iterator`]. To
3736
/// match against an iterator, use [`Iterator::collect`] to build a [`Vec`]

googletest/src/matchers/size_matcher.rs

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,50 @@
1414

1515
#[cfg(not(google3))]
1616
use crate as googletest;
17-
use googletest::matcher::{Matcher, MatcherResult};
1817
#[cfg(not(google3))]
19-
use googletest::matchers::has_size::HasSize;
18+
use crate::matchers::count_elements::count_elements;
2019
#[cfg(google3)]
21-
use has_size::HasSize;
20+
use count_elements::count_elements;
21+
use googletest::matcher::{Matcher, MatcherResult};
2222
use std::fmt::Debug;
2323

2424
/// Matches a container whose size matches `expected`.
2525
///
26-
/// `T` must be a container and implement the [`HasSize`] trait so that the size
27-
/// can be extracted.
26+
/// This matches against a container over which one can iterate. This includes
27+
/// the standard Rust containers, arrays, and (when dereferenced) slices.
2828
///
2929
/// ```
30-
/// let value = vec![1,2,3];
31-
/// verify_that!(value, size(eq(3)))?;
30+
/// let array = [1,2,3];
31+
/// verify_that!(array, size(eq(3)))?;
32+
/// let vec = vec![1,2,3];
33+
/// verify_that!(vec, size(eq(3)))?;
34+
/// let slice = value.as_slice();
35+
/// verify_that!(*slice, size(eq(3)))?;
3236
/// ```
33-
pub fn size<T: HasSize + Debug, E: Matcher<usize>>(expected: E) -> impl Matcher<T> {
37+
///
38+
/// The parameter `expected` can be any integer numeric matcher.
39+
///
40+
/// ```
41+
/// let vec = vec![1,2,3];
42+
/// verify_that!(vec, size(gt(1)))?;
43+
/// ```
44+
pub fn size<T: Debug + ?Sized, E: Matcher<usize>>(expected: E) -> impl Matcher<T>
45+
where
46+
for<'b> &'b T: IntoIterator,
47+
{
3448
SizeMatcher { expected }
3549
}
3650

3751
struct SizeMatcher<E> {
3852
expected: E,
3953
}
4054

41-
impl<T: Debug + HasSize, E: Matcher<usize>> Matcher<T> for SizeMatcher<E> {
55+
impl<T: Debug + ?Sized, E: Matcher<usize>> Matcher<T> for SizeMatcher<E>
56+
where
57+
for<'b> &'b T: IntoIterator,
58+
{
4259
fn matches(&self, actual: &T) -> MatcherResult {
43-
self.expected.matches(&actual.size())
60+
self.expected.matches(&count_elements(actual))
4461
}
4562

4663
fn describe(&self, matcher_result: MatcherResult) -> String {
@@ -75,9 +92,22 @@ mod tests {
7592
}
7693

7794
#[google_test]
78-
fn size_matcher_match_slice() -> Result<()> {
95+
fn size_matcher_match_array_reference() -> Result<()> {
96+
let value = &[1, 2, 3];
97+
verify_that!(*value, size(eq(3)))
98+
}
99+
100+
#[google_test]
101+
fn size_matcher_match_slice_of_array() -> Result<()> {
79102
let value = &[1, 2, 3];
80-
verify_that!(&value[0..1], size(eq(1)))
103+
verify_that!(value[0..1], size(eq(1)))
104+
}
105+
106+
#[google_test]
107+
fn size_matcher_match_slice_of_vec() -> Result<()> {
108+
let value = vec![1, 2, 3];
109+
let slice = value.as_slice();
110+
verify_that!(*slice, size(eq(3)))
81111
}
82112

83113
#[google_test]

googletest/src/matchers/unordered_elements_are_matcher.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
/// verify_that!(vec![3, 2, 1], unordered_elements_are![ge(3), ge(3), ge(3)])?; // Fails: no 1:1 correspondence
2727
/// ```
2828
///
29-
/// The actual value must be a container implementing [`IntoIterator`] and
30-
/// [`HasSize`][crate::matchers::has_size::HasSize]. This includes all common
31-
/// containers in the Rust standard library.
29+
/// The actual value must be a container implementing [`IntoIterator`]. This
30+
/// includes standard containers, slices (when dereferenced) and arrays.
3231
///
3332
/// This matcher does not support matching directly against an [`Iterator`]. To
3433
/// match against an iterator, use [`Iterator::collect`] to build a [`Vec`].
@@ -85,9 +84,8 @@ macro_rules! unordered_elements_are {
8584
/// verify_that!(vec![3, 2, 1], contains_each![ge(3), ge(3), ge(3)])?; // Fails: no matching
8685
/// ```
8786
///
88-
/// The actual value must be a container implementing [`IntoIterator`] and
89-
/// [`HasSize`][crate::matchers::has_size::HasSize]. This includes all common
90-
/// containers in the Rust standard library.
87+
/// The actual value must be a container implementing [`IntoIterator`]. This
88+
/// includes standard containers, slices (when dereferenced) and arrays.
9189
///
9290
/// This matcher does not support matching directly against an [`Iterator`]. To
9391
/// match against an iterator, use [`Iterator::collect`] to build a [`Vec`].
@@ -185,6 +183,10 @@ macro_rules! is_contained_in {
185183
pub mod internal {
186184
#[cfg(not(google3))]
187185
use crate as googletest;
186+
#[cfg(not(google3))]
187+
use crate::matchers::count_elements::count_elements;
188+
#[cfg(google3)]
189+
use count_elements::count_elements;
188190
#[cfg(google3)]
189191
use description::Description;
190192
use googletest::matcher::{MatchExplanation, Matcher, MatcherResult};
@@ -576,25 +578,6 @@ pub mod internal {
576578
}
577579
}
578580

579-
/// Counts the number of elements in `value`.
580-
///
581-
/// This uses [`Iterator::size_hint`] when that function returns an
582-
/// unambiguous answer, i.e., the upper bound exists and the lower and upper
583-
/// bounds agree. Otherwise it iterates through `value` and counts the
584-
/// elements.
585-
fn count_elements<T, ContainerT: ?Sized>(value: &ContainerT) -> usize
586-
where
587-
for<'b> &'b ContainerT: IntoIterator<Item = &'b T>,
588-
{
589-
let iterator = value.into_iter();
590-
if let (lower, Some(higher)) = iterator.size_hint() {
591-
if lower == higher {
592-
return lower;
593-
}
594-
}
595-
iterator.count()
596-
}
597-
598581
/// The list of elements that do not match any element in the corresponding
599582
/// set.
600583
/// These lists are represented as fixed sized bit set to avoid

0 commit comments

Comments
 (0)