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

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


The following commit(s) were added to refs/heads/main by this push:
     new 21b3604c4e56 CAMEL-23688: camel-jbang - Tests for camel version list 
without downloads (#27978)
21b3604c4e56 is described below

commit 21b3604c4e56bbe8ddcc95d847bb604fa4f8031e
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 17 00:09:31 2026 +0200

    CAMEL-23688: camel-jbang - Tests for camel version list without downloads 
(#27978)
    
    Tests for camel version list (57% covered; its JSON was not tested),
    without downloads: the Camel releases the catalog knows, here the 4.10
    to 4.12 releases, which do not change any more. The table, JSON (and []),
    --patch=false, --lts, --eol=false, --from-date and --to-date, the order
    and --tail, and --date-format. They found these bugs, fixed here:
    
    * A --date-format that is not a date pattern showed the dates
      unformatted, and a --from-date or --to-date that is not a date was
      ignored; now usage errors.
    * The "Last updated" note was printed on stdout after the table; it goes
      to stderr.
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |   7 +
 .../jbang/core/commands/version/VersionList.java   |  30 +++-
 .../commands/version/VersionListReleasesTest.java  | 195 +++++++++++++++++++++
 3 files changed, 229 insertions(+), 3 deletions(-)

diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index fea6640a6d6b..9a60548ae164 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -608,6 +608,13 @@ prints the Kamelets as JSON, as the other `camel catalog` 
commands do.
   `2`: the first showed every error, the second none. The errors of 
`--diagram` are printed on stderr, and a graphical
   `--theme` in a terminal without graphics exits with `2`.
 
+=== camel-jbang - camel version list
+
+* `camel version list` prints the `Last updated` note on stderr, so stdout has 
the table only.
+* A `--date-format` that is not a date pattern, and a `--from-date` or 
`--to-date` that is not a date in the
+  `yyyy-MM-dd` format (such as `2025-01-31`), exit with `2`: the first showed 
the dates unformatted, and the others were
+  ignored.
+
 === camel-jbang - the shared action file is deprecated for plugin commands
 
 `CamelCommand.getActionFile` and `CamelCommand.getOutputFile`, the action and 
output files that all the clients of an
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
index c5dee1e0b7e9..a0e813d1c67f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/version/VersionList.java
@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
 import java.time.Duration;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -171,6 +172,18 @@ public class VersionList extends CamelCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // the options are wrong whatever the releases are, so before reading 
them
+        Comparator<Row> order = ORDER.comparator(sort);
+        if (dateFormat != null) {
+            try {
+                new SimpleDateFormat(dateFormat, Locale.US);
+            } catch (IllegalArgumentException e) {
+                throw CliException.usage("--date-format must be a date pattern 
such as dd-MM-yyyy, was: " + dateFormat);
+            }
+        }
+        requireDate("--from-date", fromDate);
+        requireDate("--to-date", toDate);
+
         // ensure from and to-version have major.minor
         if (fromVersion != null) {
             if (!(fromVersion.contains(".") || fromVersion.contains(","))) {
@@ -234,7 +247,7 @@ public class VersionList extends CamelCommand {
         }
 
         // sort rows
-        rows = rows.sorted(ORDER.comparator(sort));
+        rows = rows.sorted(order);
 
         List<Row> rowsList = rows.toList();
         if (tail > 0) {
@@ -295,16 +308,27 @@ public class VersionList extends CamelCommand {
                     }
                 }
             }
+            // not part of the table
             if (date != null) {
-                printer().println("Last updated: " + date + " (use --fresh to 
update list from internet)");
+                printer().printDiagnostic("Last updated: " + date + " (use 
--fresh to update list from internet)");
             } else {
-                printer().println("Last updated: none (use --fresh to update 
list from internet)");
+                printer().printDiagnostic("Last updated: none (use --fresh to 
update list from internet)");
             }
         }
 
         return 0;
     }
 
+    private static void requireDate(String option, String date) {
+        if (date != null) {
+            try {
+                LocalDate.parse(date, DateTimeFormatter.ofPattern(YYYY_MM_DD));
+            } catch (DateTimeParseException e) {
+                throw CliException.usage(option + " must be a date such as 
2025-01-31, was: " + date);
+            }
+        }
+    }
+
     public static JsonObject updateCheckerFile(JsonObject root, String 
runtime, String repositories) {
         if (repositories == null) {
             repositories = "";
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
new file mode 100644
index 000000000000..1d6321230a21
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/version/VersionListReleasesTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.dsl.jbang.core.commands.version;
+
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.apache.camel.dsl.jbang.core.commands.CamelCommandBaseTestSupport;
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.dsl.jbang.core.common.CliException;
+import org.apache.camel.dsl.jbang.core.common.CliExitCode;
+import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import picocli.CommandLine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/**
+ * camel version list without downloads: the Camel releases the catalog knows, 
here the 4.10 to 4.12 releases, which do
+ * not change any more, filtered and formatted.
+ */
+class VersionListReleasesTest extends CamelCommandBaseTestSupport {
+
+    @TempDir
+    Path home;
+
+    private Path previousHome;
+
+    @BeforeEach
+    void useHome() {
+        // without the file that says when the list was updated
+        previousHome = CommandLineHelper.getHomeDir();
+        CommandLineHelper.useHomeDir(home.toString());
+    }
+
+    @AfterEach
+    void restoreHome() {
+        CommandLineHelper.useHomeDir(previousHome.toString());
+    }
+
+    @Test
+    void theReleasesOfTheCatalog() throws Exception {
+        assertThat(command().doCall()).isZero();
+
+        String[] lines = printer.getStdout().split(System.lineSeparator());
+        assertThat(lines[0]).contains("CAMEL VERSION", "JDK", "KIND", 
"RELEASED", "SUPPORTED UNTIL", "DAYS");
+        // 4.10.0 to 4.10.9, 4.11.0 and 4.12.0
+        assertThat(lines).hasSize(13);
+        assertThat(lines[1]).contains("4.10.0", "17,21", "LTS", "February 
2025", "February 2026");
+        assertThat(lines[11]).contains("4.11.0", "April 
2025").doesNotContain("LTS");
+        assertThat(lines[12]).contains("4.12.0", "May 2025");
+        // not part of the table
+        assertThat(printer.getStderr()).isEqualTo("Last updated: none (use 
--fresh to update list from internet)");
+    }
+
+    @Test
+    void json() throws Exception {
+        assertThat(command("--json", "--to-version=4.10.1").doCall()).isZero();
+
+        JsonArray releases = Jsoner.deserialize(printer.getStdout(), 
(JsonArray) null);
+        assertThat(releases).hasSize(1);
+        JsonObject release = releases.getMap(0);
+        assertThat(release.getString("camelVersion")).isEqualTo("4.10.0");
+        assertThat(release.getString("runtime")).isEqualTo("main");
+        assertThat(release.getString("jdkVersion")).isEqualTo("17,21");
+        assertThat(release.getString("kind")).isEqualTo("lts");
+        assertThat(release.getString("releaseDate")).isEqualTo("2025-02-11");
+        assertThat(release.getString("eolDate")).isEqualTo("2026-02-10");
+        // the JSON is the output
+        assertThat(printer.getStderr()).isEmpty();
+    }
+
+    @Test
+    void jsonWithoutReleasesIsAnEmptyArray() throws Exception {
+        assertThat(command("--json", 
"--from-date=2030-01-01").doCall()).isZero();
+
+        assertThat(printer.getStdout()).isEqualTo("[]");
+    }
+
+    @Test
+    void withoutPatchReleases() throws Exception {
+        assertThat(command("--patch=false").doCall()).isZero();
+
+        assertThat(versions()).containsExactly("4.10.0", "4.11.0", "4.12.0");
+    }
+
+    @Test
+    void ltsOnly() throws Exception {
+        assertThat(command("--lts", "--patch=false").doCall()).isZero();
+
+        assertThat(versions()).containsExactly("4.10.0");
+    }
+
+    @Test
+    void withoutTheReleasesAtTheirEndOfLife() throws Exception {
+        // the 4.10 releases were supported until February 2026; the others 
have no end of life
+        assertThat(command("--eol=false").doCall()).isZero();
+
+        assertThat(versions()).containsExactly("4.11.0", "4.12.0");
+    }
+
+    @Test
+    void releasedBetweenTwoDates() throws Exception {
+        assertThat(command("--from-date=2025-04-01", 
"--to-date=2025-06-01").doCall()).isZero();
+
+        assertThat(versions()).containsExactly("4.10.4", "4.11.0", "4.12.0");
+    }
+
+    @Test
+    void theNewestFirstAndTheTail() throws Exception {
+        assertThat(command("--sort=-version", "--tail=2").doCall()).isZero();
+
+        // the end of the table: the oldest two
+        assertThat(versions()).containsExactly("4.10.1", "4.10.0");
+    }
+
+    @Test
+    void theDateFormat() throws Exception {
+        assertThat(command("--date-format=yyyy-MM-dd", "--days=false", 
"--to-version=4.10.1").doCall()).isZero();
+
+        String[] lines = printer.getStdout().split(System.lineSeparator());
+        assertThat(lines[0]).doesNotContain("DAYS");
+        assertThat(lines[1]).contains("4.10.0", "2025-02-11", "2026-02-10");
+    }
+
+    @Test
+    void aDateFormatThatIsNotAPatternIsAUsageError() {
+        VersionList command = command("--date-format=yyyy-bb");
+
+        assertThatThrownBy(command::doCall)
+                .isInstanceOfSatisfying(CliException.class,
+                        e -> 
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+                .hasMessage("--date-format must be a date pattern such as 
dd-MM-yyyy, was: yyyy-bb");
+    }
+
+    @Test
+    void aFromDateThatIsNotADateIsAUsageError() {
+        VersionList command = command("--from-date=last year");
+
+        assertThatThrownBy(command::doCall)
+                .isInstanceOfSatisfying(CliException.class,
+                        e -> 
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+                .hasMessage("--from-date must be a date such as 2025-01-31, 
was: last year");
+    }
+
+    @Test
+    void aToDateThatIsNotADateIsAUsageError() {
+        VersionList command = command("--to-date=31-12-2025");
+
+        assertThatThrownBy(command::doCall)
+                .isInstanceOfSatisfying(CliException.class,
+                        e -> 
assertThat(e.getExitCode()).isEqualTo(CliExitCode.USAGE))
+                .hasMessage("--to-date must be a date such as 2025-01-31, was: 
31-12-2025");
+    }
+
+    // the 4.10 to 4.12 releases, without downloading the releases since the 
catalog
+    private VersionList command(String... args) {
+        VersionList command = new VersionList(new 
CamelJBangMain().withPrinter(printer));
+        List<String> all = Stream.concat(Stream.of("--download=false", 
"--from-version=4.10", "--to-version=4.13"),
+                Arrays.stream(args)).toList();
+        // the last of an option given twice wins, as the arguments say
+        CommandLine cl = new CommandLine(command);
+        cl.setOverwrittenOptionsAllowed(true);
+        cl.parseArgs(all.toArray(String[]::new));
+        return command;
+    }
+
+    private List<String> versions() {
+        return 
Arrays.stream(printer.getStdout().split(System.lineSeparator())).skip(1)
+                .map(l -> l.strip().split("\\s+")[0]).toList();
+    }
+}

Reply via email to