microcks / microcks-testcontainers-java

Java lib for Testcontainers that enables embedding Microcks into your JUnit tests with lightweight, throwaway instance thanks to containers.
https://microcks.io
Apache License 2.0
22 stars 5 forks source link

Artifact importing fails when path contains spaces #48

Closed frademacher closed 6 months ago

frademacher commented 6 months ago

Describe the bug

Hi all.

I'm using io.github.microcks:microcks-testcontainers:0.2.7 on a Linux Mint machine and the following code snippet to import an OpenAPI specification that resides in $SOME_PATH/src/test/resources/some_openapi_spec.json:

var microcks = new MicrocksContainer(DockerImageName.parse("quay.io/microcks/microcks-uber:" +
            microcksVersion));
microcks.withMainArtifacts("some_openapi_spec.json").start();

Unfortunately, the import fails when $SOME_PATH is a path segment that contains spaces, e.g., /home/florian/projects/example project. More precisely, an ArtifactLoadException is thrown whose cause is an IOException stating that Artifact /home/florian/projects/example%20project/some_openapi_spec.json does not exist or can't be read.

Expected behavior

microcks.withMainArtifacts("some_openapi_spec.json").start();

should result in a running instance of a Microcks testcontainer with file /home/florian/projects/example%20project/some_openapi_spec.json as an imported main artifact.

Actual behavior

As long as the absolute path of an artifact contains a space, an ArtifactLoadException will be thrown.

The root cause for this issue seems to be the implementation of MicrocksContainer.importArtifact() which creates a new File object by means of

..., new File(resource.getFile()), ...

in line 485. resource is however a URL and thus escapes spaces with %20 which File doesn't seem to support. A solution to this issue might be a conversion from URL to regular file path, e.g., via

..., new File(java.net.URLDecoder.decode(resource.getFile(), StandardCharsets.UTF_8.name())), ...

(see https://stackoverflow.com/a/56584903 for context and credit). At least for me, !artifact.exists() over at https://github.com/microcks/microcks-testcontainers-java/blob/19901df56b4e6cdd853994e789c8049d14a9b0e2/src/main/java/io/github/microcks/testcontainers/MicrocksContainer.java#L299 then doesn't return true.

How to Reproduce?

No response

Microcks version or git rev

0.2.7

Install method (docker-compose, helm chart, operator, docker-desktop extension,...)

Maven POM

Additional information

github-actions[bot] commented 6 months ago

👋 @frademacher

Welcome to the Microcks community! 💖

Thanks and congrats 🎉 for opening your first issue here! Be sure to follow the issue template or please update it accordingly.

📢 If you're using Microcks in your organization, please add your company name to this list. 🙏 It really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact.

If you need to know why and how to add yourself to the list, please read the blog post "Join the Microcks Adopters list and Empower the vibrant open source Community 🙌"

Hope you have a great time there!

🌟 ~~~~~ 🌟

📢 If you like Microcks, please ⭐ star ⭐ our repo to support it!

🙏 It really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact.

lbroudoux commented 6 months ago

Hey @frademacher!

Thanks for reporting this one and providing a detailed analysis. Will have a look at it ASAP.

frademacher commented 6 months ago

Awesome, thank you!

Just for the record, my current workaround is as follows:

@Test
void someTest() {
    ...
    microcks.start();
    microcks.importAsMainArtifact(getResourceArtifactFile("some_openapi_spec.json"));
    ...
}
...
private File getResourceArtifactFile(String artifactPath) {
    var resource = Thread.currentThread().getContextClassLoader().getResource(artifactPath);
    if (resource == null) {
        resource = MicrocksContainer.class.getClassLoader().getResource(artifactPath);
        if (resource == null)
            throw new MicrocksContainer.ArtifactLoadException("Error while importing artifact: " + artifactPath);
    }

    return new File(URLDecoder.decode(resource.getFile(), StandardCharsets.UTF_8));
}

getResourceArtifactFile is basically a copy of MicrocksContainer.importArtifact() that is local to my test class but returns the created File object.

lbroudoux commented 6 months ago

Hi there! 0.2.8 has been released with the suggested fix. Thanks for reporting it! It will be available on Maven central in a few minutes.

frademacher commented 6 months ago

Hi! Thank you for the blazingly fast fix of this issue! I can confirm that with 0.2.8 the import of artifacts with spaces in their full paths now works like a charm.