/**
 * 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.hadoop.mrunit.mapreduce;

import static org.apache.hadoop.mrunit.testutil.ExtendedAssert.assertListEquals;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import junit.framework.TestCase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Reducer.Context;
import org.apache.hadoop.mapreduce.lib.reduce.LongSumReducer;
import org.apache.hadoop.mrunit.mapreduce.TestMapDriver.ConfigurationMapper;
import org.apache.hadoop.mrunit.mapreduce.TestReduceDriver.ConfigurationReducer;
import org.apache.hadoop.mrunit.types.Pair;
import org.junit.Before;
import org.junit.Test;

public class TestMapReduceDriver extends TestCase {

  private static final int FOO_IN_A = 42;
  private static final int FOO_IN_B = 10;
  private static final int BAR_IN = 12;
  private static final int FOO_OUT = 52;

  private Mapper<Text, LongWritable, Text, LongWritable> mapper;
  private Reducer<Text, LongWritable, Text, LongWritable> reducer;
  private MapReduceDriver<Text, LongWritable,
                  Text, LongWritable,
                  Text, LongWritable> driver;

  private MapReduceDriver<Text, Text, Text, Text, Text, Text> driver2;

  @Before
  public void setUp() throws Exception {
    mapper = new Mapper<Text, LongWritable, Text, LongWritable>(); // This is the IdentityMapper
    reducer = new LongSumReducer<Text>();
    driver = new MapReduceDriver<Text, LongWritable,
                                 Text, LongWritable,
                                 Text, LongWritable>(
                        mapper, reducer);
    // for shuffle tests
    driver2 = new MapReduceDriver<Text, Text, Text, Text, Text, Text>();
  }

  @Test
  public void testRun() {
    List<Pair<Text, LongWritable>> out = null;
    try {
      out = driver
              .withInput(new Text("foo"), new LongWritable(FOO_IN_A))
              .withInput(new Text("foo"), new LongWritable(FOO_IN_B))
              .withInput(new Text("bar"), new LongWritable(BAR_IN))
              .run();
    } catch (IOException ioe) {
      fail();
    }

    List<Pair<Text, LongWritable>> expected =
      new ArrayList<Pair<Text, LongWritable>>();
    expected.add(new Pair<Text, LongWritable>(new Text("bar"),
            new LongWritable(BAR_IN)));
    expected.add(new Pair<Text, LongWritable>(new Text("foo"),
            new LongWritable(FOO_OUT)));

    assertListEquals(out, expected);
  }

  @Test
  public void testTestRun1() {
    driver
            .withInput(new Text("foo"), new LongWritable(FOO_IN_A))
            .withInput(new Text("foo"), new LongWritable(FOO_IN_B))
            .withInput(new Text("bar"), new LongWritable(BAR_IN))
            .withOutput(new Text("bar"), new LongWritable(BAR_IN))
            .withOutput(new Text("foo"), new LongWritable(FOO_OUT))
            .runTest();
  }

  @Test
  public void testTestRun2() {
    driver
            .withInput(new Text("foo"), new LongWritable(FOO_IN_A))
            .withInput(new Text("bar"), new LongWritable(BAR_IN))
            .withInput(new Text("foo"), new LongWritable(FOO_IN_B))
            .withOutput(new Text("bar"), new LongWritable(BAR_IN))
            .withOutput(new Text("foo"), new LongWritable(FOO_OUT))
            .runTest();
  }

  @Test
  public void testTestRun3() {
    try {
      driver
            .withInput(new Text("foo"), new LongWritable(FOO_IN_A))
            .withInput(new Text("bar"), new LongWritable(BAR_IN))
            .withInput(new Text("foo"), new LongWritable(FOO_IN_B))
            .withOutput(new Text("foo"), new LongWritable(FOO_OUT))
            .withOutput(new Text("bar"), new LongWritable(BAR_IN))
            .runTest();
      fail();
    } catch (RuntimeException re) {
      // expected
    }
  }

  @Test
  public void testEmptyInput() {
    driver.runTest();
  }

  @Test
  public void testEmptyInputWithOutputFails() {
    try {
      driver
              .withOutput(new Text("foo"), new LongWritable(FOO_OUT))
              .runTest();
      fail();
    } catch (RuntimeException re) {
      // expected.
    }
  }

  @Test
  public void testEmptyShuffle() {
    List<Pair<Text, Text>> inputs = new ArrayList<Pair<Text, Text>>();
    List<Pair<Text, List<Text>>> outputs = driver2.shuffle(inputs);
    assertEquals(0, outputs.size());
  }

  // just shuffle a single (k, v) pair
  @Test
  public void testSingleShuffle() {
    List<Pair<Text, Text>> inputs = new ArrayList<Pair<Text, Text>>();
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("b")));

    List<Pair<Text, List<Text>>> outputs = driver2.shuffle(inputs);

    List<Pair<Text, List<Text>>> expected = new ArrayList<Pair<Text, List<Text>>>();
    List<Text> sublist = new ArrayList<Text>();
    sublist.add(new Text("b"));
    expected.add(new Pair<Text, List<Text>>(new Text("a"), sublist));

    assertListEquals(expected, outputs);
  }

  // shuffle multiple values from the same key.
  @Test
  public void testShuffleOneKey() {
    List<Pair<Text, Text>> inputs = new ArrayList<Pair<Text, Text>>();
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("b")));
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("c")));

    List<Pair<Text, List<Text>>> outputs = driver2.shuffle(inputs);

    List<Pair<Text, List<Text>>> expected = new ArrayList<Pair<Text, List<Text>>>();
    List<Text> sublist = new ArrayList<Text>();
    sublist.add(new Text("b"));
    sublist.add(new Text("c"));
    expected.add(new Pair<Text, List<Text>>(new Text("a"), sublist));

    assertListEquals(expected, outputs);
  }

  // shuffle multiple keys
  @Test
  public void testMultiShuffle1() {
    List<Pair<Text, Text>> inputs = new ArrayList<Pair<Text, Text>>();
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("x")));
    inputs.add(new Pair<Text, Text>(new Text("b"), new Text("z")));
    inputs.add(new Pair<Text, Text>(new Text("b"), new Text("w")));
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("y")));

    List<Pair<Text, List<Text>>> outputs = driver2.shuffle(inputs);

    List<Pair<Text, List<Text>>> expected = new ArrayList<Pair<Text, List<Text>>>();
    List<Text> sublist1 = new ArrayList<Text>();
    sublist1.add(new Text("x"));
    sublist1.add(new Text("y"));
    expected.add(new Pair<Text, List<Text>>(new Text("a"), sublist1));

    List<Text> sublist2 = new ArrayList<Text>();
    sublist2.add(new Text("z"));
    sublist2.add(new Text("w"));
    expected.add(new Pair<Text, List<Text>>(new Text("b"), sublist2));

    assertListEquals(expected, outputs);
  }


  // shuffle multiple keys that are out-of-order to start.
  @Test
  public void testMultiShuffle2() {
    List<Pair<Text, Text>> inputs = new ArrayList<Pair<Text, Text>>();
    inputs.add(new Pair<Text, Text>(new Text("b"), new Text("z")));
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("x")));
    inputs.add(new Pair<Text, Text>(new Text("b"), new Text("w")));
    inputs.add(new Pair<Text, Text>(new Text("a"), new Text("y")));

    List<Pair<Text, List<Text>>> outputs = driver2.shuffle(inputs);

    List<Pair<Text, List<Text>>> expected = new ArrayList<Pair<Text, List<Text>>>();
    List<Text> sublist1 = new ArrayList<Text>();
    sublist1.add(new Text("x"));
    sublist1.add(new Text("y"));
    expected.add(new Pair<Text, List<Text>>(new Text("a"), sublist1));

    List<Text> sublist2 = new ArrayList<Text>();
    sublist2.add(new Text("z"));
    sublist2.add(new Text("w"));
    expected.add(new Pair<Text, List<Text>>(new Text("b"), sublist2));

    assertListEquals(expected, outputs);
  }
  
  @Test
  public void testConfiguration() {
	  Configuration conf = new Configuration();
	  conf.set("TestKey", "TestValue");
	  
	  MapReduceDriver<NullWritable, NullWritable, NullWritable, NullWritable, NullWritable, NullWritable> confDriver 
	      = new MapReduceDriver<NullWritable, NullWritable, NullWritable, NullWritable, NullWritable, NullWritable>();
	  
	  ConfigurationMapper<NullWritable, NullWritable, NullWritable, NullWritable> mapper 
	      = new ConfigurationMapper<NullWritable, NullWritable, NullWritable, NullWritable>();
	  ConfigurationReducer<NullWritable, NullWritable, NullWritable, NullWritable> reducer 
      = new ConfigurationReducer<NullWritable, NullWritable, NullWritable, NullWritable>();
	  
	  confDriver.withMapper(mapper).withReducer(reducer).withConfiguration(conf).
	      withInput(NullWritable.get(),NullWritable.get()).
	      withOutput(NullWritable.get(),NullWritable.get()).runTest();
	  assertEquals(mapper.setupConfiguration.get("TestKey"), "TestValue");
	  assertEquals(reducer.setupConfiguration.get("TestKey"), "TestValue");	  
  }

  // Test the key grouping and value ordering comparators
  @Test
  public void testComparators() {
    // group comparator - group by first character
    RawComparator groupComparator = new RawComparator() {
      @Override
      public int compare(Object o1, Object o2) {
        return o1.toString().substring(0, 1).compareTo(
            o2.toString().substring(0, 1));
      }

      @Override
      public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3,
          int arg4, int arg5) {
        throw new RuntimeException("Not implemented");
      }  
    };
    
    // value order comparator - order by second character
    RawComparator orderComparator = new RawComparator() {
      @Override
      public int compare(Object o1, Object o2) {
        return o1.toString().substring(1, 2).compareTo(
            o2.toString().substring(1, 2));
      }
      
      @Override
      public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3,
          int arg4, int arg5) {
        throw new RuntimeException("Not implemented");
      }
    };
    
    // reducer to track the order of the input values using bit shifting
    driver.withReducer(new Reducer<Text, LongWritable, Text, LongWritable>() {
      protected void reduce(Text key, Iterable<LongWritable> values, Context context)
          throws IOException, InterruptedException {
        long outputValue = 0;
        int count = 0;
        for (LongWritable value : values) {
          outputValue |= (value.get() << (count++*8));
        }
        
        context.write(key, new LongWritable(outputValue));
      }
    });
    
    driver.withKeyGroupingComparator(groupComparator);
    driver.withKeyOrderComparator(orderComparator);
    
    driver.addInput(new Text("a1"), new LongWritable(1));
    driver.addInput(new Text("b1"), new LongWritable(1));
    driver.addInput(new Text("a3"), new LongWritable(3));
    driver.addInput(new Text("a2"), new LongWritable(2));
    
    driver.addOutput(new Text("a1"), new LongWritable(0x1 | (0x2 << 8) | (0x3 << 16)));
    driver.addOutput(new Text("b1"), new LongWritable(0x1));
    
    driver.runTest();
  }
}

