Ricardo Martinez created CAMEL-24772:
----------------------------------------

             Summary:  camel-jbang: 
OllamaDoctorSupportTest.detectReturnsNotRunningWhenEndpointUnreachable fails on 
any machine running Ollama
                 Key: CAMEL-24772
                 URL: https://issues.apache.org/jira/browse/CAMEL-24772
             Project: Camel
          Issue Type: Bug
          Components: camel-jbang
    Affects Versions: 4.23.0
            Reporter: Ricardo Martinez


h2. Problem

{{OllamaDoctorSupportTest.detectReturnsNotRunningWhenEndpointUnreachable}} 
fails deterministically on
any developer machine that has a local Ollama instance listening on the default 
port
{{localhost:11434}}:

{code}
[ERROR] OllamaDoctorSupportTest.detectReturnsNotRunningWhenEndpointUnreachable
org.opentest4j.AssertionFailedError:

Expecting value to be false but was true
        at 
OllamaDoctorSupportTest.detectReturnsNotRunningWhenEndpointUnreachable(OllamaDoctorSupportTest.java:49)
{code}

It fails on all three surefire attempts (the module sets 
{{rerunFailingTestsCount=2}}), so it is not
flaky — it is a hard, environment-dependent failure. It passes in CI only 
because CI hosts have no
Ollama running.

h2. Root cause

The test asserts that an unreachable endpoint yields {{running() == false}}:

{code:java}
LlmClient client = 
LlmClient.create().withApiType(LlmClient.ApiType.ollama).withUrl("http://127.0.0.1:1";);

OllamaDoctorSupport.Status status = OllamaDoctorSupport.detect(client);

assertThat(status.running()).isFalse();
{code}

The assumption is that {{withUrl(...)}} pins the client to that URL. It does 
not.
{{OllamaDoctorSupport.detect(client)}} delegates to 
{{LlmClient.detectEndpoint()}}, which is a
*discovery* method with deliberate fallbacks:

{code:java}
public boolean detectEndpoint() {
    boolean found;
    if (tryExplicitUrl()) {                 // http://127.0.0.1:1 -> fails, 
nothing is listening
        found = true;
    } else if (apiType != null) {
        found = switch (apiType) {
            ...
            case ollama -> tryInfraOllama() || tryDefaultOllama();   // <-- 
falls back to localhost:11434
        };
    }
    ...
}
{code}

So when the explicit URL is unreachable the client falls back to 
{{tryInfraOllama()}} (the
{{camel infra run ollama}} PID files) and then {{tryDefaultOllama()}} 
({{http://localhost:11434}}).
On a host with Ollama running, {{tryDefaultOllama()}} succeeds and 
{{running()}} is correctly
{{true}}.

The production behaviour is right — fallback discovery is the whole point of a 
{{camel doctor}}
probe, and the javadoc says so: _"Probes {{camel infra run ollama}} PID files 
and the default
{{http://localhost:11434}} endpoint."_ The *test* is what encodes a wrong 
assumption. As written it
cannot express "unreachable endpoint means not running" on any host, because 
the fallback will always
be consulted.

Note the other tests in the same class are not affected: they start a real 
local {{HttpServer}} on an
ephemeral port and assert {{running() == true}} plus a specific {{baseUrl}}, 
which holds regardless of
host state. Only the negative test is host-dependent.

h2. How to reproduce

{code}
# with Ollama running locally (default port)
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:11434/     # 200

mvn test -pl dsl/camel-jbang/camel-jbang-core -Dtest=OllamaDoctorSupportTest
{code}

Expected: pass. Actual: {{detectReturnsNotRunningWhenEndpointUnreachable}} 
fails.
Stopping Ollama makes it pass again.

h2. Suggested fix

Test-only change; no production code needs to change.

Option 1 — skip the assertion when the host itself provides a reachable default 
endpoint. Keeps the
CI coverage and matches the class's existing "no mocking framework" style:

{code:java}
@Test
void detectReturnsNotRunningWhenEndpointUnreachable() {
    // detectEndpoint() falls back to camel infra / localhost:11434, so this 
case is only
    // meaningful when the host has no Ollama of its own
    assumeFalse(defaultOllamaReachable(), "a local Ollama is running on the 
default port");
    ...
}
{code}

Option 2 — give {{LlmClient}} a package-private seam to disable fallback 
discovery, so the negative
path can be asserted unconditionally. More thorough, and makes the explicit-URL 
contract testable in
its own right, at the cost of a small production API addition.

Option 1 is probably enough. Either way the intent is worth a comment, since 
the next person to read
the test will make the same assumption.

_Claude Code on behalf of [~ricmarti]_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to