/*
 * 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.pig.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.pig.ExecType;
import org.apache.pig.PigConfiguration;
import org.apache.pig.PigServer;
import org.apache.pig.backend.hadoop.datastorage.ConfigurationUtil;
import org.apache.pig.data.DataType;
import org.apache.pig.data.Tuple;
import org.apache.pig.impl.PigContext;
import org.apache.pig.impl.io.FileLocalizer;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.logicalLayer.schema.Schema;
import org.apache.pig.impl.util.JarManager;
import org.apache.pig.impl.util.PropertiesUtil;
import org.apache.pig.impl.util.Utils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.google.common.io.Files;

public class TestPigServer {
    private static Properties properties;
    private static MiniGenericCluster cluster;

    private File tempDir;

    @Before
    public void setUp() throws Exception{
        tempDir = Files.createTempDir();
        tempDir.deleteOnExit();
        registerNewResource(tempDir.getAbsolutePath());
    }

    @After
    public void tearDown() throws Exception{
        tempDir.delete();
    }

    @BeforeClass
    public static void oneTimeSetup() {
        cluster = MiniGenericCluster.buildCluster();
        properties = cluster.getProperties();
    }

    @AfterClass
    public static void oneTimeTearDown() throws Exception {
        cluster.shutDown();
    }

    private final static String FILE_SEPARATOR = System.getProperty("file.separator");

    // make sure that name is included or not (depending on flag "included")
    // in the given list of stings
    private static void verifyStringContained(List<URL> list, String name, boolean included) {
        int count = 0;

        for (URL url : list) {
            if (url.toString().contains(name)) {
                if (!included) {
                    fail("Included is false, but url ["+url+"] contains name ["+name+"]");
            }
                assertEquals("Too many urls contain name: " + name, 1, ++count);
            }
        }
        if (included) {
            assertEquals("Number of urls that contain name [" + name + "] != 1", 1, count);
        }
    }

    // creates an empty jar file
    private static void createFakeJarFile(String location, String name)
                                          throws IOException {
        createFakeJarFile(location, name,
                FileSystem.getLocal(cluster.getConfiguration()).getRaw());
    }

    // creates an empty jar file
    private static void createFakeJarFile(String location, String name, FileSystem fs)
                                          throws IOException {
        System.err. println("Location: " + location + " name: " + name);
        Path dir = new Path(location);
        fs.mkdirs(dir);

        assertTrue(fs.createNewFile(new Path(dir, name)));
    }

    // dynamically add more resources to the system class loader
    private static void registerNewResource(String file) throws Exception {
        URL urlToAdd = new File(file).toURI().toURL();
        ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
        // Find the class loader below bootstrap class loader
        // It is either the system class loader (first invocation), or the new URLClassLoader added below
        while (sysLoader.getParent().getParent() != null) {
            sysLoader = sysLoader.getParent();
        }
        // Check if this class loader is instance of URLClassLoader
        // On Java 8 and before it is, add resources via addURL method
        // On Java 11 and after it isn't, add a new URLClassLoader with the new resources above it
        if (sysLoader instanceof URLClassLoader) {
            Method addMethod = URLClassLoader.class.
              getDeclaredMethod("addURL", new Class[]{URL.class});
            addMethod.setAccessible(true);
            addMethod.invoke(sysLoader, new Object[]{urlToAdd});
        } else {
            Field parent = ClassLoader.class.getDeclaredField("parent");
            parent.setAccessible(true);
            ClassLoader urlClassLoader = new URLClassLoader(new URL[]{urlToAdd}, ClassLoader.getSystemClassLoader().getParent());
            parent.set(ClassLoader.getSystemClassLoader(), urlClassLoader);
        }
    }

    /**
     * The jar file to register is not present
     */
    @Test
    public void testRegisterJarFileNotPresent() throws Throwable {
        // resister a jar file that does not exist

        String jarName = "BadFileNameTestJarNotPresent.jar";

        // jar name is not present to start with
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        verifyStringContained(pig.getPigContext().extraJars, jarName, false);
        boolean raisedException = false;
        try {
            pig.registerJar(jarName);
        } catch (IOException e) {
            raisedException = true;
        }
        assertTrue("registerJar on jarName ["+jarName+"] should have raised an exception", raisedException);
        verifyStringContained(pig.getPigContext().extraJars, jarName, false);
    }

    /**
     * Jar file to register is not present in the system resources
     * in this case name of jar file is relative to current working dir
     */
    @Test
    public void testRegisterJarLocalDir() throws Throwable {
        String dir1 = "test1_register_jar_local";
        String dir2 = "test2_register_jar_local";
        String jarLocation = dir1 + FILE_SEPARATOR +
                              dir2 + FILE_SEPARATOR;
        String jarName = "TestRegisterJarLocal.jar";


        createFakeJarFile(jarLocation, jarName);

        PigServer pig = new PigServer(cluster.getExecType(), properties);
        verifyStringContained(pig.getPigContext().extraJars, jarName, false);

        pig.registerJar(jarLocation + jarName);
        verifyStringContained(pig.getPigContext().extraJars, jarName, true);

        // clean-up
        assertTrue((new File(jarLocation + jarName)).delete());
        (new File(dir1 + FILE_SEPARATOR + dir2)).delete();
        (new File(dir1)).delete();
    }

    /**
     * Jar file is located via system resources
     * Test verifies that even with multiple resources matching,
     * only one of them is registered.
     */
    @Test
    public void testRegisterJarFromResources () throws Throwable {
        String dir = "test_register_jar_res_dir";
        String subDir1 = "test_register_jar_res_sub_dir1";
        String subDir2 = "test_register_jar_res_sub_dir2";
        String jarName = "TestRegisterJarFromRes.jar";
        String jarLocation1 = dir + FILE_SEPARATOR + subDir1 + FILE_SEPARATOR;
        String jarLocation2 = dir + FILE_SEPARATOR + subDir2 + FILE_SEPARATOR;


        createFakeJarFile(jarLocation1, jarName);
        createFakeJarFile(jarLocation2, jarName);

        PigServer pig = new PigServer(cluster.getExecType(), properties);
        verifyStringContained(pig.getPigContext().extraJars, jarName, false);

        registerNewResource(jarLocation1);
        registerNewResource(jarLocation2);

        pig.registerJar(jarName);
        verifyStringContained(pig.getPigContext().extraJars, jarName, true);

        // clean-up
        assertTrue((new File(jarLocation1 + jarName)).delete());
        assertTrue((new File(jarLocation2 + jarName)).delete());
        (new File(jarLocation1)).delete();
        (new File(jarLocation2)).delete();
        (new File(dir)).delete();
    }

    /**
     * Use a resource inside a jar file.
     * Verify that the containing jar file is registered correctly.
     * @throws Exception
     */
    @Test
    public void testRegisterJarResourceInJar() throws Throwable {
        String dir = "test_register_jar_res_in_jar";
        String subDir = "sub_dir";
        String jarName = "TestRegisterJarNonEmpty.jar";
        String className = "TestRegisterJar";
        String javaSrc = "package " + subDir + "; class " + className + " { }";


        // create dirs
        (new File(dir + FILE_SEPARATOR + subDir)).mkdirs();

        // generate java file
        FileOutputStream outStream =
            new FileOutputStream(new File(dir + FILE_SEPARATOR + subDir +
                                    FILE_SEPARATOR + className + ".java"));

        OutputStreamWriter outWriter = new OutputStreamWriter(outStream);
        outWriter.write(javaSrc);
        outWriter.close();

        // compile
        int status;
        status = Util.executeJavaCommand("javac " + dir + FILE_SEPARATOR + subDir +
                               FILE_SEPARATOR + className + ".java");
        assertEquals(0, status);

        // remove src file
        (new File(dir + FILE_SEPARATOR + subDir +
                  FILE_SEPARATOR + className + ".java")).delete();

        // generate jar file
        status = Util.executeJavaCommand("jar -cf " + dir + FILE_SEPARATOR + jarName + " " +
                              "-C " + dir + " " + subDir);
        assertEquals(0, status);

        // remove class file and sub_dir
        (new File(dir + FILE_SEPARATOR + subDir +
                  FILE_SEPARATOR + className + ".class")).delete();
        (new File(dir + FILE_SEPARATOR + subDir)).delete();

        // register resource
        registerNewResource(dir + FILE_SEPARATOR + jarName);

        // load the specific resource
        boolean exceptionRaised = false;
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        try {
            pig.registerJar("sub_dir/TestRegisterJar.class");
        }
        catch (IOException e) {
            exceptionRaised = true;
        }

        // verify proper jar file is located
        assertFalse(exceptionRaised);
        verifyStringContained(pig.getPigContext().extraJars, jarName, true);

        // clean up Jar file and test dir
        (new File(dir + FILE_SEPARATOR + jarName)).delete();
        (new File(dir)).delete();
    }

    @Test
    public void testRegisterJarGlobbingRelative() throws Throwable {
        String dir = "test1_register_jar_globbing_relative";
        String jarLocation = dir + FILE_SEPARATOR;
        String jar1Name = "TestRegisterJarGlobbing1.jar";
        String jar2Name = "TestRegisterJarGlobbing2.jar";

        createFakeJarFile(jarLocation, jar1Name);
        createFakeJarFile(jarLocation, jar2Name);

        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerJar(jarLocation + "TestRegisterJarGlobbing*.jar");
        verifyStringContained(pig.getPigContext().extraJars, jar1Name, true);
        verifyStringContained(pig.getPigContext().extraJars, jar2Name, true);

        // clean-up
        assertTrue((new File(jarLocation + jar1Name)).delete());
        assertTrue((new File(jarLocation + jar2Name)).delete());
        (new File(dir)).delete();
    }

    @Test
    public void testRegisterJarGlobbingAbsolute() throws Throwable {
        String dir = "test1_register_jar_globbing_absolute";
        String jarLocation = dir + FILE_SEPARATOR;
        String jar1Name = "TestRegisterJarGlobbing1.jar";
        String jar2Name = "TestRegisterJarGlobbing2.jar";

        createFakeJarFile(jarLocation, jar1Name);
        createFakeJarFile(jarLocation, jar2Name);

        String currentDir = System.getProperty("user.dir");
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerJar(new File(currentDir, dir) + FILE_SEPARATOR + "TestRegisterJarGlobbing*.jar");
        verifyStringContained(pig.getPigContext().extraJars, jar1Name, true);
        verifyStringContained(pig.getPigContext().extraJars, jar2Name, true);

        // clean-up
        assertTrue((new File(jarLocation + jar1Name)).delete());
        assertTrue((new File(jarLocation + jar2Name)).delete());
        (new File(dir)).delete();
    }

    @Test
    public void testRegisterRemoteGlobbingJar() throws Throwable {
        String dir = "test1_register_remote_jar_globbing";
        String jarLocation = dir + FILE_SEPARATOR;
        String jar1Name = "TestRegisterRemoteJarGlobbing1.jar";
        String jar2Name = "TestRegisterRemoteJarGlobbing2.jar";

        FileSystem fs = cluster.getFileSystem();
        createFakeJarFile(jarLocation, jar1Name, fs);
        createFakeJarFile(jarLocation, jar2Name, fs);

        // find the absolute path for the directory so that it does not
        // depend on configuration
        String absPath = fs.getFileStatus(new Path(jarLocation)).getPath().toString();

        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerJar(absPath + FILE_SEPARATOR + "TestRegister{Remote}Jar*.jar");

        verifyStringContained(pig.getPigContext().extraJars, jar1Name, true);
        verifyStringContained(pig.getPigContext().extraJars, jar2Name, true);

        // clean-up
        assertTrue(fs.delete(new Path(jarLocation), true));
    }

    @Test
    public void testDescribeLoad() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        Schema dumpedSchema = pig.dumpSchema("a") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: float,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeFilter() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = filter a by field1 > 10;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: float,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeDistinct() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = distinct a ;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: float,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeSort() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = order a by * desc;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: float,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeLimit() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = limit a 10;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: float,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeForeach() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = foreach a generate field1 + 10;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = new Schema(new Schema.FieldSchema(null, DataType.INTEGER));
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeForeachFail() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = foreach a generate field1 + 10;") ;
        try {
            pig.dumpSchema("c") ;
            fail("Error expected");
        } catch (Exception e) {
            assertTrue(e.getMessage().contains("Unable to describe schema for alias c"));
        }
    }

    @Test
    public void testDescribeForeachNoSchema() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' ;") ;
        pig.registerQuery("b = foreach a generate *;") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        assertNull(dumpedSchema);
    }

    @Test
    public void testDescribeCogroup() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = load 'b' as (field4, field5: double, field6: chararray );") ;
        pig.registerQuery("c = cogroup a by field1, b by field4;") ;
        Schema dumpedSchema = pig.dumpSchema("c") ;
        Schema expectedSchema = Utils.getSchemaFromString("group:int,a:{(field1:int,field2:float,field3:chararray)},b:{(field4:bytearray,field5:double,field6:chararray)}");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeCross() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = load 'b' as (field4, field5: double, field6: chararray );") ;
        pig.registerQuery("c = cross a, b;") ;
        Schema dumpedSchema = pig.dumpSchema("c") ;
        Schema expectedSchema = Utils.getSchemaFromString("a::field1: int,a::field2: float,a::field3: chararray,b::field4: bytearray,b::field5: double,b::field6: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeJoin() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = load 'b' as (field4, field5: double, field6: chararray );") ;
        pig.registerQuery("c = join a by field1, b by field4;") ;
        Schema dumpedSchema = pig.dumpSchema("c");
        Schema expectedSchema = Utils.getSchemaFromString("a::field1: int,a::field2: float,a::field3: chararray,b::field4: bytearray,b::field5: double,b::field6: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeUnion() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: float, field3: chararray );") ;
        pig.registerQuery("b = load 'b' as (field4, field5: double, field6: chararray );") ;
        pig.registerQuery("c = union a, b;") ;
        Schema dumpedSchema = pig.dumpSchema("c") ;
        Schema expectedSchema = Utils.getSchemaFromString("field1: int,field2: double,field3: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    @Test
    public void testDescribeTuple2Elem() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int, field2: int, field3: int );") ;
        pig.registerQuery("b = foreach a generate field1, (field2, field3);") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        assertTrue(dumpedSchema.getField(0).type==DataType.INTEGER);
        assertTrue(dumpedSchema.getField(1).type==DataType.TUPLE);
    }

    @Test
    public void testDescribeComplex() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (site: chararray, count: int, itemCounts: bag { itemCountsTuple: tuple (type: chararray, typeCount: int, f: float, m: map[]) } ) ;") ;
        pig.registerQuery("b = foreach a generate site, count, FLATTEN(itemCounts);") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString(
                    "site: chararray,count: int," +
                    "itemCounts::type: chararray,itemCounts::typeCount: int," +
                    "itemCounts::f: float,itemCounts::m: map[ ]");
        assertEquals(expectedSchema, dumpedSchema);
    }

    // PIG-5243
    @Test
    public void testDescribeAsClause() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (field1: int);");
        pig.registerQuery("b = FOREACH a generate field1 as (new_field:chararray);") ;
        Schema dumpedSchema = pig.dumpSchema("b") ;
        Schema expectedSchema = Utils.getSchemaFromString("new_field: chararray");
        assertEquals(expectedSchema, dumpedSchema);
    }

    private void registerScalarScript(boolean useScalar, String expectedSchemaStr) throws IOException {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("A = load 'adata' AS (a: int, b: int);");
        //scalar
        pig.registerQuery("C = FOREACH A GENERATE *;");
        String overrideScalar = useScalar ? "C = FILTER A BY b % 2 == 0; " : "";
        pig.registerQuery("B = FOREACH (GROUP A BY a) { " +
                overrideScalar +
                "D = FILTER A BY b % 2 == 1;" +
                "GENERATE group AS a, A.b AS every, C.b AS even, D.b AS odd;" +
                "};");
        Schema dumpedSchema = pig.dumpSchema("B");
        Schema expectedSchema = Utils.getSchemaFromString(
                expectedSchemaStr);
        assertEquals(expectedSchema, dumpedSchema);
    }

    // PIG-3581
    @Test
    public void testScalarPrecedence() throws Throwable {
        registerScalarScript(true, "a: int,every: {(b: int)},even: {(b: int)},odd: {(b: int)}");
    }

    // PIG-3581
    @Test
    public void testScalarResolution() throws Throwable {
        registerScalarScript(false, "a: int,every: {(b: int)},even: int,odd: {(b: int)}");
    }

    @Test
    public void testExplainXmlComplex() throws Throwable {
        // TODO: Explain XML output is not supported in non-MR mode. Remove the
        // following condition once it's implemented in Tez.
        String execType = cluster.getExecType().toString().toLowerCase();
        Assume.assumeTrue("Skip this test for TEZ", Util.isMapredExecType(cluster.getExecType()) || Util.isSparkExecType(cluster.getExecType()));
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a' as (site: chararray, count: int, itemCounts: bag { itemCountsTuple: tuple (type: chararray, typeCount: int, f: float, m: map[]) } ) ;") ;
        pig.registerQuery("b = foreach a generate site, count, FLATTEN(itemCounts);") ;
        pig.registerQuery("c = group b by site;");
        pig.registerQuery("d = foreach c generate FLATTEN($1);");
        pig.registerQuery("e = group d by $2;");

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        pig.explain("e", "xml", true, false, ps, ps, null, null);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(bais);

        //Verify Logical and Physical Plans aren't supported.
        NodeList logicalPlan = doc.getElementsByTagName("logicalPlan");
        assertEquals(1, logicalPlan.getLength());
        assertTrue(logicalPlan.item(0).getTextContent().contains("Not Supported"));
        NodeList physicalPlan = doc.getElementsByTagName("physicalPlan");
        assertEquals(1, physicalPlan.getLength());
        assertTrue(physicalPlan.item(0).getTextContent().contains("Not Supported"));


        if (execType.equals(ExecType.MAPREDUCE.name().toLowerCase())){
            verifyExplainXmlComplexMR(doc);
        } else if (execType.equals(MiniGenericCluster.EXECTYPE_SPARK)){
            verifyExplainXmlComplexSpark(doc);
        }


    }

    private void verifyExplainXmlComplexSpark(Document doc) {
        NodeList stores = doc.getElementsByTagName("POStore");
        assertEquals(1, stores.getLength());

        NodeList groups = doc.getElementsByTagName("POJoinGroupSpark");
        assertEquals(2, groups.getLength());

        Node innerGroup = groups.item(1);

        NodeList groupChildren = innerGroup.getChildNodes();

        int foreachCount = 0;
        int castCount = 0;
        int loadCount = 0;

        for (int i = 0; i < groupChildren.getLength(); i++) {
            Node node = groupChildren.item(i);
            if (node.getNodeName().equals("POForEach")){
                ++foreachCount;
                NodeList foreachNodes = node.getChildNodes();
                for (int j = 0; j < foreachNodes.getLength(); j++) {
                    Node innerNode = foreachNodes.item(j);
                    if (innerNode.getNodeName().equals("alias")){
                        assertEquals("b",innerNode.getTextContent());
                    }else if (innerNode.getNodeName().equals("POCast")){
                        ++castCount;
                    }else if (innerNode.getNodeName().equals("POLoad")) {
                        ++loadCount;
                    }
                }
            }
        }

        assertEquals(1,foreachCount);
        assertEquals(3,castCount);
        assertEquals(1,loadCount);
    }

    private void verifyExplainXmlComplexMR(Document doc) {
        //Verify we have two loads and one is temporary
        NodeList loads = doc.getElementsByTagName("POLoad");
        assertEquals(2, loads.getLength());

        boolean sawTempLoad = false;
        boolean sawNonTempLoad = false;
        for (int i = 0; i < loads.getLength(); i++) {
            Boolean isTempLoad = null;
            boolean hasAlias = false;

            Node poLoad = loads.item(i);
            NodeList children = poLoad.getChildNodes();

            for (int j = 0; j < children.getLength(); j++) {
                Node child = children.item(j);
                if (child.getNodeName().equals("alias")) {
                    hasAlias = true;
                }
                if (child.getNodeName().equals("isTmpLoad")) {
                    if (child.getTextContent().equals("false")) {
                        isTempLoad = false;
                    } else if (child.getTextContent().equals("true")) {
                        isTempLoad = true;
                    }
                }
            }

            if (isTempLoad == null) {
                fail("POLoad elements should have isTmpLoad child node.");
            } else if (isTempLoad && hasAlias) {
                fail("Temp loads should not have aliases");
            } else if (!isTempLoad && !hasAlias) {
                fail("Non temporary loads should be associated with alias.");
            }

            sawTempLoad = sawTempLoad || isTempLoad;
            sawNonTempLoad = sawNonTempLoad || !isTempLoad;
        }

        assertTrue(sawTempLoad && sawNonTempLoad);
    }

    @Test
    public void testRegisterRemoteScript() throws Throwable {
        String scriptName = "script.py";
        File scriptFile = File.createTempFile("tmp", "");
        PrintWriter pw = new PrintWriter(new FileWriter(scriptFile));
        pw.println("@outputSchema(\"word:chararray\")\ndef helloworld():\n    return 'Hello, World'");
        pw.close();

        FileSystem fs = cluster.getFileSystem();
        fs.copyFromLocalFile(new Path(scriptFile.getAbsolutePath()), new Path(scriptName));

        // find the absolute path for the directory so that it does not
        // depend on configuration
        String absPath = fs.getFileStatus(new Path(scriptName)).getPath().toString();

        Util.createInputFile(cluster, "testRegisterRemoteScript_input", new String[]{"1", "2"});
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerCode(absPath, "jython", "pig");
        pig.registerQuery("a = load 'testRegisterRemoteScript_input';");
        pig.registerQuery("b = foreach a generate pig.helloworld($0);");
        Iterator<Tuple> iter = pig.openIterator("b");

        assertTrue(iter.hasNext());
        Tuple t = iter.next();
        assertTrue(t.size() > 0);
        assertEquals("Hello, World", t.get(0));

        assertTrue(iter.hasNext());
        t = iter.next();
        assertTrue(t.size() > 0);
        assertEquals("Hello, World", t.get(0));

        assertFalse(iter.hasNext());
    }

    @Test
    public void testPigProperties() throws Throwable {
        File propertyFile = new File(tempDir, "pig.properties");
        propertyFile.deleteOnExit();
        TestPigServer.registerNewResource(propertyFile.getAbsolutePath());
        File cliPropertyFile = new File("commandLine_pig.properties");
        cliPropertyFile.deleteOnExit();
        TestPigServer.registerNewResource(cliPropertyFile.getAbsolutePath());

        Properties properties = PropertiesUtil.loadDefaultProperties();
        assertEquals("40000000", properties.getProperty("pig.spill.gc.activation.size"));
        assertNull(properties.getProperty("test123"));

        PrintWriter out = new PrintWriter(new FileWriter(propertyFile));
        out.println("test123=properties");
        out.close();
        properties = PropertiesUtil.loadDefaultProperties();

        assertEquals("properties", properties.getProperty("test123"));

        out = new PrintWriter(new FileWriter(cliPropertyFile));
        out.println("test123=cli_properties");
        out.close();

        properties = PropertiesUtil.loadDefaultProperties();
        PropertiesUtil.loadPropertiesFromFile(properties,
                "commandLine_pig.properties");
        assertEquals("cli_properties", properties.getProperty("test123"));

        propertyFile.delete();
        cliPropertyFile.delete();
    }

    @Test
    public void testPigTempDir() throws Throwable {
        Properties properties = PropertiesUtil.loadDefaultProperties();
        File pigTempDir = new File(tempDir, FILE_SEPARATOR + "tmp" + FILE_SEPARATOR + "test");
        properties.put("pig.temp.dir", pigTempDir.getPath());
        PigContext pigContext=new PigContext(ExecType.LOCAL, properties);
        pigContext.connect();
        FileLocalizer.setInitialized(false);

        String tempPath= FileLocalizer.getTemporaryPath(pigContext).toString();
        Path path = new Path(tempPath);
        assertTrue(tempPath.startsWith(pigTempDir.toURI().toString()));

        FileSystem fs = FileSystem.get(path.toUri(),
                ConfigurationUtil.toConfiguration(pigContext.getProperties()));
        FileStatus status = fs.getFileStatus(path.getParent());
        // Temporary root dir should have 700 as permission
        assertEquals("rwx------", status.getPermission().toString());
        pigTempDir.delete();
        FileLocalizer.setInitialized(false);
    }

    @Test
    public void testUniquePigTempDir() throws Throwable {
        Properties properties = PropertiesUtil.loadDefaultProperties();
        File pigTempDir = new File(tempDir, FILE_SEPARATOR + "tmp" + FILE_SEPARATOR + "test");
        properties.put("pig.temp.dir", pigTempDir.getPath());
        PigContext pigContext = new PigContext(ExecType.LOCAL, properties);
        pigContext.connect();
        FileLocalizer.setInitialized(false);

        Random r = new Random(5);
        FileLocalizer.setR(r);
        String tempPath1 = FileLocalizer.getTemporaryPath(pigContext).toString();

        FileLocalizer.setInitialized(false);
        r = new Random(5);
        FileLocalizer.setR(r);
        String tempPath2 = FileLocalizer.getTemporaryPath(pigContext).toString();

        assertFalse(tempPath1.toString().equals(tempPath2.toString()));

        // cleanup
        pigTempDir.delete();
        FileLocalizer.setInitialized(false);
    }

    @Test
    public void testDescribeForEachFlatten() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.registerQuery("a = load 'a';") ;
        pig.registerQuery("b = group a by $0;") ;
        pig.registerQuery("c = foreach b generate flatten(a);") ;
        Schema s = pig.dumpSchema("c") ;
        assertNull(s);
    }

    @Test // PIG-2059
    public void test1() throws Throwable {
        PigServer pig = new PigServer(cluster.getExecType(), properties);
        pig.setValidateEachStatement(true);
        pig.registerQuery("A = load 'x' as (u, v);") ;
        try {
            pig.registerQuery("B = foreach A generate $2;") ;
            fail("Query is supposed to fail.");
        } catch(FrontendException ex) {
            String msg = "Out of bound access. " +
            "Trying to access non-existent column: 2";
            Util.checkMessageInException(ex, msg);
        }
    }

    @Test
    public void testDefaultPigProperties() throws Throwable {
        //Test with PigServer
        PigServer pigServer = new PigServer(cluster.getExecType());
        Properties properties = pigServer.getPigContext().getProperties();

        assertEquals("999", properties.getProperty("pig.exec.reducers.max"));
        assertEquals("true", properties.getProperty("aggregate.warning"));
        assertEquals("true", properties.getProperty(PigConfiguration.PIG_OPT_MULTIQUERY));
        assertEquals("false", properties.getProperty("stop.on.failure"));

        //Test with properties file
        File propertyFile = new File(tempDir, "pig.properties");

        properties = PropertiesUtil.loadDefaultProperties();

        assertEquals("999", properties.getProperty("pig.exec.reducers.max"));
        assertEquals("true", properties.getProperty("aggregate.warning"));
        assertEquals("true", properties.getProperty(PigConfiguration.PIG_OPT_MULTIQUERY));
        assertEquals("false", properties.getProperty("stop.on.failure"));

        PrintWriter out = new PrintWriter(new FileWriter(propertyFile));
        out.println("aggregate.warning=false");
        out.println("opt.multiquery=false");
        out.println("stop.on.failure=true");

        out.close();

        properties = PropertiesUtil.loadDefaultProperties();
        assertEquals("false", properties.getProperty("aggregate.warning"));
        assertEquals("false", properties.getProperty(PigConfiguration.PIG_OPT_MULTIQUERY));
        assertEquals("true", properties.getProperty("stop.on.failure"));

        propertyFile.delete();
    }

    @Test
    // See PIG-4109
    public void testRegisterJarRemoteScript() throws Throwable {
        if (Util.WINDOWS) {
            properties.setProperty("pig.jars.relative.to.dfs", "true");
            String jarName = JarManager.findContainingJar(org.codehaus.jackson.JsonParser.class);
            PigServer pig = new PigServer(cluster.getExecType(), properties);
            pig.registerJar(jarName);
        }
    }
}
