com.netflix.genie.web.tasks.leader.ClusterCheckerTaskUnitTests.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.genie.web.tasks.leader.ClusterCheckerTaskUnitTests.java

Source

/*
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed 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 com.netflix.genie.web.tasks.leader;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.netflix.genie.common.dto.Job;
import com.netflix.genie.common.dto.JobExecution;
import com.netflix.genie.common.dto.JobStatus;
import com.netflix.genie.common.exceptions.GenieException;
import com.netflix.genie.core.services.JobPersistenceService;
import com.netflix.genie.core.services.JobSearchService;
import com.netflix.genie.test.categories.UnitTest;
import com.netflix.genie.web.properties.ClusterCheckerProperties;
import com.netflix.genie.web.tasks.GenieTaskScheduleType;
import com.netflix.spectator.api.Counter;
import com.netflix.spectator.api.Registry;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.mockito.Mockito;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Unit tests for the ClusterCheckerTask class.
 *
 * @author tgianos
 * @since 3.0.0
 */
@Category(UnitTest.class)
public class ClusterCheckerTaskUnitTests {

    private ClusterCheckerTask task;
    private String hostName;
    private JobSearchService jobSearchService;
    private JobPersistenceService jobPersistenceService;
    private RestTemplate restTemplate;

    private Counter lostJobCounter;
    private Counter unableToUpdateJobCounter;

    /**
     * Setup for the tests.
     */
    @Before
    public void setup() {
        this.hostName = UUID.randomUUID().toString();
        final ClusterCheckerProperties properties = new ClusterCheckerProperties();
        properties.setHealthIndicatorsToIgnore("memory,genie ");
        this.jobSearchService = Mockito.mock(JobSearchService.class);
        this.jobPersistenceService = Mockito.mock(JobPersistenceService.class);
        this.restTemplate = Mockito.mock(RestTemplate.class);
        final ManagementServerProperties serverProperties = Mockito.mock(ManagementServerProperties.class);
        Mockito.when(serverProperties.getContextPath()).thenReturn("/actuator");
        final Registry registry = Mockito.mock(Registry.class);
        this.lostJobCounter = Mockito.mock(Counter.class);
        Mockito.when(registry.counter("genie.tasks.clusterChecker.lostJobs.rate")).thenReturn(this.lostJobCounter);
        this.unableToUpdateJobCounter = Mockito.mock(Counter.class);
        Mockito.when(registry.counter("genie.tasks.clusterChecker.unableToUpdateJob.rate"))
                .thenReturn(this.unableToUpdateJobCounter);
        this.task = new ClusterCheckerTask(this.hostName, properties, this.jobSearchService,
                this.jobPersistenceService, this.restTemplate, serverProperties, registry);
    }

    /**
     * Make sure run method works.
     *
     * @throws IOException    on error
     * @throws GenieException on error
     */
    @Test
    public void canRun() throws IOException, GenieException {
        final String host1 = UUID.randomUUID().toString();
        final String host2 = UUID.randomUUID().toString();
        final String host3 = UUID.randomUUID().toString();

        // Mock the 9 invocations for 3 calls to run
        Mockito.when(this.restTemplate.getForObject(Mockito.anyString(), Mockito.anyObject())).thenReturn("")
                .thenThrow(new RestClientException("blah")).thenReturn("").thenReturn("")
                .thenThrow(new RestClientException("blah")).thenReturn("").thenReturn("")
                .thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "",
                        ("{\"status\":\"OUT_OF_SERVICE\", \"genie\": { \"status\": \"OUT_OF_SERVICE\"}, "
                                + "\"db\": { \"status\": \"OUT_OF_SERVICE\"}}").getBytes(StandardCharsets.UTF_8),
                        StandardCharsets.UTF_8))
                .thenReturn("").thenReturn("")
                .thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "",
                        ("{\"status\":\"OUT_OF_SERVICE\", \"genie\": { \"status\": \"OUT_OF_SERVICE\"}, "
                                + "\"db\": { \"status\": \"OUT_OF_SERVICE\"}}").getBytes(StandardCharsets.UTF_8),
                        StandardCharsets.UTF_8))
                .thenReturn("").thenReturn("")
                .thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "",
                        ("{\"status\":\"OUT_OF_SERVICE\", \"genie\": { \"status\": \"OUT_OF_SERVICE\"}, "
                                + "\"db\": { \"status\": \"UP\"}}").getBytes(StandardCharsets.UTF_8),
                        StandardCharsets.UTF_8))
                .thenReturn("").thenReturn("")
                .thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "",
                        ("{\"status\":\"OUT_OF_SERVICE\", \"genie\": { \"status\": \"OUT_OF_SERVICE\"}, "
                                + "\"db\": { \"status\": \"OUT_OF_SERVICE\"}}").getBytes(StandardCharsets.UTF_8),
                        StandardCharsets.UTF_8))
                .thenReturn("");

        final List<String> hostsRunningJobs = Lists.newArrayList(this.hostName, host1, host2, host3);
        Mockito.when(this.jobSearchService.getAllHostsWithActiveJobs()).thenReturn(hostsRunningJobs);

        final Job job1 = Mockito.mock(Job.class);
        final String job1Id = UUID.randomUUID().toString();
        Mockito.when(job1.getId()).thenReturn(Optional.of(job1Id));
        final Job job2 = Mockito.mock(Job.class);
        final String job2Id = UUID.randomUUID().toString();
        Mockito.when(job2.getId()).thenReturn(Optional.of(job2Id));
        final Job job3 = Mockito.mock(Job.class);
        final String job3Id = UUID.randomUUID().toString();
        Mockito.when(job3.getId()).thenReturn(Optional.of(job3Id));
        final Job job4 = Mockito.mock(Job.class);
        final String job4Id = UUID.randomUUID().toString();
        Mockito.when(job4.getId()).thenReturn(Optional.of(job4Id));

        Mockito.when(this.jobSearchService.getAllActiveJobsOnHost(host2)).thenReturn(Sets.newHashSet(job1, job2));
        Mockito.when(this.jobSearchService.getAllActiveJobsOnHost(host3)).thenReturn(Sets.newHashSet(job3, job4));

        Mockito.doThrow(new RuntimeException("blah")).doNothing().when(this.jobPersistenceService)
                .setJobCompletionInformation(Mockito.eq(job1Id), Mockito.eq(JobExecution.LOST_EXIT_CODE),
                        Mockito.eq(JobStatus.FAILED), Mockito.anyString(), Mockito.eq(null), Mockito.eq(null));

        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(1));
        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(1));
        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(1));
        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(0));
        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(0));
        this.task.run();
        Assert.assertThat(this.task.getErrorCountsSize(), Matchers.is(1));

        Mockito.verify(this.jobPersistenceService, Mockito.times(2)).setJobCompletionInformation(Mockito.eq(job1Id),
                Mockito.eq(JobExecution.LOST_EXIT_CODE), Mockito.eq(JobStatus.FAILED), Mockito.anyString(),
                Mockito.eq(null), Mockito.eq(null));
        Mockito.verify(this.jobPersistenceService, Mockito.atLeast(1)).setJobCompletionInformation(
                Mockito.eq(job2Id), Mockito.eq(JobExecution.LOST_EXIT_CODE), Mockito.eq(JobStatus.FAILED),
                Mockito.anyString(), Mockito.eq(null), Mockito.eq(null));
        Mockito.verify(this.lostJobCounter, Mockito.atLeast(2)).increment();
        Mockito.verify(this.unableToUpdateJobCounter, Mockito.times(1)).increment();
    }

    /**
     * Make sure we get the right schedule type.
     */
    @Test
    public void canGetScheduleType() {
        Assert.assertThat(this.task.getScheduleType(), Matchers.is(GenieTaskScheduleType.FIXED_RATE));
    }

    /**
     * Make sure the trigger is null.
     */
    @Test(expected = UnsupportedOperationException.class)
    public void canGetTrigger() {
        this.task.getTrigger();
    }

    /**
     * Make sure the get period returns the correct value.
     */
    @Test
    public void canGetFixedRate() {
        Assert.assertThat(this.task.getFixedRate(), Matchers.is(300000L));
    }

    /**
     * Make sure the trigger is null.
     */
    @Test(expected = UnsupportedOperationException.class)
    public void canGetFixedDelay() {
        this.task.getFixedDelay();
    }
}