'''
### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
                   308-304 - Object-Oriented Software Design
                                 ASSIGNMENT  1
   TestCD.py ---
      Testing unit for class CellData.

   last modified: 01/24/02
                       ===============================
                             Copyright (c)  2002
                            Jean-Sébastien BOLDUC
                             (jseb@cs.mcgill.ca)

                        McGill University  (Montréal)
                       ===============================

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
'''

# Testing other implementations from the command line:
from sys import argv
if len(argv) > 1:
  exec('from ' + argv[-1] + ' import *')
  del argv[-1] # Don't pass this argument to unittest
else:
  from CData import * # JSeb's implementation

import unittest

# Objects that can be stored in CellData object (only integers for now)
goodParams = range(-20, 20)
# Wrongly-typed objects (cannot be stored in a CellData object)
badParams = [None, 'a', 1.5, [1, 2] ]


class CellDataConstructor(unittest.TestCase):

  def testGoodInitialization(self): # test for success
    '''CellData __init__ should succeed with integers'''
    for i in goodParams:
      self.assert_(CellData(i))
    # also test the default parameter:
    self.assert_(CellData())

  def testBadInitialization(self): # test for failure
    '''CellData __init__ should raise a TypeError on bad argument'''
    for i in badParams:
      self.assertRaises(TypeError, CellData, i)


class CellDataGetSet(unittest.TestCase):

  X = CellData()

  def testGoodSetting(self): # test for success
    '''setValue should succeed with integers'''
    for i in goodParams:
      self.assertEqual(self.X.setValue(i), None)
    # also test the default parameter:
    self.assertEqual(self.X.setValue(), None)

  def testBadSetting(self): # test for failure
    '''setValue should raise a TypeError on bad argument'''
    for i in badParams:
      self.assertRaises(TypeError, self.X.setValue, i)

  def testSanity1(self): # test for sanity
    '''getValue should return value previously set by setValue'''
    for i in goodParams:
      self.X.setValue(i)
      # test it twice, to make sure the data is not corrupted
      # by the getValue method:
      self.assertEqual(self.X.getValue(), i)
      self.assertEqual(self.X.getValue(), i)
      # Future testing (when CellData are not limited to storing integers):
      # Behaviour to determine (see also class "CellDataSharing" below).

  def testSanity2(self): # test for sanity
    '''Stored object should not be corrupted by failed setValue's attempts'''
    self.X.setValue(10)
    for i in badParams:
      try:
        self.X.setValue(i)
      except TypeError:
        pass
      self.assertEqual(self.X.getValue(), 10)


class CellDataSTR(unittest.TestCase):

  X = CellData()

  def testStringRepres(self): # test for success
    '''String representation should be same as that of stored object'''
    for i in goodParams:
      self.X.setValue(i)
      self.assertEqual( str(self.X), str(i) )


# For eventual future testing (when CellData are not limited to storing
# integers) set flag to 1 to activate.
# To complete this test, we must first answer the question: "what happens if an
# object x is stored in two different CellData objects? is x (deep)copied, or
# both CellData objects actually store the same object?". In this first stage,
# where CellData objects can only store integers, this question is not
# relevant, as integers are immutable and cannot be (deep)copied.
if 0:
  class CellDataSharing(unittest.TestCase):
  
    X = CellData()
    Y = CellData()

    def testSharedData(self): # general testing
      '''TO BE COMPLETED'''
      i = [1,2,3] # a mutable object, e.g., a list
      self.X.setValue(i)
      self.Y.setValue(i)
      # Mutable objects are (deep)copied...
      self.assertNotEqual( id(self.X.getValue()), id(self.Y.getValue()) )
      # ...OR mutable objects are not copied
      self.assertEqual( id(self.X.getValue()), id(self.Y.getValue()) )


### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###

if __name__ == "__main__":
  unittest.main()