From 34c8bda0df83f5d007d98f2b01b56000e09be5c2 Mon Sep 17 00:00:00 2001 From: David Schmalzing Date: Fri, 10 Jan 2025 16:53:05 +0100 Subject: [PATCH] Fix nullpointer in case of missing start time --- .../monticore/gradle/StatisticListener.java | 55 ++++++++++++-- .../gradle/StatisticListenerTest.java | 74 +++++++++++++++++++ 2 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 monticore-generator/src/test/java/de/monticore/gradle/StatisticListenerTest.java diff --git a/monticore-generator/src/main/java/de/monticore/gradle/StatisticListener.java b/monticore-generator/src/main/java/de/monticore/gradle/StatisticListener.java index 701da7b315..0666732cfe 100644 --- a/monticore-generator/src/main/java/de/monticore/gradle/StatisticListener.java +++ b/monticore-generator/src/main/java/de/monticore/gradle/StatisticListener.java @@ -35,8 +35,8 @@ private static synchronized StatisticListener getSingleton() { public synchronized static void registerOnce(Project project) { if (alreadyRegistered.compareAndSet(false, true) - && (!project.hasProperty(StatisticListener.enable_tracking) - || "true".equals(project.getProperties().get(StatisticListener.enable_tracking)))) { + && (!project.hasProperty(StatisticListener.enable_tracking) + || "true".equals(project.getProperties().get(StatisticListener.enable_tracking)))) { project.getGradle().addListener(getSingleton()); } } @@ -47,7 +47,7 @@ public void buildStarted(Gradle gradle) { } - public void beforeSettings(Settings settings){ + public void beforeSettings(Settings settings) { } @@ -76,7 +76,7 @@ public void buildFinished(BuildResult buildResult) { Log.debug("buildFinished", this.getClass().getName()); alreadyRegistered.set(false); // Reset is necessary, otherwise Listener is not used in next build - if(projectStartTime != null) { + if (projectStartTime != null) { data.setExecutionTime(Duration.between(projectStartTime, Instant.now())); @@ -84,21 +84,60 @@ public void buildFinished(BuildResult buildResult) { System.out.println(data.toString()); } StatisticsHandler.storeReport(data.toString(), "MC_GRADLE_JSON"); - } else{ + } else { Log.info(" was null. ", this.getClass().getName()); } } @Override public void beforeExecute(Task task) { + Log.trace( + "Start before task execution for Task `" + + task.getName() + + "`", + this.getClass().getName() + ); + startTime.put(task, Instant.now()); + + Log.trace( + "Finish before task execution for Task `" + + task.getName() + + "`", + this.getClass().getName() + ); } @Override public void afterExecute(Task task, TaskState taskState) { - Duration duration = Duration.between(startTime.remove(task), Instant.now()); - StatisticData.TaskData taskData = new StatisticData.TaskData(task, taskState, duration); - data.addTask(taskData); + Log.trace( + "Start after task execution for Task `" + + task.getName() + + "`", + this.getClass().getName() + ); + + Instant taskStartTime = startTime.remove(task); + + if (taskStartTime != null) { + Duration duration = Duration.between(taskStartTime, Instant.now()); + StatisticData.TaskData taskData = new StatisticData.TaskData(task, taskState, duration); + data.addTask(taskData); + } else { + Log.debug( + "The of Task `" + + task.getName() + + "` was null.", + this.getClass().getName() + ); + } + + Log.trace( + "Finish after task execution for Task `" + + task.getName() + + "`", + this.getClass().getName() + ); } } diff --git a/monticore-generator/src/test/java/de/monticore/gradle/StatisticListenerTest.java b/monticore-generator/src/test/java/de/monticore/gradle/StatisticListenerTest.java new file mode 100644 index 0000000000..dfd25b8f29 --- /dev/null +++ b/monticore-generator/src/test/java/de/monticore/gradle/StatisticListenerTest.java @@ -0,0 +1,74 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.gradle; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.internal.tasks.TaskStateInternal; +import org.gradle.api.invocation.Gradle; +import org.gradle.api.tasks.TaskState; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class StatisticListenerTest { + + @Test + void shouldStoreTaskExecutionTime() { + // Given + String taskName = "Task1"; + + Task task = mock(Task.class); + when(task.getName()).thenReturn(taskName); + when(task.getProject()).thenReturn(mock(Project.class)); + + TaskState state = new TaskStateInternal(); + + StatisticListener listener = new StatisticListener(); + listener.projectsEvaluated(mock(Gradle.class)); + + // Call beforeExecute before afterExecute + listener.beforeExecute(task); + + int sizePre = listener.data.tasks.size(); + + // When + listener.afterExecute(task, state); + + // Then + int size = listener.data.tasks.size(); + + Assertions.assertEquals(size, sizePre + 1); + Assertions.assertEquals(listener.data.tasks.get(size - 1) + .data.getMember("Name").getAsJsonString().getValue(), taskName); + } + + @Test + void shouldNotStoreTaskExecutionTime() { + // Given + String taskName = "Task1"; + + Task task = mock(Task.class); + when(task.getName()).thenReturn(taskName); + when(task.getProject()).thenReturn(mock(Project.class)); + + TaskState state = new TaskStateInternal(); + + StatisticListener listener = new StatisticListener(); + listener.projectsEvaluated(mock(Gradle.class)); + + // Do not call beforeExecute + // listener.beforeExecute(task); + + int sizePre = listener.data.tasks.size(); + + // When + listener.afterExecute(task, state); + + // Then + int size = listener.data.tasks.size(); + + Assertions.assertEquals(size, sizePre); + } +}