org.apache.nifi.minifi.toolkit.configuration.ConfigMainTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.nifi.minifi.toolkit.configuration.ConfigMainTest.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 org.apache.nifi.minifi.toolkit.configuration;

import org.apache.commons.io.Charsets;
import org.apache.nifi.minifi.commons.schema.serialization.SchemaLoader;
import org.apache.nifi.minifi.commons.schema.exception.SchemaLoaderException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.xml.bind.JAXBException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ConfigMainTest {
    @Mock
    PathInputStreamFactory pathInputStreamFactory;

    @Mock
    PathOutputStreamFactory pathOutputStreamFactory;

    ConfigMain configMain;

    String testInput;

    String testOutput;

    @Before
    public void setup() {
        configMain = new ConfigMain(pathInputStreamFactory, pathOutputStreamFactory);
        testInput = "testInput";
        testOutput = "testOutput";
    }

    @Test
    public void testExecuteNoArgs() {
        assertEquals(ConfigMain.ERR_INVALID_ARGS, configMain.execute(new String[0]));
    }

    @Test
    public void testExecuteInvalidCommand() {
        assertEquals(ConfigMain.ERR_INVALID_ARGS, configMain.execute(new String[] { "badCommand" }));
    }

    @Test
    public void testValidateInvalidCommand() {
        assertEquals(ConfigMain.ERR_INVALID_ARGS, configMain.execute(new String[] { ConfigMain.VALIDATE }));
    }

    @Test
    public void testValidateErrorOpeningInput() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput)).thenThrow(new FileNotFoundException());
        assertEquals(ConfigMain.ERR_UNABLE_TO_OPEN_INPUT,
                configMain.execute(new String[] { ConfigMain.VALIDATE, testInput }));
    }

    @Test
    public void testValidateUnableToParseConfig() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput))
                .thenReturn(new ByteArrayInputStream("!@#$%^&".getBytes(Charsets.UTF_8)));
        assertEquals(ConfigMain.ERR_UNABLE_TO_PARSE_CONFIG,
                configMain.execute(new String[] { ConfigMain.VALIDATE, testInput }));
    }

    @Test
    public void testValidateInvalidConfig() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput)).thenAnswer(invocation -> ConfigMainTest.class
                .getClassLoader().getResourceAsStream("config-malformed-field.yml"));
        assertEquals(ConfigMain.ERR_INVALID_CONFIG,
                configMain.execute(new String[] { ConfigMain.VALIDATE, testInput }));
    }

    @Test
    public void testTransformInvalidCommand() {
        assertEquals(ConfigMain.ERR_INVALID_ARGS, configMain.execute(new String[] { ConfigMain.TRANSFORM }));
    }

    @Test
    public void testValidateSuccess() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput))
                .thenAnswer(invocation -> ConfigMainTest.class.getClassLoader().getResourceAsStream("config.yml"));
        assertEquals(ConfigMain.SUCCESS, configMain.execute(new String[] { ConfigMain.VALIDATE, testInput }));
    }

    @Test
    public void testTransformErrorOpeningInput() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput)).thenThrow(new FileNotFoundException());
        assertEquals(ConfigMain.ERR_UNABLE_TO_OPEN_INPUT,
                configMain.execute(new String[] { ConfigMain.TRANSFORM, testInput, testOutput }));
    }

    @Test
    public void testTransformErrorOpeningOutput() throws FileNotFoundException {
        when(pathOutputStreamFactory.create(testOutput)).thenThrow(new FileNotFoundException());
        assertEquals(ConfigMain.ERR_UNABLE_TO_OPEN_OUTPUT,
                configMain.execute(new String[] { ConfigMain.TRANSFORM, testInput, testOutput }));
    }

    @Test
    public void testTransformErrorReadingTemplate() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput))
                .thenAnswer(invocation -> new ByteArrayInputStream("malformed xml".getBytes(Charsets.UTF_8)));
        assertEquals(ConfigMain.ERR_UNABLE_TO_READ_TEMPLATE,
                configMain.execute(new String[] { ConfigMain.TRANSFORM, testInput, testOutput }));
    }

    @Test
    public void testTransformErrorTransformingTemplate() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput)).thenAnswer(
                invocation -> ConfigMainTest.class.getClassLoader().getResourceAsStream("CsvToJson.xml"));
        when(pathOutputStreamFactory.create(testOutput)).thenAnswer(invocation -> new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                throw new IOException();
            }
        });
        assertEquals(ConfigMain.ERR_UNABLE_TO_TRANSFORM_TEMPLATE,
                configMain.execute(new String[] { ConfigMain.TRANSFORM, testInput, testOutput }));
    }

    @Test
    public void testTransformSuccess() throws FileNotFoundException {
        when(pathInputStreamFactory.create(testInput)).thenAnswer(
                invocation -> ConfigMainTest.class.getClassLoader().getResourceAsStream("CsvToJson.xml"));
        when(pathOutputStreamFactory.create(testOutput)).thenAnswer(invocation -> new ByteArrayOutputStream());
        assertEquals(ConfigMain.SUCCESS,
                configMain.execute(new String[] { ConfigMain.TRANSFORM, testInput, testOutput }));
    }

    @Test
    public void testTransformRoundTripCsvToJson() throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("CsvToJson");
    }

    @Test
    public void testTransformRoundTripDecompression() throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("DecompressionCircularFlow");
    }

    @Test
    public void testTransformRoundTripInvokeHttp() throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("InvokeHttpMiNiFiTemplateTest");
    }

    @Test
    public void testTransformRoundTripReplaceText() throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("ReplaceTextExpressionLanguageCSVReformatting");
    }

    @Test
    public void testTransformRoundTripStressTestFramework()
            throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("StressTestFramework");
    }

    @Test
    public void testTransformRoundTripMultipleRelationships()
            throws IOException, JAXBException, SchemaLoaderException {
        transformRoundTrip("MultipleRelationships");
    }

    @Test(expected = SchemaLoaderException.class)
    public void testFailToTransformProcessGroup() throws IOException, JAXBException, SchemaLoaderException {
        ConfigMain.transformTemplateToSchema(
                getClass().getClassLoader().getResourceAsStream("TemplateWithProcessGroup.xml")).toMap();
    }

    @Test(expected = SchemaLoaderException.class)
    public void testFailToTransformInputPort() throws IOException, JAXBException, SchemaLoaderException {
        ConfigMain.transformTemplateToSchema(
                getClass().getClassLoader().getResourceAsStream("TemplateWithOutputPort.xml")).toMap();
    }

    @Test(expected = SchemaLoaderException.class)
    public void testFailToTransformOutputPort() throws IOException, JAXBException, SchemaLoaderException {
        ConfigMain.transformTemplateToSchema(
                getClass().getClassLoader().getResourceAsStream("TemplateWithInputPort.xml")).toMap();
    }

    @Test(expected = SchemaLoaderException.class)
    public void testFailToTransformFunnel() throws IOException, JAXBException, SchemaLoaderException {
        ConfigMain.transformTemplateToSchema(
                getClass().getClassLoader().getResourceAsStream("TemplateWithFunnel.xml")).toMap();
    }

    private void transformRoundTrip(String name) throws JAXBException, IOException, SchemaLoaderException {
        Map<String, Object> templateMap = ConfigMain
                .transformTemplateToSchema(getClass().getClassLoader().getResourceAsStream(name + ".xml")).toMap();
        Map<String, Object> yamlMap = SchemaLoader
                .loadYamlAsMap(getClass().getClassLoader().getResourceAsStream(name + ".yml"));
        assertNoMapDifferences(templateMap, yamlMap);
    }

    private void assertNoMapDifferences(Map<String, Object> templateMap, Map<String, Object> yamlMap) {
        List<String> differences = new ArrayList<>();
        getMapDifferences("", differences, yamlMap, templateMap);
        if (differences.size() > 0) {
            fail(String.join("\n", differences.toArray(new String[differences.size()])));
        }
    }

    private void getMapDifferences(String path, List<String> differences, Map<String, Object> expected,
            Map<String, Object> actual) {
        for (Map.Entry<String, Object> stringObjectEntry : expected.entrySet()) {
            String key = stringObjectEntry.getKey();
            String newPath = path.isEmpty() ? key : path + "." + key;
            if (!actual.containsKey(key)) {
                differences.add("Missing key: " + newPath);
            } else {
                getObjectDifferences(newPath, differences, stringObjectEntry.getValue(), actual.get(key));
            }
        }

        Set<String> extraKeys = new HashSet<>(actual.keySet());
        extraKeys.removeAll(expected.keySet());
        for (String extraKey : extraKeys) {
            differences.add("Extra key: " + path + extraKey);
        }
    }

    private void getListDifferences(String path, List<String> differences, List<Object> expected,
            List<Object> actual) {
        if (expected.size() == actual.size()) {
            for (int i = 0; i < expected.size(); i++) {
                getObjectDifferences(path + "[" + i + "]", differences, expected.get(i), actual.get(i));
            }
        } else {
            differences.add(
                    "Expect size of " + expected.size() + " for list at " + path + " but got " + actual.size());
        }
    }

    private void getObjectDifferences(String path, List<String> differences, Object expectedValue,
            Object actualValue) {
        if (expectedValue instanceof Map) {
            if (actualValue instanceof Map) {
                getMapDifferences(path, differences, (Map) expectedValue, (Map) actualValue);
            } else {
                differences.add("Expected map at " + path + " but got " + actualValue);
            }
        } else if (expectedValue instanceof List) {
            if (actualValue instanceof List) {
                getListDifferences(path, differences, (List) expectedValue, (List) actualValue);
            } else {
                differences.add("Expected map at " + path + " but got " + actualValue);
            }
        } else if (expectedValue == null) {
            if (actualValue != null) {
                differences.add("Expected null at " + path + " but got " + actualValue);
            }
        } else if (expectedValue instanceof Number) {
            if (actualValue instanceof Number) {
                if (!expectedValue.toString().equals(actualValue.toString())) {
                    differences
                            .add("Expected value of " + expectedValue + " at " + path + " but got " + actualValue);
                }
            } else {
                differences.add("Expected Number at " + path + " but got " + actualValue);
            }
        } else if (!expectedValue.equals(actualValue)) {
            differences.add("Expected " + expectedValue + " at " + path + " but got " + actualValue);
        }
    }
}