From 86cdf4d80e8f6b12037a310ccd1a0d42c0e19015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Mu=C3=B1oz=20Redondo?= <105782439+JaimeSeqLabs@users.noreply.github.com> Date: Mon, 28 Aug 2023 10:58:45 +0200 Subject: [PATCH] fix: add null guard in duration format helper + test (#324) --- .../seqera/tower/cli/utils/FormatHelper.java | 15 ++---- .../io/seqera/tower/cli/runs/TaskCmdTest.java | 24 +++++++++ .../runcmd/runs/task_detail_null_values.json | 53 +++++++++++++++++++ .../runcmd/runs/task_object_null_values.json | 51 ++++++++++++++++++ 4 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/runcmd/runs/task_detail_null_values.json create mode 100644 src/test/resources/runcmd/runs/task_object_null_values.json diff --git a/src/main/java/io/seqera/tower/cli/utils/FormatHelper.java b/src/main/java/io/seqera/tower/cli/utils/FormatHelper.java index d63b8d3c..89cd81c9 100644 --- a/src/main/java/io/seqera/tower/cli/utils/FormatHelper.java +++ b/src/main/java/io/seqera/tower/cli/utils/FormatHelper.java @@ -11,16 +11,7 @@ package io.seqera.tower.cli.utils; -import io.seqera.tower.model.ActionResponseDto; -import io.seqera.tower.model.ActionStatus; -import io.seqera.tower.model.ComputeEnvStatus; -import io.seqera.tower.model.ListActionsResponseActionInfo; -import io.seqera.tower.model.OrgRole; -import io.seqera.tower.model.ParticipantType; -import io.seqera.tower.model.PipelineDbDto; -import io.seqera.tower.model.WorkflowStatus; -import io.seqera.tower.model.ListLabelsResponse; -import io.seqera.tower.model.ListWorkflowsResponseListWorkflowsElement; +import io.seqera.tower.model.*; import picocli.CommandLine; import java.time.Duration; @@ -39,6 +30,10 @@ public static String formatDate(OffsetDateTime date) { } public static String formatDurationMillis(Long duration) { + if (duration == null) { + return ""; + } + Duration d = Duration.ofMillis(duration); long days = d.toDaysPart(); long hours = d.toHoursPart(); diff --git a/src/test/java/io/seqera/tower/cli/runs/TaskCmdTest.java b/src/test/java/io/seqera/tower/cli/runs/TaskCmdTest.java index 11674961..487112ea 100644 --- a/src/test/java/io/seqera/tower/cli/runs/TaskCmdTest.java +++ b/src/test/java/io/seqera/tower/cli/runs/TaskCmdTest.java @@ -54,4 +54,28 @@ void testTaskDetail(MockServerClient mock) throws JsonProcessingException { assertEquals(StringUtils.chop(new TaskView(general, command, environment, times, resources, usage).toString()), out.stdOut); assertEquals(0, out.exitCode); } + + @Test + void testTaskDetailWithNullValues(MockServerClient mock) throws JsonProcessingException { + mock.when( + request().withMethod("GET").withPath("/workflow/5J9pBnWd6uoC3w/task/1"), exactly(1) + ).respond( + response().withStatusCode(200).withBody(loadResource("runs/task_detail_null_values")).withContentType(MediaType.APPLICATION_JSON) + ); + + ExecOut out = exec(mock,"runs", "view", "-i", "5J9pBnWd6uoC3w", "task", "-t", "1", "--execution-time", "--resources-requested", "--resources-usage"); + + Task task = parseJson(new String(loadResource("runs/task_object_null_values")), Task.class); + + Map general = TaskCmd.parseGeneralData(task); + String command = task.getScript() != null ? task.getScript() : null; + String environment = task.getEnv() != null ? task.getEnv() : null; + Map times = TaskCmd.parseExecutionTimeData(task); + Map resources = TaskCmd.parseResourcesRequestedData(task); + Map usage = TaskCmd.parseResourcesUsageData(task); + + assertEquals("", out.stdErr); + assertEquals(StringUtils.chop(new TaskView(general, command, environment, times, resources, usage).toString()), out.stdOut); + assertEquals(0, out.exitCode); + } } diff --git a/src/test/resources/runcmd/runs/task_detail_null_values.json b/src/test/resources/runcmd/runs/task_detail_null_values.json new file mode 100644 index 00000000..7565cc71 --- /dev/null +++ b/src/test/resources/runcmd/runs/task_detail_null_values.json @@ -0,0 +1,53 @@ +{ + "task": { + "id": 232916258, + "taskId": 1, + "status": "COMPLETED", + "dateCreated": "2021-11-15T14:59:36Z", + "lastUpdated": "2021-11-15T15:06:58Z", + "submit": "2021-11-15T14:59:36Z", + "start": "2021-11-15T15:06:38Z", + "complete": "2021-11-15T15:06:58Z", + "attempt": 1, + "scratch": null, + "workdir": "s3://nextflow-ci/scratch/5J9pBnWd6uoC3w/38/2d0f03566d485112b53f082c477338", + "env": "PYTHONNOUSERSITE=1\nR_PROFILE_USER=/.Rprofile\nR_ENVIRON_USER=/.Renviron\n", + "cloudZone": "eu-west-1a", + "priceModel": "spot", + "cost": null, + "errorAction": null, + "exitStatus": 0, + "realtime": 0, + "nativeId": "ca1878f1-169c-4013-b30d-c5807ea1a3dd", + "pcpu": 63.6, + "pmem": 0, + "rss": 10067968, + "vmem": null, + "peakRss": 10067968, + "peakVmem": 33243136, + "rchar": 673556, + "wchar": 1428, + "syscr": 242, + "syscw": 17, + "readBytes": 7213056, + "writeBytes": 12288, + "volCtxt": 15, + "invCtxt": 4, + "process": "NFCORE_RNASEQ:RNASEQ:INPUT_CHECK:SAMPLESHEET_CHECK", + "disk": null, + "container": "quay.io/biocontainers/python:3.8.3", + "queue": "TowerForge-1voNN3Mve8r49Ek6hFCN5v-work", + "cpus": 1, + "memory": 6442450944, + "machineType": "r4.large", + "executor": "awsbatch", + "tag": "samplesheet_test.csv", + "time": null, + "duration": null, + "script": "\ncheck_samplesheet.py \\\n samplesheet_test.csv \\\n samplesheet.valid.csv\n\ncat <<-END_VERSIONS > versions.yml\nSAMPLESHEET_CHECK:\n python: $(python --version | sed 's/Python //g')\nEND_VERSIONS\n", + "module": [], + "hash": "38/2d0f03", + "exit": "0", + "name": "NFCORE_RNASEQ:RNASEQ:INPUT_CHECK:SAMPLESHEET_CHECK (samplesheet_test.csv)" + } +} \ No newline at end of file diff --git a/src/test/resources/runcmd/runs/task_object_null_values.json b/src/test/resources/runcmd/runs/task_object_null_values.json new file mode 100644 index 00000000..1941d2fb --- /dev/null +++ b/src/test/resources/runcmd/runs/task_object_null_values.json @@ -0,0 +1,51 @@ +{ + "id": 232916258, + "taskId": 1, + "status": "COMPLETED", + "dateCreated": "2021-11-15T14:59:36Z", + "lastUpdated": null, + "submit": "2021-11-15T14:59:36Z", + "start": "2021-11-15T15:06:38Z", + "complete": "2021-11-15T15:06:58Z", + "attempt": 1, + "scratch": null, + "workdir": "s3://nextflow-ci/scratch/5J9pBnWd6uoC3w/38/2d0f03566d485112b53f082c477338", + "env": "PYTHONNOUSERSITE=1\nR_PROFILE_USER=/.Rprofile\nR_ENVIRON_USER=/.Renviron\n", + "cloudZone": "eu-west-1a", + "priceModel": "spot", + "cost": null, + "errorAction": null, + "exitStatus": 0, + "realtime": 0, + "nativeId": "ca1878f1-169c-4013-b30d-c5807ea1a3dd", + "pcpu": 63.6, + "pmem": 0, + "rss": 10067968, + "vmem": null, + "peakRss": 10067968, + "peakVmem": 33243136, + "rchar": 673556, + "wchar": 1428, + "syscr": 242, + "syscw": 17, + "readBytes": 7213056, + "writeBytes": 12288, + "volCtxt": 15, + "invCtxt": 4, + "process": "NFCORE_RNASEQ:RNASEQ:INPUT_CHECK:SAMPLESHEET_CHECK", + "container": "quay.io/biocontainers/python:3.8.3", + "queue": "TowerForge-1voNN3Mve8r49Ek6hFCN5v-work", + "cpus": 1, + "memory": 6442450944, + "machineType": "r4.large", + "executor": "awsbatch", + "tag": "samplesheet_test.csv", + "disk": null, + "time": null, + "duration": null, + "script": "\ncheck_samplesheet.py \\\n samplesheet_test.csv \\\n samplesheet.valid.csv\n\ncat <<-END_VERSIONS > versions.yml\nSAMPLESHEET_CHECK:\n python: $(python --version | sed 's/Python //g')\nEND_VERSIONS\n", + "module": [], + "hash": "38/2d0f03", + "exit": "0", + "name": "NFCORE_RNASEQ:RNASEQ:INPUT_CHECK:SAMPLESHEET_CHECK (samplesheet_test.csv)" +} \ No newline at end of file