Skip to content

Commit

Permalink
Add windows-sys test coverage (#2063)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Sep 23, 2022
1 parent 82feb3e commit d0ab3b5
Show file tree
Hide file tree
Showing 19 changed files with 316 additions and 26 deletions.
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()) });
}
File renamed without changes.
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);
}
File renamed without changes.
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);
}
}

0 comments on commit d0ab3b5

Please sign in to comment.