diff --git a/SUPPORT.md b/SUPPORT.md index dd69338c59..422bb0c1db 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -18,7 +18,7 @@ To ensure the relevance and manageability of our issue queue, we have an automat - Take a look at the [Azure SDK blog](https://devblogs.microsoft.com/azure-sdk/). - Search for similar issues in [our GitHub repository](https://github.com/Azure/azure-sdk-for-rust/issues) -- Ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/azure-sdk-rust) and tag it with azure-sdk-.net +- Ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/azure-sdk-rust) and tag it with azure-sdk-rust - Share or upvote feature requests on [Feedback Page](https://feedback.azure.com/forums/34192--general-feedback). - Ask a question on [Twitter](https://twitter.com/AzureSDK) - Ask a question at [Microsoft Q&A](https://learn.microsoft.com/answers/products/azure?WT.mc_id=Portal-Microsoft_Azure_Support&product=all) diff --git a/eng/scripts/Test-Packages.ps1 b/eng/scripts/Test-Packages.ps1 index d90a61e48e..2a70ce7ad4 100755 --- a/eng/scripts/Test-Packages.ps1 +++ b/eng/scripts/Test-Packages.ps1 @@ -46,6 +46,18 @@ $env:RUSTFLAGS = "-Dwarnings" foreach ($package in $packagesToTest) { Push-Location ([System.IO.Path]::Combine($RepoRoot, $package.DirectoryPath)) try { + $packageDirectory = ([System.IO.Path]::Combine($RepoRoot, $package.DirectoryPath)) + + $setupScript = Join-Path $packageDirectory "Test-Setup.ps1" + if (Test-Path $setupScript) { + Write-Host "`n`nRunning test setup script for package: '$($package.Name)'`n" + Invoke-LoggedCommand $setupScript + if (!$? -ne 0) { + Write-Error "Test setup script failed for package: '$($package.Name)'" + exit 1 + } + } + Write-Host "`n`nTesting package: '$($package.Name)'`n" Invoke-LoggedCommand "cargo +$Toolchain build --keep-going" @@ -68,6 +80,14 @@ foreach ($package in $packagesToTest) { Invoke-LoggedCommand "cargo +$Toolchain test --doc --no-fail-fast" Write-Host "`n`n" + + $cleanupScript = Join-Path $packageDirectory "Test-Cleanup.ps1" + if (Test-Path $cleanupScript) { + Write-Host "`n`nRunning test cleanup script for package: '$($package.Name)'`n" + Invoke-LoggedCommand $cleanupScript + # We ignore the exit code of the cleanup script. + + } } finally { Pop-Location diff --git a/sdk/core/azure_core_amqp/README.md b/sdk/core/azure_core_amqp/README.md index f7df7f4aa5..1f17fb071a 100644 --- a/sdk/core/azure_core_amqp/README.md +++ b/sdk/core/azure_core_amqp/README.md @@ -6,23 +6,69 @@ NOTE: THIS IS NOT A GENERAL PURPOSE AMQP LIBRARY AND SHOULD NOT BE USED AS SUCH. This crate is part of a collection of crates: for more information please refer to [https://github.com/azure/azure-sdk-for-rust](https://github.com/azure/azure-sdk-for-rust). -## Example +## Testing the AMQP Client. -```rust,no_run -use azure_messaging::*; +The AMQP package is tested using the standard `cargo test` command line: -#[tokio::main] -async fn main() -> azure_core::Result<()> { - let eventhubs_namespace = std::env::var("AZURE_EVENTHUB_NAMESPACE").expect("missing AZURE_EVENTHUB_NAMESPACE"); +```bash +cargo test --package azure_core_amqp --all-features +``` + +Certain AMQP tests requires that there be a running AMQP broker on the machine at the time of the test (the tests will run without the broker, the relevant tests will just be skipped). + +One existing AMQP broker is the "TestAMQPBroker" from the azure-amqp GitHub repository. + +To launch the TestAMQPBroker, there are two ways of installing and running the TestAmqpBroker, Scripted and Manual. + +### Scripted Broker Install +Running the broker from a script requires that you first [install Powershell](https://learn.microsoft.com/powershell/scripting/install/installing-powershell?view=powershell-7.4). +From a running powershell instance, run the powershell script in the sdk/core/azure_core_amqp directory: + +``` +./sdk/core/azure_core_amqp/Test-Setup.ps1 +``` + +This will download the TestAmqpBroker, build it and launch the executable in the background. + +Note that this requires that you have the [.NET SDK](https://dot.net/download) installed on your machine. + +You can then run the azure_core_amqp package tests. + +Once you have finished running your tests, you run: + +``` +./sdk/core/azure_core_amqp/Test-Cleanup.ps1 +``` - let client = ProducerClient::new( - eventhubs_namespace, credential, - )?; +which will terminate the test broker. - client.send_event("hello world").await?; +### Manual Broker Install +For Manual testing, first clone the azure-amqp repository to a local directory: - Ok(()) -} +```bash +cd +git clone https://github.com/Azure/azure-amqp ``` +Alternately, you can clone to a specific release in the azure-amqp repository: + +``` +git clone https://github.com/Azure/azure-amqp.git --branch hotfix +``` + +Set an environment variable the test AMQP broker should listen on: + +```powershell + $env:TEST_BROKER_ADDRESS = 'amqp://127.0.0.1:25672' +``` + +And launch the test broker: + +```powershell +cd azure-amqp/test/TestAmqpBroker +dotnet run -- $env:TEST_BROKER_ADDRESS +``` + +Now, when you run the cargo tests, the networking functionality of the AMQP APIs will be executed. + License: MIT diff --git a/sdk/core/azure_core_amqp/Test-Cleanup.ps1 b/sdk/core/azure_core_amqp/Test-Cleanup.ps1 new file mode 100644 index 0000000000..697f66d0a4 --- /dev/null +++ b/sdk/core/azure_core_amqp/Test-Cleanup.ps1 @@ -0,0 +1,21 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# cspell: ignore JOBID + +. "$PSScriptRoot\..\..\..\eng\common\scripts\common.ps1" + +Write-Host "Test Broker output:" +Receive-Job -Id $env:TEST_BROKER_JOBID + +# Check if the test broker job is still running +$job = Get-Job -Id $env:TEST_BROKER_JOBID +if ($job.State -ne "Running") { + Write-Host "Test broker terminated unexpectedly." + exit 1 +} + +# Stop the test broker job started in Test-Setup.ps1 +Write-Host "Stopping test broker" +Stop-Job -Id $env:TEST_BROKER_JOBID +Remove-Job -Id $env:TEST_BROKER_JOBID +Write-Host "Test broker stopped." diff --git a/sdk/core/azure_core_amqp/Test-Setup.ps1 b/sdk/core/azure_core_amqp/Test-Setup.ps1 new file mode 100644 index 0000000000..4beb2c4a8c --- /dev/null +++ b/sdk/core/azure_core_amqp/Test-Setup.ps1 @@ -0,0 +1,69 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# cspell: ignore JOBID depsfile + + +# Load common ES scripts +. "$PSScriptRoot\..\..\..\eng\common\scripts\common.ps1" + +# Create the test binary *outside* the repo root to avoid polluting the repo. +$WorkingDirectory = ([System.IO.Path]::Combine($RepoRoot, "../TestArtifacts")) + +# Create the working directory if it does not exist. +Write-Host "Using Working Directory $WorkingDirectory" + +if (-not (Test-Path $WorkingDirectory)) { + Write-Host "Working directory does not exist, creating working directory: $WorkingDirectory" + New-Item -ItemType Directory -Path $WorkingDirectory +} + +Write-Host "Setting current directory to working directory: $WorkingDirectory" +Push-Location -Path $WorkingDirectory + +# Clone and build the Test Amqp Broker. +try { + + $repositoryUrl = "https://github.com/Azure/azure-amqp.git" + # We would like to use the "hotfix" branch because that is current, but unfortunately it references System.Net.Security version 4.0.0 + $repositoryBranch = "master" + $cloneCommand = "git clone $repositoryUrl --branch $repositoryBranch" + + Write-Host "Cloning repository from $repositoryUrl..." + Invoke-LoggedCommand $cloneCommand + + Set-Location -Path "./azure-amqp/test/TestAmqpBroker" + + Invoke-LoggedCommand "dotnet build -p RollForward=LatestMajor --framework net6.0" + if (!$? -ne 0) { + Write-Error "Failed to build TestAmqpBroker." + exit 1 + } + + Write-Host "Test broker built successfully." + + # now that the Test broker has been built, launch the broker on a local address. + $env:TEST_BROKER_ADDRESS = 'amqp://127.0.0.1:25672' + + Write-Host "Starting test broker listening on ${env:TEST_BROKER_ADDRESS} ..." + + Set-Location -Path $WorkingDirectory/azure-amqp/bin/Debug/TestAmqpBroker/net6.0 + + $job = dotnet exec ./TestAmqpBroker.dll ${env:TEST_BROKER_ADDRESS} /headless & + + $env:TEST_BROKER_JOBID = $job.Id + + Write-Host "Waiting for test broker to start..." + Start-Sleep -Seconds 3 + + Write-Host "Job Output after wait:" + Receive-Job $job.Id + + $job = Get-Job -Id $env:TEST_BROKER_JOBID + if ($job.State -ne "Running") { + Write-Host "Test broker failed to start." + exit 1 + } +} +finally { + Pop-Location +} diff --git a/sdk/core/azure_core_amqp/examples/connection.rs b/sdk/core/azure_core_amqp/examples/connection.rs index 2b0e736130..0938cbd4ab 100644 --- a/sdk/core/azure_core_amqp/examples/connection.rs +++ b/sdk/core/azure_core_amqp/examples/connection.rs @@ -6,7 +6,6 @@ // 1. Clone the repository: // git clone https://github.com/Azure/azure-amqp // 2. Build the project: -// dotnet restore // dotnet build // 3. Run the broker: // dotnet run --project .\test\TestAmqpBroker\TestAmqpBroker.csproj --framework net462 amqp://localhost:25672 @@ -74,8 +73,10 @@ async fn amqp_connection_close_with_error() { pub async fn main() { tracing_subscriber::fmt::init(); - amqp_connection_open().await; - amqp_connection_open_with_error().await; - amqp_connection_close().await; - amqp_connection_close_with_error().await; + tokio::join!( + amqp_connection_open(), + amqp_connection_open_with_error(), + amqp_connection_close(), + amqp_connection_close_with_error() + ); } diff --git a/sdk/core/azure_core_amqp/src/connection.rs b/sdk/core/azure_core_amqp/src/connection.rs index 3675367824..a106b11690 100644 --- a/sdk/core/azure_core_amqp/src/connection.rs +++ b/sdk/core/azure_core_amqp/src/connection.rs @@ -245,50 +245,58 @@ mod tests { ); } - // Tests disabled until we have a way to start the AMQP test broker in CI - #[allow(dead_code)] - mod disabled { - use super::super::*; - - // #[tokio::test] - async fn amqp_connection_open() { - tracing_subscriber::fmt::init(); + #[tokio::test] + async fn amqp_connection_open() { + let address = std::env::var("TEST_BROKER_ADDRESS"); + if address.is_ok() { let connection = AmqpConnection::new(); - - let url = Url::parse("amqp://localhost:25672").unwrap(); + let url = Url::parse(&address.unwrap()).unwrap(); connection .open("test".to_string(), url, None) .await .unwrap(); + } else { + println!("TEST_BROKER_ADDRESS is not set. Skipping test."); } + } - // #[tokio::test] - async fn amqp_connection_open_with_error() { - tracing_subscriber::fmt::try_init().unwrap(); + #[tokio::test] + async fn amqp_connection_open_with_error() { + let address = std::env::var("TEST_BROKER_ADDRESS"); + if address.is_ok() { let connection = AmqpConnection::new(); let url = Url::parse("amqp://localhost:32767").unwrap(); assert!(connection .open("test".to_string(), url, None) .await .is_err()); + } else { + println!("TEST_BROKER_ADDRESS is not set. Skipping test."); } + } - // #[tokio::test] - async fn amqp_connection_close() { + #[tokio::test] + async fn amqp_connection_close() { + let address = std::env::var("TEST_BROKER_ADDRESS"); + if address.is_ok() { let connection = AmqpConnection::new(); - let url = Url::parse("amqp://localhost:25672").unwrap(); + let url = Url::parse(&address.unwrap()).unwrap(); connection .open("test".to_string(), url, None) .await .unwrap(); connection.close().await.unwrap(); + } else { + println!("TEST_BROKER_ADDRESS is not set. Skipping test."); } + } - // #[tokio::test] - async fn amqp_connection_close_with_error() { - tracing_subscriber::fmt::try_init().unwrap(); + #[tokio::test] + async fn amqp_connection_close_with_error() { + let address = std::env::var("TEST_BROKER_ADDRESS"); + if address.is_ok() { let connection = AmqpConnection::new(); - let url = Url::parse("amqp://localhost:25672").unwrap(); + let url = Url::parse(&address.unwrap()).unwrap(); connection .open("test".to_string(), url, None) .await @@ -306,6 +314,8 @@ mod tests { assert!(err.to_string().contains("Internal error.")); } } + } else { + println!("TEST_BROKER_ADDRESS is not set. Skipping test."); } } } diff --git a/sdk/core/azure_core_amqp/src/fe2o3/connection.rs b/sdk/core/azure_core_amqp/src/fe2o3/connection.rs index 8b3ec3e741..d0655f6959 100644 --- a/sdk/core/azure_core_amqp/src/fe2o3/connection.rs +++ b/sdk/core/azure_core_amqp/src/fe2o3/connection.rs @@ -9,7 +9,7 @@ use async_std::sync::Mutex; use azure_core::{Result, Url}; use fe2o3_amqp::connection::ConnectionHandle; use std::{borrow::BorrowMut, sync::OnceLock}; -use tracing::{debug, info, warn}; +use tracing::{debug, warn}; use super::error::{AmqpConnection, AmqpOpen}; @@ -166,7 +166,7 @@ impl AmqpConnectionApis for Fe2o3AmqpConnection { Ok(_) => Ok(()), Err(e) => match e.0 { fe2o3_amqp::connection::Error::TransportError(e) => { - info!( + debug!( "Transport error closing connection with error: {:?} - ignored", e ); diff --git a/sdk/core/azure_core_amqp/src/lib.rs b/sdk/core/azure_core_amqp/src/lib.rs index 899fb4c91d..4bf59621d2 100644 --- a/sdk/core/azure_core_amqp/src/lib.rs +++ b/sdk/core/azure_core_amqp/src/lib.rs @@ -22,6 +22,7 @@ use std::fmt::Debug; // AMQP Settle mode: // https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-sender-settle-mode + const AMQP_SENDER_SETTLE_MODE_UNSETTLED: isize = 0; const AMQP_SENDER_SETTLE_MODE_SETTLED: isize = 1; const AMQP_SENDER_SETTLE_MODE_MIXED: isize = 2;