org.pentaho.di.kitchen.KitchenIT.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.kitchen.KitchenIT.java

Source

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2019 by Hitachi Vantara : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * 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 org.pentaho.di.kitchen;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.di.base.CommandExecutorCodes;
import org.pentaho.di.core.Result;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.security.Permission;
import java.util.Base64;
import java.util.UUID;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;

public class KitchenIT {

    private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

    private PrintStream oldOut;
    private PrintStream oldErr;
    private SecurityManager oldSecurityManager;

    private static final String JOB_EXEC_RESULT_FALSE = "(result=[false])";
    private static final String JOB_EXEC_RESULT_TRUE = "(result=[true])";
    private static final String FAILED_JOB_EXEC_PATTERN = "Finished with errors";

    private static final String BASE_PATH = "." + File.separator + "test_kjbs" + File.separator;
    private static final String EXPECTED_COMPLETE_WITH_SUCCESS_PATH = BASE_PATH + "expected_complete_with_success";
    private static final String EXPECTED_COMPLETE_WITH_FAILURE_PATH = BASE_PATH + "expected_complete_with_failure";
    private static final String EXPECTED_PARAMS_PASSED_ALONG = BASE_PATH + "expected_params_passed_along";

    private static final String[] KTRS_EXPECTED_COMPLETE_WITH_SUCCESS = new String[] {
            "runs_well_hello_world.kjb" };

    private static final String[] KTRS_EXPECTED_COMPLETE_WITH_FAILURE = new String[] {
            "fail_on_exec_hello_world.kjb", "fail_on_prep_hello_world.kjb", "missing_referenced_ktr.kjb" };

    @Before
    public void setUp() {
        oldSecurityManager = System.getSecurityManager();
        System.setSecurityManager(new MySecurityManager(oldSecurityManager));
    }

    @After
    public void tearDown() {
        System.setSecurityManager(oldSecurityManager);
    }

    @Test
    public void testArchivedJobsExecution() throws Exception {
        String file = this.getClass().getResource("test-kjb.zip").getFile();
        String[] args = new String[] { "/file:zip:file://" + file + "!Job.kjb" };
        oldOut = System.out;
        oldErr = System.err;
        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));
        try {
            Kitchen.main(args);
        } catch (SecurityException e) {
            System.setOut(oldOut);
            System.setErr(oldErr);
            System.out.println(outContent);
            assertFalse(outContent.toString().contains("result=[false]"));
            assertFalse(outContent.toString().contains("ERROR"));
        }
    }

    @Test
    public void testFileJobsExecution() throws Exception {
        String file = this.getClass().getResource("Job.kjb").getFile();
        String[] args = new String[] { "/file:" + file };
        oldOut = System.out;
        oldErr = System.err;
        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));
        try {
            Kitchen.main(args);
        } catch (SecurityException e) {
            System.setOut(oldOut);
            System.setErr(oldErr);
            System.out.println(outContent);
            assertFalse(outContent.toString().contains("result=[false]"));
            assertFalse(outContent.toString().contains("ERROR"));
        }
    }

    @Test
    public void testFileJobExpectedExecutionWithFailure() throws Exception {

        for (String testKJB : KTRS_EXPECTED_COMPLETE_WITH_FAILURE) {

            long now = System.currentTimeMillis();

            String testKJBRelativePath = EXPECTED_COMPLETE_WITH_FAILURE_PATH + File.separator + testKJB;
            String testKJBFullPath = this.getClass().getResource(testKJBRelativePath).getFile();
            String logFileRelativePath = testKJBRelativePath + "." + now + ".log";
            String logFileFullPath = testKJBFullPath + "." + now + ".log";

            try {

                Kitchen.main(
                        new String[] { "/file:" + testKJBFullPath, "/level:Basic", "/logfile:" + logFileFullPath });

            } catch (SecurityException e) {
                // All OK / expected: SecurityException is purposely thrown when Kitchen triggers System.exitJVM()

                // get log file contents
                String logFileContent = getFileContentAsString(logFileRelativePath);

                assertTrue(logFileContent.contains(JOB_EXEC_RESULT_FALSE));
                assertTrue(logFileContent.contains(FAILED_JOB_EXEC_PATTERN));

                Result result = Kitchen.getCommandExecutor().getResult();
                assertNotNull(result);
                assertEquals(result.getExitStatus(),
                        CommandExecutorCodes.Kitchen.ERRORS_DURING_PROCESSING.getCode());

            } finally {
                // sanitize
                File f = new File(logFileFullPath);
                if (f != null && f.exists()) {
                    f.deleteOnExit();
                }
            }
        }
    }

    @Test
    public void testFileJobExpectedExecutionWithSuccess() throws Exception {

        for (String testKJB : KTRS_EXPECTED_COMPLETE_WITH_SUCCESS) {

            long now = System.currentTimeMillis();

            String testKJBRelativePath = EXPECTED_COMPLETE_WITH_SUCCESS_PATH + File.separator + testKJB;
            String testKJBFullPath = this.getClass().getResource(testKJBRelativePath).getFile();
            String logFileRelativePath = testKJBRelativePath + "." + now + ".log";
            String logFileFullPath = testKJBFullPath + "." + now + ".log";

            try {

                Kitchen.main(
                        new String[] { "/file:" + testKJBFullPath, "/level:Basic", "/logfile:" + logFileFullPath });

            } catch (SecurityException e) {
                // All OK / expected: SecurityException is purposely thrown when Kitchen triggers System.exitJVM()

                // get log file contents
                String logFileContent = getFileContentAsString(logFileRelativePath);

                assertTrue(logFileContent.contains(JOB_EXEC_RESULT_TRUE));
                assertFalse(logFileContent.contains(FAILED_JOB_EXEC_PATTERN));

                Result result = Kitchen.getCommandExecutor().getResult();
                assertNotNull(result);
                assertEquals(result.getExitStatus(), CommandExecutorCodes.Kitchen.SUCCESS.getCode());

            } finally {
                // sanitize
                File f = new File(logFileFullPath);
                if (f != null && f.exists()) {
                    f.deleteOnExit();
                }
            }
        }
    }

    @Test
    public void testFileJobWithParams() throws Exception {

        String param1Name = "p1";
        String param2Name = "p2";

        String param1Val = UUID.randomUUID().toString();
        String param2Val = UUID.randomUUID().toString();

        final String EXPECTED_OUTPUT = "Received params " + param1Name + ":" + param1Val + ", " + param2Name + ":"
                + param2Val;

        long now = System.currentTimeMillis();

        String testKJBRelativePath = EXPECTED_PARAMS_PASSED_ALONG + File.separator + "print_received_params.kjb";
        String testKJBFullPath = this.getClass().getResource(testKJBRelativePath).getFile();
        String logFileRelativePath = testKJBRelativePath + "." + now + ".log";
        String logFileFullPath = testKJBFullPath + "." + now + ".log";

        try {

            Kitchen.main(new String[] { "/file:" + testKJBFullPath, "/level:Basic", "/logfile:" + logFileFullPath,
                    "/param:" + param1Name + "=" + param1Val, "/param:" + param2Name + "=" + param2Val });

        } catch (SecurityException e) {
            // All OK / expected: SecurityException is purposely thrown when Pan triggers System.exitJVM()

            // get log file contents
            String logFileContent = getFileContentAsString(logFileRelativePath);

            assertTrue(logFileContent.contains(EXPECTED_OUTPUT));
            assertTrue(logFileContent.contains(JOB_EXEC_RESULT_TRUE));
            assertFalse(logFileContent.contains(FAILED_JOB_EXEC_PATTERN));

            Result result = Kitchen.getCommandExecutor().getResult();
            assertNotNull(result);
            assertEquals(result.getExitStatus(), CommandExecutorCodes.Kitchen.SUCCESS.getCode());

        } finally {
            // sanitize
            File f = new File(logFileFullPath);
            if (f != null && f.exists()) {
                f.deleteOnExit();
            }
        }
    }

    private String getFileContentAsString(String relativePath) {

        String content = "";

        try {
            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(this.getClass().getResourceAsStream(relativePath)));
            StringBuffer logFileContentBuffer = new StringBuffer();
            String line = "";
            while ((line = rd.readLine()) != null) {
                logFileContentBuffer.append(line).append("\n");
            }

            content = logFileContentBuffer.toString();

        } catch (Throwable t) {
            // no-op
        }

        return content;
    }

    @Test
    public void testJobExecutionFromWithinProvidedZip() throws Exception {

        String testZipRelativePath = "test-kjb.zip";
        String testKJBWithinZip = "Job.kjb";

        File zipFile = null;

        try {
            zipFile = new File(getClass().getResource(testZipRelativePath).toURI());
            String base64Zip = Base64.getEncoder().encodeToString(FileUtils.readFileToByteArray(zipFile));

            Kitchen.main(new String[] { "/file:" + testKJBWithinZip, "/level:Basic", "/zip:" + base64Zip });

        } catch (SecurityException e) {
            // All OK / expected: SecurityException is purposely thrown when Kitchen triggers System.exitJVM()
            Result result = Kitchen.getCommandExecutor().getResult();
            assertNotNull(result);
            assertEquals(CommandExecutorCodes.Kitchen.SUCCESS.getCode(), result.getExitStatus());
        }
    }

    public class MySecurityManager extends SecurityManager {

        private SecurityManager baseSecurityManager;

        public MySecurityManager(SecurityManager baseSecurityManager) {
            this.baseSecurityManager = baseSecurityManager;
        }

        @Override
        public void checkPermission(Permission permission) {
            if (permission.getName().startsWith("exitVM")) {
                throw new SecurityException("System exit not allowed");
            }
            if (baseSecurityManager != null) {
                baseSecurityManager.checkPermission(permission);
            } else {
                return;
            }
        }

    }
}