Skip to content

Commit

Permalink
Merge pull request #1968 from rsvoboda/AsyncFile
Browse files Browse the repository at this point in the history
Make sure AsyncFile gets closed
  • Loading branch information
michalvavrik authored Sep 4, 2024
2 parents 84fee18 + e88a571 commit a416c75
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.quarkus.ts.http.advanced.reactive;

import java.io.File;
import java.util.UUID;

import jakarta.inject.Inject;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.smallrye.mutiny.Uni;
import io.vertx.core.file.OpenOptions;
import io.vertx.mutiny.core.Vertx;

@Path("/download")
public class DownloadResource {

private static final Logger LOGGER = LoggerFactory.getLogger(DownloadResource.class);
private static final String TEST_FILE = System.getProperty("java.io.tmpdir") +
File.separator + "DownloadResource-" + UUID.randomUUID().toString() + "-test.txt";
private static final OpenOptions READ_ONLY = new OpenOptions().setWrite(false).setCreate(false);

@Inject
Vertx vertx;

@POST
@Path("/create")
public Uni<Response> createFile() {
LOGGER.info("Creating test file: {}", TEST_FILE);
return vertx.fileSystem()
.createFile(TEST_FILE)
.onItem().transform(it -> Response.ok(TEST_FILE).build());
}

@DELETE
@Path("/delete")
public Uni<Response> deleteFile() {
LOGGER.info("Deleting test file: {}", TEST_FILE);
return vertx.fileSystem()
.delete(TEST_FILE)
.onItem().transform(it -> Response.noContent().build());
}

@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Uni<Response> downloadFile() {
LOGGER.info("Downloading test file: {}", TEST_FILE);
return vertx.fileSystem()
.open(TEST_FILE, READ_ONLY)
.onItem().transform(it -> Response.ok(it).build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.quarkus.ts.http.advanced.reactive;

import static io.restassured.RestAssured.given;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.scenarios.annotations.DisabledOnNative;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.response.Response;

/**
* Test makes sure AsyncFile gets closed, coverage triggered by https://github.com/quarkusio/quarkus/issues/41811
*/
@QuarkusScenario
@DisabledOnNative(reason = "To save resources on CI")
@DisabledOnOs(value = OS.WINDOWS, disabledReason = "No lsof command on Windows")
class DownloadResourceIT {
@QuarkusApplication(classes = { DownloadResource.class }, properties = "oidcdisable.properties")
static RestService app = new RestService();

@Test
void ensureAsyncFileGetsClosed() throws IOException {
Response response = app.given()
.when().post("/download/create")
.then()
.statusCode(200)
.extract().response();
String file = response.getBody().asString();

app.given()
.when().get("/download")
.then()
.statusCode(200);

ProcessBuilder lsofBuilder = new ProcessBuilder("lsof", file);
Process lsofProcess = lsofBuilder.start();
String lsofOutput = new BufferedReader(new InputStreamReader(lsofProcess.getInputStream())).lines()
.collect(Collectors.joining("\n"));

app.given()
.when().delete("/download/delete")
.then()
.statusCode(204);

Assert.assertEquals("AsyncFile is not closed, details:\n" + lsofOutput + "\n", 0, lsofOutput.length());
}

}

0 comments on commit a416c75

Please sign in to comment.