diff --git a/sdk/core/Azure.Core.TestFramework/src/ClientTestFixtureAttribute.cs b/sdk/core/Azure.Core.TestFramework/src/ClientTestFixtureAttribute.cs
index e4056dcca563..b834dc6a4f5f 100644
--- a/sdk/core/Azure.Core.TestFramework/src/ClientTestFixtureAttribute.cs
+++ b/sdk/core/Azure.Core.TestFramework/src/ClientTestFixtureAttribute.cs
@@ -25,7 +25,18 @@ public class ClientTestFixtureAttribute : NUnitAttribute, IFixtureBuilder2, IPre
private readonly object[] _additionalParameters;
private readonly object[] _serviceVersions;
- private readonly int? _maxServiceVersion;
+ private int? _actualPlaybackServiceVersion;
+ private int[] _actualLiveServiceVersions;
+
+ ///
+ /// Specifies which service version is run during recording/playback runs.
+ ///
+ public object RecordingServiceVersion { get; set; }
+
+ ///
+ /// Specifies which service version is run during live runs.
+ ///
+ public object[] LiveServiceVersions { get; set; }
///
/// Initializes an instance of the accepting additional fixture parameters.
@@ -43,8 +54,6 @@ public ClientTestFixtureAttribute(object[] serviceVersions, object[] additionalP
{
_additionalParameters = additionalParameters ?? new object[] { };
_serviceVersions = serviceVersions ?? new object[] { };
-
- _maxServiceVersion = _serviceVersions.Any() ? _serviceVersions.Max(s => Convert.ToInt32(s)) : (int?)null;
}
public IEnumerable BuildFrom(ITypeInfo typeInfo)
@@ -54,6 +63,23 @@ public IEnumerable BuildFrom(ITypeInfo typeInfo)
public IEnumerable BuildFrom(ITypeInfo typeInfo, IPreFilter filter)
{
+ var latestVersion = _serviceVersions.Any() ? _serviceVersions.Max(Convert.ToInt32) : (int?)null;
+ _actualPlaybackServiceVersion = RecordingServiceVersion != null ? Convert.ToInt32(RecordingServiceVersion) : latestVersion;
+
+ var liveVersions = LiveServiceVersions ?? _serviceVersions;
+
+ if (liveVersions.Any())
+ {
+ if (OnlyTestLatestServiceVersionLazy.Value)
+ {
+ _actualLiveServiceVersions = new[] { liveVersions.Max(Convert.ToInt32) };
+ }
+ else
+ {
+ _actualLiveServiceVersions = liveVersions.Select(Convert.ToInt32).ToArray();
+ }
+ }
+
var suitePermutations = GeneratePermutations();
foreach (var (fixture, isAsync, serviceVersion, parameter) in suitePermutations)
@@ -114,6 +140,8 @@ public IEnumerable BuildFrom(ITypeInfo typeInfo, IPreFilter filter)
private void Process(TestSuite testSuite, object serviceVersion, bool isAsync, object parameter)
{
var serviceVersionNumber = Convert.ToInt32(serviceVersion);
+ ApplyLimits(serviceVersionNumber, testSuite);
+
foreach (Test test in testSuite.Tests)
{
if (test is ParameterizedMethodSuite parameterizedMethodSuite)
@@ -157,18 +185,23 @@ private void ProcessTest(object serviceVersion, bool isAsync, int serviceVersion
return;
}
- if (serviceVersionNumber != _maxServiceVersion)
+ if (serviceVersionNumber != _actualPlaybackServiceVersion)
{
- test.Properties.Add("SkipRecordings", $"Test is ignored when not running live because the service version {serviceVersion} is not the latest.");
+ test.Properties.Add("SkipRecordings", $"Test is ignored when not running live because the service version {serviceVersion} is not {_actualPlaybackServiceVersion}.");
}
- if (OnlyTestLatestServiceVersionLazy.Value && serviceVersionNumber != _maxServiceVersion)
+ if (_actualLiveServiceVersions != null &&
+ !_actualLiveServiceVersions.Contains(serviceVersionNumber))
{
- test.RunState = RunState.Ignored;
- test.Properties.Set("_SKIPREASON",
- $"Test ignored because {OnlyTestLatestServiceVersionKey} is set in the environment and version {serviceVersion} is not the latest.");
+ test.Properties.Set("SkipLive",
+ $"Test ignored when running live service version {serviceVersion} is not one of {string.Join(", " , _actualLiveServiceVersions)}.");
}
+ ApplyLimits(serviceVersionNumber, test);
+ }
+
+ private static void ApplyLimits(int serviceVersionNumber, Test test)
+ {
var minServiceVersion = test.GetCustomAttributes(true);
foreach (ServiceVersionAttribute serviceVersionAttribute in minServiceVersion)
{
@@ -179,7 +212,7 @@ private void ProcessTest(object serviceVersion, bool isAsync, int serviceVersion
test.Properties.Set("_SKIPREASON", $"Test ignored because it's minimum service version is set to {serviceVersionAttribute.Min}");
}
- if (serviceVersionAttribute.Max != null &&
+ if (serviceVersionAttribute.Max != null &
Convert.ToInt32(serviceVersionAttribute.Max) < serviceVersionNumber)
{
test.RunState = RunState.Ignored;
diff --git a/sdk/core/Azure.Core.TestFramework/src/RecordedTestBase.cs b/sdk/core/Azure.Core.TestFramework/src/RecordedTestBase.cs
index f5ca1cc05d8e..94571310f24b 100644
--- a/sdk/core/Azure.Core.TestFramework/src/RecordedTestBase.cs
+++ b/sdk/core/Azure.Core.TestFramework/src/RecordedTestBase.cs
@@ -143,6 +143,13 @@ public virtual void StartTestRecording()
{
throw new IgnoreException((string) test.Properties.Get("SkipRecordings"));
}
+
+ if (Mode == RecordedTestMode.Live &&
+ test.Properties.ContainsKey("SkipLive"))
+ {
+ throw new IgnoreException((string) test.Properties.Get("SkipLive"));
+ }
+
Recording = new TestRecording(Mode, GetSessionFilePath(), Sanitizer, Matcher);
ValidateClientInstrumentation = Recording.HasRequests;
}
diff --git a/sdk/core/Azure.Core.TestFramework/src/ServiceVersionAttribute.cs b/sdk/core/Azure.Core.TestFramework/src/ServiceVersionAttribute.cs
index 3b086707d204..23ec2fae2860 100644
--- a/sdk/core/Azure.Core.TestFramework/src/ServiceVersionAttribute.cs
+++ b/sdk/core/Azure.Core.TestFramework/src/ServiceVersionAttribute.cs
@@ -6,7 +6,7 @@
namespace Azure.Core.TestFramework
{
- [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ServiceVersionAttribute : NUnitAttribute
{
public object Min { get; set; }
diff --git a/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTests.cs b/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTests.cs
index c744d1111757..942d44ed5f4c 100644
--- a/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTests.cs
+++ b/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTests.cs
@@ -6,7 +6,8 @@
namespace Azure.Core.Tests
{
- [ClientTestFixture(FakeClientVersion.V1, FakeClientVersion.V2, FakeClientVersion.V3)]
+ [ClientTestFixture(FakeClientVersion.V0, FakeClientVersion.V1, FakeClientVersion.V2, FakeClientVersion.V3, FakeClientVersion.V4)]
+ [ServiceVersion(Min = FakeClientVersion.V1, Max = FakeClientVersion.V3)]
public class ClientTestBaseMultiVersionTests : ClientTestBase
{
private readonly FakeClientVersion _version;
@@ -59,9 +60,11 @@ public void SyncOnlyWorks()
public enum FakeClientVersion
{
+ V0 = 0,
V1 = 1,
V2 = 2,
- V3 = 3
+ V3 = 3,
+ V4 = 4
}
}
}
diff --git a/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTestsWithSpecificVersions.cs b/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTestsWithSpecificVersions.cs
new file mode 100644
index 000000000000..4082f0f7cb2a
--- /dev/null
+++ b/sdk/core/Azure.Core/tests/ClientTestBaseMultiVersionTestsWithSpecificVersions.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core.Pipeline;
+using Azure.Core.TestFramework;
+using NUnit.Framework;
+
+namespace Azure.Core.Tests
+{
+ [ClientTestFixture(
+ TestClientOptions.ServiceVersion.V0,
+ TestClientOptions.ServiceVersion.V1,
+ TestClientOptions.ServiceVersion.V2,
+ TestClientOptions.ServiceVersion.V3,
+ RecordingServiceVersion = TestClientOptions.ServiceVersion.V2,
+ LiveServiceVersions = new object[] { TestClientOptions.ServiceVersion.V1, TestClientOptions.ServiceVersion.V0 })]
+ public class ClientTestBaseMultiVersionTestsWithSpecificVersions : RecordedTestBase
+ {
+ private readonly TestClientOptions.ServiceVersion _version;
+
+ public ClientTestBaseMultiVersionTestsWithSpecificVersions(bool isAsync, TestClientOptions.ServiceVersion version) : base(isAsync)
+ {
+ _version = version;
+ TestDiagnostics = false;
+ }
+
+ [Test]
+ public async Task HasValidVersion()
+ {
+ var testClientOptions = new TestClientOptions(_version) { Transport = new MockTransport(new MockResponse(200))};
+ var client = InstrumentClient(new TestClient(InstrumentClientOptions(testClientOptions)));
+ await client.GetAsync(default);
+ if (Mode == RecordedTestMode.Playback || Mode == RecordedTestMode.Record)
+ {
+ Assert.IsTrue(_version == TestClientOptions.ServiceVersion.V2);
+ }
+ else
+ {
+ Assert.IsTrue(_version == TestClientOptions.ServiceVersion.V1 || _version == TestClientOptions.ServiceVersion.V0);
+ }
+ }
+
+ public class TestClientOptions: ClientOptions
+ {
+ public readonly ServiceVersion Version;
+
+ public enum ServiceVersion
+ {
+ V0 = 0,
+ V1 = 1,
+ V2 = 2,
+ V3 = 3
+ }
+
+ public TestClientOptions(ServiceVersion serviceVersion)
+ {
+ Version = serviceVersion;
+ }
+ }
+ public class TestClient
+ {
+ private readonly TestClientOptions _options;
+ private HttpPipeline _pipeline;
+
+ protected TestClient(){}
+ public TestClient(TestClientOptions options)
+ {
+ _options = options;
+ _pipeline = HttpPipelineBuilder.Build(options);
+ }
+
+ public virtual Response Get(CancellationToken cancellationToken)
+ {
+ using var request = _pipeline.CreateRequest();
+ request.Method = RequestMethod.Get;
+ request.Uri.Reset(new Uri("http://localhost"));
+ request.Uri.AppendQuery("api", _options.Version.ToString());
+ return _pipeline.SendRequest(request, cancellationToken);
+ }
+
+ public virtual async Task GetAsync(CancellationToken cancellationToken)
+ {
+ using var request = _pipeline.CreateRequest();
+ request.Method = RequestMethod.Get;
+ request.Uri.Reset(new Uri("http://localhost"));
+ request.Uri.AppendQuery("api", _options.Version.ToString());
+ return await _pipeline.SendRequestAsync(request, cancellationToken);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersion.json b/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersion.json
new file mode 100644
index 000000000000..66cfb8112d74
--- /dev/null
+++ b/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersion.json
@@ -0,0 +1,20 @@
+{
+ "Entries": [
+ {
+ "RequestUri": "http://localhost/?api=V2",
+ "RequestMethod": "GET",
+ "RequestHeaders": {
+ "User-Agent": "azsdk-net-Core.Tests/1.0.0-alpha.20210310.1 (.NET Framework 4.8.4300.0; Microsoft Windows 10.0.19042 )",
+ "x-ms-client-request-id": "dc85f443de8d5700b37ac3b4cc6f8430",
+ "x-ms-return-client-request-id": "true"
+ },
+ "RequestBody": null,
+ "StatusCode": 200,
+ "ResponseHeaders": {},
+ "ResponseBody": null
+ }
+ ],
+ "Variables": {
+ "RandomSeed": "9840729"
+ }
+}
\ No newline at end of file
diff --git a/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersionAsync.json b/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersionAsync.json
new file mode 100644
index 000000000000..1c0efc9e7b44
--- /dev/null
+++ b/sdk/core/Azure.Core/tests/SessionRecords/ClientTestBaseMultiVersionTestsWithSpecificVersions/HasValidVersionAsync.json
@@ -0,0 +1,20 @@
+{
+ "Entries": [
+ {
+ "RequestUri": "http://localhost/?api=V2",
+ "RequestMethod": "GET",
+ "RequestHeaders": {
+ "User-Agent": "azsdk-net-Core.Tests/1.0.0-alpha.20210310.1 (.NET Framework 4.8.4300.0; Microsoft Windows 10.0.19042 )",
+ "x-ms-client-request-id": "310df70d817bc1bf9908dbde885585f0",
+ "x-ms-return-client-request-id": "true"
+ },
+ "RequestBody": null,
+ "StatusCode": 200,
+ "ResponseHeaders": {},
+ "ResponseBody": null
+ }
+ ],
+ "Variables": {
+ "RandomSeed": "16931662"
+ }
+}
\ No newline at end of file