This is an automated email from the ASF dual-hosted git repository.

aldettinger pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new c3ee20ad11 file: rewrite filter and idempotent tests from scratch for 
clarity and flakiness concern #3584
c3ee20ad11 is described below

commit c3ee20ad11ef7771246a0595042cfc4dd9e52bac
Author: aldettinger <[email protected]>
AuthorDate: Thu Jun 15 15:34:26 2023 +0200

    file: rewrite filter and idempotent tests from scratch for clarity and 
flakiness concern #3584
---
 .../quarkus/component/file/it/FileRoutes.java      | 25 ++++--
 .../camel/quarkus/component/file/it/FileTest.java  | 53 -------------
 .../quarkus/component/file/it/NonFlakyFileIT.java  | 24 ++++++
 .../component/file/it/NonFlakyFileTest.java        | 85 +++++++++++++++++++++
 .../file/it/NonFlakyFileTestResource.java          | 88 ++++++++++++++++++++++
 5 files changed, 217 insertions(+), 58 deletions(-)

diff --git 
a/integration-tests/file/src/main/java/org/apache/camel/quarkus/component/file/it/FileRoutes.java
 
b/integration-tests/file/src/main/java/org/apache/camel/quarkus/component/file/it/FileRoutes.java
index 6bae9b9b68..b7fbc796db 100644
--- 
a/integration-tests/file/src/main/java/org/apache/camel/quarkus/component/file/it/FileRoutes.java
+++ 
b/integration-tests/file/src/main/java/org/apache/camel/quarkus/component/file/it/FileRoutes.java
@@ -16,11 +16,15 @@
  */
 package org.apache.camel.quarkus.component.file.it;
 
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
 import jakarta.enterprise.context.ApplicationScoped;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.file.GenericFile;
 import org.apache.camel.component.file.GenericFileFilter;
 
+import static org.apache.camel.component.file.FileConstants.FILE_NAME_CONSUMED;
 import static 
org.apache.camel.quarkus.component.file.it.FileResource.CONSUME_BATCH;
 import static org.apache.camel.quarkus.component.file.it.FileResource.SORT_BY;
 
@@ -30,6 +34,8 @@ public class FileRoutes extends RouteBuilder {
     public static final String READ_LOCK_IN = "read-lock-in";
     public static final String READ_LOCK_OUT = "read-lock-out";
 
+    private static final Set<String> IDEMPOTENT_FILES_CONSUMED = 
ConcurrentHashMap.newKeySet();
+
     @Override
     public void configure() {
         from("file://target/" + READ_LOCK_IN + "?"
@@ -60,11 +66,20 @@ public class FileRoutes extends RouteBuilder {
                 .convertBodyTo(String.class)
                 .to("mock:charsetIsoRead");
 
-        
from("file://target/idempotent?idempotent=true&move=done/${file:name}&initialDelay=0&delay=10")
-                .convertBodyTo(String.class).to("mock:idempotent");
+        
from("file://target/test-files/idempotent?idempotent=true&move=done/${file:name}&initialDelay=0&delay=10")
+                .process(ex -> {
+                    String fileNameConsumed = 
ex.getMessage().getHeader(FILE_NAME_CONSUMED, String.class);
+                    if (IDEMPOTENT_FILES_CONSUMED.add(fileNameConsumed)) {
+                        
ex.getMessage().setHeader("fileNameConsumedStatusHeader", fileNameConsumed + 
"_was-read-once");
+                    } else {
+                        
ex.getMessage().setHeader("fileNameConsumedStatusHeader",
+                                fileNameConsumed + "_was-read-more-than-once");
+                    }
+                })
+                
.convertBodyTo(String.class).toD("mock:idempotent_${header.fileNameConsumedStatusHeader}");
 
         bindToRegistry("myFilter", new MyFileFilter<>());
-        from(("file://target/filter?initialDelay=0&delay=10&filter=#myFilter"))
+        
from(("file://target/test-files/filter?initialDelay=0&delay=10&filter=#myFilter"))
                 .convertBodyTo(String.class).to("mock:filter");
 
         
from(("file://target/sortBy?initialDelay=0&delay=10&sortBy=reverse:file:name"))
@@ -84,8 +99,8 @@ public class FileRoutes extends RouteBuilder {
             if (file.isDirectory()) {
                 return true;
             }
-            // we dont accept any files starting with skip in the name
-            return !file.getFileName().startsWith("skip");
+            // we do not accept any files having name starting with 'skipped_'
+            return !file.getFileName().startsWith("skipped_");
         }
     }
 }
diff --git 
a/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/FileTest.java
 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/FileTest.java
index 8517763f3d..d72738f7c3 100644
--- 
a/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/FileTest.java
+++ 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/FileTest.java
@@ -22,7 +22,6 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -111,58 +110,6 @@ class FileTest {
         });
     }
 
-    @Test
-    public void idempotent() throws IOException {
-        // Create a new file
-        String fileName01 = createFile(FILE_CONTENT_01, 
"/file/create/idempotent");
-
-        await().atMost(10, TimeUnit.SECONDS).until(
-                () -> RestAssured
-                        .get("/file/getFromMock/idempotent")
-                        .then()
-                        .extract().asString(),
-                equalTo(FILE_CONTENT_01));
-
-        // clear the mock to assert that FILE_CONTENT_01 will not be received 
again even if presented a second time to the route
-        RestAssured
-                .get("/file/resetMock/idempotent")
-                .then()
-                .statusCode(204);
-
-        // move file back
-        Path donePath = Paths.get(fileName01.replaceFirst("target/idempotent", 
"target/idempotent/done"));
-        Path targetPath = Paths.get(fileName01);
-        Files.move(donePath, targetPath, StandardCopyOption.ATOMIC_MOVE);
-        // register file for deletion after tests
-        pathsToDelete.add(targetPath);
-
-        // create another file, to receive only this one in the next check
-        createFile(FILE_CONTENT_02, "/file/create/idempotent");
-
-        // there should be no file in mock
-        await().atMost(10, TimeUnit.SECONDS).until(
-                () -> RestAssured
-                        .get("/file/getFromMock/idempotent")
-                        .then()
-                        .extract().asString(),
-                equalTo(FILE_CONTENT_02));
-    }
-
-    @Test
-    public void filter() throws IOException {
-        String fileName = createFile(FILE_CONTENT_01, "/file/create/filter", 
null, "skip_" + UUID.randomUUID().toString());
-        createFile(FILE_CONTENT_02, "/file/create/filter");
-
-        pathsToDelete.add(Paths.get(fileName));
-
-        await().atMost(10, TimeUnit.SECONDS).until(
-                () -> RestAssured
-                        .get("/file/getFromMock/filter")
-                        .then()
-                        .extract().asString(),
-                equalTo(FILE_CONTENT_02));
-    }
-
     @Test
     public void sortBy() throws IOException, InterruptedException {
         createFile(FILE_CONTENT_03, "/file/create/" + SORT_BY, null, "c_" + 
UUID.randomUUID().toString());
diff --git 
a/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileIT.java
 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileIT.java
new file mode 100644
index 0000000000..cfb323f4d8
--- /dev/null
+++ 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileIT.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.file.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class NonFlakyFileIT extends NonFlakyFileTest {
+
+}
diff --git 
a/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTest.java
 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTest.java
new file mode 100644
index 0000000000..eccfb3aaa8
--- /dev/null
+++ 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.file.it;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.concurrent.TimeUnit;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.quarkus.component.file.it.NonFlakyFileTestResource.FILTER_NON_SKIPPED_FILE_CONTENT;
+import static 
org.apache.camel.quarkus.component.file.it.NonFlakyFileTestResource.IDEMPOTENT_FILE_CONTENT;
+import static 
org.apache.camel.quarkus.component.file.it.NonFlakyFileTestResource.IDEMPOTENT_FILE_NAME;
+import static 
org.apache.camel.quarkus.component.file.it.NonFlakyFileTestResource.TEST_FILES_FOLDER;
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+/**
+ * This is an attempt to rewrite file tests from scratch in a cleaner way. It 
aims at having the test logic more
+ * separated and avoiding synchronization issues. On the long run we may 
evaluate whether this approach is really more
+ * readable and less flaky.
+ *
+ * Linked to https://github.com/apache/camel-quarkus/issues/3584
+ */
+@QuarkusTest
+@QuarkusTestResource(NonFlakyFileTestResource.class)
+class NonFlakyFileTest {
+
+    @Test
+    void idempotent() throws IOException, InterruptedException {
+
+        // Assert that the idempotent file has been read once
+        await().atMost(1, TimeUnit.SECONDS).until(
+                () -> RestAssured
+                        .get("/file/getFromMock/idempotent_" + 
IDEMPOTENT_FILE_NAME + "_was-read-once")
+                        .then()
+                        .extract().asString(),
+                equalTo(IDEMPOTENT_FILE_CONTENT));
+
+        // Atomically move the previously read idempotent file back to input 
folder
+        Path donePath = TEST_FILES_FOLDER.resolve(Paths.get("idempotent", 
"done", IDEMPOTENT_FILE_NAME));
+        Path targetPath = 
donePath.getParent().getParent().resolve(IDEMPOTENT_FILE_NAME);
+        Files.move(donePath, targetPath, StandardCopyOption.ATOMIC_MOVE);
+
+        // Let one second to ensure that the idempotent file is NOT read once 
again
+        Thread.sleep(1000L);
+        String result = RestAssured
+                .get("/file/getFromMock/idempotent_" + IDEMPOTENT_FILE_NAME + 
"_was-read-more-than-once")
+                .then()
+                .extract().asString();
+        assertNotEquals(IDEMPOTENT_FILE_CONTENT, result);
+    }
+
+    @Test
+    void filter() {
+        await().atMost(1, TimeUnit.SECONDS).until(
+                () -> RestAssured
+                        .get("/file/getFromMock/filter")
+                        .then()
+                        .extract().asString(),
+                equalTo(FILTER_NON_SKIPPED_FILE_CONTENT));
+    }
+
+}
diff --git 
a/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTestResource.java
 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTestResource.java
new file mode 100644
index 0000000000..3e70f22af6
--- /dev/null
+++ 
b/integration-tests/file/src/test/java/org/apache/camel/quarkus/component/file/it/NonFlakyFileTestResource.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.file.it;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import org.apache.commons.io.FileUtils;
+
+/**
+ * Ensures that all test files are created with expected content before camel 
routes starts to consume them.
+ */
+public class NonFlakyFileTestResource implements 
QuarkusTestResourceLifecycleManager {
+
+    static final Path TEST_FILES_FOLDER = Paths.get("target", "test-files");
+
+    static final String IDEMPOTENT_FILE_NAME = "moved-back-read-once";
+    static final String IDEMPOTENT_FILE_CONTENT = IDEMPOTENT_FILE_NAME + 
"-CONTENT";
+    static final String FILTER_NON_SKIPPED_FILE_NAME = "non-skipped-file";
+    static final String FILTER_NON_SKIPPED_FILE_CONTENT = 
FILTER_NON_SKIPPED_FILE_NAME + "-CONTENT";
+
+    private final List<Path> createdTestFiles = new ArrayList<Path>();
+
+    @Override
+    public Map<String, String> start() {
+        try {
+            FileUtils.deleteDirectory(TEST_FILES_FOLDER.toFile());
+
+            createTestFile("filter", FILTER_NON_SKIPPED_FILE_NAME);
+            createTestFile("filter", "skipped_file");
+
+            createTestFile("idempotent", IDEMPOTENT_FILE_NAME);
+
+            ensureAllTestFilesCreatedWithExpectedContent();
+        } catch (Exception ex) {
+            throw new RuntimeException("Problem while initializing test 
files", ex);
+        }
+        return null;
+    }
+
+    private void createTestFile(String testName, String testFileName) throws 
IOException {
+        Path testFilePath = TEST_FILES_FOLDER.resolve(Paths.get(testName, 
testFileName));
+        FileUtils.writeStringToFile(testFilePath.toFile(), testFileName + 
"-CONTENT", StandardCharsets.UTF_8);
+        createdTestFiles.add(testFilePath);
+    }
+
+    private void ensureAllTestFilesCreatedWithExpectedContent() {
+        for (Path path : createdTestFiles) {
+            try {
+                String content = FileUtils.readFileToString(path.toFile(), 
StandardCharsets.UTF_8);
+                String expectedContent = path.toFile().getName() + "-CONTENT";
+
+                if (!expectedContent.equals(content)) {
+                    String format = "The NonFlakyFileTestResource failed to 
create the test file %s with expected content";
+                    throw new RuntimeException(String.format(format, path));
+                }
+            } catch (IOException ioex) {
+                String format = "The NonFlakyFileTestResource has exception 
while creating the test file %s with expected content";
+                throw new RuntimeException(String.format(format, path), ioex);
+            }
+        }
+    }
+
+    @Override
+    public void stop() {
+    }
+
+}

Reply via email to