IGNITE-21026 Fixed NPE in the performance statistics extension if there are no jobs for a task (#247)

diff --git a/modules/performance-statistics-ext/src/main/java/org/apache/ignite/internal/performancestatistics/handlers/ComputeHandler.java b/modules/performance-statistics-ext/src/main/java/org/apache/ignite/internal/performancestatistics/handlers/ComputeHandler.java
index c3618b0..4456f5c 100644
--- a/modules/performance-statistics-ext/src/main/java/org/apache/ignite/internal/performancestatistics/handlers/ComputeHandler.java
+++ b/modules/performance-statistics-ext/src/main/java/org/apache/ignite/internal/performancestatistics/handlers/ComputeHandler.java
@@ -28,6 +28,7 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.ignite.internal.performancestatistics.util.OrderedFixedSizeStructure;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteUuid;
 
@@ -134,7 +135,7 @@
 
             ArrayNode jobsJson = MAPPER.createArrayNode();
 
-            for (Job job : jobs.get(task.sesId)) {
+            for (Job job : F.view(jobs.get(task.sesId))) {
                 ObjectNode jobJson = MAPPER.createObjectNode();
 
                 jobJson.put("queuedTime", job.queuedTime);
diff --git a/modules/performance-statistics-ext/src/test/java/org/apache/ignite/internal/performancestatistics/PerformanceStatisticsReportSelfTest.java b/modules/performance-statistics-ext/src/test/java/org/apache/ignite/internal/performancestatistics/PerformanceStatisticsReportSelfTest.java
index 059913f..d214341 100644
--- a/modules/performance-statistics-ext/src/test/java/org/apache/ignite/internal/performancestatistics/PerformanceStatisticsReportSelfTest.java
+++ b/modules/performance-statistics-ext/src/test/java/org/apache/ignite/internal/performancestatistics/PerformanceStatisticsReportSelfTest.java
@@ -19,25 +19,34 @@
 
 import java.io.File;
 import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.query.IndexQuery;
 import org.apache.ignite.cache.query.ScanQuery;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeTaskAdapter;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.transactions.Transaction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.junit.Test;
 
 import static org.apache.ignite.cache.query.IndexQueryCriteriaBuilder.gt;
 import static org.apache.ignite.internal.processors.performancestatistics.AbstractPerformanceStatisticsTest.waitForStatisticsEnabled;
 import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.PERF_STAT_DIR;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -76,6 +85,8 @@
                 // No-op.
             });
 
+            assertThrowsWithCause(() -> client.compute().execute(new TaskWithoutJobs(), null), IgniteException.class);
+
             IgniteCache<Object, Object> txCache = client.createCache(new CacheConfiguration<>("txCache")
                 .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
 
@@ -127,4 +138,20 @@
             U.delete(new File(U.defaultWorkDirectory()));
         }
     }
+
+    /** */
+    private static class TaskWithoutJobs extends ComputeTaskAdapter<Object, Object> {
+        /** {@inheritDoc} */
+        @Override public @NotNull Map<? extends ComputeJob, ClusterNode> map(
+            List subgrid,
+            @Nullable Object arg
+        ) throws IgniteException {
+            return Collections.emptyMap();
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public Object reduce(List list) throws IgniteException {
+            return null;
+        }
+    }
 }