From 8a2db86c1f4a2ae9d5ce2606b763eb85c8d9e135 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 20 May 2024 14:08:30 -0500 Subject: [PATCH] Add C++ test client (#3046) --- .github/workflows/clippy.yml | 2 + .github/workflows/test.yml | 2 + .../json_validator_client/Cargo.toml | 16 +++++++ .../components/json_validator_client/build.rs | 14 ++++++ .../json_validator_client/src/client.cpp | 44 +++++++++++++++++++ .../json_validator_client/src/lib.rs | 11 +++++ 6 files changed, 89 insertions(+) create mode 100644 crates/samples/components/json_validator_client/Cargo.toml create mode 100644 crates/samples/components/json_validator_client/build.rs create mode 100644 crates/samples/components/json_validator_client/src/client.cpp create mode 100644 crates/samples/components/json_validator_client/src/lib.rs diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index d539d49a55..38dda4ca3a 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -44,6 +44,8 @@ jobs: run: cargo clippy -p sample_component_hello_world - name: Clippy sample_component_json_validator run: cargo clippy -p sample_component_json_validator + - name: Clippy sample_component_json_validator_client + run: cargo clippy -p sample_component_json_validator_client - name: Clippy sample_component_json_validator_winrt run: cargo clippy -p sample_component_json_validator_winrt - name: Clippy sample_component_json_validator_winrt_client diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee18f28095..21eb5b12aa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,6 +68,8 @@ jobs: run: cargo test -p sample_component_hello_world --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_component_json_validator run: cargo test -p sample_component_json_validator --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Test sample_component_json_validator_client + run: cargo test -p sample_component_json_validator_client --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_component_json_validator_winrt run: cargo test -p sample_component_json_validator_winrt --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_component_json_validator_winrt_client diff --git a/crates/samples/components/json_validator_client/Cargo.toml b/crates/samples/components/json_validator_client/Cargo.toml new file mode 100644 index 0000000000..ca6dbe9b69 --- /dev/null +++ b/crates/samples/components/json_validator_client/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sample_component_json_validator_client" +version = "0.0.0" +edition = "2021" +publish = false + +[build-dependencies] +cc = "1.0" + +[dependencies.windows-targets] +path = "../../../../crates/libs/targets" + +# TODO: this causes a warning about lack of linkage target. The point is to ensure that this binary dependency is built first but +# Cargo doesn't respect cdylib targets. https://github.com/rust-lang/cargo/issues/7825 +[dependencies.sample_component_json_validator] +path = "../json_validator" diff --git a/crates/samples/components/json_validator_client/build.rs b/crates/samples/components/json_validator_client/build.rs new file mode 100644 index 0000000000..a669dceeb0 --- /dev/null +++ b/crates/samples/components/json_validator_client/build.rs @@ -0,0 +1,14 @@ +fn main() { + if !cfg!(target_env = "msvc") { + return; + } + + println!("cargo:rerun-if-changed=src/client.cpp"); + println!("cargo:rustc-link-lib=windows.0.52.0"); + + cc::Build::new() + .cpp(true) + .std("c++20") + .file("src/client.cpp") + .compile("client"); +} diff --git a/crates/samples/components/json_validator_client/src/client.cpp b/crates/samples/components/json_validator_client/src/client.cpp new file mode 100644 index 0000000000..b9ef1db984 --- /dev/null +++ b/crates/samples/components/json_validator_client/src/client.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +typedef HRESULT (__stdcall *CreateJsonValidator)(char const* schema, size_t schema_len, uintptr_t* handle); + +typedef HRESULT (__stdcall *ValidateJson)(uintptr_t handle, char const* value, size_t value_len, char** sanitized_value, size_t* sanitized_value_len); + +typedef void (__stdcall *CloseJsonValidator)(uintptr_t handle); + +extern "C" { + void __stdcall client() { + auto library = LoadLibraryExW(L"sample_component_json_validator.dll", 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + assert(library != 0); + + auto create = reinterpret_cast(GetProcAddress(library, "CreateJsonValidator")); + assert(create); + + auto validate = reinterpret_cast(GetProcAddress(library, "ValidateJson")); + assert(validate); + + auto close = reinterpret_cast(GetProcAddress(library, "CloseJsonValidator")); + assert(close); + + std::string_view schema = "{\"maxLength\": 5}"; + std::string_view json = "\"Hello\" "; // trailing space will be removed from sanitized result + std::string_view json_invalid = "\"Hello world\""; // this json is too long + + uintptr_t validator = 0; + assert(S_OK == create(schema.data(), schema.size(), &validator)); + + char* sanitized_value = nullptr; + size_t sanitized_value_len = 0; + assert(S_OK == validate(validator, json.data(), json.size(), &sanitized_value, &sanitized_value_len)); + std::string_view sanitized(sanitized_value, sanitized_value_len); + assert(sanitized == "\"Hello\""); + CoTaskMemFree(sanitized_value); + + assert(E_INVALIDARG == validate(validator, json_invalid.data(), json_invalid.size(), &sanitized_value, &sanitized_value_len)); + + close(validator); + } +} diff --git a/crates/samples/components/json_validator_client/src/lib.rs b/crates/samples/components/json_validator_client/src/lib.rs new file mode 100644 index 0000000000..6f1497b02a --- /dev/null +++ b/crates/samples/components/json_validator_client/src/lib.rs @@ -0,0 +1,11 @@ +#![cfg(target_env = "msvc")] + +#[test] +fn test() { + extern "system" { + fn client(); + } + unsafe { + client(); + } +}