diff --git a/.gitattributes b/.gitattributes index ab921d0c4..30324bd14 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ * text=auto eol=lf packages/typespec-rust/test/**/src/generated/**/*.rs linguist-generated=true +# Squad: union merge for append-only team state files diff --git a/.gitignore b/.gitignore index c6b412dd9..9a43063e6 100644 --- a/.gitignore +++ b/.gitignore @@ -412,3 +412,5 @@ spec-coverage.json packages/typespec-rust/**/target/ packages/typespec-rust/pnpm-store/ +# Squad: ignore generated logs +.squad/ diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 2610d5359..dbdc82d8b 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -48,6 +48,7 @@ "lro", "lros", "msrc", + "noauth", "pageable", "reinjectable", "reinjected", diff --git a/packages/typespec-rust/.scripts/tspcompile.js b/packages/typespec-rust/.scripts/tspcompile.js index be9a80bed..040ed3ca3 100644 --- a/packages/typespec-rust/.scripts/tspcompile.js +++ b/packages/typespec-rust/.scripts/tspcompile.js @@ -21,16 +21,20 @@ const compiler = pkgRoot + 'node_modules/@typespec/compiler/cmd/tsp.js'; const httpSpecsGroup = { 'spector_apikey': {input: 'authentication/api-key'}, 'spector_customauth': {input: 'authentication/http/custom'}, + 'spector_noauth': {input: 'authentication/noauth/union'}, 'spector_oauth2': {input: 'authentication/oauth2'}, 'spector_unionauth': {input: 'authentication/union'}, + 'spector_documentation': {input: 'documentation'}, 'spector_bytes': {input: 'encode/bytes'}, // TODO: nested arrays and "raw" request/responses (i.e. the orphan problem) 'spector_datetime': {input: 'encode/datetime'}, 'spector_duration': {input: 'encode/duration'}, + 'spector_encarray': {input: 'encode/array'}, 'spector_numeric': {input: 'encode/numeric'}, 'spector_bodyoptional': {input: 'parameters/body-optionality'}, 'spector_basicparams': {input: 'parameters/basic'}, 'spector_collectionfmt': {input: 'parameters/collection-format'}, 'spector_path': {input: 'parameters/path'}, + 'spector_query': {input: 'parameters/query'}, 'spector_spread': {input: 'parameters/spread'}, 'spector_contentneg': {input: 'payload/content-negotiation'}, 'spector_jmergepatch': {input: 'payload/json-merge-patch'}, @@ -55,7 +59,8 @@ const httpSpecsGroup = { 'spector_empty': {input: 'type/model/empty'}, 'spector_enumdisc': {input: 'type/model/inheritance/enum-discriminator'}, 'spector_nodisc': {input: 'type/model/inheritance/not-discriminated'}, - //'spector_recursive': {input: 'type/model/inheritance/recursive'}, + //'spector_nesteddisc': {input: 'type/model/inheritance/nested-discriminator'}, + 'spector_recursive': {input: 'type/model/inheritance/recursive'}, 'spector_singledisc': {input: 'type/model/inheritance/single-discriminator'}, 'spector_usage': {input: 'type/model/usage'}, 'spector_visibility': {input: 'type/model/visibility'}, @@ -75,10 +80,11 @@ const httpSpecsGroup = { }; const azureHttpSpecsGroup = { - //'spector_access': {input: 'azure/client-generator-core/access'}, + 'spector_access': {input: 'azure/client-generator-core/access'}, 'spector_apiverheader': {input: 'azure/client-generator-core/api-version/header/client.tsp'}, 'spector_apiverpath': {input: 'azure/client-generator-core/api-version/path/client.tsp'}, 'spector_apiverquery': {input: 'azure/client-generator-core/api-version/query/client.tsp'}, + 'spector_clientdefault': {input: 'azure/client-generator-core/client-default-value'}, 'spector_clientinit_default': {input: 'azure/client-generator-core/client-initialization/default'}, 'spector_clientinit_individually': {input: 'azure/client-generator-core/client-initialization/individually'}, 'spector_clientinit_individually_parent': {input: 'azure/client-generator-core/client-initialization/individuallyParent'}, diff --git a/packages/typespec-rust/run_regen.ps1 b/packages/typespec-rust/run_regen.ps1 new file mode 100644 index 000000000..ea14dc434 --- /dev/null +++ b/packages/typespec-rust/run_regen.ps1 @@ -0,0 +1,2 @@ +Set-Location C:\Repos\RickWinter\typespec-rust\packages\typespec-rust +& node .scripts/tspcompile.js diff --git a/packages/typespec-rust/src/codegen/clients.ts b/packages/typespec-rust/src/codegen/clients.ts index 9e58eba4c..8b43bad63 100644 --- a/packages/typespec-rust/src/codegen/clients.ts +++ b/packages/typespec-rust/src/codegen/clients.ts @@ -271,19 +271,37 @@ export function emitClients(module: rust.ModuleContainer): ClientModules | undef body += '}\n\n'; // end client impl - // emit pub(crate) const declarations for fields with default value constants + // Emit pub(crate) const declarations for fields with default value constants. + // + // These constants are ALWAYS emitted, even when the options type is suppressed. + // In SDK crates with suppressed options, SDK authors need these constants to + // reference TypeSpec-defined default values (e.g., api-version) in their + // hand-authored Default impl. Suppressing them would force hardcoding. + // + // Visibility design: + // - Non-suppressed: constant is referenced by the generated Default impl, so + // it's alive and no dead_code suppression is needed. + // - Suppressed: the generated options type doesn't exist — SDK authors provide + // their own. The constant is a convenience they SHOULD use, but may not. + // #[allow(dead_code)] is appropriate here (parallels std library patterns). if (client.constructable) { const isSuppressed = client.constructable.suppressed === 'yes'; for (const field of client.constructable.options.type.fields) { if (field.defaultValueConstant) { if (isSuppressed) { - // When the client options type is suppressed, avoid emitting an intra-doc link - // to a type that does not exist in the generated code. + // Plain text doc comment — the options type doesn't exist when suppressed, + // so intra-doc links would be broken. body += `/// Default value for \`${client.constructable.options.type.name}::${field.name}\`.\n`; + body += `///\n`; + body += `/// This constant is available for SDK authors to use in hand-authored code.\n`; + body += `/// When the options type is suppressed (via \`@access(Access.internal)\`), the\n`; + body += `/// SDK author provides a custom options type and should reference this constant\n`; + body += `/// in their \`Default\` implementation rather than hardcoding the value.\n`; + body += `#[allow(dead_code)]\n`; } else { + // Intra-doc link — the options type exists and the link resolves. body += `/// Default value for [\`${client.constructable.options.type.name}::${field.name}\`].\n`; } - body += `#[allow(dead_code)]\n`; body += `pub(crate) const ${field.defaultValueConstant.name}: &str = "${field.defaultValueConstant.value}";\n\n`; } } diff --git a/packages/typespec-rust/test/Cargo.lock b/packages/typespec-rust/test/Cargo.lock index c02a0534d..23c1760cb 100644 --- a/packages/typespec-rust/test/Cargo.lock +++ b/packages/typespec-rust/test/Cargo.lock @@ -1714,6 +1714,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "spector_access" +version = "0.1.0" +dependencies = [ + "azure_core", + "serde", + "tokio", +] + [[package]] name = "spector_alternatetype" version = "0.1.0" @@ -1954,6 +1963,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "spector_clientdefault" +version = "0.1.0" +dependencies = [ + "azure_core", + "serde", + "tokio", +] + [[package]] name = "spector_clientinit_default" version = "0.1.0" @@ -2154,6 +2172,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "spector_documentation" +version = "0.1.0" +dependencies = [ + "azure_core", + "serde", + "tokio", +] + [[package]] name = "spector_duration" version = "0.1.0" @@ -2182,6 +2209,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "spector_encarray" +version = "0.1.0" +dependencies = [ + "azure_core", + "serde", + "tokio", +] + [[package]] name = "spector_enumconflict" version = "0.1.0" @@ -2319,6 +2355,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "spector_noauth" +version = "0.1.0" +dependencies = [ + "async-trait", + "azure_core", + "tokio", +] + [[package]] name = "spector_nodisc" version = "0.1.0" @@ -2391,6 +2436,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "spector_query" +version = "0.1.0" +dependencies = [ + "azure_core", + "tokio", +] + +[[package]] +name = "spector_recursive" +version = "0.1.0" +dependencies = [ + "azure_core", + "serde", + "tokio", +] + [[package]] name = "spector_renamedop" version = "0.1.0" diff --git a/packages/typespec-rust/test/Cargo.toml b/packages/typespec-rust/test/Cargo.toml index 04ff89cbd..10e789c39 100644 --- a/packages/typespec-rust/test/Cargo.toml +++ b/packages/typespec-rust/test/Cargo.toml @@ -14,12 +14,15 @@ members = [ "sdk/keyvault_secrets", "spector/authentication/api-key", "spector/authentication/http/custom", + "spector/authentication/noauth/union", "spector/authentication/oauth2", "spector/authentication/union", + "spector/azure/client-generator-core/access", + "spector/azure/client-generator-core/alternate-type", "spector/azure/client-generator-core/api-version/header", "spector/azure/client-generator-core/api-version/path", "spector/azure/client-generator-core/api-version/query", - "spector/azure/client-generator-core/alternate-type", + "spector/azure/client-generator-core/client-default-value", "spector/azure/client-generator-core/client-initialization/default", "spector/azure/client-generator-core/client-initialization/individually", "spector/azure/client-generator-core/client-initialization/individuallyParent", @@ -61,6 +64,8 @@ members = [ "spector/client/structure/multi-client", "spector/client/structure/renamed-operation", "spector/client/structure/two-operation-group", + "spector/documentation", + "spector/encode/array", "spector/encode/bytes", "spector/encode/datetime", "spector/encode/duration", @@ -69,6 +74,7 @@ members = [ "spector/parameters/body-optionality", "spector/parameters/collection-format", "spector/parameters/path", + "spector/parameters/query", "spector/parameters/spread", "spector/payload/content-negotiation", "spector/payload/json-merge-patch", @@ -93,6 +99,7 @@ members = [ "spector/type/model/empty", "spector/type/model/inheritance/enum-discriminator", "spector/type/model/inheritance/not-discriminated", + "spector/type/model/inheritance/recursive", "spector/type/model/inheritance/single-discriminator", "spector/type/model/usage", "spector/type/model/visibility", diff --git a/packages/typespec-rust/test/sdk/appconfiguration/src/generated/clients/azure_app_configuration_client.rs b/packages/typespec-rust/test/sdk/appconfiguration/src/generated/clients/azure_app_configuration_client.rs index e9adb591b..10b7bed87 100644 --- a/packages/typespec-rust/test/sdk/appconfiguration/src/generated/clients/azure_app_configuration_client.rs +++ b/packages/typespec-rust/test/sdk/appconfiguration/src/generated/clients/azure_app_configuration_client.rs @@ -2233,7 +2233,6 @@ impl AzureAppConfigurationClient { } /// Default value for [`AzureAppConfigurationClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2024-09-01"; impl Default for AzureAppConfigurationClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/append_blob_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/append_blob_client.rs index fc3f5f716..e687fd67e 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/append_blob_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/append_blob_client.rs @@ -594,7 +594,6 @@ impl AppendBlobClient { } /// Default value for [`AppendBlobClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for AppendBlobClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_client.rs index d21b7558a..813446375 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_client.rs @@ -1595,7 +1595,6 @@ impl BlobClient { } /// Default value for [`BlobClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for BlobClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_container_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_container_client.rs index 0b41523d9..f0f8c3817 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_container_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_container_client.rs @@ -1040,7 +1040,6 @@ impl BlobContainerClient { } /// Default value for [`BlobContainerClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for BlobContainerClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_service_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_service_client.rs index fb06de595..884786149 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_service_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/blob_service_client.rs @@ -378,7 +378,6 @@ impl BlobServiceClient { } /// Default value for [`BlobServiceClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for BlobServiceClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/block_blob_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/block_blob_client.rs index 5897e6512..1714576df 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/block_blob_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/block_blob_client.rs @@ -949,7 +949,6 @@ impl BlockBlobClient { } /// Default value for [`BlockBlobClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for BlockBlobClientOptions { diff --git a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/page_blob_client.rs b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/page_blob_client.rs index d8449e634..7dde83334 100644 --- a/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/page_blob_client.rs +++ b/packages/typespec-rust/test/sdk/blob_storage/src/generated/clients/page_blob_client.rs @@ -986,7 +986,6 @@ impl PageBlobClient { } /// Default value for [`PageBlobClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2026-04-06"; impl Default for PageBlobClientOptions { diff --git a/packages/typespec-rust/test/sdk/keyvault_secrets/src/generated/clients/secret_client.rs b/packages/typespec-rust/test/sdk/keyvault_secrets/src/generated/clients/secret_client.rs index 7dfae94f6..9ccd84a82 100644 --- a/packages/typespec-rust/test/sdk/keyvault_secrets/src/generated/clients/secret_client.rs +++ b/packages/typespec-rust/test/sdk/keyvault_secrets/src/generated/clients/secret_client.rs @@ -712,5 +712,10 @@ impl SecretClient { } /// Default value for `SecretClientOptions::api_version`. +/// +/// This constant is available for SDK authors to use in hand-authored code. +/// When the options type is suppressed (via `@access(Access.internal)`), the +/// SDK author provides a custom options type and should reference this constant +/// in their `Default` implementation rather than hardcoding the value. #[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2025-06-01-preview"; diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/Cargo.toml b/packages/typespec-rust/test/spector/authentication/noauth/union/Cargo.toml new file mode 100644 index 000000000..472c812c9 --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_noauth" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } + +[dev-dependencies] +async-trait = { workspace = true } +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/mod.rs new file mode 100644 index 000000000..945cb7615 --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod union_client; +pub use union_client::*; diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/union_client.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/union_client.rs new file mode 100644 index 000000000..60ab8dfdb --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/clients/union_client.rs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::models::{UnionClientValidNoAuthOptions, UnionClientValidTokenOptions}; +use azure_core::{ + credentials::TokenCredential, + error::CheckSuccessOptions, + fmt::SafeDebug, + http::{ + policies::{auth::BearerTokenAuthorizationPolicy, Policy}, + ClientOptions, Method, NoFormat, Pipeline, PipelineSendOptions, Request, Response, Url, + UrlExt, + }, + tracing, Result, +}; +use std::sync::Arc; + +/// Illustrates clients generated with NoAuth and OAuth2 authentication union. +#[tracing::client] +pub struct UnionClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`UnionClient`](UnionClient) +#[derive(Clone, Default, SafeDebug)] +pub struct UnionClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl UnionClient { + /// Creates a new UnionClient, using Entra ID authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `credential` - An implementation of [`TokenCredential`](azure_core::credentials::TokenCredential) that can provide an + /// Entra ID token to use when authenticating. + /// * `options` - Optional configuration for the client. + #[tracing::new("Authentication.Noauth.Union")] + pub fn new( + endpoint: &str, + credential: Arc, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + let auth_policy: Arc = Arc::new(BearerTokenAuthorizationPolicy::new( + credential, + vec!["https://security.microsoft.com/.default"], + )); + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + vec![auth_policy], + None, + ), + }) + } + + /// Creates a new UnionClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Authentication.Noauth.Union")] + pub fn with_no_credential(endpoint: &str, options: Option) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Check whether client can make a request without authentication + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Authentication.Noauth.Union.validNoAuth")] + pub async fn valid_no_auth( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/authentication/noauth/union/valid"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// Check whether client is authenticated with OAuth2 token + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Authentication.Noauth.Union.validToken")] + pub async fn valid_token( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/authentication/noauth/union/validtoken"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/mod.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/mod.rs new file mode 100644 index 000000000..8b5b83aca --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{UnionClient, UnionClientOptions}; diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/method_options.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/method_options.rs new file mode 100644 index 000000000..3cba16b03 --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/method_options.rs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`UnionClient::valid_no_auth()`](crate::generated::clients::UnionClient::valid_no_auth()) +#[derive(Clone, Default, SafeDebug)] +pub struct UnionClientValidNoAuthOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`UnionClient::valid_token()`](crate::generated::clients::UnionClient::valid_token()) +#[derive(Clone, Default, SafeDebug)] +pub struct UnionClientValidTokenOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/mod.rs new file mode 100644 index 000000000..3e484b1ed --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/generated/models/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +pub use method_options::*; diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/src/lib.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/src/lib.rs new file mode 100644 index 000000000..cc784e401 --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/authentication/noauth/union/tests/union_client_test.rs b/packages/typespec-rust/test/spector/authentication/noauth/union/tests/union_client_test.rs new file mode 100644 index 000000000..38bf9a2cb --- /dev/null +++ b/packages/typespec-rust/test/spector/authentication/noauth/union/tests/union_client_test.rs @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use azure_core::credentials::{AccessToken, TokenCredential, TokenRequestOptions}; +use azure_core::time::OffsetDateTime; +use azure_core::Result; +use spector_noauth::UnionClient; +use std::sync::Arc; + +#[derive(Debug)] +struct FakeTokenCredential { + pub token: String, +} + +impl FakeTokenCredential { + pub fn new(token: String) -> Self { + FakeTokenCredential { token } + } +} + +#[async_trait::async_trait] +impl TokenCredential for FakeTokenCredential { + async fn get_token( + &self, + _scopes: &[&str], + _options: Option>, + ) -> Result { + Ok(AccessToken::new( + self.token.clone(), + OffsetDateTime::now_utc(), + )) + } +} + +// Positive tests: verify each operation succeeds and returns the expected status code. + +#[tokio::test] +async fn valid_no_auth_returns_204() { + let client = UnionClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client.valid_no_auth(None).await.unwrap(); + assert_eq!( + resp.status(), + 204, + "valid_no_auth should return 204 No Content" + ); +} + +#[tokio::test] +async fn valid_token_returns_204() { + let client = UnionClient::new( + "http://localhost:3000", + Arc::new(FakeTokenCredential::new( + "https://security.microsoft.com/.default".to_string(), + )), + None, + ) + .unwrap(); + let resp = client.valid_token(None).await.unwrap(); + assert_eq!( + resp.status(), + 204, + "valid_token should return 204 No Content" + ); +} + +// Client construction tests: verify endpoint is stored correctly. + +#[tokio::test] +async fn client_endpoint_is_stored() { + let client = UnionClient::with_no_credential("http://localhost:3000", None).unwrap(); + assert_eq!(client.endpoint().as_str(), "http://localhost:3000/"); +} + +// Negative tests: verify client rejects invalid URLs. + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = UnionClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = UnionClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/Cargo.toml b/packages/typespec-rust/test/spector/azure/client-generator-core/access/Cargo.toml new file mode 100644 index 000000000..946bd81ae --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_access" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/access_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/access_client.rs new file mode 100644 index 000000000..b1e18764c --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/access_client.rs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::{ + internal_operation::clients::AccessInternalOperationClient, + public_operation::clients::AccessPublicOperationClient, + relative_model_in_operation::clients::AccessRelativeModelInOperationClient, + shared_model_in_operation::clients::AccessSharedModelInOperationClient, +}; +use azure_core::{ + fmt::SafeDebug, + http::{ClientOptions, Pipeline, Url}, + tracing, Result, +}; + +/// Test for internal decorator. +#[tracing::client] +pub struct AccessClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`AccessClient`](AccessClient) +#[derive(Clone, Default, SafeDebug)] +pub struct AccessClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl AccessClient { + /// Creates a new AccessClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("_Specs_.Azure.ClientGenerator.Core.Access")] + pub fn with_no_credential( + endpoint: &str, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Returns a new instance of AccessInternalOperationClient. + #[tracing::subclient] + pub fn get_access_internal_operation_client(&self) -> AccessInternalOperationClient { + AccessInternalOperationClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + /// Returns a new instance of AccessPublicOperationClient. + #[tracing::subclient] + pub fn get_access_public_operation_client(&self) -> AccessPublicOperationClient { + AccessPublicOperationClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + /// Returns a new instance of AccessRelativeModelInOperationClient. + #[tracing::subclient] + pub fn get_access_relative_model_in_operation_client( + &self, + ) -> AccessRelativeModelInOperationClient { + AccessRelativeModelInOperationClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + /// Returns a new instance of AccessSharedModelInOperationClient. + #[tracing::subclient] + pub fn get_access_shared_model_in_operation_client( + &self, + ) -> AccessSharedModelInOperationClient { + AccessSharedModelInOperationClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/mod.rs new file mode 100644 index 000000000..e06308e9a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod access_client; +pub use access_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/mod.rs new file mode 100644 index 000000000..bfed45664 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/generated/mod.rs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +pub use clients::{AccessClient, AccessClientOptions}; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/access_internal_operation_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/access_internal_operation_client.rs new file mode 100644 index 000000000..377f736c7 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/access_internal_operation_client.rs @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::internal_operation::generated::models::{ + AccessInternalOperationClientInternalDecoratorInInternalOptions, + AccessInternalOperationClientNoDecoratorInInternalOptions, + AccessInternalOperationClientPublicDecoratorInInternalOptions, + InternalDecoratorModelInInternal, NoDecoratorModelInInternal, PublicDecoratorModelInInternal, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct AccessInternalOperationClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl AccessInternalOperationClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.internalDecoratorInInternal" + )] + pub(crate) async fn internal_decorator_in_internal( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path( + "/azure/client-generator-core/access/internalOperation/internalDecoratorInInternal", + ); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.noDecoratorInInternal" + )] + pub(crate) async fn no_decorator_in_internal( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path( + "/azure/client-generator-core/access/internalOperation/noDecoratorInInternal", + ); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.InternalOperation.publicDecoratorInInternal" + )] + pub(crate) async fn public_decorator_in_internal( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path( + "/azure/client-generator-core/access/internalOperation/publicDecoratorInInternal", + ); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/mod.rs new file mode 100644 index 000000000..0babc851a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod access_internal_operation_client; +pub use access_internal_operation_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/method_options.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/method_options.rs new file mode 100644 index 000000000..874ab637a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/method_options.rs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`AccessInternalOperationClient::internal_decorator_in_internal()`](crate::internal_operation::generated::clients::AccessInternalOperationClient::internal_decorator_in_internal()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessInternalOperationClientInternalDecoratorInInternalOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`AccessInternalOperationClient::no_decorator_in_internal()`](crate::internal_operation::generated::clients::AccessInternalOperationClient::no_decorator_in_internal()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessInternalOperationClientNoDecoratorInInternalOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`AccessInternalOperationClient::public_decorator_in_internal()`](crate::internal_operation::generated::clients::AccessInternalOperationClient::public_decorator_in_internal()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessInternalOperationClientPublicDecoratorInInternalOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/mod.rs new file mode 100644 index 000000000..15d835c8f --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +#[allow(clippy::module_inception)] +mod models; +pub use models::*; +pub(crate) mod method_options; +pub(crate) use method_options::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/models.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/models.rs new file mode 100644 index 000000000..d97c4d48b --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/generated/models/models.rs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// Used in an internal operation, should be generated but not exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub(crate) struct InternalDecoratorModelInInternal { + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) name: Option, +} + +/// Used in an internal operation, should be generated but not exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub(crate) struct NoDecoratorModelInInternal { + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) name: Option, +} + +/// Used in an internal operation but with public decorator, should be generated and exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub struct PublicDecoratorModelInInternal { + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/internal_operation/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/lib.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/lib.rs new file mode 100644 index 000000000..9c2442130 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/lib.rs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; +pub mod internal_operation; +pub mod public_operation; +pub mod relative_model_in_operation; +pub mod shared_model_in_operation; + +// Exercise pub(crate) client methods so dead_code warnings stay enabled +// for real issues. These methods are internal-access and have no callers +// in a test crate, but would be called by a public convenience layer in +// a real SDK. +#[allow(dead_code)] +const _: () = { + fn _touch_internal_operation() { + let client = AccessClient::with_no_credential("https://example.com", None).unwrap(); + let sub = client.get_access_internal_operation_client(); + drop(sub.internal_decorator_in_internal("x", None)); + drop(sub.no_decorator_in_internal("x", None)); + drop(sub.public_decorator_in_internal("x", None)); + } + + fn _touch_relative_model_in_operation() { + let client = AccessClient::with_no_credential("https://example.com", None).unwrap(); + let sub = client.get_access_relative_model_in_operation_client(); + drop(sub.discriminator("x", None)); + drop(sub.operation("x", None)); + } + + fn _touch_shared_model_in_operation() { + let client = AccessClient::with_no_credential("https://example.com", None).unwrap(); + let sub = client.get_access_shared_model_in_operation_client(); + drop(sub.internal("x", None)); + } +}; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/access_public_operation_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/access_public_operation_client.rs new file mode 100644 index 000000000..42a20120b --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/access_public_operation_client.rs @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::public_operation::generated::models::{ + AccessPublicOperationClientNoDecoratorInPublicOptions, + AccessPublicOperationClientPublicDecoratorInPublicOptions, NoDecoratorModelInPublic, + PublicDecoratorModelInPublic, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct AccessPublicOperationClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl AccessPublicOperationClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.noDecoratorInPublic" + )] + pub async fn no_decorator_in_public( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/access/publicOperation/noDecoratorInPublic"); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.PublicOperation.publicDecoratorInPublic" + )] + pub async fn public_decorator_in_public( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path( + "/azure/client-generator-core/access/publicOperation/publicDecoratorInPublic", + ); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/mod.rs new file mode 100644 index 000000000..5c2e2fb29 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod access_public_operation_client; +pub use access_public_operation_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/method_options.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/method_options.rs new file mode 100644 index 000000000..f7f4ee145 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/method_options.rs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`AccessPublicOperationClient::no_decorator_in_public()`](crate::public_operation::generated::clients::AccessPublicOperationClient::no_decorator_in_public()) +#[derive(Clone, Default, SafeDebug)] +pub struct AccessPublicOperationClientNoDecoratorInPublicOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`AccessPublicOperationClient::public_decorator_in_public()`](crate::public_operation::generated::clients::AccessPublicOperationClient::public_decorator_in_public()) +#[derive(Clone, Default, SafeDebug)] +pub struct AccessPublicOperationClientPublicDecoratorInPublicOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/mod.rs new file mode 100644 index 000000000..4234131b2 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +#[allow(clippy::module_inception)] +mod models; +pub use method_options::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/models.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/models.rs new file mode 100644 index 000000000..fd442db14 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/generated/models/models.rs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// Used in a public operation, should be generated and exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub struct NoDecoratorModelInPublic { + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, +} + +/// Used in a public operation, should be generated and exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub struct PublicDecoratorModelInPublic { + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/public_operation/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/access_relative_model_in_operation_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/access_relative_model_in_operation_client.rs new file mode 100644 index 000000000..45cb28e0b --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/access_relative_model_in_operation_client.rs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::relative_model_in_operation::generated::models::{ + AbstractModel, AccessRelativeModelInOperationClientDiscriminatorOptions, + AccessRelativeModelInOperationClientOperationOptions, OuterModel, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct AccessRelativeModelInOperationClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl AccessRelativeModelInOperationClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Expected query parameter: kind="real" + /// Expected response body: + /// ```json + /// { + /// "name": "Madge", + /// "kind": "real" + /// } + /// ``` + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.discriminator" + )] + pub(crate) async fn discriminator( + &self, + kind: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path( + "/azure/client-generator-core/access/relativeModelInOperation/discriminator", + ); + let mut query_builder = url.query_builder(); + query_builder.set_pair("kind", kind); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// Expected query parameter: name="Madge" + /// Expected response body: + /// ```json + /// { + /// "name": "Madge", + /// "inner": + /// { + /// "name": "Madge" + /// } + /// } + /// ``` + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.RelativeModelInOperation.operation" + )] + pub(crate) async fn operation( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/access/relativeModelInOperation/operation"); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/mod.rs new file mode 100644 index 000000000..21bd48b1c --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod access_relative_model_in_operation_client; +pub use access_relative_model_in_operation_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/method_options.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/method_options.rs new file mode 100644 index 000000000..fd1a6a6e2 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/method_options.rs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`AccessRelativeModelInOperationClient::discriminator()`](crate::relative_model_in_operation::generated::clients::AccessRelativeModelInOperationClient::discriminator()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessRelativeModelInOperationClientDiscriminatorOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`AccessRelativeModelInOperationClient::operation()`](crate::relative_model_in_operation::generated::clients::AccessRelativeModelInOperationClient::operation()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessRelativeModelInOperationClientOperationOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/mod.rs new file mode 100644 index 000000000..cafdb5be1 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/mod.rs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +pub(crate) mod method_options; +#[allow(clippy::module_inception)] +pub(crate) mod models; +mod models_impl; +pub(crate) mod unions; +mod unions_serde; +pub(crate) use method_options::*; +pub(crate) use models::*; +pub(crate) use unions::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models.rs new file mode 100644 index 000000000..7419dd974 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models.rs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// Used in internal operations, should be generated but not exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub(crate) struct InnerModel { + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) name: Option, +} + +/// Used in internal operations, should be generated but not exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub(crate) struct OuterModel { + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) inner: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) name: Option, +} + +/// Used in internal operations, should be generated but not exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +#[serde(rename = "real", tag = "kind")] +pub(crate) struct RealModel { + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) name: Option, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models_impl.rs new file mode 100644 index 000000000..f098a7e08 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/models_impl.rs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{AbstractModel, RealModel}; + +impl From for AbstractModel { + fn from(value: RealModel) -> Self { + Self::RealModel(value) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions.rs new file mode 100644 index 000000000..6fc7c522a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions.rs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::RealModel; +use azure_core::fmt::SafeDebug; +use serde::Deserialize; + +#[doc = r#"Used in internal operations, should be generated but not exported."#] +#[derive(Clone, Deserialize, SafeDebug)] +#[serde(tag = "kind")] +pub(crate) enum AbstractModel { + #[serde(rename = "real")] + RealModel(RealModel), + + #[serde(untagged)] + UnknownKind { + /// Discriminator property for AbstractModel. + kind: Option, + + name: Option, + }, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions_serde.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions_serde.rs new file mode 100644 index 000000000..e75bfd282 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/generated/models/unions_serde.rs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{AbstractModel, RealModel}; +use serde::{Serialize, Serializer}; + +impl Serialize for AbstractModel { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + AbstractModel::RealModel(real_model) => RealModel::serialize(real_model, serializer), + AbstractModel::UnknownKind { kind, name } => { + #[derive(Serialize)] + struct UnknownKind<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + kind: &'a Option, + #[serde(skip_serializing_if = "Option::is_none")] + name: &'a Option, + } + UnknownKind::serialize(&UnknownKind { kind, name }, serializer) + } + } + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/relative_model_in_operation/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/access_shared_model_in_operation_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/access_shared_model_in_operation_client.rs new file mode 100644 index 000000000..423714d1c --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/access_shared_model_in_operation_client.rs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::shared_model_in_operation::generated::models::{ + AccessSharedModelInOperationClientInternalOptions, + AccessSharedModelInOperationClientPublicOptions, SharedModel, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct AccessSharedModelInOperationClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl AccessSharedModelInOperationClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.Access.SharedModelInOperation.internal" + )] + pub(crate) async fn internal( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/access/sharedModelInOperation/internal"); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("_Specs_.Azure.ClientGenerator.Core.Access.SharedModelInOperation.public")] + pub async fn public( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/access/sharedModelInOperation/public"); + let mut query_builder = url.query_builder(); + query_builder.set_pair("name", name); + query_builder.build(); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/mod.rs new file mode 100644 index 000000000..6a9bd1a45 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod access_shared_model_in_operation_client; +pub use access_shared_model_in_operation_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/method_options.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/method_options.rs new file mode 100644 index 000000000..8e29e4baf --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/method_options.rs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`AccessSharedModelInOperationClient::internal()`](crate::shared_model_in_operation::generated::clients::AccessSharedModelInOperationClient::internal()) +#[derive(Clone, Default, SafeDebug)] +pub(crate) struct AccessSharedModelInOperationClientInternalOptions<'a> { + /// Allows customization of the method call. + pub(crate) method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`AccessSharedModelInOperationClient::public()`](crate::shared_model_in_operation::generated::clients::AccessSharedModelInOperationClient::public()) +#[derive(Clone, Default, SafeDebug)] +pub struct AccessSharedModelInOperationClientPublicOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/mod.rs new file mode 100644 index 000000000..4234131b2 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +#[allow(clippy::module_inception)] +mod models; +pub use method_options::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/models.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/models.rs new file mode 100644 index 000000000..f9ff6c778 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/generated/models/models.rs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// Used by both public and internal operation. It should be generated and exported. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[non_exhaustive] +pub struct SharedModel { + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/src/shared_model_in_operation/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/access/tests/access_public_operation_client_test.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/access/tests/access_public_operation_client_test.rs new file mode 100644 index 000000000..ad050a253 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/access/tests/access_public_operation_client_test.rs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_access::{ + public_operation::models::{NoDecoratorModelInPublic, PublicDecoratorModelInPublic}, + shared_model_in_operation::models::SharedModel, + AccessClient, +}; + +// --- Public operation tests --- + +#[tokio::test] +async fn no_decorator_in_public_returns_200_with_name() { + let client = AccessClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_access_public_operation_client() + .no_decorator_in_public("sample", None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "no_decorator_in_public should return 200 OK" + ); + let model: NoDecoratorModelInPublic = resp.into_model().unwrap(); + assert_eq!( + model.name, + Some("sample".to_string()), + "name should match the query parameter" + ); +} + +#[tokio::test] +async fn public_decorator_in_public_returns_200_with_name() { + let client = AccessClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_access_public_operation_client() + .public_decorator_in_public("sample", None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "public_decorator_in_public should return 200 OK" + ); + let model: PublicDecoratorModelInPublic = resp.into_model().unwrap(); + assert_eq!( + model.name, + Some("sample".to_string()), + "name should match the query parameter" + ); +} + +// --- Shared model in operation tests (public method only) --- + +#[tokio::test] +async fn shared_model_public_returns_200_with_name() { + let client = AccessClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_access_shared_model_in_operation_client() + .public("sample", None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "shared model public should return 200 OK" + ); + let model: SharedModel = resp.into_model().unwrap(); + assert_eq!( + model.name, + Some("sample".to_string()), + "name should match the query parameter" + ); +} + +// --- Client construction tests --- + +#[tokio::test] +async fn client_endpoint_is_stored() { + let client = AccessClient::with_no_credential("http://localhost:3000", None).unwrap(); + assert_eq!(client.endpoint().as_str(), "http://localhost:3000/"); +} + +// --- Negative tests --- + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = AccessClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = AccessClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/header/src/generated/clients/header_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/header/src/generated/clients/header_client.rs index 8a7ab6202..67d4d5323 100644 --- a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/header/src/generated/clients/header_client.rs +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/header/src/generated/clients/header_client.rs @@ -102,7 +102,6 @@ impl HeaderClient { } /// Default value for [`HeaderClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2025-01-01"; impl Default for HeaderClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/path/src/generated/clients/path_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/path/src/generated/clients/path_client.rs index 53df9873a..97577472c 100644 --- a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/path/src/generated/clients/path_client.rs +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/path/src/generated/clients/path_client.rs @@ -100,7 +100,6 @@ impl PathClient { } /// Default value for [`PathClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2025-01-01"; impl Default for PathClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/query/src/generated/clients/query_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/query/src/generated/clients/query_client.rs index 778eb618f..6cc9d03b7 100644 --- a/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/query/src/generated/clients/query_client.rs +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/api-version/query/src/generated/clients/query_client.rs @@ -101,7 +101,6 @@ impl QueryClient { } /// Default value for [`QueryClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "2025-01-01"; impl Default for QueryClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/Cargo.toml b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/Cargo.toml new file mode 100644 index 000000000..1882cb9a2 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_clientdefault" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/client_default_value_client.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/client_default_value_client.rs new file mode 100644 index 000000000..9027f670b --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/client_default_value_client.rs @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::models::{ + ClientDefaultValueClientGetHeaderParameterOptions, + ClientDefaultValueClientGetOperationParameterOptions, + ClientDefaultValueClientGetPathParameterOptions, + ClientDefaultValueClientPutModelPropertyOptions, ModelWithDefaultValues, +}; +use azure_core::{ + error::CheckSuccessOptions, + fmt::SafeDebug, + http::{ + ClientOptions, Method, NoFormat, Pipeline, PipelineSendOptions, Request, RequestContent, + Response, Url, UrlExt, + }, + tracing, Result, +}; + +/// Test for `@clientDefaultValue` decorator. +#[tracing::client] +pub struct ClientDefaultValueClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`ClientDefaultValueClient`](ClientDefaultValueClient) +#[derive(Clone, Default, SafeDebug)] +pub struct ClientDefaultValueClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl ClientDefaultValueClient { + /// Creates a new ClientDefaultValueClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("_Specs_.Azure.ClientGenerator.Core.ClientDefaultValue")] + pub fn with_no_credential( + endpoint: &str, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("_Specs_.Azure.ClientGenerator.Core.ClientDefaultValue.getHeaderParameter")] + pub async fn get_header_parameter( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/client-default-value/header-parameter"); + let mut request = Request::new(url, Method::Get); + if let Some(accept) = options.accept.as_ref() { + request.insert_header("accept", accept); + } + if let Some(custom_header) = options.custom_header.as_ref() { + request.insert_header("x-custom-header", custom_header); + } + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function( + "_Specs_.Azure.ClientGenerator.Core.ClientDefaultValue.getOperationParameter" + )] + pub async fn get_operation_parameter( + &self, + name: &str, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/client-default-value/operation-parameter"); + let mut query_builder = url.query_builder(); + if let Some(format) = options.format.as_ref() { + query_builder.set_pair("format", format); + } + query_builder.set_pair("name", name); + if let Some(page_size) = options.page_size { + query_builder.set_pair("pageSize", page_size.to_string()); + } + query_builder.build(); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("_Specs_.Azure.ClientGenerator.Core.ClientDefaultValue.getPathParameter")] + pub async fn get_path_parameter( + &self, + segment1: &str, + segment2: &str, + options: Option>, + ) -> Result> { + if segment1.is_empty() { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + "parameter segment1 cannot be empty", + )); + } + if segment2.is_empty() { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + "parameter segment2 cannot be empty", + )); + } + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/azure/client-generator-core/client-default-value/path-parameter/{segment1}/{segment2}"); + path = path.replace("{segment1}", segment1); + path = path.replace("{segment2}", segment2); + url.append_path(&path); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("_Specs_.Azure.ClientGenerator.Core.ClientDefaultValue.putModelProperty")] + pub async fn put_model_property( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/azure/client-generator-core/client-default-value/model-property"); + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/mod.rs new file mode 100644 index 000000000..9fc5e32b4 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod client_default_value_client; +pub use client_default_value_client::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/mod.rs new file mode 100644 index 000000000..1f9a1700d --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{ClientDefaultValueClient, ClientDefaultValueClientOptions}; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/method_options.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/method_options.rs new file mode 100644 index 000000000..93254c41d --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/method_options.rs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`ClientDefaultValueClient::get_header_parameter()`](crate::generated::clients::ClientDefaultValueClient::get_header_parameter()) +#[derive(Clone, Default, SafeDebug)] +pub struct ClientDefaultValueClientGetHeaderParameterOptions<'a> { + pub accept: Option, + + pub custom_header: Option, + + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ClientDefaultValueClient::get_operation_parameter()`](crate::generated::clients::ClientDefaultValueClient::get_operation_parameter()) +#[derive(Clone, Default, SafeDebug)] +pub struct ClientDefaultValueClientGetOperationParameterOptions<'a> { + pub format: Option, + + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, + + pub page_size: Option, +} + +/// Options to be passed to [`ClientDefaultValueClient::get_path_parameter()`](crate::generated::clients::ClientDefaultValueClient::get_path_parameter()) +#[derive(Clone, Default, SafeDebug)] +pub struct ClientDefaultValueClientGetPathParameterOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ClientDefaultValueClient::put_model_property()`](crate::generated::clients::ClientDefaultValueClient::put_model_property()) +#[derive(Clone, Default, SafeDebug)] +pub struct ClientDefaultValueClientPutModelPropertyOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/mod.rs new file mode 100644 index 000000000..5dfb21b69 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/mod.rs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +#[allow(clippy::module_inception)] +mod models; +mod models_impl; +pub use method_options::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models.rs new file mode 100644 index 000000000..dd6073da6 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models.rs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// Model with client default values on properties. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct ModelWithDefaultValues { + /// Name property with no default value. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + + /// Retry property with client default value of true. + #[serde(skip_serializing_if = "Option::is_none")] + pub retry: Option, + + /// Tier property with client default value of 'standard'. + #[serde(skip_serializing_if = "Option::is_none")] + pub tier: Option, + + /// Timeout property with client default value of 30. + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models_impl.rs new file mode 100644 index 000000000..2cc631c2f --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/generated/models/models_impl.rs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::ModelWithDefaultValues; +use azure_core::{http::RequestContent, json::to_json, Result}; + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: ModelWithDefaultValues) -> Result { + Ok(to_json(&value)?.into()) + } +} diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/lib.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/lib.rs new file mode 100644 index 000000000..cc784e401 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/tests/client_default_value_client_test.rs b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/tests/client_default_value_client_test.rs new file mode 100644 index 000000000..fef402086 --- /dev/null +++ b/packages/typespec-rust/test/spector/azure/client-generator-core/client-default-value/tests/client_default_value_client_test.rs @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_clientdefault::{ + models::{ + ClientDefaultValueClientGetHeaderParameterOptions, + ClientDefaultValueClientGetOperationParameterOptions, ModelWithDefaultValues, + }, + ClientDefaultValueClient, +}; + +// --- Header parameter tests --- + +#[tokio::test] +async fn get_header_parameter_returns_204() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let options = ClientDefaultValueClientGetHeaderParameterOptions { + accept: Some("application/json;odata.metadata=none".to_string()), + custom_header: Some("default-value".to_string()), + ..Default::default() + }; + let resp = client.get_header_parameter(Some(options)).await.unwrap(); + assert_eq!( + resp.status(), + 204, + "get_header_parameter should return 204 No Content" + ); +} + +#[tokio::test] +async fn get_header_parameter_with_custom_accept() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let options = ClientDefaultValueClientGetHeaderParameterOptions { + accept: Some("application/json;odata.metadata=none".to_string()), + custom_header: Some("default-value".to_string()), + ..Default::default() + }; + let resp = client.get_header_parameter(Some(options)).await.unwrap(); + assert_eq!(resp.status(), 204); +} + +#[tokio::test] +async fn get_header_parameter_with_custom_header() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let options = ClientDefaultValueClientGetHeaderParameterOptions { + accept: Some("application/json;odata.metadata=none".to_string()), + custom_header: Some("default-value".to_string()), + ..Default::default() + }; + let resp = client.get_header_parameter(Some(options)).await.unwrap(); + assert_eq!(resp.status(), 204); +} + +// --- Operation parameter tests --- + +#[tokio::test] +async fn get_operation_parameter_returns_204() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let options = ClientDefaultValueClientGetOperationParameterOptions { + format: Some("json".to_string()), + page_size: Some(10), + ..Default::default() + }; + let resp = client + .get_operation_parameter("test", Some(options)) + .await + .unwrap(); + assert_eq!( + resp.status(), + 204, + "get_operation_parameter should return 204 No Content" + ); +} + +#[tokio::test] +async fn get_operation_parameter_with_optional_params() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let options = ClientDefaultValueClientGetOperationParameterOptions { + format: Some("json".to_string()), + page_size: Some(10), + ..Default::default() + }; + let resp = client + .get_operation_parameter("test", Some(options)) + .await + .unwrap(); + assert_eq!(resp.status(), 204); +} + +// --- Path parameter tests --- + +#[tokio::test] +async fn get_path_parameter_returns_204() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_path_parameter("default-segment1", "segment2", None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 204, + "get_path_parameter should return 204 No Content" + ); +} + +#[tokio::test] +async fn get_path_parameter_rejects_empty_segment1() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let result = client.get_path_parameter("", "segment2", None).await; + assert!(result.is_err(), "empty segment1 should be rejected"); +} + +#[tokio::test] +async fn get_path_parameter_rejects_empty_segment2() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let result = client + .get_path_parameter("default-segment1", "", None) + .await; + assert!(result.is_err(), "empty segment2 should be rejected"); +} + +#[tokio::test] +async fn get_path_parameter_rejects_both_empty() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let result = client.get_path_parameter("", "", None).await; + assert!(result.is_err(), "both empty segments should be rejected"); +} + +// --- Model property tests --- + +#[tokio::test] +async fn put_model_property_returns_200_with_matching_values() { + let client = + ClientDefaultValueClient::with_no_credential("http://localhost:3000", None).unwrap(); + let input = ModelWithDefaultValues { + name: Some("test".to_string()), + retry: None, + tier: None, + timeout: None, + }; + let resp = client + .put_model_property(input.try_into().unwrap(), None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "put_model_property should return 200 OK" + ); + let output: ModelWithDefaultValues = resp.into_model().unwrap(); + assert_eq!(output.name, Some("test".to_string()), "name should match"); + assert_eq!(output.retry, Some(true), "retry should have default value"); + assert_eq!( + output.tier, + Some("standard".to_string()), + "tier should have default value" + ); + assert_eq!( + output.timeout, + Some(30), + "timeout should have default value" + ); +} + +// --- Client construction negative tests --- + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = ClientDefaultValueClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = ClientDefaultValueClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/azure/core/basic/src/generated/clients/basic_client.rs b/packages/typespec-rust/test/spector/azure/core/basic/src/generated/clients/basic_client.rs index 769c5c875..f2be5a48a 100644 --- a/packages/typespec-rust/test/spector/azure/core/basic/src/generated/clients/basic_client.rs +++ b/packages/typespec-rust/test/spector/azure/core/basic/src/generated/clients/basic_client.rs @@ -422,7 +422,6 @@ impl BasicClient { } /// Default value for [`BasicClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for BasicClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/core/lro/rpc/src/generated/clients/rpc_client.rs b/packages/typespec-rust/test/spector/azure/core/lro/rpc/src/generated/clients/rpc_client.rs index 219e32475..debd3c4bd 100644 --- a/packages/typespec-rust/test/spector/azure/core/lro/rpc/src/generated/clients/rpc_client.rs +++ b/packages/typespec-rust/test/spector/azure/core/lro/rpc/src/generated/clients/rpc_client.rs @@ -239,7 +239,6 @@ impl RpcClient { } /// Default value for [`RpcClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for RpcClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/core/lro/standard/src/generated/clients/standard_client.rs b/packages/typespec-rust/test/spector/azure/core/lro/standard/src/generated/clients/standard_client.rs index f26bace4b..1a5197f65 100644 --- a/packages/typespec-rust/test/spector/azure/core/lro/standard/src/generated/clients/standard_client.rs +++ b/packages/typespec-rust/test/spector/azure/core/lro/standard/src/generated/clients/standard_client.rs @@ -563,7 +563,6 @@ impl StandardClient { } /// Default value for [`StandardClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for StandardClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/core/page/src/generated/clients/page_client.rs b/packages/typespec-rust/test/spector/azure/core/page/src/generated/clients/page_client.rs index 0871edd96..20620bd0f 100644 --- a/packages/typespec-rust/test/spector/azure/core/page/src/generated/clients/page_client.rs +++ b/packages/typespec-rust/test/spector/azure/core/page/src/generated/clients/page_client.rs @@ -425,7 +425,6 @@ impl PageClient { } /// Default value for [`PageClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for PageClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/core/traits/src/generated/clients/traits_client.rs b/packages/typespec-rust/test/spector/azure/core/traits/src/generated/clients/traits_client.rs index 2f676960c..3a949b270 100644 --- a/packages/typespec-rust/test/spector/azure/core/traits/src/generated/clients/traits_client.rs +++ b/packages/typespec-rust/test/spector/azure/core/traits/src/generated/clients/traits_client.rs @@ -236,7 +236,6 @@ impl TraitsClient { } /// Default value for [`TraitsClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for TraitsClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/example/basic/src/generated/clients/azure_example_client.rs b/packages/typespec-rust/test/spector/azure/example/basic/src/generated/clients/azure_example_client.rs index 10035d49c..bde466fc6 100644 --- a/packages/typespec-rust/test/spector/azure/example/basic/src/generated/clients/azure_example_client.rs +++ b/packages/typespec-rust/test/spector/azure/example/basic/src/generated/clients/azure_example_client.rs @@ -114,7 +114,6 @@ impl AzureExampleClient { } /// Default value for [`AzureExampleClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for AzureExampleClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/common-properties/src/generated/clients/common_properties_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/common-properties/src/generated/clients/common_properties_client.rs index b2261368f..c8c375dd9 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/common-properties/src/generated/clients/common_properties_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/common-properties/src/generated/clients/common_properties_client.rs @@ -110,7 +110,6 @@ impl CommonPropertiesClient { } /// Default value for [`CommonPropertiesClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for CommonPropertiesClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/large-header/src/generated/clients/large_header_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/large-header/src/generated/clients/large_header_client.rs index b3ae32556..31b4e17a3 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/large-header/src/generated/clients/large_header_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/large-header/src/generated/clients/large_header_client.rs @@ -95,7 +95,6 @@ impl LargeHeaderClient { } /// Default value for [`LargeHeaderClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for LargeHeaderClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/method-subscription-id/src/generated/clients/method_subscription_id_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/method-subscription-id/src/generated/clients/method_subscription_id_client.rs index 09ee515e7..8ef711758 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/method-subscription-id/src/generated/clients/method_subscription_id_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/method-subscription-id/src/generated/clients/method_subscription_id_client.rs @@ -125,7 +125,6 @@ impl MethodSubscriptionIdClient { } /// Default value for [`MethodSubscriptionIdClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for MethodSubscriptionIdClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/non-resource/src/generated/clients/non_resource_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/non-resource/src/generated/clients/non_resource_client.rs index 9d6ca813f..819047c92 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/non-resource/src/generated/clients/non_resource_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/non-resource/src/generated/clients/non_resource_client.rs @@ -97,7 +97,6 @@ impl NonResourceClient { } /// Default value for [`NonResourceClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for NonResourceClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/operation-templates/src/generated/clients/operation_templates_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/operation-templates/src/generated/clients/operation_templates_client.rs index e94d984de..6a3e15f77 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/operation-templates/src/generated/clients/operation_templates_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/operation-templates/src/generated/clients/operation_templates_client.rs @@ -146,7 +146,6 @@ impl OperationTemplatesClient { } /// Default value for [`OperationTemplatesClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for OperationTemplatesClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/resource-manager/resources/src/generated/clients/resources_client.rs b/packages/typespec-rust/test/spector/azure/resource-manager/resources/src/generated/clients/resources_client.rs index fb73e68b3..01737c30d 100644 --- a/packages/typespec-rust/test/spector/azure/resource-manager/resources/src/generated/clients/resources_client.rs +++ b/packages/typespec-rust/test/spector/azure/resource-manager/resources/src/generated/clients/resources_client.rs @@ -141,7 +141,6 @@ impl ResourcesClient { } /// Default value for [`ResourcesClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2023-12-01-preview"; impl Default for ResourcesClientOptions { diff --git a/packages/typespec-rust/test/spector/azure/versioning/previewVersion/src/generated/clients/preview_version_client.rs b/packages/typespec-rust/test/spector/azure/versioning/previewVersion/src/generated/clients/preview_version_client.rs index aaa0494c9..17840956a 100644 --- a/packages/typespec-rust/test/spector/azure/versioning/previewVersion/src/generated/clients/preview_version_client.rs +++ b/packages/typespec-rust/test/spector/azure/versioning/previewVersion/src/generated/clients/preview_version_client.rs @@ -207,7 +207,6 @@ impl PreviewVersionClient { } /// Default value for [`PreviewVersionClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2024-12-01-preview"; impl Default for PreviewVersionClientOptions { diff --git a/packages/typespec-rust/test/spector/documentation/Cargo.toml b/packages/typespec-rust/test/spector/documentation/Cargo.toml new file mode 100644 index 000000000..0ecf33010 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_documentation" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/documentation/src/generated/clients/documentation_client.rs b/packages/typespec-rust/test/spector/documentation/src/generated/clients/documentation_client.rs new file mode 100644 index 000000000..4bac81154 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/generated/clients/documentation_client.rs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::{ + lists::clients::DocumentationListsClient, + text_formatting::clients::DocumentationTextFormattingClient, +}; +use azure_core::{ + fmt::SafeDebug, + http::{ClientOptions, Pipeline, Url}, + tracing, Result, +}; + +/// Illustrates documentation generation and formatting features +#[tracing::client] +pub struct DocumentationClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`DocumentationClient`](DocumentationClient) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl DocumentationClient { + /// Creates a new DocumentationClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Documentation")] + pub fn with_no_credential( + endpoint: &str, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Returns a new instance of DocumentationListsClient. + #[tracing::subclient] + pub fn get_documentation_lists_client(&self) -> DocumentationListsClient { + DocumentationListsClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + /// Returns a new instance of DocumentationTextFormattingClient. + #[tracing::subclient] + pub fn get_documentation_text_formatting_client(&self) -> DocumentationTextFormattingClient { + DocumentationTextFormattingClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/documentation/src/generated/clients/mod.rs new file mode 100644 index 000000000..aa8f9269f --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod documentation_client; +pub use documentation_client::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/generated/mod.rs b/packages/typespec-rust/test/spector/documentation/src/generated/mod.rs new file mode 100644 index 000000000..f233d5b48 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/generated/mod.rs @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +pub use clients::{DocumentationClient, DocumentationClientOptions}; diff --git a/packages/typespec-rust/test/spector/documentation/src/lib.rs b/packages/typespec-rust/test/spector/documentation/src/lib.rs new file mode 100644 index 000000000..a36e54135 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lib.rs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; +pub mod lists; +pub mod text_formatting; diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/documentation_lists_client.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/documentation_lists_client.rs new file mode 100644 index 000000000..b5ce9ca1d --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/documentation_lists_client.rs @@ -0,0 +1,143 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::lists::generated::models::{ + BulletPointsModel, BulletPointsModelRequest, DocumentationListsClientBulletPointsModelOptions, + DocumentationListsClientBulletPointsOpOptions, DocumentationListsClientNumberedOptions, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{ + Method, NoFormat, Pipeline, PipelineSendOptions, Request, RequestContent, Response, Url, + UrlExt, + }, + tracing, Result, +}; + +#[tracing::client] +pub struct DocumentationListsClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl DocumentationListsClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.Lists.bulletPointsModel")] + pub async fn bullet_points_model( + &self, + input: BulletPointsModel, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/lists/bullet-points/model"); + let mut request = Request::new(url, Method::Post); + request.insert_header("content-type", "application/json"); + let body: RequestContent = + BulletPointsModelRequest { input }.try_into()?; + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// This tests: + /// - Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points + /// within documentation comments. It should properly indent the wrapped lines. + /// - Another bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved + /// when the text wraps onto multiple lines in the generated documentation. + /// - Third bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping + /// and formatting are correctly applied in the output. + /// - Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting + /// and is long enough to test the wrapping behavior in such cases. + /// - **Bold bullet point**: A bullet point that is entirely bolded. This point is also made lengthy to observe how the bold + /// formatting is maintained across wrapped lines. + /// - *Italic bullet point*: A bullet point that is entirely italicized. This final point is extended to verify that italic + /// formatting is correctly applied even when the text spans multiple lines. + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.Lists.bulletPointsOp")] + pub async fn bullet_points_op( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/lists/bullet-points/op"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// Steps to follow: + /// 1. First step with **important** note + /// 2. Second step with *emphasis* + /// 3. Third step combining **bold** and *italic* + /// 4. **Final step**: Review all steps for *accuracy*. + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.Lists.numbered")] + pub async fn numbered( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/lists/numbered"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/mod.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/mod.rs new file mode 100644 index 000000000..4f86c20f8 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod documentation_lists_client; +pub use documentation_lists_client::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/mod.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums.rs new file mode 100644 index 000000000..93ef96d9a --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums.rs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// This tests really long bullet points in enum documentation to see how wrapping and formatting are handled. This should +/// wrap around correctly and maintain proper indentation for each line. +/// - Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points +/// within documentation comments. It should properly indent the wrapped lines. +/// - Another bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved +/// when the text wraps onto multiple lines in the generated documentation. +/// - Third bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping +/// and formatting are correctly applied in the output. +/// - Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting +/// and is long enough to test the wrapping behavior in such cases. +/// - **Bold bullet point**: A bullet point that is entirely bolded. This point is also made lengthy to observe how the bold +/// formatting is maintained across wrapped lines. +/// - *Italic bullet point*: A bullet point that is entirely italicized. This final point is extended to verify that italic +/// formatting is correctly applied even when the text spans multiple lines. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum BulletPointsEnum { + /// Bullet point with **bold text**. This line is intentionally long to test text wrapping in bullet points within enum documentation + /// comments. It should properly indent the wrapped lines. + /// - **One**: one. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + /// - **Two**: two. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + Bold, + + /// Bullet point with *italic text*. This line is intentionally long to test text wrapping in bullet points within enum documentation + /// comments. It should properly indent the wrapped lines. + /// - *One*: one. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + /// - *Two*: two. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + Italic, + + /// Simple bullet point. This line is intentionally long to test text wrapping in bullet points within enum documentation + /// comments. It should properly indent the wrapped lines. + /// - One: one. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + /// - Two: two. This line is intentionally long to test text wrapping in bullet points within enum documentation comments. + /// It should properly indent the wrapped lines. + Simple, +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_impl.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_impl.rs new file mode 100644 index 000000000..ab0df9369 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_impl.rs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::BulletPointsEnum; +use azure_core::error::{Error, ErrorKind}; +use std::{ + convert::AsRef, + fmt::{Display, Formatter}, + str::FromStr, +}; + +impl FromStr for BulletPointsEnum { + type Err = Error; + fn from_str(s: &str) -> ::core::result::Result::Err> { + Ok(match s { + "Bold" => BulletPointsEnum::Bold, + "Italic" => BulletPointsEnum::Italic, + "Simple" => BulletPointsEnum::Simple, + _ => { + return Err(Error::with_message_fn(ErrorKind::DataConversion, || { + format!("unknown variant of BulletPointsEnum found: \"{s}\"") + })) + } + }) + } +} + +impl AsRef for BulletPointsEnum { + fn as_ref(&self) -> &str { + match self { + BulletPointsEnum::Bold => "Bold", + BulletPointsEnum::Italic => "Italic", + BulletPointsEnum::Simple => "Simple", + } + } +} + +impl Display for BulletPointsEnum { + fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result { + match self { + BulletPointsEnum::Bold => Display::fmt("Bold", f), + BulletPointsEnum::Italic => Display::fmt("Italic", f), + BulletPointsEnum::Simple => Display::fmt("Simple", f), + } + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_serde.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_serde.rs new file mode 100644 index 000000000..53969408e --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/enums_serde.rs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::BulletPointsEnum; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +impl<'de> Deserialize<'de> for BulletPointsEnum { + fn deserialize(deserializer: D) -> ::core::result::Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + s.parse().map_err(serde::de::Error::custom) + } +} + +impl Serialize for BulletPointsEnum { + fn serialize(&self, s: S) -> ::core::result::Result + where + S: Serializer, + { + s.serialize_str(self.as_ref()) + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/method_options.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/method_options.rs new file mode 100644 index 000000000..4210dfe43 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/method_options.rs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`DocumentationListsClient::bullet_points_model()`](crate::lists::generated::clients::DocumentationListsClient::bullet_points_model()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationListsClientBulletPointsModelOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`DocumentationListsClient::bullet_points_op()`](crate::lists::generated::clients::DocumentationListsClient::bullet_points_op()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationListsClientBulletPointsOpOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`DocumentationListsClient::numbered()`](crate::lists::generated::clients::DocumentationListsClient::numbered()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationListsClientNumberedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/mod.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/mod.rs new file mode 100644 index 000000000..b59467d7e --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod enums; +mod enums_impl; +mod enums_serde; +mod method_options; +#[allow(clippy::module_inception)] +mod models; +mod models_impl; +pub use enums::*; +pub use method_options::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models.rs new file mode 100644 index 000000000..417b86070 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models.rs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::BulletPointsEnum; +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// This tests: +/// - Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points +/// within documentation comments. It should properly indent the wrapped lines. +/// - Another bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved +/// when the text wraps onto multiple lines in the generated documentation. +/// - Third bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping +/// and formatting are correctly applied in the output. +/// - Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting +/// and is long enough to test the wrapping behavior in such cases. +/// - **Bold bullet point**: A bullet point that is entirely bolded. This point is also made lengthy to observe how the bold +/// formatting is maintained across wrapped lines. +/// - *Italic bullet point*: A bullet point that is entirely italicized. This final point is extended to verify that italic +/// formatting is correctly applied even when the text spans multiple lines. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct BulletPointsModel { + /// This property uses an enum with bullet point documentation. The enum documentation includes various formatting styles + /// to test rendering. The styles are: + /// - Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points + /// within documentation comments. It should properly indent the wrapped lines. + /// - Bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved + /// when the text wraps onto multiple + /// - Bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping and + /// formatting are correctly applied in the output. + /// - Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting + /// and is long enough to test the wrapping behavior in such cases. + /// - **Bold bullet point** + /// - *Italic bullet point* + #[serde(skip_serializing_if = "Option::is_none")] + pub prop: Option, +} + +#[derive(Clone, Deserialize, SafeDebug, Serialize)] +pub(crate) struct BulletPointsModelRequest { + pub(crate) input: BulletPointsModel, +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models_impl.rs new file mode 100644 index 000000000..b72583c7b --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/generated/models/models_impl.rs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::BulletPointsModelRequest; +use azure_core::{http::RequestContent, json::to_json, Result}; + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: BulletPointsModelRequest) -> Result { + Ok(to_json(&value)?.into()) + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/lists/mod.rs b/packages/typespec-rust/test/spector/documentation/src/lists/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/lists/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/documentation_text_formatting_client.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/documentation_text_formatting_client.rs new file mode 100644 index 000000000..2baf5813f --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/documentation_text_formatting_client.rs @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::text_formatting::generated::models::{ + DocumentationTextFormattingClientBoldTextOptions, + DocumentationTextFormattingClientCombinedFormattingOptions, + DocumentationTextFormattingClientItalicTextOptions, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, NoFormat, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct DocumentationTextFormattingClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl DocumentationTextFormattingClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// This is **bold text** in the middle of a sentence. + /// This is a sentence with **multiple bold** sections and **another bold** section. + /// **This entire sentence is bold.** + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.TextFormatting.boldText")] + pub async fn bold_text( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/text-formatting/bold"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// This sentence has **bold**, *italic*, and ***bold italic*** text. + /// You can also combine them like **bold with *italic inside* bold**. + /// Or *italic with **bold inside** italic*. + /// This is a sentence with **bold**, *italic*, and ***bold italic*** text. + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.TextFormatting.combinedFormatting")] + pub async fn combined_formatting( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/text-formatting/combined"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// This is *italic text* in the middle of a sentence. + /// This is a sentence with *multiple italic* sections and *another italic* section. + /// *This entire sentence is italic.* + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Documentation.TextFormatting.italicText")] + pub async fn italic_text( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/documentation/text-formatting/italic"); + let mut request = Request::new(url, Method::Get); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/mod.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/mod.rs new file mode 100644 index 000000000..0e68442dd --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod documentation_text_formatting_client; +pub use documentation_text_formatting_client::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/mod.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/method_options.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/method_options.rs new file mode 100644 index 000000000..2b48463f4 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/method_options.rs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`DocumentationTextFormattingClient::bold_text()`](crate::text_formatting::generated::clients::DocumentationTextFormattingClient::bold_text()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationTextFormattingClientBoldTextOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`DocumentationTextFormattingClient::combined_formatting()`](crate::text_formatting::generated::clients::DocumentationTextFormattingClient::combined_formatting()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationTextFormattingClientCombinedFormattingOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`DocumentationTextFormattingClient::italic_text()`](crate::text_formatting::generated::clients::DocumentationTextFormattingClient::italic_text()) +#[derive(Clone, Default, SafeDebug)] +pub struct DocumentationTextFormattingClientItalicTextOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/mod.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/mod.rs new file mode 100644 index 000000000..3e484b1ed --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/generated/models/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +pub use method_options::*; diff --git a/packages/typespec-rust/test/spector/documentation/src/text_formatting/mod.rs b/packages/typespec-rust/test/spector/documentation/src/text_formatting/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/src/text_formatting/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/documentation/tests/documentation_lists_client_test.rs b/packages/typespec-rust/test/spector/documentation/tests/documentation_lists_client_test.rs new file mode 100644 index 000000000..4045151ec --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/tests/documentation_lists_client_test.rs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_documentation::{ + lists::models::{BulletPointsEnum, BulletPointsModel}, + DocumentationClient, +}; + +// Positive tests: call each Lists operation and verify status codes. + +#[tokio::test] +async fn bullet_points_model_returns_200() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let input = BulletPointsModel { + prop: Some(BulletPointsEnum::Simple), + }; + let resp = client + .get_documentation_lists_client() + .bullet_points_model(input, None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "bullet_points_model should return 200 OK" + ); +} + +#[tokio::test] +async fn bullet_points_model_with_enum_prop() { + // Verify the model can be sent with an enum value set. + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let input = BulletPointsModel { + prop: Some(BulletPointsEnum::Simple), + }; + let resp = client + .get_documentation_lists_client() + .bullet_points_model(input, None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 200, + "bullet_points_model with enum prop should return 200 OK" + ); +} + +// Model construction tests: verify each enum variant can be created. + +#[tokio::test] +async fn bullet_points_model_with_bold_enum() { + let model = BulletPointsModel { + prop: Some(BulletPointsEnum::Bold), + }; + assert_eq!(model.prop, Some(BulletPointsEnum::Bold)); +} + +#[tokio::test] +async fn bullet_points_model_with_italic_enum() { + let model = BulletPointsModel { + prop: Some(BulletPointsEnum::Italic), + }; + assert_eq!(model.prop, Some(BulletPointsEnum::Italic)); +} + +#[tokio::test] +async fn bullet_points_op_returns_204() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_documentation_lists_client() + .bullet_points_op(None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 204, + "bullet_points_op should return 204 No Content" + ); +} + +#[tokio::test] +async fn numbered_returns_204() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_documentation_lists_client() + .numbered(None) + .await + .unwrap(); + assert_eq!(resp.status(), 204, "numbered should return 204 No Content"); +} diff --git a/packages/typespec-rust/test/spector/documentation/tests/documentation_text_formatting_client_test.rs b/packages/typespec-rust/test/spector/documentation/tests/documentation_text_formatting_client_test.rs new file mode 100644 index 000000000..f1b6d2694 --- /dev/null +++ b/packages/typespec-rust/test/spector/documentation/tests/documentation_text_formatting_client_test.rs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_documentation::DocumentationClient; + +// Positive tests: call each TextFormatting operation and verify status codes. + +#[tokio::test] +async fn bold_text_returns_204() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_documentation_text_formatting_client() + .bold_text(None) + .await + .unwrap(); + assert_eq!(resp.status(), 204, "bold_text should return 204 No Content"); +} + +#[tokio::test] +async fn italic_text_returns_204() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_documentation_text_formatting_client() + .italic_text(None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 204, + "italic_text should return 204 No Content" + ); +} + +#[tokio::test] +async fn combined_formatting_returns_204() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client + .get_documentation_text_formatting_client() + .combined_formatting(None) + .await + .unwrap(); + assert_eq!( + resp.status(), + 204, + "combined_formatting should return 204 No Content" + ); +} + +// Client construction tests: verify endpoint and sub-client access. + +#[tokio::test] +async fn client_endpoint_is_stored() { + let client = DocumentationClient::with_no_credential("http://localhost:3000", None).unwrap(); + assert_eq!(client.endpoint().as_str(), "http://localhost:3000/"); +} + +// Negative tests: verify client rejects invalid URLs. + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = DocumentationClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = DocumentationClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/encode/array/Cargo.toml b/packages/typespec-rust/test/spector/encode/array/Cargo.toml new file mode 100644 index 000000000..7cbd63458 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_encarray" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/clients/array_client.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/clients/array_client.rs new file mode 100644 index 000000000..8cfbd0bff --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/clients/array_client.rs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::property::clients::ArrayPropertyClient; +use azure_core::{ + fmt::SafeDebug, + http::{ClientOptions, Pipeline, Url}, + tracing, Result, +}; + +/// Test for encode decorator on array. +#[tracing::client] +pub struct ArrayClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`ArrayClient`](ArrayClient) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl ArrayClient { + /// Creates a new ArrayClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Encode.Array")] + pub fn with_no_credential(endpoint: &str, options: Option) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Returns a new instance of ArrayPropertyClient. + #[tracing::subclient] + pub fn get_array_property_client(&self) -> ArrayPropertyClient { + ArrayPropertyClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/clients/mod.rs new file mode 100644 index 000000000..daf065216 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod array_client; +pub use array_client::*; diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/mod.rs new file mode 100644 index 000000000..4c51adc2a --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{ArrayClient, ArrayClientOptions}; diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums.rs new file mode 100644 index 000000000..fb7bbce24 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums.rs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Colors { + Blue, + + Green, + + Red, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ColorsExtensibleEnum { + Blue, + + Green, + + Red, + + /// Any other value not defined in `ColorsExtensibleEnum`. + UnknownValue(String), +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_impl.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_impl.rs new file mode 100644 index 000000000..25f9b71dc --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_impl.rs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{Colors, ColorsExtensibleEnum}; +use azure_core::error::{Error, ErrorKind}; +use std::{ + convert::{AsRef, From, Infallible}, + fmt::{Display, Formatter}, + str::FromStr, +}; + +impl FromStr for Colors { + type Err = Error; + fn from_str(s: &str) -> ::core::result::Result::Err> { + Ok(match s { + "blue" => Colors::Blue, + "green" => Colors::Green, + "red" => Colors::Red, + _ => { + return Err(Error::with_message_fn(ErrorKind::DataConversion, || { + format!("unknown variant of Colors found: \"{s}\"") + })) + } + }) + } +} + +impl AsRef for Colors { + fn as_ref(&self) -> &str { + match self { + Colors::Blue => "blue", + Colors::Green => "green", + Colors::Red => "red", + } + } +} + +impl Display for Colors { + fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result { + match self { + Colors::Blue => Display::fmt("blue", f), + Colors::Green => Display::fmt("green", f), + Colors::Red => Display::fmt("red", f), + } + } +} + +impl<'a> From<&'a ColorsExtensibleEnum> for &'a str { + fn from(e: &'a ColorsExtensibleEnum) -> Self { + match e { + ColorsExtensibleEnum::Blue => "blue", + ColorsExtensibleEnum::Green => "green", + ColorsExtensibleEnum::Red => "red", + ColorsExtensibleEnum::UnknownValue(s) => s.as_ref(), + } + } +} + +impl FromStr for ColorsExtensibleEnum { + type Err = Infallible; + fn from_str(s: &str) -> ::core::result::Result::Err> { + Ok(match s { + "blue" => ColorsExtensibleEnum::Blue, + "green" => ColorsExtensibleEnum::Green, + "red" => ColorsExtensibleEnum::Red, + _ => ColorsExtensibleEnum::UnknownValue(s.to_string()), + }) + } +} + +impl AsRef for ColorsExtensibleEnum { + fn as_ref(&self) -> &str { + match self { + ColorsExtensibleEnum::Blue => "blue", + ColorsExtensibleEnum::Green => "green", + ColorsExtensibleEnum::Red => "red", + ColorsExtensibleEnum::UnknownValue(s) => s.as_str(), + } + } +} + +impl Display for ColorsExtensibleEnum { + fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result { + match self { + ColorsExtensibleEnum::Blue => f.write_str("blue"), + ColorsExtensibleEnum::Green => f.write_str("green"), + ColorsExtensibleEnum::Red => f.write_str("red"), + ColorsExtensibleEnum::UnknownValue(s) => f.write_str(s.as_str()), + } + } +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_serde.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_serde.rs new file mode 100644 index 000000000..9b9cc5a89 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/enums_serde.rs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{Colors, ColorsExtensibleEnum}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +impl<'de> Deserialize<'de> for Colors { + fn deserialize(deserializer: D) -> ::core::result::Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + s.parse().map_err(serde::de::Error::custom) + } +} + +impl Serialize for Colors { + fn serialize(&self, s: S) -> ::core::result::Result + where + S: Serializer, + { + s.serialize_str(self.as_ref()) + } +} + +impl<'de> Deserialize<'de> for ColorsExtensibleEnum { + fn deserialize(deserializer: D) -> ::core::result::Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + s.parse().map_err(serde::de::Error::custom) + } +} + +impl Serialize for ColorsExtensibleEnum { + fn serialize(&self, s: S) -> ::core::result::Result + where + S: Serializer, + { + s.serialize_str(self.as_ref()) + } +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/mod.rs new file mode 100644 index 000000000..2700f3f29 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/mod.rs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod enums; +mod enums_impl; +mod enums_serde; +#[allow(clippy::module_inception)] +mod models; +mod models_impl; +pub use enums::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/models.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/models.rs new file mode 100644 index 000000000..1eff607fa --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/models.rs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{Colors, ColorsExtensibleEnum}; +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct CommaDelimitedArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct CommaDelimitedEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct CommaDelimitedExtensibleEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct NewlineDelimitedArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct NewlineDelimitedEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct NewlineDelimitedExtensibleEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct PipeDelimitedArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct PipeDelimitedEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct PipeDelimitedExtensibleEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct SpaceDelimitedArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct SpaceDelimitedEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} + +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct SpaceDelimitedExtensibleEnumArrayProperty { + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option>, +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/encode/array/src/generated/models/models_impl.rs new file mode 100644 index 000000000..2e079836b --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/generated/models/models_impl.rs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{ + CommaDelimitedArrayProperty, CommaDelimitedEnumArrayProperty, + CommaDelimitedExtensibleEnumArrayProperty, NewlineDelimitedArrayProperty, + NewlineDelimitedEnumArrayProperty, NewlineDelimitedExtensibleEnumArrayProperty, + PipeDelimitedArrayProperty, PipeDelimitedEnumArrayProperty, + PipeDelimitedExtensibleEnumArrayProperty, SpaceDelimitedArrayProperty, + SpaceDelimitedEnumArrayProperty, SpaceDelimitedExtensibleEnumArrayProperty, +}; +use azure_core::{http::RequestContent, json::to_json, Result}; + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: CommaDelimitedArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: CommaDelimitedEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom + for RequestContent +{ + type Error = azure_core::Error; + fn try_from(value: CommaDelimitedExtensibleEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: NewlineDelimitedArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom + for RequestContent +{ + type Error = azure_core::Error; + fn try_from(value: NewlineDelimitedEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom + for RequestContent +{ + type Error = azure_core::Error; + fn try_from(value: NewlineDelimitedExtensibleEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: PipeDelimitedArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: PipeDelimitedEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom + for RequestContent +{ + type Error = azure_core::Error; + fn try_from(value: PipeDelimitedExtensibleEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: SpaceDelimitedArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: SpaceDelimitedEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} + +impl TryFrom + for RequestContent +{ + type Error = azure_core::Error; + fn try_from(value: SpaceDelimitedExtensibleEnumArrayProperty) -> Result { + Ok(to_json(&value)?.into()) + } +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/lib.rs b/packages/typespec-rust/test/spector/encode/array/src/lib.rs new file mode 100644 index 000000000..4e24cb1eb --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/lib.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; +pub mod property; diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/array_property_client.rs b/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/array_property_client.rs new file mode 100644 index 000000000..7f76ccf06 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/array_property_client.rs @@ -0,0 +1,452 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::{ + models::{ + CommaDelimitedArrayProperty, CommaDelimitedEnumArrayProperty, + CommaDelimitedExtensibleEnumArrayProperty, NewlineDelimitedArrayProperty, + NewlineDelimitedEnumArrayProperty, NewlineDelimitedExtensibleEnumArrayProperty, + PipeDelimitedArrayProperty, PipeDelimitedEnumArrayProperty, + PipeDelimitedExtensibleEnumArrayProperty, SpaceDelimitedArrayProperty, + SpaceDelimitedEnumArrayProperty, SpaceDelimitedExtensibleEnumArrayProperty, + }, + property::generated::models::{ + ArrayPropertyClientCommaDelimitedOptions, ArrayPropertyClientEnumCommaDelimitedOptions, + ArrayPropertyClientEnumNewlineDelimitedOptions, + ArrayPropertyClientEnumPipeDelimitedOptions, ArrayPropertyClientEnumSpaceDelimitedOptions, + ArrayPropertyClientExtensibleEnumCommaDelimitedOptions, + ArrayPropertyClientExtensibleEnumNewlineDelimitedOptions, + ArrayPropertyClientExtensibleEnumPipeDelimitedOptions, + ArrayPropertyClientExtensibleEnumSpaceDelimitedOptions, + ArrayPropertyClientNewlineDelimitedOptions, ArrayPropertyClientPipeDelimitedOptions, + ArrayPropertyClientSpaceDelimitedOptions, + }, +}; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, Pipeline, PipelineSendOptions, Request, RequestContent, Response, Url, UrlExt}, + tracing, Result, +}; + +#[tracing::client] +pub struct ArrayPropertyClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl ArrayPropertyClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.commaDelimited")] + pub async fn comma_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/comma-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.enumCommaDelimited")] + pub async fn enum_comma_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/enum/comma-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.enumNewlineDelimited")] + pub async fn enum_newline_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/enum/newline-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.enumPipeDelimited")] + pub async fn enum_pipe_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/enum/pipe-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.enumSpaceDelimited")] + pub async fn enum_space_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/enum/space-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.extensibleEnumCommaDelimited")] + pub async fn extensible_enum_comma_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/extensible-enum/comma-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.extensibleEnumNewlineDelimited")] + pub async fn extensible_enum_newline_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/extensible-enum/newline-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.extensibleEnumPipeDelimited")] + pub async fn extensible_enum_pipe_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/extensible-enum/pipe-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.extensibleEnumSpaceDelimited")] + pub async fn extensible_enum_space_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/extensible-enum/space-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.newlineDelimited")] + pub async fn newline_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/newline-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.pipeDelimited")] + pub async fn pipe_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/pipe-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Encode.Array.Property.spaceDelimited")] + pub async fn space_delimited( + &self, + body: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/encode/array/property/space-delimited"); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + request.set_body(body); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/mod.rs new file mode 100644 index 000000000..258bf218f --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod array_property_client; +pub use array_property_client::*; diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/generated/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/property/generated/mod.rs new file mode 100644 index 000000000..ac0b31a6a --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/generated/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/method_options.rs b/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/method_options.rs new file mode 100644 index 000000000..43dad3375 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/method_options.rs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`ArrayPropertyClient::comma_delimited()`](crate::property::generated::clients::ArrayPropertyClient::comma_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientCommaDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::enum_comma_delimited()`](crate::property::generated::clients::ArrayPropertyClient::enum_comma_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientEnumCommaDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::enum_newline_delimited()`](crate::property::generated::clients::ArrayPropertyClient::enum_newline_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientEnumNewlineDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::enum_pipe_delimited()`](crate::property::generated::clients::ArrayPropertyClient::enum_pipe_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientEnumPipeDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::enum_space_delimited()`](crate::property::generated::clients::ArrayPropertyClient::enum_space_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientEnumSpaceDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::extensible_enum_comma_delimited()`](crate::property::generated::clients::ArrayPropertyClient::extensible_enum_comma_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientExtensibleEnumCommaDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::extensible_enum_newline_delimited()`](crate::property::generated::clients::ArrayPropertyClient::extensible_enum_newline_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientExtensibleEnumNewlineDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::extensible_enum_pipe_delimited()`](crate::property::generated::clients::ArrayPropertyClient::extensible_enum_pipe_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientExtensibleEnumPipeDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::extensible_enum_space_delimited()`](crate::property::generated::clients::ArrayPropertyClient::extensible_enum_space_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientExtensibleEnumSpaceDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::newline_delimited()`](crate::property::generated::clients::ArrayPropertyClient::newline_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientNewlineDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::pipe_delimited()`](crate::property::generated::clients::ArrayPropertyClient::pipe_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientPipeDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`ArrayPropertyClient::space_delimited()`](crate::property::generated::clients::ArrayPropertyClient::space_delimited()) +#[derive(Clone, Default, SafeDebug)] +pub struct ArrayPropertyClientSpaceDelimitedOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/mod.rs new file mode 100644 index 000000000..3e484b1ed --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/generated/models/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +pub use method_options::*; diff --git a/packages/typespec-rust/test/spector/encode/array/src/property/mod.rs b/packages/typespec-rust/test/spector/encode/array/src/property/mod.rs new file mode 100644 index 000000000..bc612bfcd --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/src/property/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/encode/array/tests/array_property_client_test.rs b/packages/typespec-rust/test/spector/encode/array/tests/array_property_client_test.rs new file mode 100644 index 000000000..b4669e710 --- /dev/null +++ b/packages/typespec-rust/test/spector/encode/array/tests/array_property_client_test.rs @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use azure_core::{http::RequestContent, json::to_json}; +use serde::Serialize; +use spector_encarray::{ + models::{ + CommaDelimitedArrayProperty, CommaDelimitedEnumArrayProperty, + CommaDelimitedExtensibleEnumArrayProperty, NewlineDelimitedArrayProperty, + NewlineDelimitedEnumArrayProperty, NewlineDelimitedExtensibleEnumArrayProperty, + PipeDelimitedArrayProperty, PipeDelimitedEnumArrayProperty, + PipeDelimitedExtensibleEnumArrayProperty, SpaceDelimitedArrayProperty, + SpaceDelimitedEnumArrayProperty, SpaceDelimitedExtensibleEnumArrayProperty, + }, + ArrayClient, +}; + +/// The Spector mock expects array values encoded as delimited strings in the JSON body, +/// e.g. `{"value": "blue,red,green"}` rather than `{"value": ["blue","red","green"]}`. +/// The generated models use `Vec` which serializes as a JSON array, so we +/// construct the request body manually with the correct delimited format. +#[derive(Serialize)] +struct DelimitedBody { + value: String, +} + +fn delimited_body(delimiter: &str) -> RequestContent { + let value = ["blue", "red", "green"].join(delimiter); + to_json(&DelimitedBody { value }).unwrap().into() +} + +// --- Comma-delimited tests --- + +#[tokio::test] +async fn comma_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(","); + let resp = client + .get_array_property_client() + .comma_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200, "comma_delimited should return 200 OK"); +} + +#[tokio::test] +async fn enum_comma_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(","); + let resp = client + .get_array_property_client() + .enum_comma_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +#[tokio::test] +async fn extensible_enum_comma_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(","); + let resp = client + .get_array_property_client() + .extensible_enum_comma_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +// --- Newline-delimited tests --- + +#[tokio::test] +async fn newline_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("\n"); + let resp = client + .get_array_property_client() + .newline_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200, "newline_delimited should return 200 OK"); +} + +#[tokio::test] +async fn enum_newline_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("\n"); + let resp = client + .get_array_property_client() + .enum_newline_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +#[tokio::test] +async fn extensible_enum_newline_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("\n"); + let resp = client + .get_array_property_client() + .extensible_enum_newline_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +// --- Pipe-delimited tests --- + +#[tokio::test] +async fn pipe_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("|"); + let resp = client + .get_array_property_client() + .pipe_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200, "pipe_delimited should return 200 OK"); +} + +#[tokio::test] +async fn enum_pipe_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("|"); + let resp = client + .get_array_property_client() + .enum_pipe_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +#[tokio::test] +async fn extensible_enum_pipe_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body("|"); + let resp = client + .get_array_property_client() + .extensible_enum_pipe_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +// --- Space-delimited tests --- + +#[tokio::test] +async fn space_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(" "); + let resp = client + .get_array_property_client() + .space_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200, "space_delimited should return 200 OK"); +} + +#[tokio::test] +async fn enum_space_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(" "); + let resp = client + .get_array_property_client() + .enum_space_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +#[tokio::test] +async fn extensible_enum_space_delimited_returns_200_with_matching_values() { + let client = ArrayClient::with_no_credential("http://localhost:3000", None).unwrap(); + let body: RequestContent = delimited_body(" "); + let resp = client + .get_array_property_client() + .extensible_enum_space_delimited(body, None) + .await + .unwrap(); + assert_eq!(resp.status(), 200); +} + +// --- Negative tests: client construction --- + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = ArrayClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = ArrayClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/parameters/query/Cargo.toml b/packages/typespec-rust/test/spector/parameters/query/Cargo.toml new file mode 100644 index 000000000..49e08d83b --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "spector_query" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/mod.rs new file mode 100644 index 000000000..9ab4c5813 --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/mod.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod query_client; +mod query_constant_client; +pub use query_client::*; +pub use query_constant_client::*; diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_client.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_client.rs new file mode 100644 index 000000000..7cfdd497a --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_client.rs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::clients::QueryConstantClient; +use azure_core::{ + fmt::SafeDebug, + http::{ClientOptions, Pipeline, Url}, + tracing, Result, +}; + +/// Test for query parameter cases. +#[tracing::client] +pub struct QueryClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`QueryClient`](QueryClient) +#[derive(Clone, Default, SafeDebug)] +pub struct QueryClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl QueryClient { + /// Creates a new QueryClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Parameters.Query")] + pub fn with_no_credential(endpoint: &str, options: Option) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// Returns a new instance of QueryConstantClient. + #[tracing::subclient] + pub fn get_query_constant_client(&self) -> QueryConstantClient { + QueryConstantClient { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } +} diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_constant_client.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_constant_client.rs new file mode 100644 index 000000000..00c85f0c4 --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/clients/query_constant_client.rs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::models::QueryConstantClientPostOptions; +use azure_core::{ + error::CheckSuccessOptions, + http::{Method, NoFormat, Pipeline, PipelineSendOptions, Request, Response, Url, UrlExt}, + tracing, Result, +}; + +/// Constant query parameter verification +#[tracing::client] +pub struct QueryConstantClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +impl QueryConstantClient { + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// post constant query value + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Parameters.Query.Constant.post")] + pub async fn post( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/parameters/query/constant"); + let mut query_builder = url.query_builder(); + query_builder.set_pair("queryParam", "constantValue"); + query_builder.build(); + let mut request = Request::new(url, Method::Post); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/mod.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/mod.rs new file mode 100644 index 000000000..75cbfb57e --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{QueryClient, QueryClientOptions}; diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/models/method_options.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/models/method_options.rs new file mode 100644 index 000000000..4a85ab482 --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/models/method_options.rs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`QueryConstantClient::post()`](crate::generated::clients::QueryConstantClient::post()) +#[derive(Clone, Default, SafeDebug)] +pub struct QueryConstantClientPostOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/parameters/query/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/parameters/query/src/generated/models/mod.rs new file mode 100644 index 000000000..3e484b1ed --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/generated/models/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +pub use method_options::*; diff --git a/packages/typespec-rust/test/spector/parameters/query/src/lib.rs b/packages/typespec-rust/test/spector/parameters/query/src/lib.rs new file mode 100644 index 000000000..cc784e401 --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/parameters/query/tests/query_constant_client_test.rs b/packages/typespec-rust/test/spector/parameters/query/tests/query_constant_client_test.rs new file mode 100644 index 000000000..45dfdc5db --- /dev/null +++ b/packages/typespec-rust/test/spector/parameters/query/tests/query_constant_client_test.rs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_query::QueryClient; + +// Positive test: verify the constant query parameter post succeeds with expected status. + +#[tokio::test] +async fn post_returns_204() { + let client = QueryClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client.get_query_constant_client().post(None).await.unwrap(); + assert_eq!( + resp.status(), + 204, + "post with constant query param should return 204 No Content" + ); +} + +// Client construction tests. + +#[tokio::test] +async fn client_endpoint_is_stored() { + let client = QueryClient::with_no_credential("http://localhost:3000", None).unwrap(); + assert_eq!(client.endpoint().as_str(), "http://localhost:3000/"); +} + +// Negative tests: verify client rejects invalid URLs. + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = QueryClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = QueryClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/resiliency/srv-driven/new/src/generated/clients/resiliency_service_driven_client.rs b/packages/typespec-rust/test/spector/resiliency/srv-driven/new/src/generated/clients/resiliency_service_driven_client.rs index 56a3916a7..1a899d41c 100644 --- a/packages/typespec-rust/test/spector/resiliency/srv-driven/new/src/generated/clients/resiliency_service_driven_client.rs +++ b/packages/typespec-rust/test/spector/resiliency/srv-driven/new/src/generated/clients/resiliency_service_driven_client.rs @@ -239,7 +239,6 @@ impl ResiliencyServiceDrivenClient { } /// Default value for [`ResiliencyServiceDrivenClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "v2"; impl Default for ResiliencyServiceDrivenClientOptions { diff --git a/packages/typespec-rust/test/spector/resiliency/srv-driven/old/src/generated/clients/resiliency_service_driven_client.rs b/packages/typespec-rust/test/spector/resiliency/srv-driven/old/src/generated/clients/resiliency_service_driven_client.rs index 608e109ec..481e69292 100644 --- a/packages/typespec-rust/test/spector/resiliency/srv-driven/old/src/generated/clients/resiliency_service_driven_client.rs +++ b/packages/typespec-rust/test/spector/resiliency/srv-driven/old/src/generated/clients/resiliency_service_driven_client.rs @@ -188,7 +188,6 @@ impl ResiliencyServiceDrivenClient { } /// Default value for [`ResiliencyServiceDrivenClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "v1"; impl Default for ResiliencyServiceDrivenClientOptions { diff --git a/packages/typespec-rust/test/spector/server/path/multiple/src/generated/clients/multiple_client.rs b/packages/typespec-rust/test/spector/server/path/multiple/src/generated/clients/multiple_client.rs index 4313121ad..41de80779 100644 --- a/packages/typespec-rust/test/spector/server/path/multiple/src/generated/clients/multiple_client.rs +++ b/packages/typespec-rust/test/spector/server/path/multiple/src/generated/clients/multiple_client.rs @@ -142,7 +142,6 @@ impl MultipleClient { } /// Default value for [`MultipleClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "v1.0"; impl Default for MultipleClientOptions { diff --git a/packages/typespec-rust/test/spector/server/versions/versioned/src/generated/clients/versioned_client.rs b/packages/typespec-rust/test/spector/server/versions/versioned/src/generated/clients/versioned_client.rs index e06c2f7b2..dff855c11 100644 --- a/packages/typespec-rust/test/spector/server/versions/versioned/src/generated/clients/versioned_client.rs +++ b/packages/typespec-rust/test/spector/server/versions/versioned/src/generated/clients/versioned_client.rs @@ -203,7 +203,6 @@ impl VersionedClient { } /// Default value for [`VersionedClientOptions::api_version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_API_VERSION: &str = "2022-12-01-preview"; impl Default for VersionedClientOptions { diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/Cargo.toml b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/Cargo.toml new file mode 100644 index 000000000..bf75cd3f5 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "spector_nesteddisc" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/mod.rs new file mode 100644 index 000000000..6f83ffc39 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod nested_discriminator_client; +pub use nested_discriminator_client::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/nested_discriminator_client.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/nested_discriminator_client.rs new file mode 100644 index 000000000..4e8ae376f --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/clients/nested_discriminator_client.rs @@ -0,0 +1,263 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::models::{ + Fish, NestedDiscriminatorClientGetMissingDiscriminatorOptions, + NestedDiscriminatorClientGetModelOptions, NestedDiscriminatorClientGetRecursiveModelOptions, + NestedDiscriminatorClientGetWrongDiscriminatorOptions, + NestedDiscriminatorClientPutModelOptions, NestedDiscriminatorClientPutRecursiveModelOptions, +}; +use azure_core::{ + error::CheckSuccessOptions, + fmt::SafeDebug, + http::{ + ClientOptions, Method, NoFormat, Pipeline, PipelineSendOptions, Request, RequestContent, + Response, Url, UrlExt, + }, + tracing, Result, +}; + +/// Illustrates multiple level inheritance with multiple discriminators. +#[tracing::client] +pub struct NestedDiscriminatorClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`NestedDiscriminatorClient`](NestedDiscriminatorClient) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl NestedDiscriminatorClient { + /// Creates a new NestedDiscriminatorClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Type.Model.Inheritance.NestedDiscriminator")] + pub fn with_no_credential( + endpoint: &str, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.getMissingDiscriminator")] + pub async fn get_missing_discriminator( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/missingdiscriminator"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.getModel")] + pub async fn get_model( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/model"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.getRecursiveModel")] + pub async fn get_recursive_model( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/recursivemodel"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.getWrongDiscriminator")] + pub async fn get_wrong_discriminator( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/wrongdiscriminator"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.putModel")] + pub async fn put_model( + &self, + input: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/model"); + let mut request = Request::new(url, Method::Put); + request.insert_header("content-type", "application/json"); + request.set_body(input); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.NestedDiscriminator.putRecursiveModel")] + pub async fn put_recursive_model( + &self, + input: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/nested-discriminator/recursivemodel"); + let mut request = Request::new(url, Method::Put); + request.insert_header("content-type", "application/json"); + request.set_body(input); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/mod.rs new file mode 100644 index 000000000..c02d27cf3 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{NestedDiscriminatorClient, NestedDiscriminatorClientOptions}; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/method_options.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/method_options.rs new file mode 100644 index 000000000..0165a494c --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/method_options.rs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`NestedDiscriminatorClient::get_missing_discriminator()`](crate::generated::clients::NestedDiscriminatorClient::get_missing_discriminator()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientGetMissingDiscriminatorOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`NestedDiscriminatorClient::get_model()`](crate::generated::clients::NestedDiscriminatorClient::get_model()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientGetModelOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`NestedDiscriminatorClient::get_recursive_model()`](crate::generated::clients::NestedDiscriminatorClient::get_recursive_model()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientGetRecursiveModelOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`NestedDiscriminatorClient::get_wrong_discriminator()`](crate::generated::clients::NestedDiscriminatorClient::get_wrong_discriminator()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientGetWrongDiscriminatorOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`NestedDiscriminatorClient::put_model()`](crate::generated::clients::NestedDiscriminatorClient::put_model()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientPutModelOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`NestedDiscriminatorClient::put_recursive_model()`](crate::generated::clients::NestedDiscriminatorClient::put_recursive_model()) +#[derive(Clone, Default, SafeDebug)] +pub struct NestedDiscriminatorClientPutRecursiveModelOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/mod.rs new file mode 100644 index 000000000..9b63c9e75 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +#[allow(clippy::module_inception)] +mod models; +mod models_impl; +mod unions; +mod unions_impl; +mod unions_serde; +pub use method_options::*; +pub use models::*; +pub use unions::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models.rs new file mode 100644 index 000000000..25d5f90ba --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models.rs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::Fish; +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +/// The third level model GoblinShark in polymorphic multiple levels inheritance. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[serde(rename = "goblin", tag = "sharktype")] +pub struct GoblinShark { + #[serde(skip_serializing_if = "Option::is_none")] + pub age: Option, +} + +/// The second level model in polymorphic multiple levels inheritance which contains references to other polymorphic instances. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[serde(rename = "salmon", tag = "kind")] +pub struct Salmon { + #[serde(skip_serializing_if = "Option::is_none")] + pub age: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub friends: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub hate: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub partner: Option>, +} + +/// The third level model SawShark in polymorphic multiple levels inheritance. +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +#[serde(rename = "saw", tag = "sharktype")] +pub struct SawShark { + #[serde(skip_serializing_if = "Option::is_none")] + pub age: Option, +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models_impl.rs new file mode 100644 index 000000000..812abfbfb --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/models_impl.rs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{Fish, GoblinShark, Salmon, SawShark, Shark}; + +impl From for Shark { + fn from(value: GoblinShark) -> Self { + Self::GoblinShark(value) + } +} + +impl From for Fish { + fn from(value: Salmon) -> Self { + Self::Salmon(value) + } +} + +impl From for Shark { + fn from(value: SawShark) -> Self { + Self::SawShark(value) + } +} + +impl From for Fish { + fn from(value: Shark) -> Self { + Self::Shark(value) + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions.rs new file mode 100644 index 000000000..bd3b006e2 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions.rs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{GoblinShark, Salmon, SawShark, Shark}; +use azure_core::fmt::SafeDebug; +use serde::Deserialize; + +#[doc = r#"This is base model for polymorphic multiple levels inheritance with a discriminator."#] +#[derive(Clone, Deserialize, SafeDebug)] +#[serde(tag = "kind")] +pub enum Fish { + #[serde(rename = "salmon")] + Salmon(Salmon), + + #[serde(rename = "shark")] + Shark(Shark), + + #[serde(untagged)] + UnknownKind { + /// Discriminator property for Fish. + kind: Option, + + age: Option, + }, +} + +#[doc = r#"The second level model in polymorphic multiple levels inheritance and it defines a new discriminator."#] +#[derive(Clone, Deserialize, SafeDebug)] +#[serde(tag = "kind")] +pub enum Shark { + #[serde(rename = "goblin")] + GoblinShark(GoblinShark), + + #[serde(rename = "saw")] + SawShark(SawShark), + + #[serde(untagged)] + UnknownKind { + /// Field has constant value shark. Any specified value will be ignored. + kind: Option, + + sharktype: Option, + + age: Option, + }, +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_impl.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_impl.rs new file mode 100644 index 000000000..c657dd5a0 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_impl.rs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::Fish; +use azure_core::{http::RequestContent, json::to_json, Result}; + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: Fish) -> Result { + Ok(to_json(&value)?.into()) + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_serde.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_serde.rs new file mode 100644 index 000000000..174de8534 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/generated/models/unions_serde.rs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::{Fish, GoblinShark, Salmon, SawShark, Shark}; +use serde::{Serialize, Serializer}; + +impl Serialize for Fish { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Fish::Salmon(salmon) => Salmon::serialize(salmon, serializer), + Fish::Shark(shark) => Shark::serialize(shark, serializer), + Fish::UnknownKind { kind, age } => { + #[derive(Serialize)] + struct UnknownKind<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + kind: &'a Option, + #[serde(skip_serializing_if = "Option::is_none")] + age: &'a Option, + } + UnknownKind::serialize(&UnknownKind { kind, age }, serializer) + } + } + } +} + +impl Serialize for Shark { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Shark::GoblinShark(goblin_shark) => GoblinShark::serialize(goblin_shark, serializer), + Shark::SawShark(saw_shark) => SawShark::serialize(saw_shark, serializer), + Shark::UnknownKind { + kind, + sharktype, + age, + } => { + #[derive(Serialize)] + struct UnknownKind<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + kind: &'a Option, + #[serde(skip_serializing_if = "Option::is_none")] + sharktype: &'a Option, + #[serde(skip_serializing_if = "Option::is_none")] + age: &'a Option, + } + UnknownKind::serialize( + &UnknownKind { + kind, + sharktype, + age, + }, + serializer, + ) + } + } + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/lib.rs b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/lib.rs new file mode 100644 index 000000000..cc784e401 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/nested-discriminator/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/Cargo.toml b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/Cargo.toml new file mode 100644 index 000000000..a908f091f --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "spector_recursive" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[features] +default = ["azure_core/default"] + +[dependencies] +azure_core = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true } diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/mod.rs new file mode 100644 index 000000000..02a457d12 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod recursive_client; +pub use recursive_client::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/recursive_client.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/recursive_client.rs new file mode 100644 index 000000000..d80d8f3fa --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/clients/recursive_client.rs @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use crate::generated::models::{Extension, RecursiveClientGetOptions, RecursiveClientPutOptions}; +use azure_core::{ + error::CheckSuccessOptions, + fmt::SafeDebug, + http::{ + ClientOptions, Method, NoFormat, Pipeline, PipelineSendOptions, Request, RequestContent, + Response, Url, UrlExt, + }, + tracing, Result, +}; + +/// Illustrates inheritance recursion +#[tracing::client] +pub struct RecursiveClient { + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, +} + +/// Options used when creating a [`RecursiveClient`](RecursiveClient) +#[derive(Clone, Default, SafeDebug)] +pub struct RecursiveClientOptions { + /// Allows customization of the client. + pub client_options: ClientOptions, +} + +impl RecursiveClient { + /// Creates a new RecursiveClient requiring no authentication. + /// + /// # Arguments + /// + /// * `endpoint` - Service host + /// * `options` - Optional configuration for the client. + #[tracing::new("Type.Model.Inheritance.Recursive")] + pub fn with_no_credential( + endpoint: &str, + options: Option, + ) -> Result { + let options = options.unwrap_or_default(); + let endpoint = Url::parse(endpoint)?; + if !endpoint.scheme().starts_with("http") { + return Err(azure_core::Error::with_message( + azure_core::error::ErrorKind::Other, + format!("{endpoint} must use http(s)"), + )); + } + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + None, + ), + }) + } + + /// Returns the Url associated with this client. + pub fn endpoint(&self) -> &Url { + &self.endpoint + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.Recursive.get")] + pub async fn get( + &self, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/recursive"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[200], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } + + /// + /// # Arguments + /// + /// * `options` - Optional parameters for the request. + #[tracing::function("Type.Model.Inheritance.Recursive.put")] + pub async fn put( + &self, + input: RequestContent, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let ctx = options.method_options.context.to_borrowed(); + let mut url = self.endpoint.clone(); + url.append_path("/type/model/inheritance/recursive"); + let mut request = Request::new(url, Method::Put); + request.insert_header("content-type", "application/json"); + request.set_body(input); + let rsp = self + .pipeline + .send( + &ctx, + &mut request, + Some(PipelineSendOptions { + check_success: CheckSuccessOptions { + success_codes: &[204], + }, + ..Default::default() + }), + ) + .await?; + Ok(rsp.into()) + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/mod.rs new file mode 100644 index 000000000..071d7261d --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/mod.rs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +/// Clients used to communicate with the service. +pub mod clients; +/// Contains all the data structures and types used by the client library. +pub mod models; +pub use clients::{RecursiveClient, RecursiveClientOptions}; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/method_options.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/method_options.rs new file mode 100644 index 000000000..b98348188 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/method_options.rs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; + +/// Options to be passed to [`RecursiveClient::get()`](crate::generated::clients::RecursiveClient::get()) +#[derive(Clone, Default, SafeDebug)] +pub struct RecursiveClientGetOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} + +/// Options to be passed to [`RecursiveClient::put()`](crate::generated::clients::RecursiveClient::put()) +#[derive(Clone, Default, SafeDebug)] +pub struct RecursiveClientPutOptions<'a> { + /// Allows customization of the method call. + pub method_options: ClientMethodOptions<'a>, +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/mod.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/mod.rs new file mode 100644 index 000000000..5dfb21b69 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/mod.rs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +mod method_options; +#[allow(clippy::module_inception)] +mod models; +mod models_impl; +pub use method_options::*; +pub use models::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models.rs new file mode 100644 index 000000000..bbd16c220 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models.rs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use azure_core::fmt::SafeDebug; +use serde::{Deserialize, Serialize}; + +/// extension +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize)] +pub struct Extension { + #[serde(skip_serializing_if = "Option::is_none")] + pub extension: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub level: Option, +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models_impl.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models_impl.rs new file mode 100644 index 000000000..cc0412b85 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/generated/models/models_impl.rs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. + +use super::Extension; +use azure_core::{http::RequestContent, json::to_json, Result}; + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: Extension) -> Result { + Ok(to_json(&value)?.into()) + } +} diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/lib.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/lib.rs new file mode 100644 index 000000000..cc784e401 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// Code generated by Microsoft (R) Rust Code Generator. + +#![cfg_attr(docsrs, feature(doc_cfg))] + +mod generated; +pub use generated::*; diff --git a/packages/typespec-rust/test/spector/type/model/inheritance/recursive/tests/recursive_client_test.rs b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/tests/recursive_client_test.rs new file mode 100644 index 000000000..220b8fce3 --- /dev/null +++ b/packages/typespec-rust/test/spector/type/model/inheritance/recursive/tests/recursive_client_test.rs @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the MIT License. See License.txt in the project root for license information. + +use spector_recursive::{models::Extension, RecursiveClient}; + +// Positive tests: verify get returns expected recursive model, put accepts it. + +#[tokio::test] +async fn get_returns_200_with_recursive_model() { + let client = RecursiveClient::with_no_credential("http://localhost:3000", None).unwrap(); + let resp = client.get(None).await.unwrap(); + assert_eq!(resp.status(), 200, "get should return 200 OK"); + let model: Extension = resp.into_model().unwrap(); + // Verify the top-level model has expected fields. + assert!(model.level.is_some(), "level should be present"); + assert_eq!(model.level, Some(0)); + // Verify nested extensions exist. + assert!(model.extension.is_some(), "extension should be present"); + let extensions = model.extension.unwrap(); + assert!(!extensions.is_empty(), "extension list should not be empty"); + // Verify first nested extension. + assert_eq!(extensions[0].level, Some(1)); + assert!( + extensions[0].extension.is_some(), + "nested extension should be present" + ); + let nested = extensions[0].extension.as_ref().unwrap(); + assert_eq!(nested[0].level, Some(2)); +} + +#[tokio::test] +async fn put_returns_204() { + let client = RecursiveClient::with_no_credential("http://localhost:3000", None).unwrap(); + let input = Extension { + level: Some(0), + extension: Some(vec![ + Extension { + level: Some(1), + extension: Some(vec![Extension { + level: Some(2), + extension: None, + }]), + }, + Extension { + level: Some(1), + extension: None, + }, + ]), + }; + let resp = client.put(input.try_into().unwrap(), None).await.unwrap(); + assert_eq!(resp.status(), 204, "put should return 204 No Content"); +} + +// Test: verify a deeply-nested recursive structure can be sent. +#[tokio::test] +async fn put_deeply_nested_structure() { + let client = RecursiveClient::with_no_credential("http://localhost:3000", None).unwrap(); + let input = Extension { + level: Some(0), + extension: Some(vec![ + Extension { + level: Some(1), + extension: Some(vec![Extension { + level: Some(2), + extension: None, + }]), + }, + Extension { + level: Some(1), + extension: None, + }, + ]), + }; + // This validates the serialization of deeply nested recursive types. + client.put(input.try_into().unwrap(), None).await.unwrap(); +} + +// Test: verify model with no extensions can be constructed. +#[tokio::test] +async fn extension_model_with_no_children() { + let model = Extension { + level: Some(5), + extension: None, + }; + assert_eq!(model.level, Some(5)); + assert!(model.extension.is_none()); +} + +// Test: verify model with empty extensions list. +#[tokio::test] +async fn extension_model_with_empty_children() { + let model = Extension { + level: Some(0), + extension: Some(vec![]), + }; + assert_eq!(model.level, Some(0)); + assert_eq!(model.extension.as_ref().unwrap().len(), 0); +} + +// Negative tests: verify client rejects invalid URLs. + +#[tokio::test] +async fn client_rejects_non_http_scheme() { + let result = RecursiveClient::with_no_credential("ftp://localhost:3000", None); + assert!(result.is_err(), "non-http scheme should be rejected"); +} + +#[tokio::test] +async fn client_rejects_malformed_url() { + let result = RecursiveClient::with_no_credential("not-a-valid-url", None); + assert!(result.is_err(), "malformed URL should be rejected"); +} diff --git a/packages/typespec-rust/test/spector/versioning/madeOptional/src/generated/clients/made_optional_client.rs b/packages/typespec-rust/test/spector/versioning/madeOptional/src/generated/clients/made_optional_client.rs index 71cb74da7..bf45f9925 100644 --- a/packages/typespec-rust/test/spector/versioning/madeOptional/src/generated/clients/made_optional_client.rs +++ b/packages/typespec-rust/test/spector/versioning/madeOptional/src/generated/clients/made_optional_client.rs @@ -112,7 +112,6 @@ impl MadeOptionalClient { } /// Default value for [`MadeOptionalClientOptions::version`]. -#[allow(dead_code)] pub(crate) const DEFAULT_VERSION: &str = "v2"; impl Default for MadeOptionalClientOptions {