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 windows-sys test coverage #2063

Merged
merged 2 commits into from Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/tests/arch/Cargo.toml
Expand Up @@ -9,3 +9,9 @@ path = "../../libs/windows"
features = [
"Win32_System_Diagnostics_Debug",
]

[dependencies.windows-sys]
path = "../../libs/sys"
features = [
"Win32_System_Diagnostics_Debug",
]
13 changes: 13 additions & 0 deletions crates/tests/arch/tests/sys.rs
@@ -0,0 +1,13 @@
use windows_sys::Win32::System::Diagnostics::Debug::KNONVOLATILE_CONTEXT_POINTERS;

#[test]
#[cfg(target_arch = "x86_64")]
fn test() {
assert_eq!(256, core::mem::size_of::<KNONVOLATILE_CONTEXT_POINTERS>());
}

#[test]
#[cfg(target_arch = "x86")]
fn test() {
assert_eq!(4, core::mem::size_of::<KNONVOLATILE_CONTEXT_POINTERS>());
}
File renamed without changes.
9 changes: 9 additions & 0 deletions crates/tests/arch_feature/Cargo.toml
Expand Up @@ -12,3 +12,12 @@ features = [
"Win32_System_Environment",
"Win32_System_Kernel",
]

[dependencies.windows-sys]
path = "../../libs/sys"
features = [
"Win32_System_Diagnostics_Debug",
"Win32_System_SystemServices",
"Win32_System_Environment",
"Win32_System_Kernel",
]
31 changes: 31 additions & 0 deletions crates/tests/arch_feature/tests/sys.rs
@@ -0,0 +1,31 @@
use windows_sys::{Win32::System::Diagnostics::Debug::CONTEXT, Win32::System::Environment::VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD};

#[test]
#[cfg(target_arch = "x86_64")]
fn test() {
assert_eq!(1232, core::mem::size_of::<CONTEXT>());

use windows_sys::Win32::System::Environment::VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR64;

extern "system" fn callback(_: *const VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR64) -> i32 {
64
}

let callback: VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD = Some(callback);
assert_eq!(64, unsafe { callback.unwrap()(core::ptr::null()) });
}

#[test]
#[cfg(target_arch = "x86")]
fn test() {
assert_eq!(716, core::mem::size_of::<CONTEXT>());

use windows_sys::Win32::System::Environment::VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR32;

extern "system" fn callback(_: *const VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR32) -> i32 {
32
}

let callback: VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD = Some(callback);
assert_eq!(32, unsafe { callback.unwrap()(core::ptr::null()) });
}
7 changes: 7 additions & 0 deletions crates/tests/bcrypt/Cargo.toml
Expand Up @@ -10,3 +10,10 @@ features = [
"Win32_Foundation",
"Win32_Security_Cryptography",
]

[dependencies.windows-sys]
path = "../../libs/sys"
features = [
"Win32_Foundation",
"Win32_Security_Cryptography",
]
61 changes: 61 additions & 0 deletions crates/tests/bcrypt/tests/sys.rs
@@ -0,0 +1,61 @@
use windows_sys::{core::*, Win32::Foundation::*, Win32::Security::Cryptography::*};

#[test]
fn test() {
unsafe {
let mut rng = 0;
// TODO: workaround for https://github.com/microsoft/win32metadata/issues/1008
assert_eq!(STATUS_SUCCESS, BCryptOpenAlgorithmProvider(&mut rng, w!("RNG"), std::ptr::null(), 0));

let mut des = 0;
assert_eq!(STATUS_SUCCESS, BCryptOpenAlgorithmProvider(&mut des, w!("3DES"), std::ptr::null(), 0));

let mut object_len = [0; 4];
let mut bytes_copied = 0;
assert_eq!(STATUS_SUCCESS, BCryptGetProperty(des, w!("ObjectLength"), object_len.as_mut_ptr(), object_len.len() as _, &mut bytes_copied, 0));
let object_len = u32::from_le_bytes(object_len);

let mut shared_secret = vec![0; object_len as _];
assert_eq!(STATUS_SUCCESS, BCryptGenRandom(rng, shared_secret.as_mut_ptr(), shared_secret.len() as _, 0));

let mut encrypt_key = 0;
assert_eq!(STATUS_SUCCESS, BCryptGenerateSymmetricKey(des, &mut encrypt_key, std::ptr::null_mut(), 0, shared_secret.as_ptr(), shared_secret.len() as _, 0));

let mut block_len = [0; 4];
assert_eq!(STATUS_SUCCESS, BCryptGetProperty(des, w!("BlockLength"), block_len.as_mut_ptr(), block_len.len() as _, &mut bytes_copied, 0));
let block_len = u32::from_le_bytes(block_len) as usize;

let send_message = "I ❤️ Rust";
let mut send_buffer = vec![0; block_len * ((send_message.len() + (block_len - 1)) / block_len)];
send_buffer[..send_message.len()].copy_from_slice(send_message.as_bytes());

let mut encrypted_len = 0;
assert_eq!(STATUS_SUCCESS, BCryptEncrypt(encrypt_key, send_buffer.as_ptr(), send_buffer.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, std::ptr::null_mut(), 0, &mut encrypted_len, 0));

let mut encrypted = vec![0; encrypted_len as _];
assert_eq!(STATUS_SUCCESS, BCryptEncrypt(encrypt_key, send_buffer.as_ptr(), send_buffer.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, encrypted.as_mut_ptr(), encrypted.len() as _, &mut encrypted_len, 0));

let mut decrypt_key = 0;
assert_eq!(STATUS_SUCCESS, BCryptGenerateSymmetricKey(des, &mut decrypt_key, std::ptr::null_mut(), 0, shared_secret.as_ptr(), shared_secret.len() as _, 0));

let mut decrypted_len = 0;
assert_eq!(STATUS_SUCCESS, BCryptDecrypt(decrypt_key, encrypted.as_ptr(), encrypted.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, std::ptr::null_mut(), 0, &mut decrypted_len, 0));

let mut decrypted = vec![0; decrypted_len as _];
assert_eq!(STATUS_SUCCESS, BCryptDecrypt(decrypt_key, encrypted.as_ptr(), encrypted.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, decrypted.as_mut_ptr(), decrypted.len() as _, &mut decrypted_len, 0));

let receive_message = std::str::from_utf8(trim_null_end(&decrypted)).expect("Not a valid message");
assert_eq!(send_message, receive_message);
}
}

pub const fn trim_null_end(mut bytes: &[u8]) -> &[u8] {
while let [rest @ .., last] = bytes {
if *last == 0 {
bytes = rest;
} else {
break;
}
}
bytes
}
Expand Up @@ -45,7 +45,6 @@ fn test() -> Result<()> {
BCryptDecrypt(decrypt_key, Some(&encrypted), None, None, Some(&mut decrypted), &mut decrypted_len, Default::default())?;

let receive_message = std::str::from_utf8(trim_null_end(&decrypted)).expect("Not a valid message");
println!("`{}`", receive_message);
assert_eq!(send_message, receive_message);
}
Ok(())
Expand Down
3 changes: 3 additions & 0 deletions crates/tests/literals/Cargo.toml
Expand Up @@ -6,3 +6,6 @@ edition = "2018"

[dependencies.windows]
path = "../../libs/windows"

[dependencies.windows-sys]
path = "../../libs/sys"
42 changes: 42 additions & 0 deletions crates/tests/literals/tests/sys.rs
@@ -0,0 +1,42 @@
use windows_sys::core::*;

#[test]
fn test() {
const A: PCSTR = s!("");
assert_utf8(A, &[0]);

const B: PCWSTR = w!("");
assert_utf16(B, &[0]);

assert_utf8(s!("hello"), &[b'h', b'e', b'l', b'l', b'o', 0]);
assert_utf16(w!("hello!"), &[0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x21, 0]);
assert_utf16(w!("α & ω ❤"), &[0x03B1, 0x20, 0x26, 0x20, 0x03C9, 0x20, 0x2764, 0]);

assert_utf16(w!("\u{007f}"), &[0x007f, 0]); // Largest one byte UTF8 sequence
assert_utf16(w!("\u{0080}"), &[0x0080, 0]); // Smallest two byte UTF8 sequence
assert_utf16(w!("\u{07ff}"), &[0x07ff, 0]); // Largest two byte UTF8 sequence
assert_utf16(w!("\u{0800}"), &[0x0800, 0]); // Smallest three byte UTF8 sequence
assert_utf16(w!("\u{d7ff}"), &[0xd7ff, 0]); // Highest code point below surrogate range
assert_utf16(w!("\u{e000}"), &[0xe000, 0]); // Smallest code point above surrogate range
assert_utf16(w!("\u{010000}"), &[0xD800, 0xDC00, 0]); // Smallest four byte UTF8 sequence
assert_utf16(w!("\u{10ffff}"), &[0xDBFF, 0xDFFF, 0]); // Largest Unicode code point
}

fn assert_utf8(left: PCSTR, right: &[u8]) {
let len = unsafe { strlen(left) };
assert_eq!(len, right.len() - 1);
let left = unsafe { std::slice::from_raw_parts(left, right.len()) };
assert_eq!(left, right);
}

fn assert_utf16(left: PCWSTR, right: &[u16]) {
let len = unsafe { wcslen(left) };
assert_eq!(len, right.len() - 1);
let left = unsafe { std::slice::from_raw_parts(left, right.len()) };
assert_eq!(left, right);
}

extern "C" {
pub fn strlen(s: PCSTR) -> usize;
pub fn wcslen(s: PCWSTR) -> usize;
}
@@ -1,5 +1,4 @@
use windows::core::{HSTRING, PCSTR, PCWSTR};
use windows::{s, w};
use windows::core::*;

#[test]
fn test() {
Expand Down
6 changes: 6 additions & 0 deletions crates/tests/return_struct/Cargo.toml
Expand Up @@ -9,3 +9,9 @@ path = "../../libs/windows"
features = [
"Win32_Graphics_Direct2D_Common"
]

[dependencies.windows-sys]
path = "../../libs/sys"
features = [
"Win32_Graphics_Direct2D_Common"
]
21 changes: 21 additions & 0 deletions crates/tests/return_struct/tests/sys.rs
@@ -0,0 +1,21 @@
// This test validates that free functions are not affected by the Visual C++ quirk affecting member functions
// returning structs where the return value is effectively a trailing out parameter.
//
// TODO: D2D1ConvertColorSpace is exported by ordinal rather than by name and Rust doesn't appear to support
// this at the moment. It happens to work on x64 but not on x86, hence the cfg check below.
#[test]
#[cfg(target_pointer_width = "64")]
fn test() {
use windows_sys::Win32::Graphics::Direct2D::{Common::*, *};

let before = D2D1_COLOR_F { r: 1.0, g: 2.0, b: 3.0, a: 4.0 };

let after = unsafe { D2D1ConvertColorSpace(D2D1_COLOR_SPACE_SRGB, D2D1_COLOR_SPACE_SCRGB, &before) };

let expected = D2D1_COLOR_F { r: 1.0, g: 1.0, b: 1.0, a: 4.0 };

assert!(after.r == expected.r);
assert!(after.g == expected.g);
assert!(after.b == expected.b);
assert!(after.a == expected.a);
}
8 changes: 8 additions & 0 deletions crates/tests/unions/Cargo.toml
Expand Up @@ -11,3 +11,11 @@ features = [
"Win32_Graphics_Direct3D12",
"Win32_System_IO",
]

[dependencies.windows-sys]
path = "../../libs/sys"
features = [
"Win32_Foundation",
"Win32_Graphics_Direct3D12",
"Win32_System_IO",
]
23 changes: 0 additions & 23 deletions crates/tests/unions/tests/indirect_argument_desc.rs

This file was deleted.

85 changes: 85 additions & 0 deletions crates/tests/unions/tests/sys.rs
@@ -0,0 +1,85 @@
use windows_sys::Win32::{
Graphics::Direct3D12::*,
System::IO::{OVERLAPPED, OVERLAPPED_0_0},
};

#[test]
fn test() {
let mut o = OVERLAPPED { Internal: 1, InternalHigh: 2, Anonymous: unsafe { std::mem::zeroed() }, hEvent: Default::default() };

assert_eq!(o.Internal, 1);
o.Internal = 10;
assert_eq!(o.Internal, 10);

assert_eq!(o.InternalHigh, 2);
o.InternalHigh = 20;
assert_eq!(o.InternalHigh, 20);

assert_eq!(o.hEvent, 0);
o.hEvent = 1;
assert_eq!(o.hEvent, 1);

unsafe {
assert_eq!(o.Anonymous.Pointer, core::ptr::null_mut());
}

unsafe {
assert_eq!(o.Anonymous.Anonymous.Offset, 0);
assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 0);
}

o.Anonymous.Anonymous.Offset = 100;
o.Anonymous.Anonymous.OffsetHigh = 200;

unsafe {
assert_eq!(o.Anonymous.Anonymous.Offset, 100);
assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 200);
}

o.Anonymous.Anonymous = OVERLAPPED_0_0 { Offset: 10, OffsetHigh: 20 };

unsafe {
assert_eq!(o.Anonymous.Anonymous.Offset, 10);
assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 20);
}
}

#[test]
#[cfg(target_arch = "aarch64")]
fn test_arch() {
assert_eq!(core::mem::size_of::<OVERLAPPED>(), 32);
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_arch() {
assert_eq!(core::mem::size_of::<OVERLAPPED>(), 32);
}

#[test]
#[cfg(target_arch = "x86")]
fn test_arch() {
assert_eq!(core::mem::size_of::<OVERLAPPED>(), 20);
}

#[test]
fn d3d() {
assert_eq!(core::mem::size_of::<D3D12_INDIRECT_ARGUMENT_DESC>(), 16);

assert_eq!(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 3);

let mut desc = D3D12_INDIRECT_ARGUMENT_DESC {
Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,
Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 { VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_4 { Slot: 123 } },
};

assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW);

desc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;

assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT);

unsafe {
assert_eq!(desc.Anonymous.VertexBuffer.Slot, 123);
}
}
@@ -1,5 +1,6 @@
use windows::Win32::{
Foundation::HANDLE,
Graphics::Direct3D12::*,
System::IO::{OVERLAPPED, OVERLAPPED_0_0},
};

Expand Down Expand Up @@ -61,3 +62,25 @@ fn test_arch() {
fn test_arch() {
assert_eq!(core::mem::size_of::<OVERLAPPED>(), 20);
}

#[test]
fn d3d() {
assert_eq!(core::mem::size_of::<D3D12_INDIRECT_ARGUMENT_DESC>(), 16);

assert_eq!(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW.0, 3);

let mut desc = D3D12_INDIRECT_ARGUMENT_DESC {
Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW,
Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 { VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_4 { Slot: 123 } },
};

assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW);

desc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;

assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT);

unsafe {
assert_eq!(desc.Anonymous.VertexBuffer.Slot, 123);
}
}