def setUp(self):
     """Initializes a Tableau pile."""
     self.pile = Tableau(5)
class TestTableauPile(unittest.TestCase):    
    """
    
    Tests the functionality of a Tableau pile.
    
    """

    def setUp(self):
        """Initializes a Tableau pile."""
        self.pile = Tableau(5)

    def tearDown(self):
        """Does nothing."""
        print ""
    
    def test_init(self):
        """Tests the init() function for a Tableau pile."""
        print "tableau: test_init ",
        self.assertEqual(self.pile.name, "Tableau-5", 
                         "TestTableauPile.test_init: The name of the Tableau \
                         was incorrect.")
        self.assertEqual(len(self.pile), 0, 
                         "TestTableauPile.test_init: The Tableau pile isn't \
                         empty.")
        self.assertEqual(self.pile.id_, 5, 
                         "TestTableauPile.test_init: The id_ of the Tableau\
                          pile was incorrect.")

    def test_enqueueCard(self):
        """
        Tests that Cards are not allowed to be enqueued to a
        Tableau pile.
        """
        print "tableau: test_enqueueCard ",
        card = Card(Suit.SPADE, 4)
        self.pile.enqueue_card(card)
        self.assertEqual(len(self.pile), 0, 
                         "TestTableauPile.test_enqueueCard: A Card was \
                         enqueued to a Tableau pile.")
    
    def test_pushValidCard(self):
        """
        Tests that a Card of the appropriate rank and suit can be 
        pushed to the pile.
        """
        print "tableau: test_pushValidCard ",
        append_cards(self.pile)
        oldSize = len(self.pile)
        validCard = Card(Suit.SPADE, 4)
        validCard.flip_up()
        self.pile.push_card(validCard)
        self.assertEqual(len(self.pile), oldSize + 1, 
                         "TestTableauPile.test_pushValidCard: A valid Card \
                         was not pushed to the pile.")

    def test_pushKingEmpty(self):
        """Tests that a King can be pushed to an empty Tableau."""
        print "tableau: test_pushKingEmpty ",
        king = Card(Suit.SPADE, Rank.KING)
        king.flip_up()
        self.pile.push_card(king)
        self.assertEqual(len(self.pile), 1, 
                         "TestTableauPile.test_pushKingEmpty: A King was \
                         rejected from an empty Tableau.")
    
    def test_pushInvalidEmpty(self):
        """
        Tests that push_card() on an empty Tableau pile rejects 
        non-Kings.
        """
        print "tableau: test_pushInvalidEmpty ",
        nonking = Card(Suit.SPADE, 5)
        nonking.flip_up()
        self.pile.push_card(nonking)
        self.assertEqual(len(self.pile), 0, 
                         "TestTableauPile.test_pushInvalidEmpty: A non-King \
                         was pushed to an empty Tableau pile.")

    def test_pushInvalidRank(self):
        """
        Tests that a Foundation pile rejects a Card of the improper 
        rank.
        """
        print "tableau: test_pushInvalidRank ",
        append_cards(self.pile)
        oldSize = len(self.pile)
        invalidRankCard = Card(Suit.SPADE, 3)
        invalidRankCard.flip_up()
        self.pile.push_card(invalidRankCard)
        self.assertEqual(len(self.pile), oldSize, 
                         "TestTableauPile.test_pushInvalidRank: A Card with \
                         an invalid rank was pushed to a Tableau pile.")
    
    def test_pushInvalidColor(self):
        """
        Tests that a Foundation pile rejects a Card of the improper 
        color.
        """
        print "tableau: test_pushInvalidColor ",
        append_cards(self.pile)
        oldSize = len(self.pile)
        invalidColorCard = Card(Suit.HEART, 4)
        invalidColorCard.flip_up()
        self.pile.push_card(invalidColorCard)
        self.assertEqual(len(self.pile), oldSize, 
                         "TestTableauPile.test_pushInvalidColor: A Card with \
                         an invalid color was pushed to a Tableau pile.")
    
    def test_pushValidPile(self):
        """
        Tests that a Foundation pile accepts a properly built pile 
        whose bottom card is the proper color and rank.
        """
        print "tableau: test_pushValidPile ",
        append_cards(self.pile)
        self.pile.flip_top()
        oldCards = Pile(copy.copy(list(self.pile)))
        validPile = Pile()
        for i in range(1,5):
            card = Card(Suit.SPADE, i) if i % 2 == 0 else Card(Suit.HEART, i)
            card.flip_up()
            validPile.enqueue(card)
        newCards = copy.copy(validPile)
        oldCards.extend(newCards)
        self.pile.push_pile(validPile)
        self.assertEqual(self.pile, oldCards, 
                         "TestTableauPile.test_pushValidPile: A valid pile \
                         was rejected by the Tableau pile.")

    def test_pushInvalidRankPile(self):
        """
        Tests that a Foundation pile rejects a pile that is built 
        properly, but the top card is not of the proper rank.
        """
        print "tableau: test_pushInvalidRankPile ",
        append_cards(self.pile)
        oldCards = self.pile
        invalidPile = Pile()
        for i in range(1,4):
            card = Card(Suit.SPADE, i) if i % 2 == 1 else Card(Suit.DIAMOND, i)
            card.flip_up()
            invalidPile.enqueue(card)
        self.pile.push_pile(invalidPile)
        self.assertEqual(self.pile, oldCards, 
                         "TestTableauPile.test_pushInvalidRankPile: A pile \
                         whose top Card had an invalid rank was pushed to \
                         the Tableau.")

    def test_pushInvalidSuitPile(self):
        """
        Tests that a Foundation pile rejects a pile that is built 
        properly, but the top card is not of the proper color.
        """
        print "tableau: test_pushInvalidSuitPile ",
        append_cards(self.pile)
        oldCards = self.pile
        invalidPile = Pile()
        for i in range(1,5):
            card = Card(Suit.DIAMOND, i) if i % 2 == 0 else Card(Suit.SPADE, i)
            card.flip_up()
            invalidPile.enqueue(card)
        self.pile.push_pile(invalidPile)
        self.assertEqual(self.pile, oldCards, 
                         "TestTableauPile.test_pushInvalidSuitPile: A pile \
                         whose top Card had an invalid color was pushed onto \
                         the Tableau.")

    def test_pushInvalidAlternatingPile(self):
        """
        Tests that a Foundation pile rejects a pile with valid bottom 
        Card but is not alternating in color.
        """
        print "tableau: test_pushInvalidAlternatingPile ",
        append_cards(self.pile)
        oldCards = self.pile
        invalidPile = Pile()
        for i in range(1,5):
            card = Card(Suit.SPADE, i)
            card.flip_up()
            invalidPile.enqueue(card)
        self.pile.push_pile(invalidPile)
        self.assertEqual(self.pile, oldCards, 
                         "TestTableauPile.test_pushInvalidAlternatingPile: \
                         A pile whose top Card had an invalid rank was pushed\
                         onto the Tableau.")

    def test_pushInvalidBuiltPile(self):
        """
        Tests that a Foundation pile rejects a pile with valid bottom 
        Card but is not built properly.
        """
        print "tableau: test_pushInvalidBuiltPile ",
        append_cards(self.pile)
        oldCards = Pile(copy.copy(list(self.pile)))
        invalidPile = Pile()
        for i in range(1,5):
            card = Card(Suit.SPADE, i) if i % 2 == 0 else Card(Suit.DIAMOND, i)
            card.flip_up()
            invalidPile.enqueue_card(card)
        card = Card(Suit.CLUB, 6)
        card.flip_up()
        invalidPile.push_card(card)
        self.pile.push_pile(invalidPile)
        self.assertEqual(self.pile, oldCards, 
                         "An invalid pile was pushed to the Tableau.")

    def test_popCard(self):
        """
        Tests that popping a Card will also flip the new top Card 
        face-up.
        """
        print "tableau: test_popCard ",
        append_cards(self.pile)
        self.pile.pop_card()
        #top = self.pile.peek()
        #self.assertTrue(top.is_face_up(), 
        #                "The new top card was not flipped after popping.")
    
    def test_popValidPile(self):
        """
        Tests that a Foundation pile will pop a pile that is properly 
        built and alternating in color.
        """
        print "tableau: test_popValidPile ",
        append_cards(self.pile)
        length = len(self.pile)
        for i in range(length):
            popped = self.pile.pop_pile(self.pile.card_at(i))
            self.assertEqual(len(popped), length - i, 
                             "TestTableauPile.test_popValidPile: The size \
                             of the popped pile was incorrect.")
            self.assertEqual(len(self.pile), i, 
                             "TestTableauPile.test_popValidPile: The size of \
                             the original Pile was incorrect.")
            for card in popped:
                self.pile.push_card(card)

    def test_popFaceDownPile(self):
        """Tests that face-down Cards cannot be popped."""
        print "tableau: test_popFaceDownPile ",
        append_cards(self.pile)
        length = len(self.pile)
        for i in range(3):
            self.pile.card_at(i).flip_down()
        for i in range(3):
            self.pile.pop_pile(self.pile.card_at(i))
            self.assertEqual(len(self.pile), length, 
                             "A pile with face-down Cards was popped \
                             from the Pile.")

    def test_popNonBuiltPile(self):
        """Tests that a non-built pile cannot be popped from a Pile."""
        print "tableau: test_popNonBuiltPile ",
        append_cards(self.pile)
        ten = self.pile.card_at(5)
        ten.rank = 9
        for i in range(5):
            popped = self.pile.pop_pile(self.pile.card_at(i))
            self.assertIsNone(popped, 
                              "The Tableau pile popped a non-built pile.")

    def test_popNonAlternatingPile(self):
        """
        Tests that a Pile that does not alternate in color cannot be 
        popped from a Tableau pile.
        """
        print "tableau: test_popNonAlternatingPile ",
        append_cards(self.pile)
        redcard = self.pile.card_at(6)
        redcard.suit = Suit.CLUB
        for i in range(6):
            popped = self.pile.pop_pile(self.pile.card_at(i))
            self.assertIsNone(popped, 
                              "A pile that doesn't alternate in color was \
                              popped from the Tableau.")