Github user lfrancke commented on a diff in the pull request: https://github.com/apache/nifi/pull/2872#discussion_r201489283 --- Diff: nifi-testharness/src/main/java/org/apache/nifi/testharness/TestNiFiInstance.java --- @@ -0,0 +1,485 @@ +/* + * 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.testharness; + +import org.apache.nifi.testharness.api.FlowFileEditorCallback; +import org.apache.nifi.EmbeddedNiFi; +import org.apache.nifi.testharness.util.FileUtils; +import org.apache.nifi.testharness.util.NiFiCoreLibClassLoader; +import org.apache.nifi.testharness.util.XmlUtils; +import org.apache.nifi.testharness.util.Zip; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.zip.ZipEntry; + +/** + * <p> + * An API wrapper of a "test" NiFi instance to which a flow definition is installed for testing.</p> + * + * <p> + * Due to NiFi design restrictions, {@code TestNiFiInstance} has to take <i>full command</i> + * of the current working directory: it installs a full NiFi installation to there. To ensure + * this is desired, <strong>it will only run if the current directory is called + * "nifi_testharness_nifi_home"</strong>. As such the JVM process has to be started inside a directory + * called "nifi_testharness_nifi_home" so that the following is true: + * + * <pre><tt> + * new File(System.getProperty("user.dir")).getName().equals("nifi_testharness_nifi_home") + * </tt></pre> + * </p> + * + * <p> + * Before {@code TestNiFiInstance} can be used, it has to be configured via its builder + * interface: + * <ul> + * <li> + * {@link Builder#setFlowXmlToInstallForTesting(File)} specifies the location of the NiFi binary + * distribution ZIP file to be used. + * </li> + * <li> + * {@link Builder#setFlowXmlToInstallForTesting(File)} specifies the location of the NiFi flow + * to install. + * </li> + * <li> + * {@link Builder#modifyFlowXmlBeforeInstalling(FlowFileEditorCallback)} allows on-the-fly + * changes to be performed to the Flow file before it is actually installed. + * </li> + * </ul> + * + * <h5>Sample</h5> + * <pre><tt> + * TestNiFiInstance testNiFiInstance = TestNiFiInstance.builder() + * .setNiFiBinaryDistributionZip(YourConstants.NIFI_ZIP_FILE) + * .setFlowXmlToInstallForTesting(YourConstants.FLOW_XML_FILE) + * .modifyFlowXmlBeforeInstalling(YourConstants.FLOW_FILE_CHANGES_FOR_TESTS) + * .build(); + * </tt></pre> + * + * </p> + * + * <p> + * If the current working directory is called "nifi_testharness_nifi_home", the caller can + * {@link #install()} this {@code TestNiFiInstance}, which will + * <ol> + * <li> + * (as a first cleanup step) erase all content of the current working directory. + * (NOTE: this potentially destructive operation is the reason why we have the + * "nifi_testharness_nifi_home" directory name guard in place!) + * </li> + * <li> + * Extracts the contents of the NiFi binary distribution ZIP file specified in + * the configuration to a to a temporary directory. + * <li> + * Symlinks all files from the temporary directory to the current working + * directory, causing the to hold a fully functional + * NiFi installation. + * </li> + * <li> + * Installs the flow definition files(s) to the NiFi instance specified in + * the configuration. + * </li> + * </ol> + * </p> + * + * <p> + * + * The caller then can proceed to {@link #start()}} this {@code TestNiFiInstance}, + * which will bootstrap the NiFi engine, which in turn will pick up and start processing + * the flow definition supplied by the caller in the configuration. + * </p> + * + * <p> + * Once the previous step is done, the caller can perform asserts regarding the observed behaviour + * of the NiFi flow, just like one would do it with standard Java test cases. + * </p> + * + * <p> + * To perform a clean shutdown of the hosted NiFi instance, the caller is required to call + * {@link #stopAndCleanup()}, which will shut down NiFi and remove all temporary files, including + * the symlinks created int current working directory. + * </p> + * + * + * <h4>NOTES</h4> + * <ul> + * <li> + * {@code TestNiFiInstance} is NOT thread safe: if more than one thread uses it, + * external synchronisation is required. + * </li> + * <li> + * Only one {@code TestNiFiInstance} can be started in the same "nifi_testharness_nifi_home" + * directory at the same time. + * </li> + * <li> + * Currently, due to NiFi limitations, one {@TestNiFiInstance} can be started per JVM process. --- End diff -- wrong javadoc tag missing "code"
---