From be5f2d0acf413de846443aacbda2c0d615606f1c Mon Sep 17 00:00:00 2001 From: Simon Oberzier Date: Wed, 12 Aug 2026 13:40:49 +0200 Subject: [PATCH] More realsitic tests --- pom.xml | 9 -- src/test/java/de/asedem/HttpTestServer.java | 70 +++++++++++++ .../java/de/asedem/rest/HttpMethodeTest.java | 23 +++++ .../java/de/asedem/rest/RestResponseTest.java | 42 ++++++++ src/test/java/de/asedem/rest/RestTest.java | 88 +++++++++++++++++ .../de/asedem/service/ChatServiceTest.java | 68 ++++++------- .../de/asedem/service/CopyServiceTest.java | 47 ++++----- .../de/asedem/service/CreateServiceTest.java | 48 ++++----- .../de/asedem/service/DeleteServiceTest.java | 46 ++++----- .../de/asedem/service/EmbedServiceTest.java | 59 +++++------ .../asedem/service/GenerateServiceTest.java | 83 +++++++--------- .../asedem/service/ListModelsServiceTest.java | 96 +++++++++--------- .../de/asedem/service/PullServiceTest.java | 47 ++++----- .../de/asedem/service/PushServiceTest.java | 47 ++++----- .../service/RunningModelsServiceTest.java | 99 +++++++++---------- .../asedem/service/ShowInfoServiceTest.java | 68 +++++++------ .../de/asedem/service/VersionServiceTest.java | 44 ++++----- 17 files changed, 558 insertions(+), 426 deletions(-) create mode 100644 src/test/java/de/asedem/HttpTestServer.java create mode 100644 src/test/java/de/asedem/rest/HttpMethodeTest.java create mode 100644 src/test/java/de/asedem/rest/RestResponseTest.java create mode 100644 src/test/java/de/asedem/rest/RestTest.java diff --git a/pom.xml b/pom.xml index 7439d11..d40d32a 100644 --- a/pom.xml +++ b/pom.xml @@ -38,12 +38,6 @@ 5.9.2 test - - org.mockito - mockito-junit-jupiter - 5.7.0 - test - @@ -58,9 +52,6 @@ org.apache.maven.plugins maven-surefire-plugin 3.5.0 - - @{argLine} -Dnet.bytebuddy.experimental=true - diff --git a/src/test/java/de/asedem/HttpTestServer.java b/src/test/java/de/asedem/HttpTestServer.java new file mode 100644 index 0000000..064ba3e --- /dev/null +++ b/src/test/java/de/asedem/HttpTestServer.java @@ -0,0 +1,70 @@ +package de.asedem; + +import com.sun.net.httpserver.HttpServer; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Minimal in-process HTTP server used to exercise the real {@link de.asedem.rest.Rest} + * client end-to-end without mocking it. Each test configures the response body/status + * and can inspect the captured request. + */ +public class HttpTestServer implements AutoCloseable { + + private final HttpServer server; + private volatile Response response = new Response(200, ""); + private final AtomicReference lastMethod = new AtomicReference<>(); + private final AtomicReference lastPath = new AtomicReference<>(); + private final AtomicReference lastBody = new AtomicReference<>(); + + public HttpTestServer() throws IOException { + server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0); + server.createContext("/", exchange -> { + lastMethod.set(exchange.getRequestMethod()); + lastPath.set(exchange.getRequestURI().getPath()); + final String method = exchange.getRequestMethod(); + if ("POST".equals(method) || "PUT".equals(method) || "DELETE".equals(method) || "PATCH".equals(method)) { + try (var stream = exchange.getRequestBody()) { + lastBody.set(new String(stream.readAllBytes(), StandardCharsets.UTF_8)); + } + } + final byte[] payload = response.body().getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(response.status(), payload.length); + try (var stream = exchange.getResponseBody()) { + stream.write(payload); + } + }); + server.start(); + } + + public int getPort() { + return server.getAddress().getPort(); + } + + public void setResponse(int status, String body) { + this.response = new Response(status, body); + } + + public String getLastMethod() { + return lastMethod.get(); + } + + public String getLastPath() { + return lastPath.get(); + } + + public String getLastBody() { + return lastBody.get(); + } + + @Override + public void close() { + server.stop(0); + } + + private record Response(int status, String body) { + } +} diff --git a/src/test/java/de/asedem/rest/HttpMethodeTest.java b/src/test/java/de/asedem/rest/HttpMethodeTest.java new file mode 100644 index 0000000..22229aa --- /dev/null +++ b/src/test/java/de/asedem/rest/HttpMethodeTest.java @@ -0,0 +1,23 @@ +package de.asedem.rest; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class HttpMethodeTest { + + @Test + void testGetString() { + assertEquals("GET", HttpMethode.GET.get()); + } + + @Test + void testPostString() { + assertEquals("POST", HttpMethode.POST.get()); + } + + @Test + void testDeleteString() { + assertEquals("DELETE", HttpMethode.DELETE.get()); + } +} diff --git a/src/test/java/de/asedem/rest/RestResponseTest.java b/src/test/java/de/asedem/rest/RestResponseTest.java new file mode 100644 index 0000000..cba3f75 --- /dev/null +++ b/src/test/java/de/asedem/rest/RestResponseTest.java @@ -0,0 +1,42 @@ +package de.asedem.rest; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class RestResponseTest { + + @Test + void testStatusCodeAndBody() { + final RestResponse response = new RestResponse(200, "hello"); + + assertEquals(200, response.getStatusCode()); + assertEquals("hello", response.asValueString()); + } + + @Test + void testAsJavaObjectParsesJson() throws JsonProcessingException { + final RestResponse response = new RestResponse(200, "{\"value\":42}"); + + final Map map = response.asJavaObject(Map.class); + + assertEquals(42, map.get("value")); + } + + @Test + void testAsJavaObjectReturnsNullForNullBody() throws JsonProcessingException { + final RestResponse response = new RestResponse(200, null); + + assertNull(response.asJavaObject(Map.class)); + } + + @Test + void testAsJavaObjectThrowsOnInvalidJson() { + final RestResponse response = new RestResponse(200, "not json"); + + assertThrows(JsonProcessingException.class, () -> response.asJavaObject(Map.class)); + } +} diff --git a/src/test/java/de/asedem/rest/RestTest.java b/src/test/java/de/asedem/rest/RestTest.java new file mode 100644 index 0000000..e2afc9f --- /dev/null +++ b/src/test/java/de/asedem/rest/RestTest.java @@ -0,0 +1,88 @@ +package de.asedem.rest; + +import de.asedem.HttpTestServer; +import org.junit.jupiter.api.Test; + +import java.net.URL; + +import static org.junit.jupiter.api.Assertions.*; + +class RestTest { + + @Test + void testGetRequest() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, "{\"ok\":true}"); + + final RestResponse response = Rest.requestSync( + new URL("http://127.0.0.1:" + server.getPort() + "/api/tags"), HttpMethode.GET); + + assertEquals(200, response.getStatusCode()); + assertEquals("{\"ok\":true}", response.asValueString()); + assertEquals("GET", server.getLastMethod()); + assertNull(server.getLastBody()); + } + } + + @Test + void testPostRequestSendsBody() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, "{\"ok\":true}"); + + final RestResponse response = Rest.requestSync( + new URL("http://127.0.0.1:" + server.getPort() + "/api/generate"), + HttpMethode.POST, new GenerateBody("llama2", "hi")); + + assertEquals(200, response.getStatusCode()); + assertTrue(server.getLastBody().contains("\"model\":\"llama2\"")); + } + } + + @Test + void testDeleteRequest() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, ""); + + final RestResponse response = Rest.requestSync( + new URL("http://127.0.0.1:" + server.getPort() + "/api/delete"), + HttpMethode.DELETE, new DeleteBody("llama2")); + + assertEquals(200, response.getStatusCode()); + assertEquals("DELETE", server.getLastMethod()); + } + } + + @Test + void testErrorStatusReturnsStatusCodeAndNoBody() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(404, "not found"); + + final RestResponse response = Rest.requestSync( + new URL("http://127.0.0.1:" + server.getPort() + "/api/copy"), + HttpMethode.POST, new CopyBody("a", "b")); + + assertEquals(404, response.getStatusCode()); + assertNull(response.asValueString()); + } + } + + @Test + void testThrowsOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); + + assertThrows(java.io.IOException.class, () -> Rest.requestSync( + new URL("http://127.0.0.1:" + port + "/api/tags"), HttpMethode.GET)); + } + } + + record GenerateBody(String model, String prompt) { + } + + record DeleteBody(String name) { + } + + record CopyBody(String source, String destination) { + } +} diff --git a/src/test/java/de/asedem/service/ChatServiceTest.java b/src/test/java/de/asedem/service/ChatServiceTest.java index eaafb8c..8163d82 100644 --- a/src/test/java/de/asedem/service/ChatServiceTest.java +++ b/src/test/java/de/asedem/service/ChatServiceTest.java @@ -1,18 +1,13 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.ChatRequest; import de.asedem.model.ChatResponse; import de.asedem.model.Message; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import java.io.IOException; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -25,31 +20,27 @@ class ChatServiceTest { ); @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/chat"), - HttpMethode.POST, request, 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "model": "llama3.2", - "created_at": "2023-12-12T14:13:43.416799Z", - "message": { - "role": "assistant", - "content": "Hello! How are you today?" - }, - "done": true, - "total_duration": 5191566416, - "load_duration": 2154458, - "prompt_eval_count": 26, - "prompt_eval_duration": 383809000, - "eval_count": 298, - "eval_duration": 4799921000 - } - """)); + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "model": "llama3.2", + "created_at": "2023-12-12T14:13:43.416799Z", + "message": { + "role": "assistant", + "content": "Hello! How are you today?" + }, + "done": true, + "total_duration": 5191566416, + "load_duration": 2154458, + "prompt_eval_count": 26, + "prompt_eval_duration": 383809000, + "eval_count": 298, + "eval_duration": 4799921000 + } + """); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final ChatResponse response = ollama.chat(request); assertEquals("llama3.2", response.model()); @@ -58,18 +49,21 @@ void testMethodCall() { assertTrue(response.done()); assertEquals(5191566416L, response.totalDuration()); assertEquals(4799921000L, response.evalDuration()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/chat", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"llama3.2\"")); + assertTrue(server.getLastBody().contains("\"stream\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/chat"), - HttpMethode.POST, request, 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.chat(request)); } diff --git a/src/test/java/de/asedem/service/CopyServiceTest.java b/src/test/java/de/asedem/service/CopyServiceTest.java index a7c5c92..2f91740 100644 --- a/src/test/java/de/asedem/service/CopyServiceTest.java +++ b/src/test/java/de/asedem/service/CopyServiceTest.java @@ -1,57 +1,48 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; class CopyServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, ""); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/copy"), - HttpMethode.POST, new CopyService.CopyRequest("llama2:latest", "llama2:copy"))) - .thenReturn(new RestResponse(200, "")); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); assertTrue(ollama.copy("llama2:latest", "llama2:copy")); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/copy", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"source\":\"llama2:latest\"")); + assertTrue(server.getLastBody().contains("\"destination\":\"llama2:copy\"")); } } @Test - void testFalseIfNotSuccessful() { + void testFalseIfNotSuccessful() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(404, ""); - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/copy"), - HttpMethode.POST, new CopyService.CopyRequest("llama2:latest", "llama2:copy"))) - .thenReturn(new RestResponse(404, "")); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); assertFalse(ollama.copy("llama2:latest", "llama2:copy")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/copy"), - HttpMethode.POST, new CopyService.CopyRequest("llama2:latest", "llama2:copy"))) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.copy("llama2:latest", "llama2:copy")); } diff --git a/src/test/java/de/asedem/service/CreateServiceTest.java b/src/test/java/de/asedem/service/CreateServiceTest.java index fe818d5..56a83b0 100644 --- a/src/test/java/de/asedem/service/CreateServiceTest.java +++ b/src/test/java/de/asedem/service/CreateServiceTest.java @@ -1,17 +1,11 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.CreateRequest; import de.asedem.model.CreateResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; @@ -20,34 +14,34 @@ class CreateServiceTest { private final CreateRequest request = new CreateRequest("mario", "llama3.2"); @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/create"), - HttpMethode.POST, request, 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "status": "success" - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "status": "success" + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final CreateResponse response = ollama.create(request); assertEquals("success", response.status()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/create", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"mario\"")); + assertTrue(server.getLastBody().contains("\"from\":\"llama3.2\"")); + assertTrue(server.getLastBody().contains("\"stream\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/create"), - HttpMethode.POST, request, 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.create(request)); } diff --git a/src/test/java/de/asedem/service/DeleteServiceTest.java b/src/test/java/de/asedem/service/DeleteServiceTest.java index 8187ca8..1504304 100644 --- a/src/test/java/de/asedem/service/DeleteServiceTest.java +++ b/src/test/java/de/asedem/service/DeleteServiceTest.java @@ -1,57 +1,47 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; class DeleteServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, ""); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/delete"), - HttpMethode.DELETE, new DeleteService.DeleteRequest("llama2:latest"))) - .thenReturn(new RestResponse(200, "")); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); assertTrue(ollama.delete("llama2:latest")); + + assertEquals("DELETE", server.getLastMethod()); + assertEquals("/api/delete", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"name\":\"llama2:latest\"")); } } @Test - void testFalseIfNotSuccessful() { + void testFalseIfNotSuccessful() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(404, ""); - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/delete"), - HttpMethode.DELETE, new DeleteService.DeleteRequest("llama2:latest"))) - .thenReturn(new RestResponse(404, "")); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); assertFalse(ollama.delete("llama2:latest")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/delete"), - HttpMethode.DELETE, new DeleteService.DeleteRequest("llama2:latest"))) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.delete("llama2:latest")); } diff --git a/src/test/java/de/asedem/service/EmbedServiceTest.java b/src/test/java/de/asedem/service/EmbedServiceTest.java index 5b6c956..d4977ec 100644 --- a/src/test/java/de/asedem/service/EmbedServiceTest.java +++ b/src/test/java/de/asedem/service/EmbedServiceTest.java @@ -1,17 +1,13 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.EmbedRequest; import de.asedem.model.EmbedResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import java.io.IOException; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -20,25 +16,21 @@ class EmbedServiceTest { private final EmbedRequest request = new EmbedRequest("all-minilm", "Why is the sky blue?"); @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/embed"), - HttpMethode.POST, request, 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "model": "all-minilm", - "embeddings": [ - [0.010071029, -0.0017594862, 0.05007221] - ], - "total_duration": 14143917, - "load_duration": 1019500, - "prompt_eval_count": 8 - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "model": "all-minilm", + "embeddings": [ + [0.010071029, -0.0017594862, 0.05007221] + ], + "total_duration": 14143917, + "load_duration": 1019500, + "prompt_eval_count": 8 + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final EmbedResponse response = ollama.embed(request); assertEquals("all-minilm", response.model()); @@ -46,18 +38,21 @@ void testMethodCall() { assertEquals(3, response.embeddings().getFirst().size()); assertEquals(14143917L, response.totalDuration()); assertEquals(8L, response.promptEvalCount()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/embed", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"all-minilm\"")); + assertTrue(server.getLastBody().contains("\"input\":\"Why is the sky blue?\"")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/embed"), - HttpMethode.POST, request, 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.embed(request)); } diff --git a/src/test/java/de/asedem/service/GenerateServiceTest.java b/src/test/java/de/asedem/service/GenerateServiceTest.java index 007cc48..83de069 100644 --- a/src/test/java/de/asedem/service/GenerateServiceTest.java +++ b/src/test/java/de/asedem/service/GenerateServiceTest.java @@ -1,61 +1,43 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.GenerationRequest; import de.asedem.model.GenerationResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; class GenerateServiceTest { private final GenerationRequest request = new GenerationRequest( - "llama:latest", + "llama2:latest", "Why is the sky blue?" ); @Test - void testStreamGenerationRequestConstruction() { - - assertTrue(new GenerateService.StreamGenerationRequest(this.request, true).stream()); - assertFalse(new GenerateService.StreamGenerationRequest(this.request, false).stream()); - } - - @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/generate"), - HttpMethode.POST, new GenerateService.StreamGenerationRequest(request, false), - 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "model": "llama2:7b", - "created_at": "2023-08-04T19:22:45.499127Z", - "response": "The sky is blue because it is the color of the sky.", - "context": [1, 2, 3], - "done": true, - "total_duration": 5589157167, - "load_duration": 3013701500, - "sample_count": 114, - "sample_duration": 81442000, - "prompt_eval_count": 46, - "prompt_eval_duration": 1160282000, - "eval_count": 13, - "eval_duration": 1325948000 - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "model": "llama2:7b", + "created_at": "2023-08-04T19:22:45.499127Z", + "response": "The sky is blue because it is the color of the sky.", + "context": [1, 2, 3], + "done": true, + "total_duration": 5589157167, + "load_duration": 3013701500, + "sample_count": 114, + "sample_duration": 81442000, + "prompt_eval_count": 46, + "prompt_eval_duration": 1160282000, + "eval_count": 13, + "eval_duration": 1325948000 + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final GenerationResponse response = ollama.generate(request); assertEquals("llama2:7b", response.model()); @@ -68,19 +50,22 @@ void testMethodCall() { assertEquals(1160282000L, response.promptEvalDuration()); assertEquals(13L, response.evalCount()); assertEquals(1325948000L, response.evalDuration()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/generate", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"llama2:latest\"")); + assertTrue(server.getLastBody().contains("\"prompt\":\"Why is the sky blue?\"")); + assertTrue(server.getLastBody().contains("\"stream\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/generate"), - HttpMethode.POST, new GenerateService.StreamGenerationRequest(request, false), - 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.generate(request)); } diff --git a/src/test/java/de/asedem/service/ListModelsServiceTest.java b/src/test/java/de/asedem/service/ListModelsServiceTest.java index b86b2af..94a8c2d 100644 --- a/src/test/java/de/asedem/service/ListModelsServiceTest.java +++ b/src/test/java/de/asedem/service/ListModelsServiceTest.java @@ -1,16 +1,11 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.Model; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import java.io.IOException; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -18,34 +13,31 @@ class ListModelsServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/tags"), HttpMethode.GET)) - .thenReturn(new RestResponse(200, """ - { - "models": [ - { - "modified_at": "2023-11-06T17:27:55.025369326+01:00", - "name": "llama2:latest", - "model": "llama2:latest", - "digest": "fe938a131f40e6f6d40083c9f0f430a515233eb2edaa6d72eb85c50d64f2300e", - "size": 3825819519, - "details": { - "parent_model": "", - "parameter_size": "7B", - "quantization_level": "Q4_0", - "format": "gguf", - "family": "llama", - "families": null - } - } - ] - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "models": [ + { + "modified_at": "2023-11-06T17:27:55.025369326+01:00", + "name": "llama2:latest", + "model": "llama2:latest", + "digest": "fe938a131f40e6f6d40083c9f0f430a515233eb2edaa6d72eb85c50d64f2300e", + "size": 3825819519, + "details": { + "parent_model": "", + "parameter_size": "7B", + "quantization_level": "Q4_0", + "format": "gguf", + "family": "llama", + "families": null + } + } + ] + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final List models = ollama.listModels(); assertEquals(1, models.size()); @@ -61,22 +53,23 @@ void testMethodCall() { assertEquals("gguf", models.getFirst().details().format()); assertEquals("llama", models.getFirst().details().family()); assertNull(models.getFirst().details().families()); + + assertEquals("GET", server.getLastMethod()); + assertEquals("/api/tags", server.getLastPath()); + assertNull(server.getLastBody()); } } @Test - void testEmptyListIfNoModelInstalled() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/tags"), HttpMethode.GET)) - .thenReturn(new RestResponse(200, """ - { - "models": [] - } - """)); - + void testEmptyListIfNoModelInstalled() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "models": [] + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final List models = ollama.listModels(); assertEquals(0, models.size()); @@ -84,13 +77,12 @@ void testEmptyListIfNoModelInstalled() { } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/tags"), HttpMethode.GET)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, ollama::listModels); } diff --git a/src/test/java/de/asedem/service/PullServiceTest.java b/src/test/java/de/asedem/service/PullServiceTest.java index e6b2600..b254eb6 100644 --- a/src/test/java/de/asedem/service/PullServiceTest.java +++ b/src/test/java/de/asedem/service/PullServiceTest.java @@ -1,17 +1,11 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.PullRequest; import de.asedem.model.PullResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; @@ -20,34 +14,33 @@ class PullServiceTest { private final PullRequest request = new PullRequest("llama3.2"); @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/pull"), - HttpMethode.POST, request, 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "status": "success" - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "status": "success" + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final PullResponse response = ollama.pull(request); assertEquals("success", response.status()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/pull", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"llama3.2\"")); + assertTrue(server.getLastBody().contains("\"stream\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/pull"), - HttpMethode.POST, request, 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.pull(request)); } diff --git a/src/test/java/de/asedem/service/PushServiceTest.java b/src/test/java/de/asedem/service/PushServiceTest.java index 52c6937..5ae3b5c 100644 --- a/src/test/java/de/asedem/service/PushServiceTest.java +++ b/src/test/java/de/asedem/service/PushServiceTest.java @@ -1,17 +1,11 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.PushRequest; import de.asedem.model.PushResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; @@ -20,34 +14,33 @@ class PushServiceTest { private final PushRequest request = new PushRequest("mattw/pygmalion:latest"); @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/push"), - HttpMethode.POST, request, 10000, 30000)) - .thenReturn(new RestResponse(200, """ - { - "status": "success" - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "status": "success" + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final PushResponse response = ollama.push(request); assertEquals("success", response.status()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/push", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"mattw/pygmalion:latest\"")); + assertTrue(server.getLastBody().contains("\"stream\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/push"), - HttpMethode.POST, request, 10000, 30000)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.push(request)); } diff --git a/src/test/java/de/asedem/service/RunningModelsServiceTest.java b/src/test/java/de/asedem/service/RunningModelsServiceTest.java index 767f881..e80b26e 100644 --- a/src/test/java/de/asedem/service/RunningModelsServiceTest.java +++ b/src/test/java/de/asedem/service/RunningModelsServiceTest.java @@ -1,17 +1,11 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.ProcessModel; -import de.asedem.model.RunningModelsResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import java.io.IOException; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -19,35 +13,32 @@ class RunningModelsServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/ps"), HttpMethode.GET)) - .thenReturn(new RestResponse(200, """ - { - "models": [ - { - "name": "mistral:latest", - "model": "mistral:latest", - "size": 5137025024, - "digest": "2ae6f6dd7a3dd734790bbbf58b8909a606e0e7e97e94b7604e0aa7ae4490e6d8", - "details": { - "parent_model": "", - "format": "gguf", - "family": "llama", - "families": ["llama"], - "parameter_size": "7.2B", - "quantization_level": "Q4_0" - }, - "expires_at": "2024-06-04T14:38:31.83753-07:00", - "size_vram": 5137025024 - } - ] - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "models": [ + { + "name": "mistral:latest", + "model": "mistral:latest", + "size": 5137025024, + "digest": "2ae6f6dd7a3dd734790bbbf58b8909a606e0e7e97e94b7604e0aa7ae4490e6d8", + "details": { + "parent_model": "", + "format": "gguf", + "family": "llama", + "families": ["llama"], + "parameter_size": "7.2B", + "quantization_level": "Q4_0" + }, + "expires_at": "2024-06-04T14:38:31.83753-07:00", + "size_vram": 5137025024 + } + ] + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final List models = ollama.runningModels(); assertEquals(1, models.size()); @@ -55,22 +46,23 @@ void testMethodCall() { assertEquals(5137025024L, models.getFirst().sizeVram()); assertNotNull(models.getFirst().details()); assertEquals("Q4_0", models.getFirst().details().quantizationLevel()); + + assertEquals("GET", server.getLastMethod()); + assertEquals("/api/ps", server.getLastPath()); + assertNull(server.getLastBody()); } } @Test - void testEmptyListIfNoModelRunning() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/ps"), HttpMethode.GET)) - .thenReturn(new RestResponse(200, """ - { - "models": [] - } - """)); - + void testEmptyListIfNoModelRunning() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "models": [] + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final List models = ollama.runningModels(); assertEquals(0, models.size()); @@ -78,13 +70,12 @@ void testEmptyListIfNoModelRunning() { } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/ps"), HttpMethode.GET)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, ollama::runningModels); } diff --git a/src/test/java/de/asedem/service/ShowInfoServiceTest.java b/src/test/java/de/asedem/service/ShowInfoServiceTest.java index c4d5d0d..712b624 100644 --- a/src/test/java/de/asedem/service/ShowInfoServiceTest.java +++ b/src/test/java/de/asedem/service/ShowInfoServiceTest.java @@ -1,59 +1,65 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.ModelInfo; -import de.asedem.model.ShowInfoRequest; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; class ShowInfoServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/show"), - HttpMethode.POST, new ShowInfoRequest("llama2:latest", false))) - .thenReturn(new RestResponse(200, """ - { - "license": "MIT", - "modelfile": "# Modelfile", - "parameters": "num_ctx 4096", - "template": "{{ .Prompt }}", - "capabilities": ["completion", "vision"] - } - """)); + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "license": "MIT", + "modelfile": "# Modelfile", + "parameters": "num_ctx 4096", + "template": "{{ .Prompt }}", + "details": { + "parent_model": "", + "format": "gguf", + "family": "llama", + "families": ["llama"], + "parameter_size": "8B", + "quantization_level": "Q4_0" + }, + "model_info": { + "general.architecture": "llama" + }, + "capabilities": ["completion", "vision"] + } + """); + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final ModelInfo modelInfo = ollama.showInfo("llama2:latest"); assertEquals("MIT", modelInfo.license()); assertEquals("# Modelfile", modelInfo.modelFile()); assertEquals("num_ctx 4096", modelInfo.parameters()); assertEquals("{{ .Prompt }}", modelInfo.template()); + assertNotNull(modelInfo.details()); + assertEquals("8B", modelInfo.details().parameterSize()); + assertEquals("llama", modelInfo.modelInfo().get("general.architecture")); assertEquals(2, modelInfo.capabilities().size()); + + assertEquals("POST", server.getLastMethod()); + assertEquals("/api/show", server.getLastPath()); + assertTrue(server.getLastBody().contains("\"model\":\"llama2:latest\"")); + assertTrue(server.getLastBody().contains("\"verbose\":false")); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/show"), - HttpMethode.POST, new ShowInfoRequest("llama2:latest", false))) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, () -> ollama.showInfo("llama2:latest")); } diff --git a/src/test/java/de/asedem/service/VersionServiceTest.java b/src/test/java/de/asedem/service/VersionServiceTest.java index 2be7395..b2b91df 100644 --- a/src/test/java/de/asedem/service/VersionServiceTest.java +++ b/src/test/java/de/asedem/service/VersionServiceTest.java @@ -1,48 +1,42 @@ package de.asedem.service; +import de.asedem.HttpTestServer; import de.asedem.Ollama; import de.asedem.exception.OllamaConnectionException; import de.asedem.model.VersionResponse; -import de.asedem.rest.HttpMethode; -import de.asedem.rest.Rest; -import de.asedem.rest.RestResponse; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import java.io.IOException; import static org.junit.jupiter.api.Assertions.*; class VersionServiceTest { @Test - void testMethodCall() { - - final Ollama ollama = Ollama.initDefault(); - - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/version"), HttpMethode.GET)) - .thenReturn(new RestResponse(200, """ - { - "version": "0.5.1" - } - """)); - + void testMethodCall() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + server.setResponse(200, """ + { + "version": "0.5.1" + } + """); + + final Ollama ollama = Ollama.init("http://127.0.0.1", server.getPort()); final VersionResponse response = ollama.version(); assertEquals("0.5.1", response.version()); + + assertEquals("GET", server.getLastMethod()); + assertEquals("/api/version", server.getLastPath()); + assertNull(server.getLastBody()); } } @Test - void testException() { - - final Ollama ollama = Ollama.initDefault(); + void testExceptionOnConnectionFailure() throws Exception { + try (HttpTestServer server = new HttpTestServer()) { + final int port = server.getPort(); + server.close(); - try (MockedStatic utilities = Mockito.mockStatic(Rest.class)) { - utilities.when(() -> Rest.requestSync(ollama.buildUrl("/api/version"), HttpMethode.GET)) - .thenThrow(new IOException()); + final Ollama ollama = Ollama.init("http://127.0.0.1", port); assertThrows(OllamaConnectionException.class, ollama::version); }