Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more tests and run code coverage analysis #53

Merged
merged 15 commits into from
Jun 20, 2023
Merged
1 change: 1 addition & 0 deletions .github/actions-rs/grcov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output-path: ./coverage.xml
11 changes: 11 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
github_checks:
annotations: false

coverage:
status:
project:
default:
informational: true
patch:
default:
informational: true
44 changes: 37 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,27 @@ concurrency:

jobs:
build_and_test:
name: cargo build
name: cargo test
runs-on: ubuntu-latest
env:
RUSTFLAGS: -D warnings
strategy:
fail-fast: false
matrix:
toolchain: ["stable", "beta"]
coverage: [false]
include:
- toolchain: "nightly"
coverage: true
steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Setup Rust toolchain
run: rustup install stable


- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
override: true

- name: Configure CI cache
uses: Swatinem/rust-cache@v2

Expand All @@ -34,12 +44,32 @@ jobs:
with:
command: build
args: --all-targets

- name: Run tests
uses: actions-rs/cargo@v1
if: ${{ !matrix.coverage }}
with:
command: test
args: --all-targets
args: --all-targets --no-fail-fast

- name: Run tests
uses: actions-rs/cargo@v1
if: ${{ matrix.coverage }}
with:
command: test
args: --all-targets --no-fail-fast
env:
CARGO_INCREMENTAL: '0'
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'

- name: Generate code coverage
uses: actions-rs/[email protected]
if: ${{ matrix.coverage }}

- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v3
if: ${{ matrix.coverage }}

rustfmt:
name: rustfmt
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ thiserror = "1.0"

[dev-dependencies]
doc-comment = "0.3"
rstest = "0.17"
rstest_reuse = "0.5"
anyhow = "1"
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ extern crate bincode;
#[macro_use]
extern crate doc_comment;

#[cfg(test)]
use rstest_reuse;

#[cfg(test)]
doctest!("../README.md");

Expand Down
145 changes: 79 additions & 66 deletions src/phone_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,76 +251,89 @@ impl<'a> Deref for Country<'a> {

#[cfg(test)]
mod test {
use crate::country;
use crate::country::{self, *};
use crate::metadata::DATABASE;
use crate::parser;
use crate::Type;
use crate::{parser, Mode, PhoneNumber};
use anyhow::Context;
use rstest::rstest;
use rstest_reuse::{self, *};

fn parsed(number: &str) -> PhoneNumber {
parser::parse(None, number)
.with_context(|| format!("parsing {number}"))
.unwrap()
}

#[template]
#[rstest]
#[case(parsed("+80012340000"), None, Type::TollFree)]
#[case(parsed("+61406823897"), Some(AU), Type::Mobile)]
#[case(parsed("+611900123456"), Some(AU), Type::PremiumRate)]
#[case(parsed("+32474091150"), Some(BE), Type::Mobile)]
#[case(parsed("+34666777888"), Some(ES), Type::Mobile)]
#[case(parsed("+34612345678"), Some(ES), Type::Mobile)]
#[case(parsed("+441212345678"), Some(GB), Type::FixedLine)]
#[case(parsed("+13459492311"), Some(KY), Type::FixedLine)]
#[case(parsed("+16137827274"), Some(CA), Type::FixedLineOrMobile)]
#[case(parsed("+1 520 878 2491"), Some(US), Type::FixedLineOrMobile)]
#[case(parsed("+1-520-878-2491"), Some(US), Type::FixedLineOrMobile)]
// Case for issues
// https://github.com/whisperfish/rust-phonenumber/issues/46 and
// https://github.com/whisperfish/rust-phonenumber/issues/47
// #[case(parsed("+1 520-878-2491"), US)]
rubdos marked this conversation as resolved.
Show resolved Hide resolved
fn phone_numbers(
#[case] number: PhoneNumber,
#[case] country: Option<country::Id>,
#[case] r#type: Type,
) {
}

#[apply(phone_numbers)]
fn country_id(
#[case] number: PhoneNumber,
#[case] country: Option<country::Id>,
#[case] _type: Type,
) -> anyhow::Result<()> {
assert_eq!(country, number.country().id());

Ok(())
}

#[test]
fn country_id() {
assert_eq!(
None,
parser::parse(None, "+80012340000").unwrap().country().id()
);

assert_eq!(
country::AU,
parser::parse(None, "+61406823897")
.unwrap()
.country()
.id()
.unwrap()
);

assert_eq!(
country::ES,
parser::parse(None, "+34666777888")
.unwrap()
.country()
.id()
.unwrap()
);

assert_eq!(
country::KY,
parser::parse(None, "+13459492311")
.unwrap()
.country()
.id()
.unwrap()
);

assert_eq!(
country::CA,
parser::parse(None, "+16137827274")
.unwrap()
.country()
.id()
.unwrap()
);
#[apply(phone_numbers)]
#[ignore]
// Format-parse roundtrip
fn round_trip_parsing(
#[case] number: PhoneNumber,
#[case] country: Option<country::Id>,
#[case] _type: Type,
#[values(Mode::International, Mode::E164, Mode::Rfc3966, Mode::National)] mode: Mode,
) -> anyhow::Result<()> {
let country_hint = if mode == Mode::National {
country
} else {
None
};

let formatted = number.format().mode(mode).to_string();
let parsed = parser::parse(country_hint, &formatted).with_context(|| {
format!("parsing {number} after formatting in {mode:?} mode as {formatted}")
})?;

// impl Eq for PhoneNumber does not consider differently parsed phone numbers to be equal.
// E.g., parsing 047409110 with BE country hint is the same phone number as +32474091150,
// but Eq considers them different.
assert_eq!(number, parsed);

Ok(())
}

#[test]
fn number_type() {
assert_eq!(
Type::FixedLine,
parser::parse(None, "+441212345678")
.unwrap()
.number_type(&DATABASE)
);

assert_eq!(
Type::Mobile,
parser::parse(None, "+34612345678")
.unwrap()
.number_type(&DATABASE)
);

assert_eq!(
Type::PremiumRate,
parser::parse(None, "+611900123456")
.unwrap()
.number_type(&DATABASE)
);
#[apply(phone_numbers)]
fn number_type(
#[case] number: PhoneNumber,
#[case] _country: Option<country::Id>,
#[case] r#type: Type,
) {
assert_eq!(r#type, number.number_type(&DATABASE));
}
}