JUnit: FEGA
E2E_SUITE=java with E2E_TESTS_INTEGRATION=FEGA runs
no.elixir.e2eTests.FEGAIntegrationTest, nine @Order-ed tests covering the same ground as
e2e-fega in the same sequence: the fallback the coexistence period exists
for.
Running it in the container
Section titled “Running it in the container”-
Start with the JUnit runner
Terminal window E2E_SUITE=java E2E_TESTS_INTEGRATION=FEGA ./dev.sh startFEGAis the default test class, soE2E_TESTS_INTEGRATIONcan be dropped, andenv.shsupplies every other variable. -
Read the verdict
The result is the
e2e-testscontainer’s exit code, which./dev.sh startdoes not wait for. See the boot chain for how to follow the run.
why is there more than one selector?
E2E_SUITE picks the runner: go or java. E2E_TESTS_INTEGRATION picks the JUnit test
class; the Go runner uses its own E2E_ENV instead and ignores E2E_TESTS_INTEGRATION.
Choosing the environment is choosing the program (a test class here, a binary for Go), and
the entrypoint refuses an unknown value with a non-zero exit rather than falling back to a
default.
which nine tests does it run?
The same sequence as e2e-fega: the C1 forged-JWT check, upload via lega-commander,
ingest, accession, finalize, mapping, inbox cleanup, release, download.
why does it need keytool?
Before running anything the entrypoint imports the root CA into the JDK truststore with
keytool -importcert -file /storage/certs/rootCA.pem -cacerts -alias fega-root-ca, and logs
an info line and continues if the file is absent. The Go runner has no such step: it reads
the same PEM directly and builds its pools in process.
why do ingest and release die with a NullPointerException?
E2E_TESTS_TRUSTSTORE_PASSWORD is unset. It is load-bearing here and dead for Go:
CertificateUtils calls .toCharArray() on it when building the AMQPS context, so ingest,
accession, mapping and release all fail with a null-pointer dereference without it. env.sh
keeps it in a clearly marked JUnit-only block for exactly this reason, to be deleted with the
module (#851).
what command runs inside the container?
The suite is packaged as a fat jar and launched through the JUnit console:
java -jar e2eTests.jar execute --select-class no.elixir.e2eTests.FEGAIntegrationTest.
Running it from your IDE
Section titled “Running it from your IDE”E2E_TESTS_RUNTIME=local runs the suite outside the container: from IntelliJ IDEA’s green
play button on the test class, or by executing the jar on the host, while the stack itself
stays in docker. Usually the point is a debugger on localega-tsd-proxy or tsd-api-mock
rather than on the test, and the stack ships with JDWP already open on both, but the run
works the same without one.
-
Bring the stack up, and wait for it
Terminal window ./dev.sh startdocker compose -f e2e/docker-compose.yml psdev.sh startisdocker compose up --build -d, so it returns whileproxyanddoaare stillhealth: starting. Starting the tests before both reporthealthyproduces connection errors that look like the trust or endpoint problems below. Note this also runs the Go suite in thee2e-testscontainer, sinceE2E_SUITEdefaults togo; that is a separate run and does not interfere. -
Build and install
lega-commanderTerminal window (cd cli/lega-commander && go build -o /tmp/lega-commander .)sudo install /tmp/lega-commander /usr/local/bin/lega-commanderUploadViaLegaCMDTestshells out to the absolute path/usr/local/bin/lega-commander, so putting the binary anywhere else onPATHdoes not work. Without it the upload fails instantly withCannot run program, andFinalizeTestthen fails too because nothing was ever uploaded. -
Trust the stack’s root CA
dev.shdoes this for you. Run it with no arguments and pick 14) Replace RootCA:Terminal window ./dev.shThat copies
rootCA.pemout of thefile-orchestratorcontainer and imports it into your JDK’scacertsunder the aliasfega, finding the keystore fromJAVA_HOMEor falling back to the usual Linux and macOS locations. It deletes the alias first, so running it again after a stack rebuild is safe. It usessudo, because the system keystore is root-owned.The stack serves mkcert certificates, so until the host JVM trusts that CA every HTTPS call the suite makes fails PKIX validation.
Without root, copy the truststore instead of editing it and point the JVM at the copy. In IntelliJ the same two
-Dflags go in the run configuration’s VM options:Terminal window docker cp file-orchestrator:/storage/certs/rootCA.pem /tmp/rootCA.pemJDK_HOME=$(dirname "$(dirname "$(readlink -f "$(command -v keytool)")")")cp "$JDK_HOME/lib/security/cacerts" /tmp/fega-cacerts && chmod u+w /tmp/fega-cacertskeytool -importcert -noprompt -alias fega-root-ca \-file /tmp/rootCA.pem -keystore /tmp/fega-cacerts -storepass changeitexport JAVA_TOOL_OPTIONS="-Djavax.net.ssl.trustStore=/tmp/fega-cacerts -Djavax.net.ssl.trustStorePassword=changeit" -
Export the environment, in this order
Terminal window export E2E_TESTS_RUNTIME=localsource e2e/env.shThe order is load-bearing.
env.shreadsE2E_TESTS_RUNTIMEto decide whether to rewrite the endpoints, so exporting it after sourcing leaves every host on its in-network name and the run fails on connection errors. Launch IntelliJ from that shell, or copy the values into the run configuration’s environment. -
Run the test class
The green play button on
FEGAIntegrationTest, or from the same shell:Terminal window ./gradlew :e2eTests:test --tests no.elixir.e2eTests.FEGAIntegrationTest --rerun--testsis not optional::e2eTests:testhas no filter of its own, so without it Gradle also runsEgaDevIntegrationTest, which fails on theE2E_TESTS_EGA_DEV_*variablesenv.shships commented out, plus the vacuousGDIIntegrationTest.--rerunmatters from the second run on: environment variables are not task inputs, so Gradle otherwise reportsUP-TO-DATEwithout running anything, which reads as a pass. -
Attach a debugger, if that is why you are here
A Remote JVM Debug configuration pointed at
localhostand the port of the service you are chasing: proxy5005, tsd-api-mock5006, DOA8088.If you have not set one up before, Debugging a running Java app in Docker walks through it screen by screen, with the same flags and the same port. It starts its container with plain
docker run, which is the only part that differs: here the compose stack already carries the agent and publishes the port.
which ports do I attach to?
| Service | JDWP port |
|---|---|
proxy (localega-tsd-proxy) |
5005 |
tsd-api-mock |
5006 |
doa |
8088 |
All three are published by the compose stack and carry
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n in the container command.
do I have to enable JDWP first?
No. The agents are in the container commands and the ports are published; nothing needs
switching on. suspend=n means each service boots normally without waiting for a debugger,
so you attach and detach whenever you like and never have to race the stack coming up.
why does the suite fail as soon as it starts on my host?
E2E_TESTS_RUNTIME is still at its default, container, which uses the in-network service
names, so the suite resolves proxy and doa as hostnames and fails immediately outside
the docker network. local rewrites four endpoints onto localhost and the stack’s
published ports:
| Variable | Value under local |
|---|---|
E2E_TESTS_PROXY_HOST / _PORT |
localhost / 10443 |
E2E_TESTS_SDA_DOA_HOST / _PORT |
localhost / 80 |
E2E_TESTS_SDA_DB_HOST |
localhost |
E2E_TESTS_CEGAMQ_CONN_STR |
amqps://…@localhost:5673/… |
The last two are easy to overlook and carry the most: the database host is what
FinalizeTest asserts against, and the broker string is what every ingest, accession,
mapping and release message publishes to. Only the JUnit runner reads E2E_TESTS_RUNTIME,
and it is not an egadev switch.
why did four tests pass when nothing was uploaded?
Because four of the nine only publish a message to the CEGA broker and assert that the
publish succeeded. IngestTest, AccessionTest, MappingTest and ReleaseTest will all go
green against a stack that never received a file. Only FinalizeTest, InboxCleanupTest and
DownloadTest assert pipeline state, and UploadViaLegaCMDTest and
C1JwtSignatureVerificationTest talk to the proxy. So “4 passed, 5 failed” is not the suite
half working: it is the suite failing with four tests that cannot tell.
can I skip the CA import because the suite disables TLS verification?
No, and the code makes it look as though you could. BaseE2ETest.setupTestEnvironment does:
try (UnirestInstance instance = Unirest.primaryInstance()) { instance.config().verifySsl(false)...;}Try-with-resources closes the primary instance immediately, so verifySsl(false) never
applies to any later request. In the container this is invisible, because the entrypoint’s
keytool import makes the CA trusted anyway. On a host it is exactly what surfaces as PKIX
failures. The bug is in the retiring module and is recorded on
#851 rather than fixed.
doesn’t ./dev.sh start already run the suite in the container?
Yes, and there is no supported way to avoid it. e2e-tests is a service in the stack, dev.sh
brings the stack up with a bare docker compose up --build -d, and the compose file declares no
profiles, so nothing selects a subset. Your IDE run is therefore a second run alongside the
container one. That is harmless: each run namespaces itself by a UUID fixture name and random
accession and dataset ids, so the two do not collide. It is still wasted time and log noise on
every start, tracked in
known gaps.
can I run the jar instead of gradle?
Yes, and it needs the same steps 1 to 4. ./gradlew :e2eTests:jar builds
e2eTests/build/libs/e2eTests.jar with the JUnit ConsoleLauncher as its main class, so from
the same shell:
java -jar e2eTests/build/libs/e2eTests.jar execute --select-class no.elixir.e2eTests.FEGAIntegrationTest.
It selects the class directly, so no --tests filter and no --rerun are involved. One
difference worth knowing: the 10 MiB fixture and its .enc are written to the working
directory you launch from, whereas Gradle’s test worker writes them under e2eTests/. Neither
is gitignored, and they are only cleaned up if the run finishes.
Built from f91944d