Skip to content

Commit

Permalink
chore: add Unit tests for selector controller (#46)
Browse files Browse the repository at this point in the history
Co-authored-by: Aliaksandr Stsiapanay <[email protected]>
  • Loading branch information
astsiapanay and astsiapanay authored Nov 22, 2023
1 parent 6208c6d commit c513091
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 2 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ dependencies {
implementation 'org.apache.jclouds:jclouds-allblobstore:2.5.0'

runtimeOnly 'com.epam.deltix:gflog-slf4j:3.0.0'
testImplementation 'org.mockito:mockito-core:5.4.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
testImplementation 'commons-io:commons-io:2.11.0'
testImplementation 'io.vertx:vertx-web-client:4.4.6'
testImplementation 'io.vertx:vertx-junit5:4.4.6'
testImplementation 'org.apache.jclouds.api:filesystem:2.5.0'
testImplementation 'org.mockito:mockito-core:5.7.0'
testImplementation 'org.mockito:mockito-junit-jupiter:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
}

Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/epam/aidial/core/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package com.epam.aidial.core.controller;

public interface Controller {
import java.io.Serializable;

/**
* Common interface for HTTP controllers.
* <p>
* Note. The interface must extends {@link Serializable} for exposing internal lambda fields in Unit tests.
* </p>
*/
public interface Controller extends Serializable {

void handle() throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
package com.epam.aidial.core.controller;

import com.epam.aidial.core.Proxy;
import com.epam.aidial.core.ProxyContext;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nullable;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class ControllerSelectorTest {

@Mock
private ProxyContext context;
@Mock
private Proxy proxy;

@Mock
private HttpServerRequest request;

@BeforeEach
public void beforeEach() {
when(context.getRequest()).thenReturn(request);
}

@Test
public void testSelectGetDeploymentController() {
when(request.path()).thenReturn("/openai/deployments/deployment1");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(DeploymentController.class, arg1);
assertEquals("deployment1", arg2);
}

@Test
public void testSelectGetDeploymentsController() {
when(request.path()).thenReturn("/openai/deployments");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(1, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
assertInstanceOf(DeploymentController.class, arg1);
assertEquals("getDeployments", lambda.getImplMethodName());
}

@Test
public void testSelectGetModelController() {
when(request.path()).thenReturn("/openai/models/model1");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(ModelController.class, arg1);
assertEquals("model1", arg2);
}

@Test
public void testSelectGetModelsController() {
when(request.path()).thenReturn("/openai/models");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(1, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
assertInstanceOf(ModelController.class, arg1);
assertEquals("getModels", lambda.getImplMethodName());
}

@Test
public void testSelectGetAddonController() {
when(request.path()).thenReturn("/openai/addons/addon1");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(AddonController.class, arg1);
assertEquals("addon1", arg2);
}

@Test
public void testSelectGetAddonsController() {
when(request.path()).thenReturn("/openai/addons");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(1, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
assertInstanceOf(AddonController.class, arg1);
assertEquals("getAddons", lambda.getImplMethodName());
}

@Test
public void testSelectGetAssistantController() {
when(request.path()).thenReturn("/openai/assistants/as1");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(AssistantController.class, arg1);
assertEquals("as1", arg2);
}

@Test
public void testSelectGetAssistantsController() {
when(request.path()).thenReturn("/openai/assistants");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(1, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
assertInstanceOf(AssistantController.class, arg1);
assertEquals("getAssistants", lambda.getImplMethodName());
}

@Test
public void testSelectGetApplicationController() {
when(request.path()).thenReturn("/openai/applications/app1");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(ApplicationController.class, arg1);
assertEquals("app1", arg2);
}

@Test
public void testSelectGetApplicationsController() {
when(request.path()).thenReturn("/openai/applications");
when(request.method()).thenReturn(HttpMethod.GET);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(1, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
assertInstanceOf(ApplicationController.class, arg1);
assertEquals("getApplications", lambda.getImplMethodName());
}

@Test
public void testSelectListMetadataFileController() {
when(request.path()).thenReturn("/v1/files/folder1/file1?purpose=metadata");
when(request.method()).thenReturn(HttpMethod.GET);
MultiMap params = mock(MultiMap.class);
when(request.params()).thenReturn(params);
when(params.get("purpose")).thenReturn("metadata");
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(2, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(FileMetadataController.class, arg1);
assertEquals("/folder1/file1?purpose=metadata", arg2);
}

@Test
public void testSelectDownloadFileController() {
when(request.path()).thenReturn("/v1/files/folder1/file1");
when(request.method()).thenReturn(HttpMethod.GET);
MultiMap params = mock(MultiMap.class);
when(request.params()).thenReturn(params);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(2, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(DownloadFileController.class, arg1);
assertEquals("/folder1/file1", arg2);
}

@Test
public void testSelectPostDeploymentController() {
when(request.path()).thenReturn("/openai/deployments/app1/completions");
when(request.method()).thenReturn(HttpMethod.POST);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(3, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
Object arg3 = lambda.getCapturedArg(2);
assertInstanceOf(DeploymentPostController.class, arg1);
assertEquals("app1", arg2);
assertEquals("completions", arg3);
}

@Test
public void testSelectUploadFileController() {
when(request.path()).thenReturn("/v1/files/folder1/file1");
when(request.method()).thenReturn(HttpMethod.POST);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(2, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(UploadFileController.class, arg1);
assertEquals("/folder1/file1", arg2);
}

@Test
public void testSelectDeleteFileController() {
when(request.path()).thenReturn("/v1/files/folder1/file1");
when(request.method()).thenReturn(HttpMethod.DELETE);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
assertEquals(2, lambda.getCapturedArgCount());
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(DeleteFileController.class, arg1);
assertEquals("/folder1/file1", arg2);
}

@Test
public void testSelectRateResponseController() {
when(request.path()).thenReturn("/v1/app/rate");
when(request.method()).thenReturn(HttpMethod.POST);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
SerializedLambda lambda = getSerializedLambda(controller);
assertNotNull(lambda);
Object arg1 = lambda.getCapturedArg(0);
Object arg2 = lambda.getCapturedArg(1);
assertInstanceOf(RateResponseController.class, arg1);
assertEquals("app", arg2);
}

@Test
public void testSelectRouteController() {
when(request.path()).thenReturn("/route/request");
when(request.method()).thenReturn(HttpMethod.POST);
Controller controller = ControllerSelector.select(proxy, context);
assertNotNull(controller);
assertInstanceOf(RouteController.class, controller);
}

@Nullable
private static SerializedLambda getSerializedLambda(Serializable lambda) {
for (Class<?> cl = lambda.getClass(); cl != null; cl = cl.getSuperclass()) {
try {
Method m = cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
Object replacement = m.invoke(lambda);
if (!(replacement instanceof SerializedLambda)) {
break;
}
return (SerializedLambda) replacement;
} catch (NoSuchMethodException e) {
// skip, continue
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
throw new IllegalStateException("Failed to call writeReplace", e);
}
}
return null;
}
}

0 comments on commit c513091

Please sign in to comment.