Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion azuremanaged/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.0'
testImplementation 'org.mockito:mockito-core:5.3.1'
testImplementation 'org.mockito:mockito-junit-jupiter:5.3.1'
testImplementation "io.grpc:grpc-netty:${grpcVersion}"
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
}

Expand All @@ -61,6 +62,7 @@ compileTestJava {

test {
useJUnitPlatform()
include '**/*Test.class'
}

publishing {
Expand Down Expand Up @@ -174,4 +176,5 @@ compileJava.dependsOn generateVersionInfo

tasks.named('sourcesJar') {
dependsOn generateVersionInfo
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public void start(ClientCall.Listener<RespT> responseListener, Metadata headers)
);

headers.put(
Metadata.Key.of("user-agent", Metadata.ASCII_STRING_MARSHALLER),
Metadata.Key.of("x-user-agent", Metadata.ASCII_STRING_MARSHALLER),
DurableTaskUserAgentUtil.getUserAgent()
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void start(ClientCall.Listener<RespT> responseListener, Metadata headers)
);

headers.put(
Metadata.Key.of("user-agent", Metadata.ASCII_STRING_MARSHALLER),
Metadata.Key.of("x-user-agent", Metadata.ASCII_STRING_MARSHALLER),
DurableTaskUserAgentUtil.getUserAgent()
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.microsoft.durabletask.azuremanaged;

import com.microsoft.durabletask.DurableTaskClient;
import com.microsoft.durabletask.DurableTaskGrpcClientBuilder;
import com.microsoft.durabletask.NewOrchestrationInstanceOptions;
import io.grpc.*;
import io.grpc.stub.ServerCalls;
import io.grpc.stub.StreamObserver;
import io.grpc.netty.NettyServerBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.*;

public class DurableTaskSchedulerClientExtensionsUserAgentTest {
private Server server;
private Channel channel;
private final AtomicReference<String> capturedUserAgent = new AtomicReference<>();
private static final String EXPECTED_USER_AGENT_PREFIX = "durabletask-java/";

// Dummy gRPC service definition
public static class DummyService implements io.grpc.BindableService {
@Override
public ServerServiceDefinition bindService() {
return ServerServiceDefinition.builder("TaskHubSidecarService")
.addMethod(
MethodDescriptor.<com.google.protobuf.Empty, com.google.protobuf.Empty>newBuilder()
.setType(MethodDescriptor.MethodType.UNARY)
.setFullMethodName(MethodDescriptor.generateFullMethodName("TaskHubSidecarService", "StartInstance"))
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(com.google.protobuf.Empty.getDefaultInstance()))
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(com.google.protobuf.Empty.getDefaultInstance()))
.build(),
ServerCalls.asyncUnaryCall(
new ServerCalls.UnaryMethod<com.google.protobuf.Empty, com.google.protobuf.Empty>() {
@Override
public void invoke(com.google.protobuf.Empty request, StreamObserver<com.google.protobuf.Empty> responseObserver) {
// Mock response for StartInstance
responseObserver.onNext(com.google.protobuf.Empty.getDefaultInstance());
responseObserver.onCompleted();
}
}
)
)
.build();
}
}

@BeforeEach
public void setUp() throws IOException {
// Use NettyServerBuilder to expose the server via HTTP
server = NettyServerBuilder.forPort(0)
.addService(new DummyService()) // Register DummyService
.intercept(new ServerInterceptor() {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
String userAgent = headers.get(Metadata.Key.of("x-user-agent", Metadata.ASCII_STRING_MARSHALLER));
capturedUserAgent.set(userAgent);
return next.startCall(call, headers);
}
})
.directExecutor()
.build()
.start();
int port = server.getPort();
String endpoint = "localhost:" + port;
DurableTaskSchedulerClientOptions options = new DurableTaskSchedulerClientOptions();
options.setEndpointAddress(endpoint);
options.setTaskHubName("testHub");
options.setAllowInsecureCredentials(true); // Netty is insecure for localhost
channel = options.createGrpcChannel();
}

@AfterEach
public void tearDown() {
if (server != null) server.shutdownNow();
if (channel != null && channel instanceof ManagedChannel) {
((ManagedChannel) channel).shutdownNow();
}
}

@Test
public void testUserAgentHeaderIsSet() {
DurableTaskGrpcClientBuilder builder = new DurableTaskGrpcClientBuilder();
builder.grpcChannel(channel);
DurableTaskClient client = builder.build();

// Schedule a new orchestration instance
String instanceId = client.scheduleNewOrchestrationInstance(
"TestOrchestration",
new NewOrchestrationInstanceOptions().setInput("TestInput"));

// Make a dummy call to trigger the request
String userAgent = capturedUserAgent.get();
assertNotNull(userAgent, "X-User-Agent header should be set");
assertTrue(userAgent.startsWith(EXPECTED_USER_AGENT_PREFIX), "X-User-Agent should start with durabletask-java/");
}
}

Loading