runAsync() {
+ if (!trigger) {
+ trigger = true;
+ return service.listSubscriptions().then();
+ } else {
+ return Mono.empty();
+ }
+
+ }
+
+ private HttpResponse createMockClaimsResponse(HttpRequest httpRequest, String contentType) {
+ HttpHeaders headers = new HttpHeaders().set(CONTENT_TYPE, contentType);
+ headers.set(BearerTokenAuthenticationChallengePolicy.WWW_AUTHENTICATE, MOCK_CHALLENGE);
+ HttpResponse res = new MockHttpResponse(httpRequest, 401, headers);
+ return res;
+ }
+
+ private HttpResponse createMockSuccessResponse(HttpRequest httpRequest, String contentType) {
+ HttpHeaders headers = new HttpHeaders().set(CONTENT_TYPE, contentType);
+ HttpResponse res = new MockHttpResponse(httpRequest, 200, headers);
+ return res;
+ }
+}
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/App.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/App.java
new file mode 100644
index 000000000000..907c38d9a696
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/App.java
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.perf;
+
+import com.azure.perf.test.core.PerfStressProgram;
+
+/**
+ * Runs the Storage performance test.
+ *
+ * To run from command line. Package the project into a jar with dependencies via mvn clean package.
+ * Then run the program via java -jar 'compiled-jar-with-dependencies-path'
+ *
+ * To run from IDE, set all the required environment variables in IntelliJ via Run -> EditConfigurations
+ * section.
+ * Then run the App's main method via IDE.
+ */
+public class App {
+
+ /**
+ * The main method for the performance testing package.
+ * @param args the command line arguments.
+ * @throws RuntimeException if the performance tests implementation classes cannot be found.
+ */
+ public static void main(String[] args) {
+ Class>[] testClasses;
+
+ try {
+ testClasses = new Class>[]{
+ Class.forName("com.azure.core.perf.ARMChallengeAuthenticationPolicyTest")
+ };
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ PerfStressProgram.run(testClasses, args);
+ }
+}
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MockHttpClient.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MockHttpClient.java
new file mode 100644
index 000000000000..e2824f3f7809
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MockHttpClient.java
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.perf.core;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import reactor.core.publisher.Mono;
+
+import java.util.function.Function;
+
+/**
+ * The Mock Http Client to send recorded responses back to the Http Pipeline.
+ */
+public class MockHttpClient implements HttpClient {
+ private final Function responseSupplier;
+
+ /**
+ * Creates an instance of the {@link MockHttpClient}
+ *
+ * @param responseSupplier the supplier to supply the {@link HttpResponse}
+ */
+ public MockHttpClient(Function responseSupplier) {
+ this.responseSupplier = responseSupplier;
+ }
+
+ @Override
+ public Mono send(HttpRequest request) {
+ return Mono.just(responseSupplier.apply(request));
+ }
+}
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MyRestProxyService.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MyRestProxyService.java
new file mode 100644
index 000000000000..3aeb6b27f1ee
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/MyRestProxyService.java
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.perf.core;
+
+import com.azure.core.annotation.Get;
+import com.azure.core.annotation.Host;
+
+import com.azure.core.annotation.ServiceInterface;
+import reactor.core.publisher.Mono;
+
+
+/**
+ * Mock Rest Proxy Service for Performance Testing.
+ */
+@Host("https://unused")
+@ServiceInterface(name = "MyMockService")
+public interface MyRestProxyService {
+
+ /**
+ * List all the subscriptions
+ * @return A {@link Mono} containing Void.
+ */
+ @Get("ListSubscriptions")
+ Mono listSubscriptions();
+}
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/package-info.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/package-info.java
new file mode 100644
index 000000000000..ba911ea58024
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/core/package-info.java
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+/**
+ * Core package of azure-core-experimental-perf.
+ */
+package com.azure.core.perf.core;
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/MockHttpResponse.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/MockHttpResponse.java
new file mode 100644
index 000000000000..011ec524ff50
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/MockHttpResponse.java
@@ -0,0 +1,151 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.perf.models;
+
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import com.azure.core.http.HttpHeaders;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.azure.core.util.serializer.JacksonAdapter;
+import com.azure.core.util.serializer.SerializerAdapter;
+import com.azure.core.util.serializer.SerializerEncoding;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Represents a Mock {@link HttpResponse} for performance testing.
+ */
+public class MockHttpResponse extends HttpResponse {
+ private static final SerializerAdapter SERIALIZER = new JacksonAdapter();
+
+ private final int statusCode;
+
+ private final HttpHeaders headers;
+
+ private final byte[] bodyBytes;
+
+ /**
+ * Creates an instance of {@link MockHttpResponse}
+ *
+ * @param request The Incoming request
+ * @param statusCode The response status code
+ * @param headers The headers of the response
+ * @param bodyBytes the body of the response
+ */
+ public MockHttpResponse(HttpRequest request, int statusCode, HttpHeaders headers, byte[] bodyBytes) {
+ super(request);
+ this.statusCode = statusCode;
+ this.headers = headers;
+ this.bodyBytes = bodyBytes;
+ }
+
+ /**
+ * Creates an instance of {@link MockHttpResponse}
+ *
+ * @param request The Incoming request
+ * @param statusCode The response status code
+ */
+ public MockHttpResponse(HttpRequest request, int statusCode) {
+ this(request, statusCode, new HttpHeaders(), new byte[0]);
+ }
+
+ /**
+ * Creates an instance of {@link MockHttpResponse}
+ *
+ * @param request The Incoming request
+ * @param statusCode The response status code
+ * @param headers The headers of the response
+ */
+ public MockHttpResponse(HttpRequest request, int statusCode, HttpHeaders headers) {
+ this(request, statusCode, headers, new byte[0]);
+ }
+
+ /**
+ * Creates an instance of {@link MockHttpResponse}
+ *
+ * @param request The Incoming request
+ * @param statusCode The response status code
+ * @param headers The headers of the response
+ * @param serializable the serializable body data
+ */
+ public MockHttpResponse(HttpRequest request, int statusCode, HttpHeaders headers, Object serializable) {
+ this(request, statusCode, headers, serialize(serializable));
+ }
+
+ /**
+ * Creates an instance of {@link MockHttpResponse}
+ *
+ * @param request The Incoming request
+ * @param statusCode The response status code
+ * @param serializable the serializable body data
+ */
+ public MockHttpResponse(HttpRequest request, int statusCode, Object serializable) {
+ this(request, statusCode, new HttpHeaders(), serialize(serializable));
+ }
+
+ private static byte[] serialize(Object serializable) {
+ byte[] result = null;
+ try {
+ final String serializedString = SERIALIZER.serialize(serializable, SerializerEncoding.JSON);
+ result = serializedString == null ? null : serializedString.getBytes(StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ @Override
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ @Override
+ public String getHeaderValue(String name) {
+ return headers.getValue(name);
+ }
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return new HttpHeaders(headers);
+ }
+
+ @Override
+ public Mono getBodyAsByteArray() {
+ if (bodyBytes == null) {
+ return Mono.empty();
+ } else {
+ return Mono.just(bodyBytes);
+ }
+ }
+
+ @Override
+ public Flux getBody() {
+ if (bodyBytes == null) {
+ return Flux.empty();
+ } else {
+ return Flux.just(ByteBuffer.wrap(bodyBytes));
+ }
+ }
+
+ @Override
+ public Mono getBodyAsString() {
+ return getBodyAsString(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public Mono getBodyAsString(Charset charset) {
+ if (bodyBytes == null) {
+ return Mono.empty();
+ } else {
+ return Mono.just(new String(bodyBytes, charset));
+ }
+ }
+}
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/package-info.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/package-info.java
new file mode 100644
index 000000000000..9685e18b91a1
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/models/package-info.java
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+/**
+ * Models package of azure-core-experimental-perf.
+ */
+package com.azure.core.perf.models;
diff --git a/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/package-info.java b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/package-info.java
new file mode 100644
index 000000000000..f79b92072f23
--- /dev/null
+++ b/sdk/core/azure-core-experimental-perf/src/main/java/com/azure/core/perf/package-info.java
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+/**
+ * Performance Test package of azure-core-experimental-perf.
+ */
+package com.azure.core.perf;
diff --git a/sdk/core/pom.xml b/sdk/core/pom.xml
index 31612387f1ca..ac47db15467c 100644
--- a/sdk/core/pom.xml
+++ b/sdk/core/pom.xml
@@ -123,6 +123,7 @@
azure-core-amqp
azure-core-amqp-experimental
azure-core-experimental
+ azure-core-experimental-perf
azure-core-http-jdk-httpclient
azure-core-http-netty
azure-core-http-okhttp
diff --git a/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/ReadCache.java b/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/ReadCache.java
index e3a87ea9fe68..db7b7ff0b4d8 100644
--- a/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/ReadCache.java
+++ b/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/ReadCache.java
@@ -16,6 +16,7 @@ public ReadCache(PerfStressOptions options) {
super(options);
credential = new SharedTokenCacheCredentialBuilder()
.clientId(CLI_CLIENT_ID)
+ .tokenCachePersistenceOptions(TOKEN_CACHE_PERSISTENCE_OPTIONS)
.build();
}
diff --git a/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/core/ServiceTest.java b/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/core/ServiceTest.java
index 6b2ac25f18e4..031d0d181bb8 100644
--- a/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/core/ServiceTest.java
+++ b/sdk/identity/azure-identity-perf/src/main/java/com/azure/identity/perf/core/ServiceTest.java
@@ -6,6 +6,7 @@
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.InteractiveBrowserCredential;
import com.azure.identity.InteractiveBrowserCredentialBuilder;
+import com.azure.identity.TokenCachePersistenceOptions;
import com.azure.perf.test.core.PerfStressOptions;
import com.azure.perf.test.core.PerfStressTest;
import reactor.core.publisher.Mono;
@@ -14,9 +15,12 @@ public abstract class ServiceTest extends Pe
protected static final String CLI_CLIENT_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
protected static final TokenRequestContext ARM_TOKEN_REQUEST_CONTEXT = new TokenRequestContext()
.addScopes("https://management.azure.com/.default");
+ protected static final TokenCachePersistenceOptions TOKEN_CACHE_PERSISTENCE_OPTIONS =
+ new TokenCachePersistenceOptions().setName("azure-identity-perf-test");
private InteractiveBrowserCredential interactiveBrowserCredential = new InteractiveBrowserCredentialBuilder()
.port(8765)
+ .tokenCachePersistenceOptions(TOKEN_CACHE_PERSISTENCE_OPTIONS)
.clientId(CLI_CLIENT_ID)
.build();