package simpledb.unittest;

import simpledb.*;
import java.util.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import junit.framework.JUnit4TestAdapter;

public class AggregateTest {

  int width1 = 2;
  DbIterator scan1;
  DbIterator sum;
  DbIterator avg;
  DbIterator max;
  DbIterator min;

  /**
   * Initialize each unit test
   */
  @Before public void setUp() throws Exception {
    this.scan1 = Utility.createTupleList(width1, 
        new int[] { 1, 2,
                    1, 4,
                    1, 6,
                    3, 2,
                    3, 4,
                    3, 6,
                    5, 7 });
    this.sum = Utility.createTupleList(width1, 
        new int[] { 1, 12,
                    3, 12,
                    5, 7 });
    this.avg = Utility.createTupleList(width1, 
        new int[] { 1, 4,
                    3, 4,
                    5, 7 });
    this.min = Utility.createTupleList(width1, 
        new int[] { 1, 2,
                    3, 2,
                    5, 7 });
    this.max = Utility.createTupleList(width1, 
        new int[] { 1, 6,
                    3, 6,
                    5, 7 });
  }

  /**
   * Unit test for Aggregate.getTupleDesc()
   */
  @Test public void getTupleDesc() {
    Aggregate op = new Aggregate(scan1, 0, 0, 
        new IntAggregator(Aggregator.Op.MIN));
    TupleDesc expected = Utility.getTupleDesc(2);
    TupleDesc actual = op.getTupleDesc();
    assertTrue(expected.equals(actual));
  }

  /**
   * Unit test for Aggregate.rewind()
   */
  @Test public void rewind() throws Exception {
    Aggregate op = new Aggregate(scan1, 1, 0, 
        new IntAggregator(Aggregator.Op.MIN));
    op.open();
    try {
      while (true)
        op.getNext();
    } catch (NoSuchElementException e) {
      // explicitly ignore this.
    }

    op.rewind();
    min.open();
    Utility.matchAllTuples(op, min);
  }

  /**
   * Unit test for Aggregate.getNext() using a sum aggregate
   */
  @Test public void sumAggregate() throws Exception {
    Aggregate op = new Aggregate(scan1, 1, 0, 
        new IntAggregator(Aggregator.Op.SUM));
    op.open();
    sum.open();
    Utility.matchAllTuples(sum, op);
  }

  /**
   * Unit test for Aggregate.getNext() using an avg aggregate
   */
  @Test public void avgAggregate() throws Exception {
    Aggregate op = new Aggregate(scan1, 1, 0, 
        new IntAggregator(Aggregator.Op.AVG));
    op.open();
    avg.open();
    Utility.matchAllTuples(avg, op);
  }

  /**
   * Unit test for Aggregate.getNext() using a max aggregate
   */
  @Test public void maxAggregate() throws Exception {
    Aggregate op = new Aggregate(scan1, 1, 0, 
        new IntAggregator(Aggregator.Op.MAX));
    op.open();
    max.open();
    Utility.matchAllTuples(max, op);
  }

  /**
   * Unit test for Aggregate.getNext() using a min aggregate
   */
  @Test public void minAggregate() throws Exception {
    Aggregate op = new Aggregate(scan1, 1, 0, 
        new IntAggregator(Aggregator.Op.MIN));
    op.open();
    min.open();
    Utility.matchAllTuples(min, op);
  }

  /**
   * JUnit suite target
   */
  public static junit.framework.Test suite() {
    return new JUnit4TestAdapter(AggregateTest.class);
  }
}

