package simpledb.unittest;

import simpledb.*;

import java.util.*;
import java.io.*;

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

public class HeapFileTest {

    private byte[] data;
    private HeapFile hf;
    private HeapFile empty;
    
    private static final String dataPath = 
	"src/simpledb/unittest/testdata/simple.dat";

    private static final String emptyPath = 
	"src/simpledb/unittest/testdata/empty.dat";

    /**
     * Set up initial resources for each unit test.
     */
    @Before public void setUp() throws Exception {
	this.hf = new HeapFile(new File(dataPath));
	this.data = Utility.readFileBytes(dataPath);
	Database.getCatalog().addTable(hf, Utility.getTupleDesc(2));
	
	// create a new empty HeapFile with a single page and no tuples
	this.empty = Utility.createEmptyHeapFile(emptyPath, 2);
    }

    /**
     * Unit test for HeapFile.id()
     */
    @Test public void id() throws Exception {
	int id = hf.id();
	
	// NOTE(ghuo): the value could be anything. test determinism, at least.
	assertEquals(id, hf.id());
	assertEquals(id, hf.id());
    }

    /**
     * Unit test for HeapFile.numPages()
     */
    @Test public void numPages() throws Exception {
	assertEquals(1, hf.numPages());
	assertEquals(1, empty.numPages());
    }

    /**
     * Unit test for HeapFile.readPage()
     */
    @Test public void readPage() throws Exception {
	HeapPageId pid = new HeapPageId(hf.id(), 0);
	HeapPage page = (HeapPage) hf.readPage(pid);
	
	// NOTE(ghuo): we try not to dig too deeply into the Page API here; we
	// rely on HeapPageTest for that. perform some basic checks.
	assertEquals(492, page.getNumEmptySlots());
	assertTrue(page.getSlot(1));
	assertFalse(page.getSlot(20));
    }
    
    /**
     * Unit test for HeapFile.addTuple()
     */
    @Test public void addTuple() throws Exception {
	TransactionId tid = new TransactionId();
	// we should be able to add 512 tuples on an empty page.
	for (int i = 0; i < 512; ++i) {
	    empty.addTuple(tid, Utility.getHeapTuple(i, 2));
	    assertEquals(1, empty.numPages());
	}

	// the next 512 additions should live on a new page
	for (int i = 0; i < 512; ++i) {
	    empty.addTuple(tid, Utility.getHeapTuple(i, 2));
	    assertEquals(2, empty.numPages());
	}

	// and one more, just for fun...
	empty.addTuple(tid, Utility.getHeapTuple(0, 2));
	assertEquals(3, empty.numPages());
    }

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

