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

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;

import org.apache.pig.PigServer;
import org.apache.pig.backend.executionengine.ExecException;
import org.apache.pig.backend.executionengine.ExecJob;
import org.apache.pig.backend.hadoop.executionengine.optimizer.SecondaryKeyOptimizer;
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.schema.Schema;
import org.apache.pig.impl.plan.VisitorException;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

// ant sends abstract classes also to junit. skipNonTests attribute does not work with all ant versions
@Ignore
public abstract class TestSecondarySort {
    protected static MiniGenericCluster cluster = null;
    protected PigServer pigServer;
    protected static PigContext pc;

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

    @Before
    public void setUp() throws Exception {
        if (cluster == null) {
            cluster = getCluster();
            pc = new PigContext(cluster.getExecType(), cluster.getProperties());
            try {
                pc.connect();
            } catch (ExecException e) {
                throw new RuntimeException(e);
            }
        }
        pigServer = new PigServer(pc);
    }

    public abstract SecondaryKeyOptimizer visitSecondaryKeyOptimizer(
            String query) throws Exception, VisitorException;

    public abstract MiniGenericCluster getCluster();

    @Test
    public void testDistinctOptimization1() throws Exception {
        // Distinct on one entire input
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);"+
        "B = group A by $0;"+
        "C = foreach B { D = distinct A; generate group, D;};"+

        "store C into 'output';");
        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);

        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(0, so.getNumSortRemoved());
        assertEquals(1, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization1() throws Exception {
        // Sort on something other than the main key
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = limit A 10; E = order D by $1; generate group, E;};" +

        "store C into 'output';");
        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);

        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization2() throws Exception {
        // Sort on the prefix of the main key
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = limit A 10; E = order D by $0; generate group, E;};" +

        "store C into 'output';");
        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);

        assertEquals(0, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization3() throws Exception {
        // Sort on the main key prefix / non main key prefix mixed
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = limit A 10; E = order D by $1; F = order E by $0; generate group, F;};"+

        "store C into 'output';");
        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);

        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(2, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization4() throws Exception {
        // Sort on the main key again
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = limit A 10; E = order D by $0, $1, $2; generate group, E;};" +

        "store C into 'output';");

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);
        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization5() throws Exception {
        // Sort on the two keys, we can only take off 1
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = limit A 10; E = order D by $1; F = order E by $2; generate group, F;};" +
        "store C into 'output';");

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);
        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization6() throws Exception {
        // Sort desc
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by $0;" +
        "C = foreach B { D = order A by $0 desc; generate group, D;};" +

        "store C into 'output';");

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);
        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testSortOptimization7() throws Exception {
        // Sort asc on 1st key, desc on 2nd key
        String query = ("A=LOAD 'input1' AS (a0, a1, a2);" +
        "B = group A by ($0, $1);" +
        "C = foreach B { D = order A by $0, $1 desc; generate group, D;};" +

        "store C into 'output';");

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);
        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(1, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    // See PIG-1193
    @Test
    public void testSortOptimization8() throws Exception {
        // Sort desc, used in UDF twice
        String query = ("A=LOAD 'input1' AS (a0);" +
        "B = group A all;" +
        "C = foreach B { D = order A by $0 desc; generate DIFF(D, D);};" +

        "store C into 'output';");

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);
        assertEquals(1, so.getNumUseSecondaryKey());
        assertEquals(2, so.getNumSortRemoved());
        assertEquals(0, so.getNumDistinctChanged());
    }

    @Test
    public void testNestedDistinctEndToEnd1() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        File tmpFile2 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps2 = new PrintStream(new FileOutputStream(tmpFile2));
        ps2.println("1\t4\t4");
        ps2.println("2\t3\t1");
        ps2.close();
        String file1ClusterPath = Util.removeColon(tmpFile1.getCanonicalPath());
        String file2ClusterPath = Util.removeColon(tmpFile2.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), file1ClusterPath);
        Util.copyFromLocalToCluster(cluster, tmpFile2.getCanonicalPath(), file2ClusterPath);

        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(file1ClusterPath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = LOAD '" + Util.encodeEscape(file2ClusterPath) + "' AS (b0, b1, b2);");
        pigServer.registerQuery("C = cogroup A by a0, B by b0 parallel 2;");
        pigServer
                .registerQuery("D = foreach C { E = limit A 10; F = E.a1; G = DISTINCT F; generate group, COUNT(G);};");
        Iterator<Tuple> iter = pigServer.openIterator("D");
        String[] expectedRes = new String[]{"(2,1)","(1,2)"};
        Schema s = pigServer.dumpSchema("D");
        Util.checkQueryOutputs(iter,expectedRes,org.apache
                .pig.newplan.logical.Util.translateSchema(s),
                Util.isSparkExecType(cluster.getExecType()));
        Util.deleteFile(cluster, file1ClusterPath);
        Util.deleteFile(cluster, file2ClusterPath);
    }

    @Test
    public void testNestedDistinctEndToEnd2() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        String clusterPath = Util.removeColon(tmpFile1.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterPath);
        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(clusterPath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = group A by $0 parallel 2;");
        pigServer.registerQuery("C = foreach B { D = distinct A; generate group, D;};");
        Iterator<Tuple> iter = pigServer.openIterator("C");
        Schema s = pigServer.dumpSchema("C");
        String expected[] = {
                "(2,{(2,3,4)})",
                "(1,{(1,2,3),(1,2,4),(1,3,4)})"
        };
        Util.checkQueryOutputs(iter, expected, org.apache
                .pig.newplan.logical.Util.translateSchema(s),
                Util.isSparkExecType(Util.getLocalTestMode()));
        Util.deleteFile(cluster, clusterPath);
    }

    @Test
    public void testNestedSortEndToEnd1() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        String expected[] = {
                "(2,{(2,3,4)})",
                "(1,{(1,2,3),(1,2,4),(1,2,4),(1,2,4),(1,3,4)})"
        };

        String clusterPath = Util.removeColon(tmpFile1.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterPath);
        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(clusterPath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = group A by $0 parallel 2;");
        pigServer.registerQuery("C = foreach B { D = limit A 10; E = order D by $1; generate group, E;};");
        Iterator<Tuple> iter = pigServer.openIterator("C");
        Schema s = pigServer.dumpSchema("C");

        Util.checkQueryOutputsAfterSortRecursive(iter, expected, org.apache.pig.newplan.logical.Util.translateSchema(s));
        Util.deleteFile(cluster, clusterPath);
    }

    @Test
    public void testNestedSortEndToEnd2() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t4\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t8\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        String expected[] = {
                "(2,{(2,3,4)})",
                "(1,{(1,8,4),(1,4,4),(1,3,4),(1,2,3),(1,2,4)})"
        };

        String clusterPath = Util.removeColon(tmpFile1.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterPath);
        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(clusterPath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = group A by $0 parallel 2;");
        pigServer.registerQuery("C = foreach B { D = order A by a1 desc; generate group, D;};");
        Iterator<Tuple> iter = pigServer.openIterator("C");
        Schema s = pigServer.dumpSchema("C");

        Util.checkQueryOutputsAfterSortRecursive(iter, expected, org.apache.pig.newplan.logical.Util.translateSchema(s));
        Util.deleteFile(cluster, clusterPath);
    }

    @Test
    public void testNestedSortEndToEnd3() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("2\t3\t4");
        ps1.close();
        File tmpFile2 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps2 = new PrintStream(new FileOutputStream(tmpFile2));
        ps2.println("1\t4\t4");
        ps2.println("2\t3\t1");
        ps2.close();
        String clusterPath1 = tmpFile1.getName();
        String clusterPath2 = tmpFile2.getName();
        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterPath1);
        Util.copyFromLocalToCluster(cluster, tmpFile2.getCanonicalPath(), clusterPath2);
        pigServer.registerQuery("A = LOAD '" + clusterPath1 + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = LOAD '" + clusterPath2 + "' AS (b0, b1, b2);");
        pigServer.registerQuery("C = cogroup A by (a0,a1), B by (b0,b1) parallel 2;");
        pigServer.registerQuery("D = ORDER C BY group;");
        pigServer.registerQuery("E = foreach D { F = limit A 10; G = ORDER F BY a2; generate group, COUNT(G);};");
        Iterator<Tuple> iter = pigServer.openIterator("E");
        Schema s = pigServer.dumpSchema("E");
        String[] expectedRes = new String[]{"((1,2),4)","((1,3),1)","((1,4),0)","((2,3),1)"};
        Util.checkQueryOutputs(iter, expectedRes,org.apache.pig.newplan.logical.Util.translateSchema(s),
        		Util.isSparkExecType(cluster.getExecType()));
        Util.deleteFile(cluster, clusterPath1);
        Util.deleteFile(cluster, clusterPath2);
    }

    @Test
    public void testNestedSortMultiQueryEndToEnd1() throws Exception {
        try {
            pigServer.setBatchOn();
            Util.copyFromLocalToCluster(cluster, "test/org/apache/pig/test/data/passwd",
                    "testNestedSortMultiQueryEndToEnd1-input.txt");
            pigServer.registerQuery("a = load 'testNestedSortMultiQueryEndToEnd1-input.txt'"
                    + " using PigStorage(':') as (uname:chararray, passwd:chararray, uid:int, gid:int);");
            pigServer.registerQuery("b = group a by uname parallel 2;");
            pigServer.registerQuery("c = group a by gid parallel 2;");
            pigServer.registerQuery("d = foreach b generate SUM(a.gid);");
            pigServer.registerQuery("e = foreach c { f = order a by uid; generate group, f; };");
            pigServer.registerQuery("store d into '/tmp/output1';");
            pigServer.registerQuery("store e into '/tmp/output2';");

            List<ExecJob> jobs = pigServer.executeBatch();
            for (ExecJob job : jobs) {
                assertEquals(ExecJob.JOB_STATUS.COMPLETED, job.getStatus());
            }
        } finally {
            FileLocalizer.delete("/tmp/output1", pigServer.getPigContext());
            FileLocalizer.delete("/tmp/output2", pigServer.getPigContext());
            Util.deleteFile(cluster, "testNestedSortMultiQueryEndToEnd1-input.txt");
        }
    }

    @Test
    public void testNestedSortMultiQueryEndToEnd2() throws Exception {
        File input = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(input));
        ps1.println("2\t2\t4");
        ps1.println("2\t3\t4");
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t5");
        ps1.close();
        Util.copyFromLocalToCluster(cluster, input.getCanonicalPath(), "testNestedSortMultiQueryEndToEnd2-input.txt");

        try {
            pigServer.setBatchOn();
            pigServer.registerQuery("a = load 'testNestedSortMultiQueryEndToEnd2-input.txt' as (a0, a1, a2);");
            pigServer.registerQuery("b = group a by a0 parallel 2;");
            pigServer.registerQuery("c = group a by a1 parallel 2;");
            pigServer.registerQuery("d = foreach b generate group, SUM(a.a2);");
            pigServer.registerQuery("e = foreach c { f = order a by a0,a2; generate group, f; };");
            pigServer.registerQuery("store d into '/tmp/output1';");
            pigServer.registerQuery("store e into '/tmp/output2';");

            List<ExecJob> jobs = pigServer.executeBatch();
            for (ExecJob job : jobs) {
                assertTrue(job.getStatus() == ExecJob.JOB_STATUS.COMPLETED);
            }
            pigServer.registerQuery("D = load '/tmp/output1';");
            pigServer.registerQuery("E = load '/tmp/output2';");
            pigServer.executeBatch();

            Iterator<Tuple> iter = pigServer.openIterator("D");
            Schema s = pigServer.dumpSchema("D");
            String[] expectedD = { "(1,16.0)", "(2,8.0)" };
            Util.checkQueryOutputsAfterSortRecursive(iter, expectedD,
                    org.apache.pig.newplan.logical.Util.translateSchema(s));

            iter = pigServer.openIterator("E");
            s = pigServer.dumpSchema("E");
            String[] expectedE = { "(2,{(1,2,3),(1,2,4),(1,2,5),(2,2,4)})", "(3,{(1,3,4),(2,3,4)})" };
            Util.checkQueryOutputsAfterSortRecursive(iter, expectedE,
                    org.apache.pig.newplan.logical.Util.translateSchema(s));
        } finally {
            FileLocalizer.delete("/tmp/output1", pigServer.getPigContext());
            FileLocalizer.delete("/tmp/output2", pigServer.getPigContext());
            Util.deleteFile(cluster, "testNestedSortMultiQueryEndToEnd2-input.txt");
        }

    }

    @Test
    public void testNestedSortMultiQueryEndToEnd3() throws Exception {
        File input1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(input1));
        ps1.println("a\t0");
        ps1.println("a\t2");
        ps1.println("a\t1");
        ps1.close();
        Util.copyFromLocalToCluster(cluster, input1.getCanonicalPath(), "testNestedSortMultiQueryEndToEnd3-input-1.txt");

        File input2 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps2 = new PrintStream(new FileOutputStream(input2));
        ps2.println("a");
        ps2.close();
        Util.copyFromLocalToCluster(cluster, input2.getCanonicalPath(), "testNestedSortMultiQueryEndToEnd3-input-2.txt");

        try {
            pigServer.setBatchOn();
            pigServer.registerQuery("a = load 'testNestedSortMultiQueryEndToEnd3-input-1.txt' as (a0:chararray, a1:chararray);");
            pigServer.registerQuery("b = load 'testNestedSortMultiQueryEndToEnd3-input-2.txt' as (b0);");
            pigServer.registerQuery("c = cogroup b by b0, a by a0;");
            pigServer.registerQuery("d = foreach c {a_sorted = order a by a1 desc;generate group, a_sorted, b;}");
            Iterator<Tuple> iter = pigServer.openIterator("d");

            assertEquals(iter.next().toString(), "(a,{(a,2),(a,1),(a,0)},{(a)})");
        } finally {
            Util.deleteFile(cluster, "testNestedSortMultiQueryEndToEnd3-input-1.txt");
            Util.deleteFile(cluster, "testNestedSortMultiQueryEndToEnd3-input-2.txt");
        }

    }

    // See PIG-1978
    @Test
    public void testForEachTwoInput() throws Exception {
        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t2\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        String expected[] = {
                "((1,2),{(2,3),(2,4),(2,4),(2,4)})",
                "((1,3),{(3,4)})",
                "((2,3),{(3,4)})"
        };
        String clusterFilePath = Util.removeColon(tmpFile1.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterFilePath);
        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(clusterFilePath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = group A by (a0, a1);");
        pigServer.registerQuery("C = foreach B { C1 = A.(a1,a2); generate group, C1;};");
        Iterator<Tuple> iter = pigServer.openIterator("C");
        Schema s = pigServer.dumpSchema("C");

        Util.checkQueryOutputsAfterSortRecursive(iter, expected, org.apache.pig.newplan.logical.Util.translateSchema(s));

        Util.deleteFile(cluster, clusterFilePath);
    }

    @Test
    // Once custom partitioner is used, we cannot use secondary key optimizer, see PIG-3827
    public void testCustomPartitionerWithSort() throws Exception {
        Assume.assumeFalse("Skip this test for Spark", Util.isSparkExecType(cluster.getExecType()));

        File tmpFile1 = Util.createTempFileDelOnExit("test", "txt");
        PrintStream ps1 = new PrintStream(new FileOutputStream(tmpFile1));
        ps1.println("1\t2\t3");
        ps1.println("1\t3\t4");
        ps1.println("1\t4\t4");
        ps1.println("1\t2\t4");
        ps1.println("1\t8\t4");
        ps1.println("2\t3\t4");
        ps1.close();

        String clusterPath = Util.removeColon(tmpFile1.getCanonicalPath());

        Util.copyFromLocalToCluster(cluster, tmpFile1.getCanonicalPath(), clusterPath);
        pigServer.registerQuery("A = LOAD '" + Util.encodeEscape(clusterPath) + "' AS (a0, a1, a2);");
        pigServer.registerQuery("B = group A by $0 PARTITION BY org.apache.pig.test.utils.WrongCustomPartitioner parallel 2;");
        pigServer.registerQuery("C = foreach B { D = order A by a1 desc; generate group, D;};");
        boolean captureException = false;
        try {
            pigServer.openIterator("C");
        } catch (Exception e) {
            captureException = true;
        }

        assertTrue(captureException);

        Util.deleteFile(cluster, clusterPath);
    }

    @Test
    // Once NestedLimitedOptimizer is used, we cannot use secondary key optimizer
    public void testNestedLimitedSort() throws Exception {
        String query = "a = load 'studenttab10k' as (name:chararray, age:int, gpa:double);" +
                       "b = group a by name;" +
                       "c = foreach b {" +
                       "c1 = order a by age;" +
                       "c2 = limit c1 5;" +
                       "generate c2;}" +
                       "store c into 'empty';";

        SecondaryKeyOptimizer so = visitSecondaryKeyOptimizer(query);

        assertEquals(0, so.getNumUseSecondaryKey());
        assertEquals(0, so.getNumSortRemoved());
    }
}
