0.2: Error and Testing improvements (#120)

This commit is contained in:
Joseph Richey
2019-10-28 01:06:05 -07:00
committed by Artyom Pavlov
parent cf2d81bfff
commit 8096bac100
12 changed files with 79 additions and 99 deletions
+16 -26
View File
@@ -21,7 +21,6 @@ matrix:
- rustup target add aarch64-apple-ios
script:
- cargo test
- cargo test --examples
- cargo build --target aarch64-apple-ios
- name: "Linux, beta"
@@ -40,11 +39,11 @@ matrix:
# Get latest geckodriver
- export VERSION=$(curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | jq -r ".tag_name")
- wget -O geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/$VERSION/geckodriver-$VERSION-linux64.tar.gz
- tar -xzf geckodriver.tar.gz
- tar -xzf geckodriver.tar.gz -C $HOME
# Get latest chromedirver
- export VERSION=$(wget -q -O - https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
- wget -O chromedriver.zip https://chromedriver.storage.googleapis.com/$VERSION/chromedriver_linux64.zip
- unzip chromedriver.zip
- unzip chromedriver.zip -d $HOME
# Get cargo-web
- export VERSION=0.6.26 # Pin version for stability
- wget -O cargo-web.gz https://github.com/koute/cargo-web/releases/download/$VERSION/cargo-web-x86_64-unknown-linux-gnu.gz
@@ -76,44 +75,34 @@ matrix:
- cargo web test --target=wasm32-unknown-unknown --features=stdweb
# wasm-bindgen tests (Node, Firefox, Chrome)
- cargo test --target wasm32-unknown-unknown --features=wasm-bindgen
- GECKODRIVER=$PWD/geckodriver cargo test --target wasm32-unknown-unknown --features=test-in-browser
- CHROMEDRIVER=$PWD/chromedriver cargo test --target wasm32-unknown-unknown --features=test-in-browser
- GECKODRIVER=$HOME/geckodriver cargo test --target wasm32-unknown-unknown --features=test-in-browser
- CHROMEDRIVER=$HOME/chromedriver cargo test --target wasm32-unknown-unknown --features=test-in-browser
- name: "Linux, nightly, docs"
- &nightly_and_docs
name: "Linux, nightly, docs"
rust: nightly
os: linux
install:
- cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks
- cargo deadlinks -V
script:
# Check that our tests pass in the default configuration
- cargo test
- cargo test --benches
- cargo test --examples
# Check that setting various features does not break the build
- cargo build --features=std
- cargo build --features=log
# remove cached documentation, otherwise files from previous PRs can get included
- rm -rf target/doc
- cargo doc --no-deps --all --features=std,log
- cargo doc --no-deps --features=std
- cargo deadlinks --dir target/doc
# also test minimum dependency versions are usable
- cargo generate-lockfile -Z minimal-versions
- cargo test
- cargo test --features=std,log
- name: "OSX, nightly, docs"
rust: nightly
- <<: *nightly_and_docs
name: "OSX, nightly, docs"
os: osx
install:
- cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks
- cargo deadlinks -V
script:
- cargo test
- cargo test --benches
- cargo test --examples
# remove cached documentation, otherwise files from previous PRs can get included
- rm -rf target/doc
- cargo doc --no-deps --all --features=std,log
- cargo deadlinks --dir target/doc
# also test minimum dependency versions are usable
- cargo generate-lockfile -Z minimal-versions
- cargo test
- name: "cross-platform build only"
rust: nightly
@@ -139,6 +128,7 @@ matrix:
- cargo xbuild --target=x86_64-unknown-uefi
- cargo xbuild --target=x86_64-unknown-hermit
- cargo xbuild --target=x86_64-unknown-l4re-uclibc
- cargo xbuild --target=x86_64-uwp-windows-gnu
- cargo xbuild --target=x86_64-wrs-vxworks
# also test minimum dependency versions are usable
- cargo generate-lockfile -Z minimal-versions
@@ -153,6 +143,7 @@ matrix:
- cargo xbuild --target=x86_64-unknown-hermit
- cargo xbuild --target=x86_64-unknown-l4re-uclibc
- cargo xbuild --target=x86_64-uwp-windows-gnu
- cargo xbuild --target=x86_64-wrs-vxworks
# Trust cross-built/emulated targets. We must repeat all non-default values.
- name: "Linux (MIPS, big-endian)"
@@ -199,7 +190,6 @@ before_script:
script:
- cargo test
- cargo test --examples
after_script: set +e
+4 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "getrandom"
version = "0.1.12"
version = "0.2.0"
edition = "2018"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
@@ -41,3 +41,6 @@ std = []
rustc-dep-of-std = ["compiler_builtins", "core"]
# Unstable feature for testing
test-in-browser = ["wasm-bindgen"]
[package.metadata.docs.rs]
features = ["std"]
+43 -40
View File
@@ -19,13 +19,36 @@ use core::num::NonZeroU32;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Error(NonZeroU32);
// TODO: Convert to a function when min_version >= 1.33
macro_rules! internal_error {
($n:expr) => {
Error(unsafe { NonZeroU32::new_unchecked(Error::INTERNAL_START + $n as u16 as u32) })
};
}
impl Error {
#[deprecated(since = "0.1.7")]
/// Unknown error.
pub const UNKNOWN: Error = UNSUPPORTED;
#[deprecated(since = "0.1.7")]
/// System entropy source is unavailable.
pub const UNAVAILABLE: Error = UNSUPPORTED;
/// This target/platform is not supported by `getrandom`.
pub const UNSUPPORTED: Error = internal_error!(0);
/// The platform-specific `errno` returned a non-positive value.
pub const ERRNO_NOT_POSITIVE: Error = internal_error!(1);
/// Call to iOS [`SecRandomCopyBytes`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes) failed.
pub const IOS_SEC_RANDOM: Error = internal_error!(3);
/// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed.
pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error!(4);
/// RDRAND instruction failed due to a hardware issue.
pub const FAILED_RDRAND: Error = internal_error!(5);
/// RDRAND instruction unsupported on this target.
pub const NO_RDRAND: Error = internal_error!(6);
/// Using `wasm-bindgen`, browser does not support `self.crypto`.
pub const BINDGEN_CRYPTO_UNDEF: Error = internal_error!(7);
/// Using `wasm-bindgen`, browser does not support `crypto.getRandomValues`.
pub const BINDGEN_GRV_UNDEF: Error = internal_error!(8);
/// Using `stdweb`, no cryptographic RNG is available.
pub const STDWEB_NO_RNG: Error = internal_error!(9);
/// Using `stdweb`, invoking a cryptographic RNG failed.
pub const STDWEB_RNG_FAILED: Error = internal_error!(10);
/// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
pub const VXWORKS_RAND_SECURE: Error = internal_error!(11);
/// Codes below this point represent OS Errors (i.e. positive i32 values).
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are
@@ -38,9 +61,11 @@ impl Error {
/// Extract the raw OS error code (if this error came from the OS)
///
/// This method is identical to `std::io::Error::raw_os_error()`, except
/// This method is identical to [`std::io::Error::raw_os_error()`][1], except
/// that it works in `no_std` contexts. If this method returns `None`, the
/// error value can still be formatted via the `Display` implementation.
///
/// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error
#[inline]
pub fn raw_os_error(self) -> Option<i32> {
if self.0.get() < Self::INTERNAL_START {
@@ -126,41 +151,19 @@ impl From<NonZeroU32> for Error {
}
}
// TODO: Convert to a function when min_version >= 1.33
macro_rules! internal_error {
($n:expr) => {
Error(unsafe { NonZeroU32::new_unchecked(Error::INTERNAL_START + $n as u16 as u32) })
};
}
/// Internal Error constants
pub(crate) const UNSUPPORTED: Error = internal_error!(0);
pub(crate) const ERRNO_NOT_POSITIVE: Error = internal_error!(1);
pub(crate) const UNKNOWN_IO_ERROR: Error = internal_error!(2);
pub(crate) const SEC_RANDOM_FAILED: Error = internal_error!(3);
pub(crate) const RTL_GEN_RANDOM_FAILED: Error = internal_error!(4);
pub(crate) const FAILED_RDRAND: Error = internal_error!(5);
pub(crate) const NO_RDRAND: Error = internal_error!(6);
pub(crate) const BINDGEN_CRYPTO_UNDEF: Error = internal_error!(7);
pub(crate) const BINDGEN_GRV_UNDEF: Error = internal_error!(8);
pub(crate) const STDWEB_NO_RNG: Error = internal_error!(9);
pub(crate) const STDWEB_RNG_FAILED: Error = internal_error!(10);
pub(crate) const RAND_SECURE_FATAL: Error = internal_error!(11);
fn internal_desc(error: Error) -> Option<&'static str> {
match error {
UNSUPPORTED => Some("getrandom: this target is not supported"),
ERRNO_NOT_POSITIVE => Some("errno: did not return a positive value"),
UNKNOWN_IO_ERROR => Some("Unknown std::io::Error"),
SEC_RANDOM_FAILED => Some("SecRandomCopyBytes: call failed"),
RTL_GEN_RANDOM_FAILED => Some("RtlGenRandom: call failed"),
FAILED_RDRAND => Some("RDRAND: failed multiple times: CPU issue likely"),
NO_RDRAND => Some("RDRAND: instruction not supported"),
BINDGEN_CRYPTO_UNDEF => Some("wasm-bindgen: self.crypto is undefined"),
BINDGEN_GRV_UNDEF => Some("wasm-bindgen: crypto.getRandomValues is undefined"),
STDWEB_NO_RNG => Some("stdweb: no randomness source available"),
STDWEB_RNG_FAILED => Some("stdweb: failed to get randomness"),
RAND_SECURE_FATAL => Some("randSecure: random number generator module is not initialized"),
Error::UNSUPPORTED => Some("getrandom: this target is not supported"),
Error::ERRNO_NOT_POSITIVE => Some("errno: did not return a positive value"),
Error::IOS_SEC_RANDOM => Some("SecRandomCopyBytes: iOS Secuirty framework failure"),
Error::WINDOWS_RTL_GEN_RANDOM => Some("RtlGenRandom: Windows system function failure"),
Error::FAILED_RDRAND => Some("RDRAND: failed multiple times: CPU issue likely"),
Error::NO_RDRAND => Some("RDRAND: instruction not supported"),
Error::BINDGEN_CRYPTO_UNDEF => Some("wasm-bindgen: self.crypto is undefined"),
Error::BINDGEN_GRV_UNDEF => Some("wasm-bindgen: crypto.getRandomValues is undefined"),
Error::STDWEB_NO_RNG => Some("stdweb: no randomness source available"),
Error::STDWEB_RNG_FAILED => Some("stdweb: failed to get randomness"),
Error::VXWORKS_RAND_SECURE => Some("randSecure: VxWorks RNG module is not initialized"),
_ => None,
}
}
+1 -13
View File
@@ -7,22 +7,10 @@
// except according to those terms.
extern crate std;
use crate::{error::UNKNOWN_IO_ERROR, Error};
use crate::Error;
use core::convert::From;
use core::num::NonZeroU32;
use std::io;
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
if let Some(errno) = err.raw_os_error() {
if let Some(code) = NonZeroU32::new(errno as u32) {
return Error::from(code);
}
}
UNKNOWN_IO_ERROR
}
}
impl From<Error> for io::Error {
fn from(err: Error) -> Self {
match err.raw_os_error() {
+2 -2
View File
@@ -7,7 +7,7 @@
// except according to those terms.
//! Implementation for iOS
use crate::{error::SEC_RANDOM_FAILED, Error};
use crate::Error;
// TODO: Make extern once extern_types feature is stabilized. See:
// https://github.com/rust-lang/rust/issues/43467
@@ -24,7 +24,7 @@ extern "C" {
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, dest.len(), dest.as_mut_ptr()) };
if ret == -1 {
Err(SEC_RANDOM_FAILED)
Err(Error::IOS_SEC_RANDOM)
} else {
Ok(())
}
+1 -1
View File
@@ -243,7 +243,7 @@ cfg_if! {
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
if dest.is_empty() {
return Ok(());
}
+2 -3
View File
@@ -7,7 +7,6 @@
// except according to those terms.
//! Implementation for SGX using RDRAND instruction
use crate::error::{FAILED_RDRAND, NO_RDRAND};
#[cfg(not(target_feature = "rdrand"))]
use crate::util::LazyBool;
use crate::Error;
@@ -37,7 +36,7 @@ unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
// Keep looping in case this was a false positive.
}
}
Err(FAILED_RDRAND)
Err(Error::FAILED_RDRAND)
}
// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653.
@@ -64,7 +63,7 @@ fn is_rdrand_supported() -> bool {
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
if !is_rdrand_supported() {
return Err(NO_RDRAND);
return Err(Error::NO_RDRAND);
}
// SAFETY: After this point, rdrand is supported, so calling the rdrand
+1 -2
View File
@@ -6,7 +6,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(dead_code)]
use crate::error::ERRNO_NOT_POSITIVE;
use crate::util::LazyUsize;
use crate::Error;
use core::num::NonZeroU32;
@@ -34,7 +33,7 @@ pub fn last_os_error() -> Error {
if errno > 0 {
Error::from(NonZeroU32::new(errno as u32).unwrap())
} else {
ERRNO_NOT_POSITIVE
Error::ERRNO_NOT_POSITIVE
}
}
+2 -2
View File
@@ -7,8 +7,8 @@
// except according to those terms.
//! Implementation for VxWorks
use crate::error::{Error, RAND_SECURE_FATAL};
use crate::util_libc::last_os_error;
use crate::Error;
use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
@@ -16,7 +16,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
while !RNG_INIT.load(Relaxed) {
let ret = unsafe { libc::randSecure() };
if ret < 0 {
return Err(RAND_SECURE_FATAL);
return Err(Error::VXWORKS_RAND_SECURE);
} else if ret > 0 {
RNG_INIT.store(true, Relaxed);
break;
+2 -3
View File
@@ -15,7 +15,6 @@ use std::thread_local;
use wasm_bindgen::prelude::*;
use crate::error::{BINDGEN_CRYPTO_UNDEF, BINDGEN_GRV_UNDEF};
use crate::Error;
#[derive(Clone, Debug)]
@@ -66,13 +65,13 @@ fn getrandom_init() -> Result<RngSource, Error> {
let crypto = self_.crypto();
if crypto.is_undefined() {
return Err(BINDGEN_CRYPTO_UNDEF);
return Err(Error::BINDGEN_CRYPTO_UNDEF);
}
// Test if `crypto.getRandomValues` is undefined as well
let crypto: BrowserCrypto = crypto.into();
if crypto.get_random_values_fn().is_undefined() {
return Err(BINDGEN_GRV_UNDEF);
return Err(Error::BINDGEN_GRV_UNDEF);
}
return Ok(RngSource::Browser(crypto));
+3 -4
View File
@@ -10,14 +10,13 @@
extern crate std;
use core::mem;
use std::sync::Once;
use stdweb::js;
use stdweb::unstable::TryInto;
use stdweb::web::error::Error as WebError;
use crate::error::{STDWEB_NO_RNG, STDWEB_RNG_FAILED};
use crate::Error;
use std::sync::Once;
#[derive(Clone, Copy, Debug)]
enum RngSource {
@@ -71,7 +70,7 @@ fn getrandom_init() -> Result<RngSource, Error> {
} else {
let _err: WebError = js! { return @{ result }.error }.try_into().unwrap();
error!("getrandom unavailable: {}", _err);
Err(STDWEB_NO_RNG)
Err(Error::STDWEB_NO_RNG)
}
}
@@ -107,7 +106,7 @@ fn getrandom_fill(source: RngSource, dest: &mut [u8]) -> Result<(), Error> {
if js! { return @{ result.as_ref() }.success } != true {
let _err: WebError = js! { return @{ result }.error }.try_into().unwrap();
error!("getrandom failed: {}", _err);
return Err(STDWEB_RNG_FAILED);
return Err(Error::STDWEB_RNG_FAILED);
}
}
Ok(())
+2 -2
View File
@@ -7,7 +7,7 @@
// except according to those terms.
//! Implementation for Windows
use crate::{error::RTL_GEN_RANDOM_FAILED, Error};
use crate::Error;
extern "system" {
#[link_name = "SystemFunction036"]
@@ -19,7 +19,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
for chunk in dest.chunks_mut(u32::max_value() as usize) {
let ret = unsafe { RtlGenRandom(chunk.as_mut_ptr(), chunk.len() as u32) };
if ret == 0 {
return Err(RTL_GEN_RANDOM_FAILED);
return Err(Error::WINDOWS_RTL_GEN_RANDOM);
}
}
Ok(())