/* * 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.flink.runtime.webmonitor.handlers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.flink.runtime.checkpoint.stats.CheckpointStats; import org.apache.flink.runtime.checkpoint.stats.CheckpointStatsTracker; import org.apache.flink.runtime.checkpoint.stats.JobCheckpointStats; import org.apache.flink.runtime.executiongraph.ExecutionGraph; import org.apache.flink.runtime.webmonitor.ExecutionGraphHolder; import org.junit.Test; import scala.Option; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class JobCheckpointsHandlerTest { @Test public void testNoCoordinator() throws Exception { JobCheckpointsHandler handler = new JobCheckpointsHandler( mock(ExecutionGraphHolder.class)); ExecutionGraph graph = mock(ExecutionGraph.class); // No coordinator when(graph.getCheckpointStatsTracker()).thenReturn(null); String response = handler.handleRequest(graph, Collections.<String, String>emptyMap()); // Expecting empty response assertEquals("{}", response); } @Test public void testNoStats() throws Exception { JobCheckpointsHandler handler = new JobCheckpointsHandler( mock(ExecutionGraphHolder.class)); ExecutionGraph graph = mock(ExecutionGraph.class); CheckpointStatsTracker tracker = mock(CheckpointStatsTracker.class); when(graph.getCheckpointStatsTracker()).thenReturn(tracker); // No stats when(tracker.getJobStats()).thenReturn(Option.<JobCheckpointStats>empty()); String response = handler.handleRequest(graph, Collections.<String, String>emptyMap()); // Expecting empty response assertEquals("{}", response); } @Test public void testStats() throws Exception { JobCheckpointsHandler handler = new JobCheckpointsHandler( mock(ExecutionGraphHolder.class)); ExecutionGraph graph = mock(ExecutionGraph.class); CheckpointStatsTracker tracker = mock(CheckpointStatsTracker.class); when(graph.getCheckpointStatsTracker()).thenReturn(tracker); final List<CheckpointStats> history = new ArrayList<>(); history.add(new CheckpointStats(0, 1, 1, 124)); history.add(new CheckpointStats(1, 5, 177, 0)); history.add(new CheckpointStats(2, 6, 8282, 2)); history.add(new CheckpointStats(3, 6812, 2800, 1024)); JobCheckpointStats stats = new JobCheckpointStats() { @Override public List<CheckpointStats> getRecentHistory() { return history; } @Override public long getCount() { return 4; } @Override public String getExternalPath() { return null; } @Override public long getMinDuration() { return 1; } @Override public long getMaxDuration() { return 8282; } @Override public long getAverageDuration() { return 2815; } @Override public long getMinStateSize() { return 0; } @Override public long getMaxStateSize() { return 1024; } @Override public long getAverageStateSize() { return 287; } }; when(tracker.getJobStats()).thenReturn(Option.apply(stats)); // Request stats String response = handler.handleRequest(graph, Collections.<String, String>emptyMap()); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(response); // Count int count = rootNode.get("count").asInt(); assertEquals(stats.getCount(), count); // Duration JsonNode durationNode = rootNode.get("duration"); assertNotNull(durationNode); long minDuration = durationNode.get("min").asLong(); long maxDuration = durationNode.get("max").asLong(); long avgDuration = durationNode.get("avg").asLong(); assertEquals(stats.getMinDuration(), minDuration); assertEquals(stats.getMaxDuration(), maxDuration); assertEquals(stats.getAverageDuration(), avgDuration); // State size JsonNode sizeNode = rootNode.get("size"); assertNotNull(sizeNode); long minSize = sizeNode.get("min").asLong(); long maxSize = sizeNode.get("max").asLong(); long avgSize = sizeNode.get("avg").asLong(); assertEquals(stats.getMinStateSize(), minSize); assertEquals(stats.getMaxStateSize(), maxSize); assertEquals(stats.getAverageStateSize(), avgSize); JsonNode historyNode = rootNode.get("history"); assertNotNull(historyNode); assertTrue(historyNode.isArray()); Iterator<JsonNode> it = historyNode.elements(); for (int i = 0; i < history.size(); i++) { CheckpointStats s = history.get(i); JsonNode node = it.next(); long checkpointId = node.get("id").asLong(); long timestamp = node.get("timestamp").asLong(); long duration = node.get("duration").asLong(); long size = node.get("size").asLong(); assertEquals(s.getCheckpointId(), checkpointId); assertEquals(s.getTriggerTimestamp(), timestamp); assertEquals(s.getDuration(), duration); assertEquals(s.getStateSize(), size); } assertFalse(it.hasNext()); } }