gobblin.scheduler.JobConfigFileMonitorTest.java Source code

Java tutorial

Introduction

Here is the source code for gobblin.scheduler.JobConfigFileMonitorTest.java

Source

/*
 * 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 gobblin.scheduler;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ServiceManager;

import gobblin.configuration.ConfigurationKeys;
import gobblin.testing.AssertWithBackoff;

/**
 * Unit tests for the job configuration file monitor in {@link gobblin.scheduler.JobScheduler}.
 *
 * @author Yinan Li
 */
@Test(groups = { "gobblin.scheduler" })
public class JobConfigFileMonitorTest {

    private static final String JOB_CONFIG_FILE_DIR = "gobblin-test/resource/job-conf";

    private String jobConfigDir;
    private ServiceManager serviceManager;
    private JobScheduler jobScheduler;
    private File newJobConfigFile;

    private class GetNumScheduledJobs implements Function<Void, Integer> {

        @Override
        public Integer apply(Void input) {
            return JobConfigFileMonitorTest.this.jobScheduler.getScheduledJobs().size();
        }
    }

    @BeforeClass
    public void setUp() throws Exception {
        this.jobConfigDir = Files
                .createTempDirectory(String.format("gobblin-test_%s_job-conf", this.getClass().getSimpleName()))
                .toString();

        FileUtils.forceDeleteOnExit(new File(this.jobConfigDir));
        FileUtils.copyDirectory(new File(JOB_CONFIG_FILE_DIR), new File(jobConfigDir));

        Properties properties = new Properties();
        try (Reader schedulerPropsReader = new FileReader("gobblin-test/resource/gobblin.test.properties")) {
            properties.load(schedulerPropsReader);
        }
        properties.setProperty(ConfigurationKeys.JOB_CONFIG_FILE_DIR_KEY, jobConfigDir);
        properties.setProperty(ConfigurationKeys.JOB_CONFIG_FILE_GENERAL_PATH_KEY, jobConfigDir);
        properties.setProperty(ConfigurationKeys.JOB_CONFIG_FILE_MONITOR_POLLING_INTERVAL_KEY, "1000");
        properties.setProperty(ConfigurationKeys.METRICS_ENABLED_KEY, "false");

        SchedulerService quartzService = new SchedulerService(new Properties());
        this.jobScheduler = new JobScheduler(properties, quartzService);
        this.serviceManager = new ServiceManager(Lists.newArrayList(quartzService, this.jobScheduler));
        this.serviceManager.startAsync().awaitHealthy(10, TimeUnit.SECONDS);
        ;
    }

    @Test
    public void testAddNewJobConfigFile() throws Exception {
        final Logger log = LoggerFactory.getLogger("testAddNewJobConfigFile");
        log.info("testAddNewJobConfigFile: start");
        AssertWithBackoff assertWithBackoff = AssertWithBackoff.create().logger(log).timeoutMs(15000);
        assertWithBackoff.assertEquals(new GetNumScheduledJobs(), 3, "3 scheduled jobs");

        /* Set a time gap, to let the monitor recognize the "3-file" status as old status,
        so that new added file can be discovered */
        Thread.sleep(1000);

        // Create a new job configuration file by making a copy of an existing
        // one and giving a different job name
        Properties jobProps = new Properties();
        jobProps.load(new FileReader(new File(this.jobConfigDir, "GobblinTest1.pull")));
        jobProps.setProperty(ConfigurationKeys.JOB_NAME_KEY, "Gobblin-test-new");
        this.newJobConfigFile = new File(this.jobConfigDir, "Gobblin-test-new.pull");
        jobProps.store(new FileWriter(this.newJobConfigFile), null);

        assertWithBackoff.assertEquals(new GetNumScheduledJobs(), 4, "4 scheduled jobs");

        Set<String> jobNames = Sets.newHashSet(this.jobScheduler.getScheduledJobs());
        Set<String> expectedJobNames = ImmutableSet.<String>builder()
                .add("GobblinTest1", "GobblinTest2", "GobblinTest3", "Gobblin-test-new").build();

        Assert.assertEquals(jobNames, expectedJobNames);
        log.info("testAddNewJobConfigFile: end");
    }

    @Test(dependsOnMethods = { "testAddNewJobConfigFile" })
    public void testChangeJobConfigFile() throws Exception {
        final Logger log = LoggerFactory.getLogger("testChangeJobConfigFile");
        log.info("testChangeJobConfigFile: start");
        Assert.assertEquals(this.jobScheduler.getScheduledJobs().size(), 4);

        // Make a change to the new job configuration file
        Properties jobProps = new Properties();
        jobProps.load(new FileReader(this.newJobConfigFile));
        jobProps.setProperty(ConfigurationKeys.JOB_COMMIT_POLICY_KEY, "partial");
        jobProps.setProperty(ConfigurationKeys.JOB_NAME_KEY, "Gobblin-test-new2");
        jobProps.store(new FileWriter(this.newJobConfigFile), null);

        AssertWithBackoff.create().logger(log).timeoutMs(30000).assertEquals(new GetNumScheduledJobs(), 4,
                "4 scheduled jobs");

        final Set<String> expectedJobNames = ImmutableSet.<String>builder()
                .add("GobblinTest1", "GobblinTest2", "GobblinTest3", "Gobblin-test-new2").build();
        AssertWithBackoff.create().logger(log).timeoutMs(30000).assertEquals(new Function<Void, Set<String>>() {
            @Override
            public Set<String> apply(Void input) {
                return Sets.newHashSet(JobConfigFileMonitorTest.this.jobScheduler.getScheduledJobs());
            }
        }, expectedJobNames, "Job change detected");
        log.info("testChangeJobConfigFile: end");
    }

    @Test(dependsOnMethods = { "testChangeJobConfigFile" })
    public void testUnscheduleJob() throws Exception {
        final Logger log = LoggerFactory.getLogger("testUnscheduleJob");
        log.info("testUnscheduleJob: start");
        Assert.assertEquals(this.jobScheduler.getScheduledJobs().size(), 4);

        // Disable the new job by setting job.disabled=true
        Properties jobProps = new Properties();
        jobProps.load(new FileReader(this.newJobConfigFile));
        jobProps.setProperty(ConfigurationKeys.JOB_DISABLED_KEY, "true");
        jobProps.store(new FileWriter(this.newJobConfigFile), null);

        AssertWithBackoff.create().logger(log).timeoutMs(7500).assertEquals(new GetNumScheduledJobs(), 3,
                "3 scheduled jobs");

        Set<String> jobNames = Sets.newHashSet(this.jobScheduler.getScheduledJobs());
        Assert.assertEquals(jobNames.size(), 3);
        Assert.assertTrue(jobNames.contains("GobblinTest1"));
        Assert.assertTrue(jobNames.contains("GobblinTest2"));
        Assert.assertTrue(jobNames.contains("GobblinTest3"));
        log.info("testUnscheduleJob: end");
    }

    @AfterClass
    public void tearDown() throws TimeoutException, IOException {
        if (jobConfigDir != null) {
            FileUtils.forceDelete(new File(jobConfigDir));
        }
        this.serviceManager.stopAsync().awaitStopped(30, TimeUnit.SECONDS);
    }
}