Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion sdk/core/azure_core_test_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use syn::{
};

const INVALID_RECORDED_ATTRIBUTE_MESSAGE: &str =
"expected `#[recorded::test]` or `#[recorded::test(live)]`";
"expected `#[recorded::test]`, `#[recorded::test(live)]`, or `#[recorded::test(playback)]`";
const INVALID_RECORDED_FUNCTION_MESSAGE: &str =
"expected `async fn(TestContext)` function signature with `Result<T, E>` return";

Expand Down Expand Up @@ -50,6 +50,13 @@ pub fn parse_test(attr: TokenStream, item: TokenStream) -> Result<TokenStream> {
});
}

// Ignore playback-only tests if not running playback tests.
if recorded_attrs.playback && test_mode != TestMode::Playback {
test_attr.extend(quote! {
#[ignore = "skipping playback-only tests"]
});
}

let fn_name = &original_sig.ident;
let mut inputs = original_sig.inputs.iter();
let setup = match inputs.next() {
Expand Down Expand Up @@ -110,6 +117,7 @@ static TEST_MODE: LazyLock<TestMode> = LazyLock::new(|| {
#[derive(Debug, Default)]
struct Attributes {
live: bool,
playback: bool,
}

impl Parse for Attributes {
Expand All @@ -123,6 +131,7 @@ impl Parse for Attributes {
})?;
match ident.to_string().as_str() {
"live" => attrs.live = true,
"playback" => attrs.playback = true,
_ => {
return Err(syn::Error::new(
arg.span(),
Expand All @@ -140,6 +149,13 @@ impl Parse for Attributes {
}
}

if attrs.live && attrs.playback {
return Err(syn::Error::new(
input.span(),
"cannot specify both 'live' and 'playback' attributes",
));
}

Ok(attrs)
}
}
Expand Down Expand Up @@ -274,4 +290,33 @@ mod tests {
};
parse_test(attr, item).unwrap();
}

#[test]
fn attributes_parse_playback() {
let attr: Attribute = syn::parse_quote! {
#[recorded(playback)]
};
let attrs: Attributes = attr.parse_args().unwrap();
assert!(attrs.playback);
assert!(!attrs.live);
}

#[test]
fn attributes_parse_conflicting() {
let attr: Attribute = syn::parse_quote! {
#[recorded(live, playback)]
};
attr.parse_args::<Attributes>().unwrap_err();
}

#[test]
fn parse_recorded_playback_only() {
let attr = quote! { playback };
let item = quote! {
async fn playback_only(ctx: TestContext) -> azure_core::Result<()> {
todo!()
}
};
parse_test(attr, item).unwrap();
}
}
6 changes: 2 additions & 4 deletions sdk/storage/azure_storage_blob/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Features Added

- Added support for `set_legal_hold` to `BlobClient`.

### Breaking Changes

### Bugs Fixed
Expand Down Expand Up @@ -35,10 +37,6 @@
- The `credential` parameter is now `Optional` on `new()` client constructors, allowing for construction of public access clients.
- Renamed `Response<T, F>::into_body(self) -> Result<Response<T>>` to `into_model(self) -> Result<Response<T>>`. `into_body(self)` now returns a `ResponseBody`.

### Bugs Fixed

### Other Changes

## 0.6.0 (2025-10-06)

### Features Added
Expand Down
2 changes: 1 addition & 1 deletion sdk/storage/azure_storage_blob/assets.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "rust",
"Tag": "rust/azure_storage_blob_1e5e3b2c6c",
"Tag": "rust/azure_storage_blob_ceab74b7c5",
"TagPrefix": "rust/azure_storage_blob"
}
20 changes: 17 additions & 3 deletions sdk/storage/azure_storage_blob/src/clients/blob_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use crate::{
AccessTier, BlobClientAcquireLeaseOptions, BlobClientBreakLeaseOptions,
BlobClientChangeLeaseOptions, BlobClientDeleteOptions, BlobClientDownloadOptions,
BlobClientGetAccountInfoOptions, BlobClientGetPropertiesOptions, BlobClientGetTagsOptions,
BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetMetadataOptions,
BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions,
BlobTags, BlockBlobClientUploadOptions, StorageErrorCode,
BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetLegalHoldOptions,
BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions,
BlobClientSetTierOptions, BlobTags, BlockBlobClientUploadOptions, StorageErrorCode,
},
pipeline::StorageHeadersPolicy,
AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient,
Expand Down Expand Up @@ -436,4 +436,18 @@ impl BlobClient {
Err(e) => Err(e),
}
}

/// Sets a legal hold on the blob.
///
/// # Arguments
///
/// * `legal_hold` - Specifies the legal hold status to set on the blob.
/// * `options` - Optional configuration for the request.
pub async fn set_legal_hold(
&self,
legal_hold: bool,
options: Option<BlobClientSetLegalHoldOptions<'_>>,
) -> Result<Response<(), NoFormat>> {
self.client.set_legal_hold(legal_hold, options).await
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading